fix: answer a modern strict refusal with -32021 and cover the configs (#2374 review)

SEP-2575 gives a modern request that needs an undeclared capability its
own error, -32021 MissingRequiredClientCapability with
data.requiredCapabilities; -32601 there claims the method does not
exist. The strict fixture now throws MissingRequiredClientCapabilityError
on the modern leg and keeps -32601 on legacy, which has no such code.

The negative-control test now asserts the code and data per era, and a
new integration test resolves both checked-in strict configs through
loadConfig/resolveConfig, so a misspelled key or a dropped mapping
fails instead of leaving the manual fixtures permissive.

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:54:06 -04:00
commit 07411047cc

View file

@ -86,10 +86,13 @@ declaration and passed against this fixture regardless
([#2373](https://github.com/modelcontextprotocol/inspector/issues/2373)).
`skills-strict-legacy-http.json` (port 3232) and
`skills-strict-modern-http.json` (port 3233) add
`"skillsRequireClientExtension": true`, which answers `skills/list`,
`skills/get` and `resources/directory/read` with `-32601` unless the client
declared it (skill files still come through ordinary `resources/read`, which
needs no extension). ⚠️ **Connect each with its own era.** A modern request
`"skillsRequireClientExtension": true`, which refuses `skills/list`,
`skills/get` and `resources/directory/read` unless the client declared it
(skill files still come through ordinary `resources/read`, which needs no
extension). The refusal differs by era: a **modern** request gets SEP-2575's
`-32021` MissingRequiredClientCapability (HTTP 400) with the Skills extension
under `data.requiredCapabilities`; a **legacy** one, whose era has no such code,
gets `-32601`. ⚠️ **Connect each with its own era.** A modern request
carries the declaration in its `_meta` envelope; a legacy one relies on what
`initialize` declared, which only a stateful legacy server keeps. A legacy
client reaching the modern file is served statelessly, holds no declaration,