resume long running requst from new client

This commit is contained in:
ihrpr 2025-04-13 21:40:15 +01:00
commit 43cb015844
No known key found for this signature in database

View file

@ -217,7 +217,6 @@ export class StreamableHTTPServerTransport implements Transport {
// Assign the response to the standalone SSE stream
this._streamMapping.set(this._standaloneSseStreamId, res);
// Set up close handler for client disconnects
res.on("close", () => {
this._streamMapping.delete(this._standaloneSseStreamId);
@ -345,8 +344,10 @@ export class StreamableHTTPServerTransport implements Transport {
const isInitializationRequest = messages.some(
msg => 'method' in msg && msg.method === 'initialize'
);
const mcpSessionId = req.headers["mcp-session-id"] as string | undefined;
if (isInitializationRequest) {
if (this._initialized) {
// if generateSessionId is not set, the server does not support session management
if (this._initialized && this.sessionId !== undefined && mcpSessionId !== this.sessionId) {
res.writeHead(400).end(JSON.stringify({
jsonrpc: "2.0",
error: {
@ -368,7 +369,7 @@ export class StreamableHTTPServerTransport implements Transport {
}));
return;
}
this.sessionId = this.sessionIdGenerator();
this.sessionId = mcpSessionId ?? this.sessionIdGenerator();
this._initialized = true;
}
@ -419,17 +420,8 @@ export class StreamableHTTPServerTransport implements Transport {
this._requestToStreamMapping.set(message.id, streamId);
}
}
// Set up close handler for client disconnects
res.on("close", () => {
// find a stream ID for this response
// Remove all entries that reference this response
for (const [id, stream] of this._requestToStreamMapping.entries()) {
if (streamId === stream) {
this._requestToStreamMapping.delete(id);
this._requestResponseMap.delete(id);
}
}
this._streamMapping.delete(streamId);
});
@ -577,7 +569,7 @@ export class StreamableHTTPServerTransport implements Transport {
// Get the response for this request
const streamId = this._requestToStreamMapping.get(requestId);
const response = this._streamMapping.get(streamId!);
if (!streamId || !response) {
if (!streamId) {
throw new Error(`No connection established for request ID: ${String(requestId)}`);
}
@ -588,9 +580,10 @@ export class StreamableHTTPServerTransport implements Transport {
if (this._eventStore) {
eventId = await this._eventStore.storeEvent(streamId, message);
}
// Write the event to the response stream
this.writeSSEEvent(response, message, eventId);
if (response) {
// Write the event to the response stream
this.writeSSEEvent(response, message, eventId);
}
}
if (isJSONRPCResponse(message)) {
@ -603,6 +596,9 @@ export class StreamableHTTPServerTransport implements Transport {
const allResponsesReady = relatedIds.every(id => this._requestResponseMap.has(id));
if (allResponsesReady) {
if (!response) {
throw new Error(`No connection established for request ID: ${String(requestId)}`);
}
if (this._enableJsonResponse) {
// All responses ready, send as JSON
const headers: Record<string, string> = {