Adopt go-sdk v1.7.0-pre.3 for MCP 2026-07-28 groundwork - #185
Merged
Conversation
Bump the go-sdk dependency from v1.6.1 (MCP 2025-11-25) to v1.7.0-pre.3, which implements the MCP 2026-07-28 stateless revision natively (stateless server serving and discover-based client negotiation). This is the foundational step (PR1 of the Phase 1 mcpcompat stateless work) that lets downstream ToolHive replace its hand-rolled Modern wire code with a shim-provided path backed by the real SDK. The shim compiles against v1.7 with zero production source edits — v1.7 is purely additive (382->491 exported symbols, no removals or signature changes), verified by an exported-symbol diff. Changes here are limited to: - go.mod/go.sum bump, with an inline PRE-RELEASE marker on the require line and a release-workflow guard that fails any release tagged while go.mod still pins a go-sdk -pre/-rc version (toolhive-core is a shared library; the pre-release must not propagate to consumers via a tagged release). - A directory-scoped staticcheck SA1019 exclusion for mcpcompat/: v1.7 deprecates the sampling/logging/roots surface (SEP-2577) that the shim intentionally retains for mark3labs/mcp-go drop-in parity. Re-audit on every SDK bump. - Regression tests pinning the one behavioral change from the bump: v1.7's Modern-first client Connect probes server/discover before falling back to the legacy initialize handshake, so a stateful shim server negotiates down to 2025-11-25 (unchanged wire version) but mints two sessions per Initialize. The discover-probe session leaks (the discover handler sets InitializeParams, defeating go-sdk's #578 cleanup; SessionTimeout unset), and the shim-layer placeholder record is never promoted/reaped. This is an availability concern only (no identity/tool binding on the orphan). The test asserts the Generate/Terminate delta as a tripwire; the stateful-server leak needs an upstream fix (export the client protocol-version pin) and the stateless-serving path (PR2) avoids it for stateless backends. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRh394VZgnqbYjJwjrcJWm
JAORMX
marked this pull request as ready for review
July 24, 2026 17:12
ChrisJBurns
approved these changes
Jul 24, 2026
This was referenced Jul 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why:
mcpcompatwraps go-sdk v1.6.1, which only speaks MCP 2025-11-25. The MCP 2026-07-28 ("stateless") revision — noinitializehandshake,server/discover, noMcp-Session-Id,pingremoved — is implemented natively by go-sdk v1.7.x. Downstream ToolHive currently hand-rolls the 2026-07-28 wire path because the shim can't provide it; the point of this workstream is to replace that hand-rolled code with a shim-provided path backed by the real SDK.What: This is PR1 of 3 in the Phase 1 mcpcompat stateless work — the foundational dependency bump. It does not add any stateless feature yet; it makes the shim build and pass on v1.7 and pins the one behavioral change the bump introduces.
go-sdkv1.6.1 → v1.7.0-pre.3. The shim compiles against v1.7 with zero production source edits — v1.7 is purely additive (382→491 exported symbols, no removals or signature changes), verified by an exported-symbol diff. No existing exported signature or shim-owned constant changes (drop-in contract preserved;mcp.LATEST_PROTOCOL_VERSIONstays2025-11-25, error-code constants unchanged).staticcheckSA1019 exclusion formcpcompat/. v1.7 deprecates the sampling/logging/roots surface (SEP-2577) that the shim intentionally retains formark3labs/mcp-godrop-in parity. The exclusion comment notes it must be re-audited on every SDK bump.v1.7.0is not final (onlypre.1/2/3exist, and the 2026-07-28 wire surface is still settling between them). toolhive-core is a shared library, so a pinned pre-release propagates to every consumer via MVS. This PR adds two guards:// PRE-RELEASE:marker on thego.modrequire line, andrelease.ymlguard step that fails any release job whilego.modstill pins a go-sdk-pre/-rcversion.Re-bump to
v1.7.0final before tagging. It's the first of a sequence and takes a pre-release dep — the code is independently mergeable and green, but please review the approach as a set.Behavioral change this PR documents
v1.7's client
Connectis Modern-first: it probesserver/discoverbefore falling back to the legacyinitializehandshake. Against a stateful shim server this means oneInitialize()now:Generate×2): the discover probe + the legacy fallback. The discover-probe session leaks — go-sdk'sdiscoverhandler setsInitializeParams(mcp/server.go:898-902), defeating the#578cleanup guard (mcp/streamable.go:733), andSessionTimeoutis unset — and the shim-layer placeholder record is never promoted/reaped.This is an availability concern only (no identity/tool binding on the orphan —
OnRegisterSessionnever fires). The stateful-server leak needs an upstream fix (export the client protocol-version pin, which is unexported today — the#5911blocker); PR2's stateless-serving path avoids it for stateless backends. The regression test asserts theGenerate−Terminatedelta (2−1=1) as a tripwire so a future fix fails loudly.Next in this series
WithStatelessserver option + make the per-session projection/rehydration machinery no-op cleanly under stateless (per-request isolation).-3202xerror codes /NeedsInput()for downstream.Test plan
task test(race) — all existing suites green + new regression teststask lint— 0 issues (SA1019 exclusion resolves the intentional deprecations)task license-check— cleango build ./...— clean, no source edits tomcpcompat/**🤖 Generated with Claude Code