Skip to content

[v1.x] fix(server): emit JSON Schema 2020-12 in tools/list (SEP-1613)#2085

Open
rsalus wants to merge 2 commits into
modelcontextprotocol:v1.xfrom
rsalus:fix/sep-1613-emit-2020-12
Open

[v1.x] fix(server): emit JSON Schema 2020-12 in tools/list (SEP-1613)#2085
rsalus wants to merge 2 commits into
modelcontextprotocol:v1.xfrom
rsalus:fix/sep-1613-emit-2020-12

Conversation

@rsalus
Copy link
Copy Markdown

@rsalus rsalus commented May 14, 2026

Fixes #2084.

Summary

McpServer's tools/list handler calls toJsonSchemaCompat() without a target, so mapMiniTarget(undefined) returns 'draft-7' and every inputSchema/outputSchema advertises draft-07 instead of the 2020-12 dialect SEP-1613 requires.

The target: 'draft-2020-12' plumbing was added in #1135, but the mcp.ts call sites weren't updated to use it. This PR does that, plus an extra fix for the Zod v3 path that the 2-liner doesn't reach.

What changed

src/server/mcp.ts — pass target: 'draft-2020-12' at both call sites. That's the 2-line patch from the issue. For Zod v4 it's the whole fix: z4mini.toJSONSchema then emits the right $schema and uses prefixItems for tuples.

src/server/zod-json-schema-compat.ts — the v3 branch needed more. zod-to-json-schema has no draft-2020-12 target (only jsonSchema7 and jsonSchema2019-09), so passing the option through is a silent no-op. The v3 branch now overrides $schema to https://json-schema.org/draft/2020-12/schema when 2020-12 is requested.

A caveat on the v3 override: the keywords zod-to-json-schema actually emits (type, properties, required, additionalProperties, oneOf/anyOf/allOf, enum, const) have identical semantics in draft-07 and 2020-12. The one keyword that diverges is tuples. items: [...] is a positional tuple in draft-07 but means "every item matches one of these schemas" in 2020-12. A Zod v3 tuple stamped as 2020-12 is therefore subtly wrong; an inline comment in the file flags this and points at Zod v4 for native prefixItems. IMO, leaving v3 stuck on draft-07 is worse than the caveat.

test/server/mcp.test.ts: three new tests in the existing zodTestMatrix block so they run on v3 and v4: inputSchema $schema, outputSchema $schema, and a v4-only tuple → prefixItems check.

.changeset/fix-sep-1613-emit-2020-12.md: patch-level changeset.

Tests

  • npm test: 1584 / 1584 pass
  • npm run typecheck: clean
  • npm run lint: clean

On v2.0.0-alpha

main doesn't have this bug. standardSchemaToJsonSchema hardcodes target: 'draft-2020-12' at the conversion site, and v2 dropped Zod v3.

Test plan

  • New tests fail on unpatched v1.x
  • New tests pass with the fix
  • Full npm test (1584 / 1584)
  • npm run typecheck passes
  • npm run lint passes
  • Changeset added

McpServer's tools/list handler called toJsonSchemaCompat() without the
target option, so mapMiniTarget(undefined) fell back to 'draft-7' and
every inputSchema/outputSchema advertised draft-07, contradicting
SEP-1613 / MCP 2025-11-25 spec.

Pass target: 'draft-2020-12' at both call sites. For the Zod v4 branch,
this surfaces native 2020-12 output (including prefixItems for tuples).
For the Zod v3 branch — which uses zod-to-json-schema, a library with
no 2020-12 target — overlay $schema in toJsonSchemaCompat when 2020-12
is requested; the emitted keyword subset (type, properties, required,
additionalProperties, oneOf/anyOf/allOf, enum, const) is unchanged
between draft-07 and 2020-12.

Tests cover inputSchema and outputSchema $schema across both Zod
versions, plus Zod v4 tuples emitting prefixItems.

Fixes modelcontextprotocol#2084
@rsalus rsalus requested a review from a team as a code owner May 14, 2026 05:35
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 14, 2026

🦋 Changeset detected

Latest commit: 4f16599

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 14, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@2085

commit: 4f16599

Wrap long line in .changeset/fix-sep-1613-emit-2020-12.md to satisfy
the repo's prettier config. No semantic change.
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.

1 participant