Skip to content

mcp: tool schemas and metadata lose JSON number precision #1310

Open

Description

@Tangerg

On upstream main at 7cb505c (Go 1.27.0, darwin/arm64), tools/list schema numbers and tool/result/content _meta numbers are rounded before the client receives them. structuredContent already preserves these numbers.

For example, register a tool with the low-level Server.AddTool API using this raw input/output schema:

{"type":"object","properties":{"id":{"const":9007199254740993}},"required":["id"]}

Return structuredContent: {"id":9007199254740993} and _meta: {"revision":9007199254740993}. After client/server transport, the schema constant and metadata revision re-marshal as 9007199254740992, while structured content still contains 9007199254740993. The same loss affects tool metadata, text content metadata, resource-link metadata, and embedded resource metadata. Negative large integers and high-precision decimals are also affected.

Expected: preserve numeric values in these arbitrary JSON fields at the protocol decode boundary, so consumers can use their original schemas and metadata. This is about descriptor/result fidelity, not implementing a new schema validator.

A regression reproduces this over both the SDK's serialized in-memory NDJSON transport and Streamable HTTP. It does not involve a downstream fork or custom transport decoder.

This differs from #1201 / #1244 / #1302, which address server-side applySchema, and from the explicit-null fix in #1285.

Proposed change: decode Tool and the CallToolResult wire object with the existing UnmarshalUseNumber helper. This keeps exported fields intact but changes decoded dynamic numeric types from float64 to json.Number for the affected fields. Callers asserting float64 need to adapt; maintainer agreement on this behavioral compatibility change is needed. No new compatibility switch or alternate value format is proposed. The current schema-validation dependency's precision limitations remain a separate concern.

Activity

  1. Tangerg commented on Nov 5, 2026

    @Tangerg
    ContributorAuthor

    Still reproduces on main at f91620f: a tool schema const of 9007199254740993 and a _meta value of the same number arrive as 9007199254740992, and so do negative large integers and long decimals. #1462 fixed precision during schema validation, but descriptor and metadata decoding still go through float64. Elicitation schemas and their _meta have the same problem.

    I'd like to fix this myself. #1311 was closed when I deleted its branch by mistake; I've restored the branch, merged current main into it, and added ElicitParams decoding with UseNumber (which also stops a failed decode from leaving the params half-populated). The compatibility question in #1311 still stands: decoded numbers in these generic JSON fields become json.Number instead of float64.

    AI assistance: the investigation and patch were prepared with Claude; I reviewed them and can answer questions about them.

  2. Tangerg commented on Nov 6, 2026

    @Tangerg
    ContributorAuthor

    Updated #1311. Following the review of #1239, the switch to json.Number is now gated behind MCPGODEBUG=schemaandmetafloat64=1, which answers the compatibility question above the same way. The fix adds UnmarshalJSON methods to Tool and ElicitParams; if that needs a proposal, I'll file one. #1311 stays a draft until this issue is assigned.

    AI assistance: prepared with Claude; I reviewed it.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions