You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[v2] Expose per-request stream end (onRequestStreamEnd) in RequestOptions for custom long-lived requests #3060
Protocol.request() gives callers no way to learn that the per-request response stream ended. The client transport already supports this: TransportSendOptions.onRequestStreamEnd, which StreamableHTTPClientTransport fires when a request's SSE response ends. But only Client.listen() uses it (it calls transport.send() directly). RequestOptions has no equivalent, and _requestWithSchemaViaCodec passes requestSignal to transport.send() but not onRequestStreamEnd.
Why it matters
Extensions that define long-lived streaming requests can't detect a dead stream promptly. One example is events/stream from the Events extension (SEP-3415, see #2945). If the server restarts mid-stream, the POST's SSE body ends without a JSON-RPC response. The pending request then waits for its timeout, or for an application-level heartbeat watchdog. In @mastra/mcp we detect this through a 30s heartbeat window, so it takes up to 60s. subscriptions/listen gets immediate detection because it uses the transport option directly.
This is the request-level counterpart of #2739, which covers non-streaming requests left pending when their SSE response ends.
Proposal
Add an option to RequestOptions, for example onRequestStreamEnd?: () => void, and forward it to transport.send() the same way requestSignal is forwarded. Alternatively, reject the pending request with a distinct error when its stream ends before a response arrives. Transports with no per-request stream (stdio, InMemory) would keep ignoring it, as they do today.
Versions
We hit this on @modelcontextprotocol/client@2.2.0. It's still present on main (c05225a6): see RequestOptions in packages/core-internal/src/shared/protocol.ts and the transport.send(...) call in _requestWithSchemaViaCodec.
Activity