Skip to content

Conversation

@felixweinberger
Copy link
Contributor

Summary

Restores the ability for ToolAnnotations to accept additional properties beyond the standard fields.

Problem

In SDK v1.22.0, the .passthrough() modifier was accidentally removed from ToolAnnotationsSchema during the SEP-1319 cleanup (commit f59996a). This broke consumers like Cloudflare's x402 integration that rely on extending annotations with custom fields (e.g., paymentHint, paymentPriceUSD).

Justification from Spec

The MCP specification allows additional properties on ToolAnnotations. Looking at the JSON Schema for ToolAnnotations:

{
  "description": "Additional properties describing a Tool to clients...",
  "properties": {
    "title": { ... },
    "readOnlyHint": { ... },
    "destructiveHint": { ... },
    "idempotentHint": { ... },
    "openWorldHint": { ... },
    "taskHint": { ... }
  },
  "type": "object"
}

Note: No "additionalProperties": false is specified, which per JSON Schema semantics means additional properties ARE allowed.

Solution

Add .catchall(z.unknown()) to ToolAnnotationsSchema to match the spec's extensibility. Using .catchall(z.unknown()) rather than .passthrough() for consistency with other schemas per commit 913ca2a.

Test Plan

  • All existing tests pass (1092 tests)
  • Lint passes
  • Build passes

The ToolAnnotations schema should allow additional properties per the
MCP specification. The JSON Schema at:
https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.json

does NOT include "additionalProperties": false for ToolAnnotations,
which means additional properties are allowed by default per JSON Schema
semantics.

This was accidentally removed in commit f59996a (SEP-1319) when
.passthrough() was dropped during schema cleanup. This broke consumers
like Cloudflare's x402 integration that rely on extending annotations
with custom fields (e.g., paymentHint, paymentPriceUSD).

Using .catchall(z.unknown()) rather than .passthrough() for consistency
with other schemas per commit 913ca2a.
@felixweinberger felixweinberger requested a review from a team as a code owner November 20, 2025 17:54
@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 20, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1144

commit: f1c3238

@vincentdestrait
Copy link

vincentdestrait commented Nov 25, 2025

@felixweinberger hello, we observed this breaking change as we also extend annotations with custom fields. Can you please explain why the PR was closed? Is there any plan to fix this? Otherwise how are we expected to update our implementation instead?

@felixweinberger
Copy link
Contributor Author

@felixweinberger hello, we observed this breaking change as we also extend annotations with custom fields. Can you please explain why the PR was closed? Is there any plan to fix this? Otherwise how are we expected to update our implementation instead?

Hm, I'm pretty sure that's not intended; we were letting through a lot of additional fields via .passthrough(), but that's a thing we fixed to tighten up the spec schema, so not really supported by the protocol.

I've opened an issue here as technically speaking JSON Schema without setting additionalProperties: false would mean anything could be added. But I highly doubt that was the original design intent given we added _meta (which is specifically intended for additional fields like this) and have specified additionalProperties: true in several places.

modelcontextprotocol/modelcontextprotocol#1898

@felixweinberger felixweinberger deleted the fweinberger/fix-tool-annotations-passthrough branch December 15, 2025 18:11
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.

3 participants