[Conformance] Cover the JSON Schema 2020-12 preservation scenario

## Motivation and Context

The `json-schema-2020-12-preservation` client scenario (SEP-1613, SEP-2106; not scored for
2026-07-28, as it was added after the requirements anchor) failed only because the conformance client
had no branch for it: an unknown scenario aborts after connecting, so the harness never observed
a `tools/list` nor the schema echo it diffs.

The client itself already preserves the vocabulary the scenario checks (`$schema`, `$defs` with
`$anchor`, `$ref`, `allOf`/`anyOf`, `if`/`then`/`else`, `additionalProperties`):
`Client::Tool#input_schema` is the parsed `tools/list` response untouched, with no dereferencing,
validation-time rewriting, or keyword stripping, the same fixture-echo approach
the TypeScript and Python conformance clients take. The new branch lists the tools and echoes
the focal tool's observed `inputSchema` verbatim through `json_schema_echo`,
and the expected-failures entry is removed.

## How Has This Been Tested?

The scenario passes 9/9 at its default 2025-11-25 wire. On top of the modern-lifecycle client selection
(the SEP-2322 driver branch) it also passes 9/9 at `--spec-version 2026-07-28`, where the SEP-2106 keyword checks
are failure-gated instead of skipped. `bundle exec rake` is green, with the conformance task passing its baseline check
on both legs, and RuboCop reports no offenses.

## Breaking Changes

None. The change is confined to the conformance client and its baseline; the shipped gem is untouched.
This commit is contained in:
Koichi ITO 2026-08-12 02:26:41 +09:00
commit 927ccdd161
2 changed files with 10 additions and 2 deletions

View file

@ -182,6 +182,14 @@ begin
case scenario
when "initialize"
client.tools
when "json-schema-2020-12-preservation"
# SEP-1613/SEP-2106: echo the focal tool's observed inputSchema verbatim so the harness
# can diff what the client preserved. Preservation holds because `Client::Tool#input_schema`
# is the parsed response untouched.
tools = client.tools
focal = tools.find { |t| t.name == "json_schema_2020_12_tool" }
abort("Tool json_schema_2020_12_tool not found") unless focal
client.call_tool(name: "json_schema_echo", arguments: { "schema" => focal.input_schema })
when "tools_call"
tools = client.tools
add_numbers = tools.find { |t| t.name == "add_numbers" }

View file

@ -8,9 +8,9 @@ client:
# are not implemented in `MCP::Client::HTTP` yet.
- http-custom-headers
- http-invalid-tool-headers
# Client-side JSON Schema preservation gaps: `$ref` values must reach the caller unresolved.
# Client-side JSON Schema handling: `$ref` values must reach the caller unresolved,
# and the conformance client does not run the scenario over the modern lifecycle yet.
- json-schema-ref-no-deref
- json-schema-2020-12-preservation
# Unimplemented authorization extensions.
- auth/dpop
- auth/dpop-nonce