stacklok / stacklok/toolhive

Retire the hand-rolled Modern wire shim in vMCP

Open
#6,018 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs-triage
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Part of #5743. Split out of #6002 (item 6) so that issue can close — this item is blocked on an upstream change and does not belong in a list of otherwise-actionable follow-ups.

Context

vMCP hand-rolls the MCP 2026-07-28 ("Modern") wire shape across roughly 1,600 lines (measured on main):

File Lines
pkg/vmcp/client/modern.go 441
pkg/vmcp/server/modern_envelope.go 562
pkg/mcp/revision.go 627

Five code comments justified that on the grounds that go-sdk v1.6.1 could not express the revision — a premise #5993 (go-sdk v1.7 adoption) invalidated and #5997 corrected in place.

Why the shim is still required

The reason is now much narrower than those comments implied: mcpcompat's public Client API exposes no no-initialize primitive — only the private, Legacy-shaped resumeCall. go-sdk itself implements the revision fine; TestListCapabilities_MisCachedLegacy_SelfHealsViaSDKNegotiation shows its client negotiating Modern unaided, and #5997's in-band self-heal reads the negotiated version straight off InitializeResult.

Note also that the server-side envelope cannot simply be deleted even on a newer go-sdk: modern_envelope.go documents that the Modern result types remain unexported in v1.7.0-pre.3, and that resultType / _meta.serverInfo are set by unexported SDK functions (setCompleteResultType, annotateServerInfo) which run inside the exact ServerSession dispatch the Modern stateless path bypasses. So this is not a pure deletion.

Work, in order

  1. Upstream: add a no-initialize primitive to toolhive-core's mcpcompat public client API.
  2. In-repo: retire the client-side shim in favour of it — deleting the hand-rolled egress envelope, the raw modernCall path, and the revision-classification machinery that exists only to choose between the two shims.

Scope caveat

Confirm step 2's true scope before committing. Part of revision.go serves the ingress classifier (hasModernSignal, ValidateHeaderConsistency) and survives regardless; the split of ReservedModernMetaKeys vs modernSignalMetaKeys is likewise ingress/egress infrastructure, not shim. The client-side egress duplication looks squarely deletable; the server-side envelope likely does not, for the reason above.

Blocked on

Step 1 landing in toolhive-core.

Generated with Claude Code

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with pkg/vmcp/client/modern.go and pkg/mcp/revision.go, then review mcpcompat's public client API and the TestListCapabilities_MisCachedLegacy_SelfHealsViaSDKNegotiation test. Wait for the upstream no-initialize primitive in toolhive-core, then confirm the client-side egress shim and related classification code can be retired while preserving ingress handling and the server envelope.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.