Skip to content

Report two mcpcompat/go-sdk conformance issues upstream #6019

Description

@JAORMX

Part of #5743. Split out of #6002 (item 7) so that issue can close — neither of these is fixable in this repo.

Both were surfaced by tracing why pkg/mcp/parser_integration_test.go changed behaviour under the go-sdk v1.7 bump (#5993). Both are worth reporting to toolhive-core, and possibly modelcontextprotocol/go-sdk.

(a) server/discover is sent over the deprecated HTTP+SSE message channel

MCP 2026-07-28 defines exactly two transport bindings — stdio and Streamable HTTP. mcpcompat's SSE server uses go-sdk's NewSSEHandler, whose transport implements no ProtocolVersionSupporter gate (only streamable.go does), so filterSupportedVersions advertises 2026-07-28 and the Modern-first client negotiates Modern over a 2024-11-05 transport. The Modern revision constrains the Streamable HTTP binding, not whatever an SDK pushes through a legacy channel — so this is non-conformant client/server behaviour, not spec.

Worth knowing: this produces an apparent contradiction inside ToolHive that is not a bug. parser_integration_test.go observes Modern negotiation over an sse-labelled endpoint, while probeRevision asserts that can never happen. Both are correct, because they are different layers: mcpcompat's SSE client reaches /messages, whereas vMCP's modernCall only ever POSTs to BaseURL, which is the /sse path. Anyone reconciling those two facts should read this issue first.

(b) mcpcompat/client.Initialize silently ignores the caller's requested ProtocolVersion

It calls Connect(ctx, tr, nil) with nil ClientSessionOptions, so the negotiated version is always latestProtocolVersion; only ClientInfo and Capabilities carry over from the caller's InitializeRequest. A caller explicitly asking for 2024-11-05 gets 2026-07-28 requested on the wire, with no error and no warning.

parser_integration_test.go does exactly this, which is why that test's behaviour changed on the v1.7 bump.

Work

  • File both against toolhive-core; escalate (a) to modelcontextprotocol/go-sdk if the gate belongs in the SDK's SSE transport rather than the shim.
  • Link back here so the in-repo contradiction in (a) stays explained.

Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageIssue needs initial triage by a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions