Repository navigation
Conversation
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).
🦋 Changeset detectedLatest commit: 26564b0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
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 |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
| */ | ||
| function isJsonSchemaDocument(schema: StandardJSONSchemaV1): boolean { | ||
| const { $schema, properties } = schema as { $schema?: unknown; properties?: unknown }; | ||
| if (typeof $schema === 'string') return true; |
There was a problem hiding this comment.
I am new to this library so this my not be relevant but would it also be worthwhile validating that the $schema matches JSON_SCHEMA_CONVERSION_TARGET. If so this function may be more suitably named isCompatibleJsonSchemaDocument.
|
Thanks for the review. On the Validating |
Summary
registerTool()/registerPrompt()schemas (and elicitationrequestedSchema) that are themselves already-converted JSON Schema documents — most prominently the output of zod'stoJSONSchema(), which retains a~standardprop whose converters reference the original zod schema — were re-converted through those converters on everytools/listandtoolInputSchemaJson()call, instead of being used directly (#3132).standardSchemaToJsonSchema()now detects a JSON Schema document by its own$schema/propertieskeywords and uses it as-is, before consulting~standard.jsonSchema. Live Standard Schemas cannot be misdetected this way: zod schemas carrydef, valibot usesentries, and ArkType nodes are functions — none expose$schemaorpropertiesat the root.Fixes #3132
Behavior notes
toJSONSchema()document the advertised schema is now the document itself. For example,additionalProperties: falsethat zod emits is preserved as registered — matching the documentedfromJsonSchema()contract — where the previous re-conversion path dropped it.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.$schemanorproperties(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: atoJSONSchema()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 —registerToolwith a pre-converted document, thentoolInputSchemaJson()andtools/list, each with zero converter invocations.core-internalandserversuites 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.