@@ -89,16 +89,15 @@ export class StreamableHTTPServerTransport implements Transport {
89
89
} else if ( req . method === "DELETE" ) {
90
90
await this . handleDeleteRequest ( req , res ) ;
91
91
} else {
92
- await this . handleUnsupportedRequest ( req , res ) ;
92
+ await this . handleUnsupportedRequest ( res ) ;
93
93
}
94
94
}
95
95
96
96
/**
97
97
* Handles unsupported requests (GET, PUT, PATCH, etc.)
98
98
* For now we support only POST and DELETE requests. Support for GET for SSE connections will be added later.
99
99
*/
100
- private async handleUnsupportedRequest ( req : IncomingMessage , res : ServerResponse ) : Promise < void > {
101
-
100
+ private async handleUnsupportedRequest ( res : ServerResponse ) : Promise < void > {
102
101
res . writeHead ( 405 , {
103
102
"Allow" : "POST, DELETE"
104
103
} ) . end ( JSON . stringify ( {
@@ -119,8 +118,7 @@ export class StreamableHTTPServerTransport implements Transport {
119
118
// Validate the Accept header
120
119
const acceptHeader = req . headers . accept ;
121
120
// The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.
122
- if ( ! acceptHeader ||
123
- ! acceptHeader . includes ( "application/json" ) || ! acceptHeader . includes ( "text/event-stream" ) ) {
121
+ if ( ! acceptHeader ?. includes ( "application/json" ) || ! acceptHeader . includes ( "text/event-stream" ) ) {
124
122
res . writeHead ( 406 ) . end ( JSON . stringify ( {
125
123
jsonrpc : "2.0" ,
126
124
error : {
@@ -172,6 +170,17 @@ export class StreamableHTTPServerTransport implements Transport {
172
170
msg => 'method' in msg && msg . method === 'initialize'
173
171
) ;
174
172
if ( isInitializationRequest ) {
173
+ if ( messages . length > 1 ) {
174
+ res . writeHead ( 400 ) . end ( JSON . stringify ( {
175
+ jsonrpc : "2.0" ,
176
+ error : {
177
+ code : - 32600 ,
178
+ message : "Invalid Request: Only one initialization request is allowed"
179
+ } ,
180
+ id : null
181
+ } ) ) ;
182
+ return ;
183
+ }
175
184
const headers : Record < string , string > = { } ;
176
185
177
186
if ( this . _sessionId !== undefined ) {
@@ -280,7 +289,18 @@ export class StreamableHTTPServerTransport implements Transport {
280
289
id : null
281
290
} ) ) ;
282
291
return false ;
283
- } else if ( ( Array . isArray ( sessionId ) ? sessionId [ 0 ] : sessionId ) !== this . _sessionId ) {
292
+ } else if ( Array . isArray ( sessionId ) ) {
293
+ res . writeHead ( 400 ) . end ( JSON . stringify ( {
294
+ jsonrpc : "2.0" ,
295
+ error : {
296
+ code : - 32000 ,
297
+ message : "Bad Request: Mcp-Session-Id header must be a single value"
298
+ } ,
299
+ id : null
300
+ } ) ) ;
301
+ return false ;
302
+ }
303
+ else if ( sessionId !== this . _sessionId ) {
284
304
// Reject requests with invalid session ID with 404 Not Found
285
305
res . writeHead ( 404 ) . end ( JSON . stringify ( {
286
306
jsonrpc : "2.0" ,
@@ -331,7 +351,12 @@ export class StreamableHTTPServerTransport implements Transport {
331
351
// This is a response to the original request, we can close the stream
332
352
// after sending all related responses
333
353
this . _sseResponseMapping . delete ( relatedRequestId ) ;
334
- sseResponse . end ( ) ;
354
+
355
+ // Only close the connection if it's not needed by other requests
356
+ const canCloseConnection = ! [ ...this . _sseResponseMapping . entries ( ) ] . some ( ( [ id , res ] ) => res === sseResponse && id !== relatedRequestId ) ;
357
+ if ( canCloseConnection ) {
358
+ sseResponse . end ( ) ;
359
+ }
335
360
}
336
361
}
337
362
}
0 commit comments