fix(mcp): connect tools into the default catalog: Claude.ai cannot call search-only tools (#1936)

First real onboarding run (SilverPark, 2026-08-26): the flow worked
through signup, preview, confirm and company creation, then dead-ended
when the onboarding skill pointed at gnubok_connect_bank and
gnubok_connect_skatteverket. Both were catalogVisibility 'search', and
Claude.ai can only invoke tools present in tools/list, so the client
refused the calls itself: event_log shows the server never received
them. Search-only stays valid for reference tools, but anything a skill
tells the agent to CALL must be in the default catalog. tools/list
ceiling bumped 60.7K -> 61.2K, documented in the guard.


Claude-Session: https://claude.ai/code/session_018wCdzRTatKiDByKB8hCNT6

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-26 10:41:38 +02:00
committed by GitHub
parent b1a03de34e
commit a97943d00d
3 changed files with 9 additions and 3 deletions
+1
View File
@@ -1247,3 +1247,4 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
[2026-08-25] Woo bulk revenue template = per-rate account choice, no hardcoded varor/tjanster preset: BAS 2026 has no standard 30xx goods/services subdivision (3040-series is company-specific), so presets would invent accounts; chosen accounts are validated against the company chart instead, and only diffs from the 3001-series default are sent.
[2026-08-26] RFC 9728 protected-resource metadata is served at THREE locations (root, path-based /.well-known/oauth-protected-resource/<mcp path>, and <mcp url>/.well-known/oauth-protected-resource): Claude.ai's connector setup derives the metadata URL from the server URL and fetches it before any 401, so the root document our WWW-Authenticate header points at was not enough ('Authorization with Accounted failed' with only 404s in the logs). One builder, three routes; the path-based route answers 404 for any path other than the MCP endpoint so no phantom resource is advertised.
[2026-08-20] The swedish-e-invoicing skill now names Upphandlingsmyndigheten as Sweden Peppol Authority across all eight files, not just the one that was flagged: the handover completed 1 July 2026 (regeringsbeslut Fi2025/01826) and the skill was written in future tense, so a partial fix would have left the atom internally contradictory and still pointed agents at peppol@digg.se. Four digg.se URLs were repointed to their verified 301 targets on upphandlingsmyndigheten.se; the fifth, DIGG Peppol testbadd, is a hard 404 with no redirect and no successor page at the new authority, so it was replaced with the SFTI Validex verification service (https://sfti.validex.net/) rather than left dead or guessed at. Historical attributions (Q4 2025 traffic statistics, the 0007:2021006883 Peppol-ID example) deliberately still say DIGG because they were accurate when published.
[2026-08-26] gnubok_connect_bank / gnubok_connect_skatteverket moved from catalogVisibility 'search' to the default catalog: Claude.ai can only invoke tools present in tools/list, so search-only tools are discover-only there and the onboarding skill's steps 3-4 dead-ended on client-side tool-not-found (verified via event_log: the server never received the calls). Search-only visibility remains fine for tools an agent reads about before asking the user, but anything a skill instructs the agent to CALL must be in the default catalog.
@@ -216,9 +216,14 @@ describe('tools/list payload size guard', () => {
// trimmed to bare property names first (the two connect-link tools
// are search-only); headroom before the change was ~0 after the skatteverket_connection bump, so even the
// bare contract crossed by ~420.
// * 60.7K to 61.2K with the two connect-link tools moved into the default
// catalog (issue #1814): Claude.ai can only CALL tools present in
// tools/list, so catalogVisibility 'search' means discover-only there;
// the onboarding flow dead-ended on client-side tool-not-found when
// the skill pointed at them (SilverPark session, 2026-08-26).
// Long-term answer to growth is leaning harder on gnubok_search_tools: if this
// fires again, prefer trimming descriptions or making a tool opt-in via search
// before bumping further.
expect(approxTokens).toBeLessThan(60_700)
expect(approxTokens).toBeLessThan(61_200)
})
})
+2 -2
View File
@@ -3121,7 +3121,7 @@ export const tools: McpTool[] = [
},
required: ['connected', 'connections', 'connect_url', 'instructions'],
},
catalogVisibility: 'search',
annotations: {
readOnlyHint: true,
destructiveHint: false,
@@ -3177,7 +3177,7 @@ export const tools: McpTool[] = [
},
required: ['available', 'connected', 'token_expires_at', 'connect_url', 'instructions'],
},
catalogVisibility: 'search',
annotations: {
readOnlyHint: true,
destructiveHint: false,