Skip to content

fix: throw error when plain JSON Schema is passed as inputSchema to server.tool()#1598

Open
giulio-leone wants to merge 4 commits intomodelcontextprotocol:v1.xfrom
giulio-leone:fix/tool-json-schema-silent-drop
Open

fix: throw error when plain JSON Schema is passed as inputSchema to server.tool()#1598
giulio-leone wants to merge 4 commits intomodelcontextprotocol:v1.xfrom
giulio-leone:fix/tool-json-schema-silent-drop

Conversation

@giulio-leone
Copy link

Summary

server.tool() silently drops inputSchema when a plain JSON Schema object is passed instead of a Zod schema. The object is misinterpreted as ToolAnnotations, and the tool registers with an empty parameter schema — a silent data-loss bug.

Root Cause

In mcp.ts, the tool registration overload resolution checks isZodRawShapeCompat(firstArg). When this returns false (as it does for plain JSON Schema objects, which lack .parse()/.safeParse() methods), the fallback else if branch unconditionally treats the object as ToolAnnotations:

} else if (typeof firstArg === 'object' && firstArg !== null) {
    annotations = rest.shift() as ToolAnnotations; // ← JSON Schema lands here
}

Fix

Added a looksLikeJsonSchema() helper that detects objects with JSON Schema characteristic fields (type, properties, $schema, items, allOf, anyOf, oneOf). When detected, a descriptive error is thrown:

Tool "my.tool": Plain JSON Schema objects are not supported as inputSchema.
Use Zod schemas instead (e.g., z.object({ ... })).

Tests

Added 3 new tests:

  • Throws for plain JSON Schema with type/properties/required
  • Throws for JSON Schema with $schema property
  • Does NOT false-positive on valid ToolAnnotations (readOnlyHint, destructiveHint)

Verification

2 consecutive clean test runs: 1553/1553 tests passed, 0 failures.

Fixes #1585

@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

🦋 Changeset detected

Latest commit: 98010e1

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

pkg-pr-new bot commented Feb 27, 2026

Open in StackBlitz

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

commit: 2b5f642

g97iulio1609 added 4 commits February 28, 2026 15:50
…erver.tool()

Previously, passing a plain JSON Schema object (e.g. { type: 'object', properties: {...} })
as the inputSchema parameter to server.tool() would silently misinterpret it as
ToolAnnotations, causing the schema to be dropped entirely. Tools would register
with empty parameter schemas ({ type: 'object', properties: {} }), leading to
silent data loss at runtime.

This adds a looksLikeJsonSchema() check that detects objects with JSON Schema
characteristic fields (type, properties, $schema, etc.) and throws a descriptive
error instructing users to use Zod schemas instead.

Fixes modelcontextprotocol#1585
@giulio-leone
Copy link
Author

All CI checks pass. Ready for review.

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