11import { IncomingMessage , ServerResponse } from "node:http" ;
22import { Transport } from "../shared/transport.js" ;
3- import { isJSONRPCRequest , isJSONRPCResponse , JSONRPCMessage , JSONRPCMessageSchema , RequestId } from "../types.js" ;
3+ import { isInitializeRequest , isJSONRPCRequest , isJSONRPCResponse , JSONRPCMessage , JSONRPCMessageSchema , RequestId } from "../types.js" ;
44import getRawBody from "raw-body" ;
55import contentType from "content-type" ;
66import { randomUUID } from "node:crypto" ;
@@ -39,6 +39,15 @@ export interface StreamableHTTPServerTransportOptions {
3939 */
4040 sessionIdGenerator : ( ) => string | undefined ;
4141
42+ /**
43+ * A callback for session initialization events
44+ * This is called when the server initializes a new session.
45+ * Usefult in cases when you need to register multiple mcp sessions
46+ * and need to keep track of them.
47+ * @param sessionId The generated session ID
48+ */
49+ onsessioninitialized ?: ( sessionId : string ) => void ;
50+
4251 /**
4352 * If true, the server will return JSON responses instead of starting an SSE stream.
4453 * This can be useful for simple request/response scenarios without streaming.
@@ -98,6 +107,7 @@ export class StreamableHTTPServerTransport implements Transport {
98107 private _enableJsonResponse : boolean = false ;
99108 private _standaloneSseStreamId : string = '_GET_stream' ;
100109 private _eventStore ?: EventStore ;
110+ private _onsessioninitialized ?: ( sessionId : string ) => void ;
101111
102112 sessionId ?: string | undefined ;
103113 onclose ?: ( ) => void ;
@@ -108,6 +118,7 @@ export class StreamableHTTPServerTransport implements Transport {
108118 this . sessionIdGenerator = options . sessionIdGenerator ;
109119 this . _enableJsonResponse = options . enableJsonResponse ?? false ;
110120 this . _eventStore = options . eventStore ;
121+ this . _onsessioninitialized = options . onsessioninitialized ;
111122 }
112123
113124 /**
@@ -328,9 +339,7 @@ export class StreamableHTTPServerTransport implements Transport {
328339
329340 // Check if this is an initialization request
330341 // https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle/
331- const isInitializationRequest = messages . some (
332- msg => 'method' in msg && msg . method === 'initialize'
333- ) ;
342+ const isInitializationRequest = messages . some ( isInitializeRequest ) ;
334343 if ( isInitializationRequest ) {
335344 // If it's a server with session management and the session ID is already set we should reject the request
336345 // to avoid re-initialization.
@@ -359,6 +368,12 @@ export class StreamableHTTPServerTransport implements Transport {
359368 this . sessionId = this . sessionIdGenerator ( ) ;
360369 this . _initialized = true ;
361370
371+ // If we have a session ID and an onsessioninitialized handler, call it immediately
372+ // This is needed in cases where the server needs to keep track of multiple sessions
373+ if ( this . sessionId && this . _onsessioninitialized ) {
374+ this . _onsessioninitialized ( this . sessionId ) ;
375+ }
376+
362377 }
363378 // If an Mcp-Session-Id is returned by the server during initialization,
364379 // clients using the Streamable HTTP transport MUST include it
0 commit comments