fix(mcp): drop JSON Schema annotations from tool schemas - #3560
Open
jsiu93 wants to merge 1 commit into
Open
Conversation
Client Capability validation intentionally keeps a strict keyword allowlist. Normalize MCP tool descriptors during discovery by removing only the non-semantic $schema and $comment annotations from supported schema positions. Keep $id because it changes $ref base resolution and must remain subject to protocol validation. Generated-by: pi (gpt-5.6-sol)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MCP servers built with the TypeScript SDK advertise Zod-derived input schemas with a root
$schema. The capability provider copied those schemas into Client Capability frames, and the protocol's strict keyword allowlist rejected them, so publication stopped before the first tool.This normalizes tool descriptors at MCP discovery (
descriptorFromToolinpackages/mcp): clone the input schema and delete exactly$schemaand$commentfrom the root and from the child positions the validator walks (properties,items,additionalProperties,propertyNames,$defs/definitions,allOf/anyOf/oneOf).$idstays because it changes$refbase resolution; every other unsupported keyword still fails closed. The validator itself is unchanged.The descriptor is the one place every MCP consumer reads from. Desktop's Client Capability projection covers Desktop-native Zod tools, not MCP descriptors, and already strips the
$schemait generates.Evidence for how common this is: a direct
tools/listfrom XcodeBuildMCP 2.7.0 had$schemaon 44/44 tools and no other disallowed keyword; an earlier probe throughmcp_routersaw it on 31/31. The SDK'sserver/zod-json-schema-compat.jsemits it on both thezod-to-json-schemaandz.toJSONSchemapaths.Fixes #3559
Verification
Regression test
drops non-semantic JSON Schema annotations from discovered tools(stdio fixture with root$schema, nested$schema,$comment,$id): red before the change (descriptor still carried all three annotations), green after ($schemaand$commentgone,$idkept).biome lintandbiome formaton the three changed files reported no fixes.Live, with fresh Runtime Host roots and
bunx xcodebuildmcp mcpas the server:The live server advertised 24 tools in that fresh environment (XcodeBuildMCP exposes tools by workflow); the fixed provider published all 24 it received. The 44-tool figure comes from a separate direct capture of the same server.
Not run: the full monorepo
npm test, root-wide typecheck, the Desktop and runtime workspace suites, Windows or Linux, a model turn that invokes a published tool.AI use
Select exactly one:
Tool(s) and scope: pi (gpt-5.6-sol) traced the MCP-to-Client-Capability path, wrote the regression test and the normalization helper, ran the live publication and the suites, and drafted this description. Claude Code chose the design, reviewed the diff, re-ran the mcp and CLI suites, and edited this text. The commit carries the trailer.
Generated-by: pi (gpt-5.6-sol)
Checklist
Does this PR entail a change in behavior?