@@ -48,20 +48,31 @@ export class HTTPStreamableTransport implements Transport {
48
48
messageHandler : MessageHandler | null = null ;
49
49
closeCallback : ( ( ) => void ) | null = null ;
50
50
51
+ private headers : Record < string , string > ;
51
52
private options : TransportOptions ;
52
53
private connected = false ;
53
54
private enableStreaming = false ;
54
55
private sessions : Map < string , Session > = new Map ( ) ;
55
56
private streams : Map < string , StreamInfo > = new Map ( ) ;
56
57
private logger : Logger ;
57
58
59
+ setHeaders ( headers : Record < string , string > ) : void {
60
+ this . headers = { ...this . headers , ...headers } ;
61
+ }
62
+
58
63
constructor ( options : TransportOptions = { } , streamable = false ) {
59
64
// Set defaults
60
65
this . options = {
61
66
timeout : 30 * 60 * 1000 , // 30 minutes
62
67
enableSessions : false ,
63
68
...options ,
64
69
} ;
70
+
71
+ this . headers = {
72
+ "Content-Type" : "application/json" ,
73
+ ...options . headers ,
74
+ } ;
75
+
65
76
this . logger = options . logger || createDefaultLogger ( ) ;
66
77
67
78
// Start session cleanup timer if sessions are enabled
@@ -189,7 +200,7 @@ export class HTTPStreamableTransport implements Transport {
189
200
) ,
190
201
{
191
202
status : 503 ,
192
- headers : { "Content-Type" : "application/json" } ,
203
+ headers : this . headers ,
193
204
}
194
205
) ;
195
206
}
@@ -205,7 +216,7 @@ export class HTTPStreamableTransport implements Transport {
205
216
) ,
206
217
{
207
218
status : 500 ,
208
- headers : { "Content-Type" : "application/json" } ,
219
+ headers : this . headers ,
209
220
}
210
221
) ;
211
222
}
@@ -260,7 +271,7 @@ export class HTTPStreamableTransport implements Transport {
260
271
) ,
261
272
{
262
273
status : 400 ,
263
- headers : { "Content-Type" : "application/json" } ,
274
+ headers : this . headers ,
264
275
}
265
276
) ;
266
277
}
@@ -295,7 +306,7 @@ export class HTTPStreamableTransport implements Transport {
295
306
) ,
296
307
{
297
308
status : 406 ,
298
- headers : { "Content-Type" : "application/json" } ,
309
+ headers : this . headers ,
299
310
}
300
311
) ;
301
312
}
@@ -313,7 +324,7 @@ export class HTTPStreamableTransport implements Transport {
313
324
) ,
314
325
{
315
326
status : 400 ,
316
- headers : { "Content-Type" : "application/json" } ,
327
+ headers : this . headers ,
317
328
}
318
329
) ;
319
330
}
@@ -347,9 +358,10 @@ export class HTTPStreamableTransport implements Transport {
347
358
}
348
359
return new Response ( null , {
349
360
status : 202 ,
350
- headers : currentSession
351
- ? { "Mcp-Session-Id" : currentSession . id }
352
- : undefined ,
361
+ headers : {
362
+ ...this . headers ,
363
+ ...( currentSession && { "Mcp-Session-Id" : currentSession . id } ) ,
364
+ } ,
353
365
} ) ;
354
366
}
355
367
@@ -373,17 +385,12 @@ export class HTTPStreamableTransport implements Transport {
373
385
374
386
// Return a direct JSON response
375
387
const responseBody = responses . length === 1 ? responses [ 0 ] : responses ;
376
- const headers : Record < string , string > = {
377
- "Content-Type" : "application/json" ,
378
- } ;
379
-
380
- if ( currentSession ) {
381
- headers [ "Mcp-Session-Id" ] = currentSession . id ;
382
- }
383
-
384
388
return new Response ( JSON . stringify ( responseBody ) , {
385
389
status : 200 ,
386
- headers,
390
+ headers : {
391
+ ...this . headers ,
392
+ ...( currentSession && { "Mcp-Session-Id" : currentSession . id } ) ,
393
+ } ,
387
394
} ) ;
388
395
}
389
396
@@ -407,18 +414,15 @@ export class HTTPStreamableTransport implements Transport {
407
414
}
408
415
}
409
416
410
- const headers : Record < string , string > = {
411
- "Content-Type" : "text/event-stream" ,
412
- "Cache-Control" : "no-cache" ,
413
- Connection : "keep-alive" ,
414
- } ;
415
-
416
- if ( currentSession ) {
417
- headers [ "Mcp-Session-Id" ] = currentSession . id ;
418
- }
419
-
420
417
// Let responses be handled by the message handler and sent to the stream
421
- return new Response ( stream . readable , { headers } ) ;
418
+ return new Response ( stream . readable , {
419
+ headers : {
420
+ "Cache-Control" : "no-cache" ,
421
+ Connection : "keep-alive" ,
422
+ ...this . headers ,
423
+ ...( currentSession && { "Mcp-Session-Id" : currentSession . id } ) ,
424
+ } ,
425
+ } ) ;
422
426
} catch ( error ) {
423
427
return new Response (
424
428
JSON . stringify (
@@ -430,7 +434,7 @@ export class HTTPStreamableTransport implements Transport {
430
434
) ,
431
435
{
432
436
status : 500 ,
433
- headers : { "Content-Type" : "application/json" } ,
437
+ headers : this . headers ,
434
438
}
435
439
) ;
436
440
}
@@ -441,19 +445,19 @@ export class HTTPStreamableTransport implements Transport {
441
445
*/
442
446
private async handleGetRequest (
443
447
request : Request ,
444
- session ?: Session
448
+ currentSession ?: Session
445
449
) : Promise < Response > {
446
450
// Check Accept header as required by the spec
447
451
const acceptHeader = request . headers . get ( "Accept" ) || "" ;
448
452
if ( ! acceptHeader . includes ( "text/event-stream" ) ) {
449
453
return new Response ( null , {
450
454
status : 406 , // Not Acceptable
451
- headers : { "Content-Type" : "application/json" } ,
455
+ headers : this . headers ,
452
456
} ) ;
453
457
}
454
458
455
459
// If no session and sessions are required, reject
456
- if ( this . options . enableSessions && ! session ) {
460
+ if ( this . options . enableSessions && ! currentSession ) {
457
461
return new Response (
458
462
JSON . stringify (
459
463
newJSONRPCError ( {
@@ -464,33 +468,29 @@ export class HTTPStreamableTransport implements Transport {
464
468
) ,
465
469
{
466
470
status : 400 ,
467
- headers : { "Content-Type" : "application/json" } ,
471
+ headers : this . headers ,
468
472
}
469
473
) ;
470
474
}
471
475
472
476
// Create a new stream for server-to-client communication
473
- const { stream, streamId } = this . createStream ( session ) ;
477
+ const { stream, streamId } = this . createStream ( currentSession ) ;
474
478
475
479
// Check for Last-Event-ID for resumability
476
480
const lastEventId = request . headers . get ( "Last-Event-ID" ) ;
477
- if ( lastEventId && session ) {
481
+ if ( lastEventId && currentSession ) {
478
482
// Replay messages if needed
479
- await this . replayMessages ( session , streamId , lastEventId ) ;
483
+ await this . replayMessages ( currentSession , streamId , lastEventId ) ;
480
484
}
481
485
482
- // Return the stream
483
- const headers : Record < string , string > = {
484
- "Content-Type" : "text/event-stream" ,
485
- "Cache-Control" : "no-cache" ,
486
- Connection : "keep-alive" ,
487
- } ;
488
-
489
- if ( session ) {
490
- headers [ "Mcp-Session-Id" ] = session . id ;
491
- }
492
-
493
- return new Response ( stream . readable , { headers } ) ;
486
+ return new Response ( stream . readable , {
487
+ headers : {
488
+ "Cache-Control" : "no-cache" ,
489
+ Connection : "keep-alive" ,
490
+ ...this . headers ,
491
+ ...( currentSession && { "Mcp-Session-Id" : currentSession . id } ) ,
492
+ } ,
493
+ } ) ;
494
494
}
495
495
496
496
/**
0 commit comments