fix: declare the skills extension in the Inspector's client capabilities (#2373)

SEP-2133 negotiates an extension from both sides, and a strict server
refuses skills/* to a client that did not declare
io.modelcontextprotocol/skills. The Inspector called those methods
without ever declaring it. Add it to ADVERTISABLE_EXTENSIONS, on by
default, which also gives it a Server Settings toggle.

Give the composable test server skillsRequireClientExtension and two
per-era strict showcase configs, so a strict server is reproducible here.

Writing the modern-era test exposed two defects the existing suite hid:
its "modern" cases set protocolEra on the transport config, which
InspectorClient does not read, so they connected on legacy; and once
they really ran modern, every skills result failed, because the modern
schemas required resultType, which the SDK codec checks and then lifts
off before a caller schema runs. Connect with versionNegotiation and
assert the era, and drop the resultType requirement (and the two modern
schema variants it was the only difference in).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q3RsrgCxVoFPokLB4vAkxi
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-14 08:36:37 -04:00
commit 1d765b8af6

View file

@ -1,6 +1,7 @@
import type { ClientCapabilities } from "@modelcontextprotocol/client";
import { RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/app-bridge";
import { TASKS_EXTENSION_KEY } from "./modernTaskSchemas.js";
import { SKILLS_EXTENSION_KEY } from "./skillsSchemas.js";
/**
* Extension identifier for SEP-2350 enterprise-managed authorization. Advertised
@ -91,6 +92,18 @@ export const ADVERTISABLE_EXTENSIONS: readonly AdvertisableExtension[] = [
defaultAdvertised: true,
advertisement: { mimeTypes: [MCP_APP_MIME_TYPE] },
},
{
key: SKILLS_EXTENSION_KEY,
label: "Skills (io.modelcontextprotocol/skills)",
// The Skills extension (SEP-2640). SEP-2133 negotiates an extension from
// both sides, so a server may refuse `skills/list`, `skills/get` and
// `resources/directory/read` to a client that did not declare it — and the
// Inspector calls all three once the server declares its half. Advertised
// by default for that reason; turning it off is how to check a server's
// refusal path. Declared with no settings: SEP-2640 defines none for the
// client side. (#2373)
defaultAdvertised: true,
},
];
export interface BuildClientExtensionsInput {