Skip to content

feat: add client-side JSON Schema 2020-12 preservation scenario#335

Open
pugsatoshi wants to merge 1 commit into
modelcontextprotocol:mainfrom
pugsatoshi:feat/101-client-schema-preservation
Open

feat: add client-side JSON Schema 2020-12 preservation scenario#335
pugsatoshi wants to merge 1 commit into
modelcontextprotocol:mainfrom
pugsatoshi:feat/101-client-schema-preservation

Conversation

@pugsatoshi

Copy link
Copy Markdown
Contributor

This PR adds a new JSON-Schema-2020-12-preservation client conformance scenario that closes Issue #101. The existing json-schema-2020-12 scenario tests server-side keyword emission; this new scenario tests the client-side preservation path that SEP-1613 and TypeScript SDK PR #1135 actually fixed (.catchall() so the parser retains the 2020-12 vocabulary).

The scenario sets up a mock MCP server (via the version-aware MockServer abstraction from #321) that advertises:

  • json_schema_2020_12_tool — focal tool whose inputSchema contains the full SEP-1613 + SEP-2106 vocabulary
  • json_schema_echo — permissive echo tool

The client under test calls tools/list, then round-trips the observed inputSchema back via tools/call json_schema_echo with { schema: <observed> }.
The scenario diffs the echoed schema against the canonical fixture and emits eight per-keyword checks. SEP-2106 vocabulary checks are soft-gated via sep2106KeywordCheckStatus so they only fail on DRAFT-2026-v1 runs.

Motivation and Context

Closes #101.

Issue #101 noted that the existing json-schema-2020-12 scenario covers only the server's wire output, while the actual SEP-1613 / TS SDK PR #1135 fix was on the client side.
This PR fills that gap with a dedicated client-side scenario that mirrors the server-side scenario, one check at a time.

Scope is intentionally pinned to introducedIn: '2025-11-25'.
The 2026-07-28-RC changelog (draft changelog) does not change the preservation requirements for SEP-1613 / SEP-2106, so the wire shape under test remains unchanged.
The broader 2026-07-28-RC changes (SEP-2575 stateless, SEP-2549 CacheableResult, SEP-2243 Mcp-Method MUST) are deliberately out of scope for this PR; once 2026-07-28 is finalized and lands in DATED_SPEC_VERSIONS, the same scenario can be re-targeted in a follow-up.

The focal-schema fixture (a 2020-12 inputSchema with $schema, $defs.address.$anchor, allOf/anyOf, if/then/else, additionalProperties: false) was previously embedded only in the server-side scenario's description markdown block.
This PR extracts it into an exported JSON_SCHEMA_2020_12_FIXTURE, so the new scenario can reuse it verbatim; the server-side description now derives its example from the same constant via JSON.stringify, eliminating the risk of documentation/runtime drift.

How Has This Been Tested?

  • npm run check — typecheck + lint pass.
  • npm test — 274/274 tests pass (6 new vitest cases for this scenario, covering no-client, compliant-on-dated, compliant-on-draft, $schema/$defs strip, SEP-2106 strip on draft, and a round-trip-fidelity sanity check).
  • End-to-end against the bundled reference client (CONTRIBUTING.md "Running your scenario" form):
$ npm run build
$ node dist/index.js client \
  --command "npx tsx examples/clients/typescript/everything-client.ts" \
  --scenario json-schema-2020-12-preservation
Starting scenario: json-schema-2020-12-preservation
Checks:
2026-06-05T03:25:14.074Z [json-schema-2020-12-client-tool-found                    ] SUCCESS Client called tools/list and
the mock server advertised 'json_schema_2020_12_tool'
2026-06-05T03:25:14.074Z [json-schema-2020-12-client-echo-completed                ] SUCCESS Client called tools/call
'json_schema_echo' with a 'schema' object argument
2026-06-05T03:25:14.074Z [json-schema-2020-12-client-$schema-preserved             ] SUCCESS Client preserved $schema =
'https://json-schema.org/draft/2020-12/schema'
2026-06-05T03:25:14.074Z [json-schema-2020-12-client-$defs-preserved               ] SUCCESS Client preserved $defs with the
expected nested definitions
2026-06-05T03:25:14.074Z [json-schema-2020-12-client-additionalProperties-preserved] SUCCESS Client preserved
additionalProperties = false on the focal inputSchema
2026-06-05T03:25:14.074Z [sep-2106-client-composition-keywords-preserved           ] SUCCESS Client preserved composition
keywords (allOf/anyOf) on the focal inputSchema
2026-06-05T03:25:14.074Z [sep-2106-client-conditional-keywords-preserved           ] SUCCESS Client preserved conditional
keywords (if/then/else) on the focal inputSchema
2026-06-05T03:25:14.074Z [sep-2106-client-anchor-keyword-preserved                 ] SUCCESS Client preserved $anchor inside
$defs.address

Test Results:
Passed: 8/8, 0 failed, 0 warnings

The negative case (a client that strips $schema/$defs before echoing) is covered by src/scenarios/client/json-schema-2020-12-preservation.test.ts rather than by a separate broken example client, matching the pattern used by json-schema-ref-deref.test.ts.

src/seps/traceability.json will drift after this change picks up the six new requirement rows in sep-2106.yaml; per AGENTS.md the traceability workflow will refresh it via a follow-up PR rather than as part of this one.

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

The mock server, using the version-aware `MockServer` abstraction from modelcontextprotocol#321,
first advertises a focal tool with a detailed inputSchema and also offers a
permissive `json_schema_echo` tool. The client under test retrieves the
inputSchema via `tools/list`, then sends the same inputSchema back to the server
using the echo tool, completing the round-trip.

The scenario diffs from the echoed schema against the canonical fixture. It
emits eight per-keyword conformance checks. SEP-2106 vocabulary checks are
soft-gated using the existing sep2106KeywordCheckStatus helper. They only flip
to FAILURE during DRAFT-2026-v1 runs.

Signed-off-by: Satoshi Ito <satoshi.ito.tf@hitachi.com>
@pkg-pr-new

pkg-pr-new Bot commented Jun 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@modelcontextprotocol/conformance@335

commit: 3f45fb0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider adding client test for JSON Schema 2020-12 preservation (SEP-1613)

1 participant