Support MRTR pass-through for Modern backends in vMCP
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
When a Modern (2026-07-28) backend answers a relayed tools/call, prompts/get or resources/read with resultType: "input_required", vMCP currently fails with errModernInputRequired — a deliberate seam at pkg/vmcp/client/modern.go:64. This issue tracks implementing the relay.
This is the coherent shape of MRTR support in vMCP, and it is deliberately not the shape that was rejected. Recording the distinction, because the two look similar and only one is buildable.
What to build: pure relay, stateless at vMCP
Per SEP-2322's ephemeral flow, the server holds no state between rounds — the handler is re-invoked from scratch and all cross-round state round-trips through an opaque requestState blob. So:
- Forward the backend's
inputRequeststo the Modern client. - Wrap the backend's opaque
requestStatewith vMCP routing context (which backend it came from), keeping it opaque to the client. - On the client's re-issued call carrying
inputResponsesplus the echoedrequestState, unwrap it and relay to the same backend, which re-invokes its own handler.
vMCP holds no per-round state. That is what makes it viable under a revision that removed sessions.
Prerequisite: the egress half — driving and propagating the loop in pkg/vmcp/client. The errModernInputRequired seam is where that begins.
What was rejected, and why
Bridging a Legacy backend's live mid-call elicitation to a Modern client. That backend interaction is a blocked goroutine holding an open session; it cannot be serialized into requestState, and re-invoking is impossible because side effects have already run. Making it work would mean parking the in-flight call server-side behind an unguessable resume token, with TTL and eviction, replica affinity (no Mcp-Session-Id means a load balancer cannot route the resume), and identity binding on a token that becomes a capability to hijack someone else's in-flight call.
That is a session in disguise — precisely what 2026-07-28 removed. The specification's own answer for genuinely stateful input_required work is the Tasks extension (SEP-2663: tools/call returns resultType: "task" with a taskId; the client polls tasks/get and answers via inputResponses on tasks/update). If Legacy-backend elicitation for Modern clients is ever genuinely required, Tasks is the path — not parked calls.
See the "elicitation and sampling are unavailable to Modern clients" section in docs/arch/10-virtual-mcp-architecture.md for the full rationale as landed.
Scope note worth reading before prioritising
SEP-2577 deprecates sampling, logging and roots as of 2026-07-28 (annotation-only, functional for at least twelve months), with the sanctioned migration for sampling being direct LLM-provider integration. So by the time Modern backends exist to relay from, elicitation is MRTR's only durable consumer. That materially shrinks the value of this work relative to how it looks at first glance, and is why it was deferred rather than built alongside the Modern client-facing surface.
Also relevant: go-sdk's assertServerInitiatedRequestAllowed gates elicitation, sampling and roots on the negotiated protocol version alone and never consults client capabilities — so there is no "advertise less" alternative that recovers these features for Modern clients. It is MRTR or nothing.
Refs #5743. Related: #6051 (the disposition that made the current behaviour explicit and honest).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the errModernInputRequired seam in pkg/vmcp/client/modern.go:64 and read the egress flow in pkg/vmcp/client. Review the elicitation and sampling discussion in docs/arch/10-virtual-mcp-architecture.md and the MRTR ephemeral flow described here. Done means inputRequests, wrapped requestState, and later inputResponses are relayed to the same backend without vMCP-held per-round state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 44/100