Skip to content

Commit fad62e3

Browse files
committed
fix: sse reconnect issues
1 parent b6f186c commit fad62e3

File tree

4 files changed

+31
-35
lines changed

4 files changed

+31
-35
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mcp-framework",
3-
"version": "0.1.24",
3+
"version": "0.1.25",
44

55
"description": "Framework for building Model Context Protocol (MCP) servers in Typescript",
66
"type": "module",

src/cli/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const program = new Command();
1111
program
1212
.name("mcp")
1313
.description("CLI for managing MCP server projects")
14-
.version("0.1.24");
14+
.version("0.1.25");
1515

1616
program
1717
.command("build")

src/cli/project/create.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export async function createProject(name?: string) {
6161
start: "node dist/index.js"
6262
},
6363
dependencies: {
64-
"mcp-framework": "^0.1.24",
64+
"mcp-framework": "^0.1.25",
6565
},
6666
devDependencies: {
6767
"@types/node": "^20.11.24",

src/transports/sse/server.ts

+28-32
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ export class SSEServerTransport extends AbstractTransport {
4646
}
4747

4848
private getCorsHeaders(includeMaxAge: boolean = false): Record<string, string> {
49-
// Ensure all CORS properties are present by merging with defaults
5049
const corsConfig = {
5150
allowOrigin: DEFAULT_CORS_CONFIG.allowOrigin,
5251
allowMethods: DEFAULT_CORS_CONFIG.allowMethods,
@@ -125,13 +124,13 @@ export class SSEServerTransport extends AbstractTransport {
125124
if (this._sseResponse?.writableEnded) {
126125
this._sseResponse = undefined
127126
}
128-
127+
129128
if (this._sseResponse) {
130-
logger.warn("SSE connection already established")
131-
res.writeHead(409).end("SSE connection already established")
132-
return
129+
logger.warn("SSE connection already established; closing the old connection to allow a new one.")
130+
this._sseResponse.end()
131+
this.cleanupConnection()
133132
}
134-
133+
135134
this.setupSSEConnection(res)
136135
return
137136
}
@@ -204,48 +203,48 @@ export class SSEServerTransport extends AbstractTransport {
204203
}
205204

206205
private setupSSEConnection(res: ServerResponse): void {
207-
logger.debug(`Setting up SSE connection for session: ${this._sessionId}`);
206+
logger.debug(`Setting up SSE connection for session: ${this._sessionId}`)
208207

209208
const headers = {
210209
...SSE_HEADERS,
211210
...this.getCorsHeaders(),
212211
...this._config.headers
213212
}
214213
setResponseHeaders(res, headers)
215-
logger.debug(`SSE headers set: ${JSON.stringify(headers)}`);
214+
logger.debug(`SSE headers set: ${JSON.stringify(headers)}`)
216215

217216
if (res.socket) {
218-
res.socket.setNoDelay(true)
219-
res.socket.setTimeout(0)
220-
res.socket.setKeepAlive(true, 1000)
221-
logger.debug('Socket optimized for SSE connection');
217+
res.socket.setNoDelay(true)
218+
res.socket.setTimeout(0)
219+
res.socket.setKeepAlive(true, 1000)
220+
logger.debug('Socket optimized for SSE connection')
222221
}
223222

224-
const endpointUrl = `${this._config.messageEndpoint}?sessionId=${this._sessionId}`;
225-
logger.debug(`Sending endpoint URL: ${endpointUrl}`);
226-
res.write(`event: endpoint\ndata: ${endpointUrl}\n\n`);
223+
const endpointUrl = `${this._config.messageEndpoint}?sessionId=${this._sessionId}`
224+
logger.debug(`Sending endpoint URL: ${endpointUrl}`)
225+
res.write(`event: endpoint\ndata: ${endpointUrl}\n\n`)
227226

228-
logger.debug('Sending initial keep-alive');
229-
res.write(": keep-alive\n\n");
227+
logger.debug('Sending initial keep-alive')
228+
res.write(": keep-alive\n\n")
230229

231230
this._keepAliveInterval = setInterval(() => {
232231
if (this._sseResponse && !this._sseResponse.writableEnded) {
233232
try {
234-
logger.debug('Sending keep-alive ping');
235-
this._sseResponse.write(": keep-alive\n\n");
233+
logger.debug('Sending keep-alive ping')
234+
this._sseResponse.write(": keep-alive\n\n")
236235

237236
const pingMessage = {
238237
jsonrpc: "2.0",
239238
method: "ping",
240239
params: { timestamp: Date.now() }
241-
};
242-
this._sseResponse.write(`data: ${JSON.stringify(pingMessage)}\n\n`);
240+
}
241+
this._sseResponse.write(`data: ${JSON.stringify(pingMessage)}\n\n`)
243242
} catch (error) {
244-
logger.error(`Error sending keep-alive: ${error}`);
245-
this.cleanupConnection();
243+
logger.error(`Error sending keep-alive: ${error}`)
244+
this.cleanupConnection()
246245
}
247246
}
248-
}, 15000)
247+
}, 15000)
249248

250249
this._sseResponse = res
251250

@@ -294,26 +293,26 @@ export class SSEServerTransport extends AbstractTransport {
294293
return parsed
295294
})()
296295

297-
const { id, method, params } = rawMessage as any;
298-
logger.debug(`Parsed message - ID: ${id}, Method: ${method}`);
296+
const { id, method, params } = rawMessage as any
297+
logger.debug(`Parsed message - ID: ${id}, Method: ${method}`)
299298

300299
const rpcMessage: JSONRPCMessage = {
301300
jsonrpc: "2.0",
302301
id: id,
303302
method: method,
304303
params: params
305-
};
304+
}
306305

307306
currentMessage = {
308307
id: id,
309308
method: method
310-
};
309+
}
311310

312311
logger.debug(`Processing RPC message: ${JSON.stringify({
313312
id: id,
314313
method: method,
315314
params: params
316-
})}`);
315+
})}`)
317316

318317
if (!this._onmessage) {
319318
throw new Error("No message handler registered")
@@ -382,9 +381,6 @@ export class SSEServerTransport extends AbstractTransport {
382381
})
383382
}
384383

385-
/**
386-
* Clean up SSE connection resources
387-
*/
388384
private cleanupConnection(): void {
389385
if (this._keepAliveInterval) {
390386
clearInterval(this._keepAliveInterval)

0 commit comments

Comments
 (0)