go-sdk/docs/mcpgodebug.md
Luca Candela 3785c500b5
mcp: preserve structured content number precision (#1239)
CallToolResult currently decodes structuredContent through an any field,
which converts JSON numbers to float64 and silently rounds integers
outside the IEEE-754 safe range.

This change decodes structuredContent separately with UseNumber,
preserving wire numbers as json.Number while retaining the existing
decoded object, array, and primitive shapes. The field documentation now
describes that representation. Users who depend on the previous float64
behavior can temporarily restore it with
MCPGODEBUG=structuredcontentfloat64=1.

An end-to-end in-memory client/server regression covers 9007199254740993
from a low-level Server.AddTool result. Additional coverage verifies the
compatibility option restores the legacy rounded float64 value.

Verification:
- gofmt -l .
- go test ./...
- go vet ./...

Fixes #1236

---------

Co-authored-by: Guglielmo Colombo <guglielmoc@google.com>
2026-09-16 09:22:16 +02:00

178 lines
8.3 KiB
Markdown

<!-- Autogenerated by weave; DO NOT EDIT -->
# Backwards compatibility and MCPGODEBUG
According to our compatibility promise, we can't break backward compatibility
of the SDK API. However, sometimes we need to change the behavior of the SDK
in a backward-incompatible way in order to fix bugs or security issues.
In those cases we introduce temporary compatibility parameters, that can be
used to opt-out of the new behavior. They are usually maintained for two
minor release cycles and then removed.
The compatibility parameters are provided via the `MCPGODEBUG` environment
variable. The value of the variable is a comma-separated list of parameter
value assignments, e.g.:
```
MCPGODEBUG=parameter1=value1,parameter2=value2
```
## `MCPGODEBUG` history
### 1.9.0
Options listed below were added and will be removed in the 1.11.0 version of the SDK.
- `structuredcontentfloat64` added. If set to `1`, numbers in
`CallToolResult.StructuredContent` are decoded as `float64`, restoring the
previous behavior. The default behavior decodes numbers as `json.Number` so
that large integers and other exact JSON values do not silently lose
precision.
### 1.8.0
Options listed below were added and will be removed in the 1.9.0 version of the SDK.
- `plaintextstatefulrejection` added. If set to `1`, a stateful
`StreamableHTTPHandler` will respond with a plain-text `http.Error` 400 body
when it receives a request carrying per-request metadata (i.e. an
`io.modelcontextprotocol/protocolVersion` `_meta` field, or an
`MCP-Protocol-Version` header >= `2026-07-28`), restoring the previous
behavior. The default behavior was changed so that the server responds with a
JSON-RPC error of code `CodeUnsupportedProtocolVersion` (`-32022`) carrying
an `UnsupportedProtocolVersionData` payload that advertises the legacy
versions the server supports. This lets the client's
existing renegotiation logic recover and prevents the failure from tearing
down the underlying connection.
- `blockingcancelnotify` added. If set to `1`, a cancelled call waits
synchronously for the best-effort `notifications/cancelled` message to be
delivered (up to `notifyCancellationTimeout`, currently 5 s) before
returning to the caller, restoring the previous behavior. The delivery
error is joined into the caller's returned error. The default behavior was
changed so that the call is retired immediately and the notification is
sent asynchronously off the caller's return path: the caller returns as
soon as its context is cancelled and cannot be delayed by a slow or
unresponsive peer. See issue #1150.
Options below were removed, according to plan:
- `seterroroverwrite`. `SetError` now always preserves existing `Content`.
- `enableoriginverification`. A nil
`StreamableHTTPOptions.CrossOriginProtection` now always means no
cross-origin protection. Wrap the handler with cross-origin protection
middleware instead.
- `disablecontenttypecheck`. Content-Type validation on HTTP POST requests can
no longer be disabled.
- `disablelocalhostprotection`, whose removal had been postponed to this
release. Set the `DisableLocalhostProtection` field in
`StreamableHTTPOptions` or `SSEOptions` to opt out of DNS rebinding
protection.
### 1.7.0
Options listed below were added and will be removed in the 1.9.0 version of the SDK.
- `customresnotfounderrcode` added. If set to `1`, `ResourceNotFoundError` will
use the custom error code `-32002` instead of the standard `-32602` (Invalid
Params), restoring the previous behavior. The default behavior was changed to
align with SEP-2164 and the JSON-RPC specification.
- `hintomitempty` added. If set to `1`, `ToolAnnotations` JSON marshaling
will omit `ReadOnlyHint` and `IdempotentHint` when their value is `false`,
restoring the previous behavior. The default behavior was changed to always
serialize these fields, since their Go types are bare `bool` (not `*bool`)
and omitting `false` made it indistinguishable from unset.
- `allowsessionsinstateless` added. If set to `1`, stateless streamable HTTP
servers will read the `Mcp-Session-Id` request header (or generate one via
`GetSessionID`), set it on response headers, and accept `DELETE` requests,
restoring the previous behavior. The default behavior was changed so that
stateless servers ignore session IDs entirely and reject `DELETE` with 405.
- `nomethodnotfoundcodeinerror` added. If set to `1`, the jsonrpc2 layer will not
include the MethodNotFound Error (`-32601`) in the error response when the
requested method in STDIO transport is not found. The default behavior was
changed to include the MethodNotFound Error in the error response when the
requested method in STDIO transport is not found.
- `noprotocolerrorbody` added. If set to `1`, the streamable HTTP client will
not attempt to decode the JSON-RPC error body of a non-2xx HTTP response,
and any non-transient error will permanently fail the connection, restoring
the previous behavior. The default behavior was changed so that the client
attempts to decode the JSON-RPC error body of a non-2xx response, surfaces
the underlying JSON-RPC error, and wraps it with `jsonrpc2.ErrRejected` so
that per-call rejections do not tear down the session.
- `nowrapinvalidparams` added. If set to `1`, the server will not wrap
params-decoding failures with `jsonrpc2.ErrInvalidParams`, so wire responses
carry the zero-value error code `0` instead of `-32602` ("invalid params"),
restoring the previous behavior. The default behavior was changed so that
the server always reports params-decoding failures with the standard
`-32602` code.
- `disablecompleteparamsvalidation` added. If set to `1`, `Server.complete`
will not validate that the required `ref` and `argument.name` fields on
`CompleteParams` are present, restoring the previous behavior of dispatching
the request to the completion handler unconditionally. The default behavior
was changed to reject malformed requests with `-32602` (Invalid Params).
### 1.6.1
Options listed below were added and will be removed in the 1.8.0 version of the SDK.
- `disablecontenttypecheck` added. If set to `1`, Content-Type validation on
HTTP POST requests will be disabled, allowing requests with non-JSON or missing
Content-Type headers. The default behavior is to validate that HTTP POST
requests have Content-Type: application/json.
### 1.6.0
Options listed below were added and will be removed in the 1.8.0 version of the SDK.
- `seterroroverwrite` added. If set to `1`, `SetError` will always overwrite
`Content` with the error text, restoring the previous behavior. The default
behavior was changed to preserve existing `Content` if it has already been
populated.
- `enableoriginverification` added. If set to `1`, default (zero-value)
cross-origin protection will be applied when
`StreamableHTTPOptions.CrossOriginProtection` is nil, restoring the
behavior from v1.4.1-v1.5.0. The default behavior was changed to not
enable cross-origin protection.
- `disablelocalhostprotection` removal was postponed until 1.8.0, as it is now
also used in the SSE transport.
Options below were removed:
- `jsonescaping`, according to plan,
- `disablecrossoriginprotection`, it was replaced by
`enableoriginverification` after the default was changed to not enable
cross-origin protection.
### 1.4.1
Options listed below will be removed in the 1.6.0 version of the SDK.
- `disablecrossoriginprotection` added. If set to `1`, newly added cross-origin
protection will be disabled. The default behavior was changed to enable
cross-origin protection.
### 1.4.0
Options listed below will be removed in the 1.6.0 version of the SDK.
- `jsonescaping` added. If set to `1`, JSON marshaling will preserve the previous
behavior of escaping HTML characters in JSON strings. The default behavior
was changed to not escape HTML characters, to be consistent with other SDKs.
- `disablelocalhostprotection` added. If set to `1`, newly added DNS rebinding
protection will be disabled. The default behavior was changed to enable DNS rebinding
protection. The protection can also be disabled by setting the
`DisableLocalhostProtection` field in the `StreamableHTTPOptions` or
`SSEOptions` struct to `true`, which is the recommended way to disable
the protection long term. **Removal of this option was postponed until 1.8.0.**