Human note: Cursor generated this report for me, since it helped me give perfect specifics, but it's all from me and human-edited.
The impact is that we can't actually tell if an agent is still there when using http-transport, since the SSE stream closing is hidden from our app-code, and agents do not send DELETE requests when they poof.
When a client opens a GET SSE stream and then disconnects (e.g. the agent process exits, network drops, etc.), the transport's internal stream.onAbort handler fires and cleans up #streamMapping, but the disconnection is never propagated to the onclose callback or any other external hook.
Current behavior
// Inside handleGetRequest — stream abort only cleans up internal state
stream.onAbort(() => {
this.#streamMapping.get(resolvedStreamId)?.cleanup();
});
onclose is only called inside close(), which is only triggered by an explicit DELETE request. In practice, MCP clients (Cursor, Claude Code, etc.) do not send DELETE when they disconnect — the SSE stream dropping is the only signal available.
Expected behavior:
When the standalone SSE stream (_GET_stream) aborts, the transport should notify the application. This could be:
- Calling
onclose when the standalone SSE stream aborts (since it represents the client's only persistent connection), or
- A new callback like
onsessiondisconnected that fires specifically for SSE stream drops, keeping onclose reserved for explicit termination.
Option 1 seems simplest and matches the semantic intent of onclose — the client is gone.
Human note: Cursor generated this report for me, since it helped me give perfect specifics, but it's all from me and human-edited.
The impact is that we can't actually tell if an agent is still there when using http-transport, since the SSE stream closing is hidden from our app-code, and agents do not send DELETE requests when they poof.
When a client opens a GET SSE stream and then disconnects (e.g. the agent process exits, network drops, etc.), the transport's internal
stream.onAborthandler fires and cleans up#streamMapping, but the disconnection is never propagated to theonclosecallback or any other external hook.Current behavior
oncloseis only called insideclose(), which is only triggered by an explicit DELETE request. In practice, MCP clients (Cursor, Claude Code, etc.) do not send DELETE when they disconnect — the SSE stream dropping is the only signal available.Expected behavior:
When the standalone SSE stream (
_GET_stream) aborts, the transport should notify the application. This could be:onclosewhen the standalone SSE stream aborts (since it represents the client's only persistent connection), oronsessiondisconnectedthat fires specifically for SSE stream drops, keepingonclosereserved for explicit termination.Option 1 seems simplest and matches the semantic intent of
onclose— the client is gone.