Skip to content

fix(core-internal): use an already-converted JSON Schema document directly - #3138

Open
BlueX888 wants to merge 1 commit into
modelcontextprotocol:mainfrom
BlueX888:contrib/zod-preconverted-json-schema-direct-use
Open

BlueX888 wants to merge 1 commit into
modelcontextprotocol:mainfrom
BlueX888:contrib/zod-preconverted-json-schema-direct-use

Conversation

@BlueX888

Copy link
Copy Markdown

Summary

registerTool() / registerPrompt() schemas (and elicitation requestedSchema) that are themselves already-converted JSON Schema documents — most prominently the output of zod's toJSONSchema(), which retains a ~standard prop whose converters reference the original zod schema — were re-converted through those converters on every tools/list and toolInputSchemaJson() call, instead of being used directly (#3132).

standardSchemaToJsonSchema() now detects a JSON Schema document by its own $schema / properties keywords and uses it as-is, before consulting ~standard.jsonSchema. Live Standard Schemas cannot be misdetected this way: zod schemas carry def, valibot uses entries, and ArkType nodes are functions — none expose $schema or properties at the root.

Fixes #3132

Behavior notes

  • For a toJSONSchema() document the advertised schema is now the document itself. For example, additionalProperties: false that zod emits is preserved as registered — matching the documented fromJsonSchema() contract — where the previous re-conversion path dropped it.
  • The same direct use applies to elicitation requestedSchema: a document carrying root-level constraints elicitation does not support (e.g. additionalProperties) now fails with the documented unsupported-constraint error — the same treatment a raw JSON Schema already receives — where the previous re-conversion silently dropped them.
  • Documents with neither $schema nor properties (e.g. an openapi-3.0-style scalar root) keep the previous best-effort re-conversion behavior.

Testing

  • packages/core-internal/test/util/standardSchema.test.ts: a toJSONSchema() document is used directly with zero converter invocations; a live zod schema still converts exactly once.
  • packages/server/test/server/lazyToolSchemaConversion.test.ts: the reporter's scenario — registerTool with a pre-converted document, then toolInputSchemaJson() and tools/list, each with zero converter invocations.
  • Full core-internal and server suites pass (the two pre-existing core-internal conformance failures are identical on unpatched main); tsgo, eslint and prettier are clean. The reporter's 1000-tool MRE drops from ~7.8 ms to ~1.9 ms of conversion work.

Zod's toJSONSchema() retains a ~standard prop on its output whose
converters re-run the conversion from the original zod schema, so such a
document passed to registerTool()/registerPrompt() was re-converted on
every tools/list and toolInputSchemaJson() call (modelcontextprotocol#3132). A schema
carrying $schema or properties is now recognized as a document and used
as-is; live schemas never carry those keywords (zod: def, valibot:
entries, ArkType nodes are functions).
@BlueX888
BlueX888 requested a review from a team as a code owner October 31, 2026 06:59
@changeset-bot

changeset-bot Bot commented Oct 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 26564b0

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

This PR includes changesets to release 6 packages
Name Type
@modelcontextprotocol/core-internal Patch
@modelcontextprotocol/server Patch
@modelcontextprotocol/client Patch
@modelcontextprotocol/codemod Patch
@modelcontextprotocol/core Patch
@modelcontextprotocol/server-legacy Patch

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

pkg-pr-new Bot commented Oct 31, 2026

Copy link
Copy Markdown

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@3138

@modelcontextprotocol/codemod

npm i https://pkg.pr.new/@modelcontextprotocol/codemod@3138

@modelcontextprotocol/core

npm i https://pkg.pr.new/@modelcontextprotocol/core@3138

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@3138

@modelcontextprotocol/server-legacy

npm i https://pkg.pr.new/@modelcontextprotocol/server-legacy@3138

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@3138

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@3138

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@3138

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@3138

commit: 26564b0

@claude claude Bot added the v2 Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes label Oct 31, 2026

This branch has not been deployed

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

Labels

v2 Ideas, requests and plans for v2 of the SDK which will incorporate major changes and fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v2] Unnecessary zod schema conversion

1 participant