vMCP Modern dispatch cannot stream a per-request response
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
dispatchModern answers every request with a single JSON body via writeModernResult — it never produces a text/event-stream response for a call verb. Anything the 2026-07-28 spec delivers as a request-scoped notification on the POST-initiated SSE response stream is therefore undeliverable to Modern clients:
notifications/progress— SEP-2260 requires that messages a server sends before the response relate to the originating request, andprogressTokenis unchanged in the draft schema.notifications/message(log records) — additionally gated on the per-requestio.modelcontextprotocol/logLevel_metakey, which replaces the removedlogging/setLevelRPC.
This is a vMCP limitation, not a gap in the specification. Worth stating explicitly, because the natural assumption is the opposite: Modern removed the standalone GET stream, so it is easy to conclude progress has nowhere to go. It does — just not on a channel vMCP currently produces.
It is also distinct from the two mechanisms it is most likely to be confused with:
- Not
subscriptions/listen. That channel's subscribable set is fixed at exactly four types (toolsListChanged,promptsListChanged,resourcesListChanged,resourceSubscriptions), and the spec requires a server not to send types the client did not request. Progress is structurally not on it. - Not MRTR. Progress and log records are notifications, not server-initiated requests, so multi-round retrieval does not touch them.
Observable impact
With Modern dispatch enabled, a Modern client calling a tool that reports progress receives no progress notifications and no error — the notification is silently dropped and the caller waits to its own deadline. Measured against a real backend, TestForwarding_Progress_RealBackend runs for 60.03s before failing on timed out waiting for notifications/progress. A Modern client with no deadline of its own would simply appear to hang.
logging/setLevel is separately unusable from a Modern go-sdk client for an upstream reason (modelcontextprotocol/go-sdk#1116), so the log-delivery half is not currently reachable to test end to end.
What implementing it involves
Answering tools/call with an SSE stream when the request carries a progressToken (or a logLevel _meta key), relaying the backend's mid-call notifications onto that stream, then terminating it with the JSON-RPC response. pkg/vmcp/server/modern_subscriptions.go now establishes the SSE-writing pattern in this package, though its fan-out needs are different — it has no delivery source today, whereas this feature has one (the backend connection) and needs the stream.
Note the ordering constraint from SEP-2260: notifications sent before the response MUST relate to the originating request, so the relay has to be scoped per call rather than multiplexed.
Current state, and why there is no test
Both affected behaviours are pinned to the Legacy revision in pkg/vmcp/server/forwarding_realbackend_integration_test.go, with comments recording that progress is pinned because vMCP cannot stream, not because Modern lacks the channel. That disposition is deliberate and documented, but after the Modern dispatch kill-switch is removed (#5959) there will be no executable coverage of either behaviour on the Modern path. Two bounded assertions would close that — that no progress notification arrives within a short window, and that a Modern logging/setLevel is rejected with the header/_meta mismatch — and are worth adding whether or not this feature is scheduled.
Refs #5743.
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 with pkg/vmcp/server/modern_subscriptions.go and the Modern dispatch path around writeModernResult, then read the pinned cases in pkg/vmcp/server/forwarding_realbackend_integration_test.go. Trace the backend connection used by tools/call and confirm how per-request notifications are scoped. Done means Modern clients receive progress or eligible log notifications on the POST-initiated SSE stream before the final JSON-RPC response, with executable coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100