Skip to content

initialize with protocolVersion 2026-07-28 returns -32601 instead of negotiating (behaviour changed in 1.8.0) #3834

Description

@roanny

Summary

An initialize request carrying "protocolVersion": "2026-07-28" is answered with -32601 invalid method initialize on 1.8.0 and 1.9.0. On 1.7.0 the same request negotiates normally and the server replies with 2025-11-25.

The graceful downgrade is otherwise intact — 2026-07-28 is the only value that fails. Unknown versions still negotiate fine, which is what makes this look like a gap rather than a policy: the version is known well enough to be routed, and being known is exactly what removes it from the "unknown → downgrade" path.

Reproduction

Server started from the published linux/amd64 binary with a minimal BigQuery config, then:

curl -s -X POST http://localhost:8080/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"<VERSION>","capabilities":{},"clientInfo":{"name":"probe","version":"0"}}}'
requested protocolVersion 1.7.0 1.8.0 1.9.0
2026-07-28 result.protocolVersion: 2025-11-25 -32601 invalid method initialize -32601 invalid method initialize
2025-11-25 2025-11-25 2025-11-25
2025-06-18 2025-06-18 2025-06-18
2999-01-01 2025-11-25 2025-11-25
banana 2025-11-25 2025-11-25

Same result with and without --enable-draft-specs, and with and without an Mcp-Protocol-Version header. Same result on /mcp and /mcp/.

Likely cause

ProcessMethod in internal/server/mcp/mcp.go routes mcputil.VERSION_20260728 to v20260728.ProcessMethod. initialize appears not to be handled on that path, so it falls through to the generic method-not-found rather than to the unsupported-version branch that default: reaches — which is where NewUnsupportedProtocolVersionError lives.

Why the error code matters beyond the message

toolbox-core's protocol fallback keys on UNSUPPORTED_PROTOCOL_VERSION_ERROR_CODE (-32022) or on the message containing invalid protocol version / unsupported protocol version. A -32601 matches neither, so it is not recognisable as a negotiation failure by the client contract the server otherwise implements.

In practice clients do recover — we observe Protocol fallback required. Switching from 2026-07-28 to 2025-11-25 in production logs against a 1.8.0 server, and toolbox-core 1.3.0 loads a full toolset against 1.9.0 without error. So this is not a broken-client report. It is that the rejection is not expressed in the vocabulary the negotiation contract defines, which makes the recovery incidental rather than guaranteed.

Suggested resolution

Either implement initialize on the v20260728 path, or have an unimplemented-but-routed version answer -32022 with the supported list, so that the documented fallback contract applies. The second also covers any future version added to the routing table before its handlers land.

Context

Found while bumping a downstream packaging repository from 1.8.0 to 1.9.0. Happy to test a patch against the same matrix.

Metadata

Metadata

Assignees

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