Rescoped. This issue originally bundled two conformance findings that turned out to be upstream-only; those are now go-sdk#1112 and go-sdk#1113. See the correction comment for why neither was fixable here. What remains below is shim-side.
The defect
mcpcompat exports a constant that no longer describes what the shim does:
// mcpcompat/mcp/jsonrpc.go:15
const LATEST_PROTOCOL_VERSION = "2025-11-25"
Meanwhile go-sdk's latestProtocolVersion is 2026-07-28, and client.Initialize calls Connect(ctx, tr, nil) — so the shim always requests 2026-07-28 on the wire, whatever the caller asked for. request.Params.ProtocolVersion is read nowhere in Initialize.
The combination is what makes this worth fixing: a consumer reads LATEST_PROTOCOL_VERSION, reasonably concludes the shim speaks 2025-11-25, passes it to Initialize, and gets 2026-07-28 requested — silently.
That is not hypothetical. Every ToolHive production initialize does exactly this:
pkg/transport/bridge.go:197
pkg/vmcp/client/client.go:852
pkg/vmcp/session/internal/backend/mcp_session.go:553
Important: do not "fix" this by honouring the request
The substitution is load-bearing for ToolHive today. Because the wire request is 2026-07-28, a Modern-capable backend answers initialize with 2026-07-28, which is precisely how ToolHive's legacyInit detects a mis-cached backend and flips its revision cache Legacy→Modern (stacklok/toolhive#5997, pinned by TestListCapabilities_MisCachedLegacy_SelfHealsViaSDKNegotiation).
Honouring a requested 2025-11-25 would make that backend negotiate 2025-11-25, the self-heal would never fire, and vMCP's Legacy→Modern correction would silently regress. Rejecting an unhonourable request would break all three production call sites immediately, since they all pass a version that cannot be honoured.
Honouring is also not currently possible: ClientSessionOptions.protocolVersion is unexported upstream (go-sdk#1113).
Proposed work — documentation and validation only, no behaviour change
Non-goal
Making the shim honour arbitrary requested versions. That is blocked on go-sdk#1113 and, per the above, would need a coordinated change in toolhive because the current behaviour is depended upon.
Generated with Claude Code
Rescoped. This issue originally bundled two conformance findings that turned out to be upstream-only; those are now go-sdk#1112 and go-sdk#1113. See the correction comment for why neither was fixable here. What remains below is shim-side.
The defect
mcpcompatexports a constant that no longer describes what the shim does:Meanwhile go-sdk's
latestProtocolVersionis2026-07-28, andclient.InitializecallsConnect(ctx, tr, nil)— so the shim always requests2026-07-28on the wire, whatever the caller asked for.request.Params.ProtocolVersionis read nowhere inInitialize.The combination is what makes this worth fixing: a consumer reads
LATEST_PROTOCOL_VERSION, reasonably concludes the shim speaks 2025-11-25, passes it toInitialize, and gets 2026-07-28 requested — silently.That is not hypothetical. Every ToolHive production initialize does exactly this:
pkg/transport/bridge.go:197pkg/vmcp/client/client.go:852pkg/vmcp/session/internal/backend/mcp_session.go:553Important: do not "fix" this by honouring the request
The substitution is load-bearing for ToolHive today. Because the wire request is
2026-07-28, a Modern-capable backend answersinitializewith2026-07-28, which is precisely how ToolHive'slegacyInitdetects a mis-cached backend and flips its revision cache Legacy→Modern (stacklok/toolhive#5997, pinned byTestListCapabilities_MisCachedLegacy_SelfHealsViaSDKNegotiation).Honouring a requested
2025-11-25would make that backend negotiate 2025-11-25, the self-heal would never fire, and vMCP's Legacy→Modern correction would silently regress. Rejecting an unhonourable request would break all three production call sites immediately, since they all pass a version that cannot be honoured.Honouring is also not currently possible:
ClientSessionOptions.protocolVersionis unexported upstream (go-sdk#1113).Proposed work — documentation and validation only, no behaviour change
client.Initialize: state plainly thatParams.ProtocolVersiondoes not influence the wire version, that go-sdk requests its own latest and negotiates down, and link go-sdk#1113. This removes the silence, which is the actual harm.LATEST_PROTOCOL_VERSION. Two options, and this is the decision worth discussing:2026-07-28. Behaviourally a no-op forInitialize(the value is discarded anyway), but it is exported and consumers may compare against it, so it needs a consumer sweep first.toolhiveuses it in at least the three production sites above plus several tests.Non-goal
Making the shim honour arbitrary requested versions. That is blocked on go-sdk#1113 and, per the above, would need a coordinated change in
toolhivebecause the current behaviour is depended upon.Generated with Claude Code