modelcontextprotocol / modelcontextprotocol/go-sdk

mcp: typed tool arguments lose precision for large int64 values

Open
#1,201 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
5.1k
Forks
543
Avg merge
1d 17h
Merged PRs (30d)
37

Description

Describe the bug

When using the typed mcp.AddTool API, an integer larger than the IEEE-754
safe integer range can be silently rounded before it reaches the tool handler.
The value is accepted as a JSON integer, but the handler receives a different
value.

To Reproduce

Environment:

  • Go MCP SDK: v1.7.0
  • Go: go1.25.7 linux/amd64

Save the following as main.go in a module that requires
github.com/modelcontextprotocol/go-sdk v1.7.0:

package main

import (
  "context"
  "fmt"
  "log"

  "github.com/modelcontextprotocol/go-sdk/mcp"
)

type input struct {
  ID int64 `json:"id"`
}

func main() {
  const want int64 = 9007199254740993 // 2^53 + 1

  server := mcp.NewServer(
    &mcp.Implementation{Name: "server", Version: "repro"}, nil)
  mcp.AddTool(server, &mcp.Tool{Name: "echo_id"},
    func(_ context.Context, _ *mcp.CallToolRequest, in input) (
      *mcp.CallToolResult, input, error) {
      fmt.Printf("handler_received=%d\n", in.ID)
      return nil, in, nil
    })

  clientTransport, serverTransport := mcp.NewInMemoryTransports()
  ctx := context.Background()

  serverSession, err := server.Connect(ctx, serverTransport, nil)
  if err != nil {
    log.Fatal(err)
  }
  defer serverSession.Close()

  client := mcp.NewClient(
    &mcp.Implementation{Name: "client", Version: "repro"}, nil)
  clientSession, err := client.Connect(ctx, clientTransport, nil)
  if err != nil {
    log.Fatal(err)
  }
  defer clientSession.Close()

  _, err = clientSession.CallTool(ctx, &mcp.CallToolParams{
    Name: "echo_id",
    Arguments: map[string]any{"id": want},
  })
  if err != nil {
    log.Fatal(err)
  }
  fmt.Printf("want=%d\n", want)
}

Run:

go mod init example.com/mcp-int64-repro
go get github.com/modelcontextprotocol/go-sdk@v1.7.0
go run .

Observed output:

handler_received=9007199254740992
want=9007199254740993

The issue is reproducible with the in-memory transport and does not depend on
an external server.

Expected behavior

The typed tool handler should receive exactly the integer sent by the client:

handler_received=9007199254740993
want=9007199254740993

Values representable by Go int64 should not be silently changed during
schema validation or default application.

Logs

No error is returned. The value is silently rounded.

Additional context

The behavior appears to come from the schema application path in
mcp/tool.go: tool arguments are decoded into map[string]any, and the
generic JSON number is then represented as float64. Applying defaults causes
the value to be marshaled again, making the rounding observable before the
typed handler decodes it.

A possible implementation direction is to preserve JSON numbers (for example,
using Decoder.UseNumber()) while applying the schema and defaults, while
retaining strict validation of trailing JSON data. The low-level
Server.AddTool handler path does not have this particular schema round-trip,
but it also does not provide the typed validation/default behavior.

This affects any tool that accepts IDs or counters outside the IEEE-754 safe
integer range, even though those values are valid JSON integers and valid Go
int64 values.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in mcp/tool.go and trace the typed AddTool argument schema-application and default path, using the supplied in-memory reproduction as the first check. Add a regression test covering the int64 value 9007199254740993 and verify that the typed handler receives it unchanged while existing validation and trailing-data behavior remain intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.