Skip to content

Commit 8673db2

Browse files
committed
fix cursor timeouts
1 parent 2a4d6ce commit 8673db2

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

src/index.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,58 @@ if (useHttp) {
444444
// For now, we log the request but don't implement full resumability
445445
}
446446

447-
// Let the transport handle SSE headers and response
447+
logger.info(`Opening SSE stream for session: ${sessionId}`);
448+
449+
// Prevent connection timeout and keep it alive
450+
req.socket?.setTimeout(0);
451+
req.socket?.setKeepAlive(true, 30000);
452+
453+
let streamClosed = false;
454+
455+
// Handle client disconnection gracefully
456+
req.on('close', () => {
457+
streamClosed = true;
458+
logger.info(`Client disconnected SSE stream for session: ${sessionId}`);
459+
});
460+
461+
req.on('aborted', () => {
462+
streamClosed = true;
463+
logger.info(`Client aborted SSE stream for session: ${sessionId}`);
464+
});
465+
466+
// Let the MCP transport handle the SSE stream completely
448467
const transport = transports[sessionId];
449-
await transport.handleRequest(req, res);
468+
469+
try {
470+
await transport.handleRequest(req, res);
471+
472+
// If the transport completes without the client disconnecting,
473+
// it might have closed the stream prematurely. Keep it open with heartbeat.
474+
if (!streamClosed && !res.destroyed) {
475+
logger.info(`Transport completed, maintaining SSE stream for session: ${sessionId}`);
476+
477+
// Send periodic heartbeat to keep connection alive
478+
const heartbeat = setInterval(() => {
479+
if (streamClosed || res.destroyed) {
480+
clearInterval(heartbeat);
481+
return;
482+
}
483+
484+
try {
485+
res.write(': heartbeat\n\n');
486+
} catch (error) {
487+
logger.error(`Heartbeat error for session ${sessionId}:`, error);
488+
clearInterval(heartbeat);
489+
}
490+
}, 30000);
491+
492+
// Clean up heartbeat when connection closes
493+
req.on('close', () => clearInterval(heartbeat));
494+
res.on('close', () => clearInterval(heartbeat));
495+
}
496+
} catch (error) {
497+
logger.error(`SSE transport error for session ${sessionId}:`, error);
498+
}
450499

451500
} else if (req.method === 'DELETE') {
452501
// Handle session termination

0 commit comments

Comments
 (0)