Split out of #2063, which resolved into a documentation/spec question everywhere except this one point.
The gap
A modern-era (2026-07-28) subscriptions/listen is a long-lived request. The first message on the stream must be notifications/subscriptions/acknowledged; the JSON-RPC result for the listen id is reserved as the graceful-closure marker (spec: Subscriptions → Graceful Closure).
A server that answers the listen request with a result immediately — never acknowledging — is therefore saying "acknowledged and closed in the same breath". In @modelcontextprotocol/client, Client._onresponse settles that subscription with cause graceful and rejects the pending acknowledgment promise, so the Inspector's re-listen rejects.
What the Inspector does with that today (core/mcp/inspectorClient.ts):
refreshModernSubscription rejects → onModernReconnectFailed() → scheduleModernReconnect()
- up to
MODERN_RECONNECT_MAX_ATTEMPTS = 8 consecutive failures, with capped exponential backoff
- then the stream badge lands on
ended
From the user's side that is: the Subscriptions badge flickers reconnecting, eight subscriptions/listen requests with increasing SDK-assigned ids go out over roughly a minute, and it finally settles on ended — with no statement anywhere about why. That is exactly the report in #2063, where it read as the Inspector "accepting" an invalid response.
Expected
Say what happened. Something on the order of:
The server closed the subscription without acknowledging it. A subscriptions/listen request must first be answered with a notifications/subscriptions/acknowledged notification; a JSON-RPC result for the listen id means graceful closure.
Concretely:
- Distinguish the case. A
graceful settlement that arrives before any acknowledgment is not the same as a graceful shutdown of an established stream. Only the latter is the expected ended path.
- Don't retry it. Eight re-lists against a server that will answer the same way each time is noise, not recovery — the condition is deterministic. This case should end the stream on the first occurrence.
- Surface the reason in the UI. The Subscriptions section badge already carries a status; the never-acknowledged case needs an accompanying message rather than a bare
ended.
- Optionally note the missing
resultType discriminator, which the reporter's payload also lacked and which the spec's example carries.
Notes
Split out of #2063, which resolved into a documentation/spec question everywhere except this one point.
The gap
A modern-era (2026-07-28)
subscriptions/listenis a long-lived request. The first message on the stream must benotifications/subscriptions/acknowledged; the JSON-RPCresultfor the listen id is reserved as the graceful-closure marker (spec: Subscriptions → Graceful Closure).A server that answers the listen request with a
resultimmediately — never acknowledging — is therefore saying "acknowledged and closed in the same breath". In@modelcontextprotocol/client,Client._onresponsesettles that subscription with causegracefuland rejects the pending acknowledgment promise, so the Inspector's re-listen rejects.What the Inspector does with that today (
core/mcp/inspectorClient.ts):refreshModernSubscriptionrejects →onModernReconnectFailed()→scheduleModernReconnect()MODERN_RECONNECT_MAX_ATTEMPTS = 8consecutive failures, with capped exponential backoffendedFrom the user's side that is: the Subscriptions badge flickers
reconnecting, eightsubscriptions/listenrequests with increasing SDK-assigned ids go out over roughly a minute, and it finally settles onended— with no statement anywhere about why. That is exactly the report in #2063, where it read as the Inspector "accepting" an invalid response.Expected
Say what happened. Something on the order of:
Concretely:
gracefulsettlement that arrives before any acknowledgment is not the same as a graceful shutdown of an established stream. Only the latter is the expectedendedpath.ended.resultTypediscriminator, which the reporter's payload also lacked and which the spec's example carries.Notes
test-servers/configs/subscriptions-modern-http.jsonis the natural place for a preset that reproduces this (answersubscriptions/listenwith a bareresult).