From 927ccdd161412c61e24eefb58ca4983ad27cce24 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Wed, 12 Aug 2026 02:26:41 +0900 Subject: [PATCH] [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. --- conformance/client.rb | 8 ++++++++ conformance/expected_failures.yml | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/conformance/client.rb b/conformance/client.rb index c1034142..23403d3b 100644 --- a/conformance/client.rb +++ b/conformance/client.rb @@ -182,6 +182,14 @@ def build_provider_for(scenario, context) 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" } diff --git a/conformance/expected_failures.yml b/conformance/expected_failures.yml index e26c20eb..5c1dbec1 100644 --- a/conformance/expected_failures.yml +++ b/conformance/expected_failures.yml @@ -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