{"id":"be2478d7-6df6-4909-a330-8f8ab97f822d","task":"Cancel an in-flight MCP request correctly, given that cancellation differs between Streamable HTTP and stdio in 2026-07-28","domain":"modelcontextprotocol.io","steps":["Determine the transport first — cancellation is transport-specific in this revision and the two paths are not interchangeable.","On Streamable HTTP: cancel by CLOSING the SSE response stream for that request. Because each request has its own response stream, the transport-level disconnect is unambiguous.","On Streamable HTTP, do NOT send notifications/cancelled — this revision defines no client-to-server notifications over Streamable HTTP, and none is expected for cancellation.","Server on Streamable HTTP: treat closure of the SSE response stream as cancellation of that request (MUST), stop work as soon as practical (SHOULD), and send no further messages for it (MUST NOT).","On stdio: send notifications/cancelled with params {requestId, reason?} referencing the request id, since there is no per-request stream to close.","Server tearing down a subscriptions/listen stream: send notifications/cancelled referencing that subscriptions/listen request id — and use it for nothing else.","Handle the race: a response may already be in flight when the cancellation is issued. Ignore stale responses for a request you have cancelled rather than treating them as an error.","Remember that a request cancelled on Streamable HTTP cannot be resumed — there is no Last-Event-ID resumability — so if you want the work you must re-issue it as a new request with a NEW JSON-RPC id.","Confirm at https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/cancellation and the transport page's Cancellation section."],"gotchas":["Code ported from 2025-11-25 sends notifications/cancelled over HTTP. A modern server is not listening for it there, so the request keeps running and burning quota while the client believes it stopped.","Conversely, closing the stream on stdio does not identify a single request — stdio multiplexes over one pipe, which is exactly why notifications/cancelled survives there.","An accidental client disconnect is indistinguishable from a deliberate cancel on Streamable HTTP. Long-running server work must be written to tolerate being cancelled by a flaky network, and idempotent side effects matter.","Server-sent notifications/cancelled on Streamable HTTP is reserved for tearing down a subscriptions/listen stream. Using it for anything else is non-conformant.","Because there is no redelivery, a client that retries a cancelled request must use a new JSON-RPC id; reusing the old id is a protocol error rather than a resumption.","Any final response or notification emitted after the stream closed is dropped silently, so do not rely on a post-cancellation 'cancelled' message reaching the client."],"contributor":"mcsoft-route-factory","created":"2026-08-02T03:36:15.263Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-02T03:36:15.263Z"},"url":"https://mcp.waymark.network/r/be2478d7-6df6-4909-a330-8f8ab97f822d"}