Skip to content

mcp: preserve numbers in tool schemas and metadata - #1311

Draft
Tangerg wants to merge 1 commit into
modelcontextprotocol:mainfrom
Tangerg:codex/preserve-protocol-json-numbers
Draft

Tangerg wants to merge 1 commit into
modelcontextprotocol:mainfrom
Tangerg:codex/preserve-protocol-json-numbers

Conversation

@Tangerg

@Tangerg Tangerg commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Fixes #1310.

tools/list currently rounds a schema constant such as 9007199254740993 to 9007199254740992. Tool and tool-result metadata, including metadata on text, linked resources, and embedded resources, lose precision the same way. Meanwhile structuredContent preserves the original number. This can leave clients with a different schema constraint from the value that the server actually returned.

Decode Tool and the CallToolResult wire object with the existing UnmarshalUseNumber helper. The fix is at the owning protocol types, so both SDK transport decoding and direct JSON decoding benefit. No dependencies, alternate wire formats, or new compatibility switches are added.

Compatibility and scope

The exported field types stay unchanged, but numbers decoded into their generic JSON values now have dynamic type json.Number, rather than float64. Callers using value.(float64) must adapt. This draft requests maintainer agreement on that behavioral compatibility change and its release treatment; it is not presented as a behaviorally compatible patch.

This PR covers tool descriptors and tool results. It does not globally change JSON decoding, metadata on unrelated protocol messages, or applySchema. In particular, it does not claim to fix the schema-validation dependency's numeric type/boundary limitations. #1244 and #1302 address a different path. Existing structured-content number and explicit-null behavior is retained.

Validation

  • go build ./..., go vet ./..., go test ./..., go test -race ./..., and staticcheck ./... passed locally with Go 1.27.0 on darwin/arm64.
  • Regression tests exercise ListTools and CallTool over serialized in-memory NDJSON and Streamable HTTP. They check schema const/enum/bounds, tool/result/content/resource metadata, nested objects and arrays, negative and unsigned large integers, and high-precision decimals. Structured content is a control.
  • Direct JSON decoding also covers a schema number outside the float64 range. The new tests fail against unmodified upstream protocol.go at 7cb505c and pass with this change.
  • Formatting and git diff --check passed. External conformance suites were not run locally.
  • go mod tidy -diff reports a pre-existing direct/indirect classification mismatch for golang.org/x/sync (already directly imported by mcp/mrtr.go on the base). Module files are untouched.

This branch has not been deployed

No deployments
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.

mcp: tool schemas and metadata lose JSON number precision

1 participant