@@ -34,11 +34,18 @@ export interface StreamableHTTPServerTransportOptions {
3434 /**
3535 * Function that generates a session ID for the transport.
3636 * The session ID SHOULD be globally unique and cryptographically secure (e.g., a securely generated UUID, a JWT, or a cryptographic hash)
37- *
38- * Return undefined to disable session management .
37+ *
38+ * Not used in stateless mode .
3939 */
4040 sessionIdGenerator : ( ( ) => string ) | undefined ;
4141
42+ /**
43+ * Whether to run in stateless mode (no session management).
44+ * In stateless mode, no initialization is required and there's no session tracking.
45+ * Default is false (stateful mode).
46+ */
47+ statelessMode ?: boolean ;
48+
4249 /**
4350 * A callback for session initialization events
4451 * This is called when the server initializes a new session.
@@ -64,37 +71,39 @@ export interface StreamableHTTPServerTransportOptions {
6471
6572/**
6673 * Server transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
67- * It supports both SSE streaming and direct HTTP responses.
68- *
74+ * It supports both SSE streaming and direct HTTP responses.r
75+ *
6976 * Usage example:
70- *
77+ *
7178 * ```typescript
7279 * // Stateful mode - server sets the session ID
7380 * const statefulTransport = new StreamableHTTPServerTransport({
74- * sessionId: randomUUID(),
81+ * sessionIdGenerator: () => randomUUID(),
7582 * });
76- *
77- * // Stateless mode - explicitly set session ID to undefined
83+ *
84+ * // Stateless mode - explicitly enable stateless mode
7885 * const statelessTransport = new StreamableHTTPServerTransport({
79- * sessionId: undefined,
86+ * statelessMode: true,
87+ * enableJsonResponse: true, // Optional
8088 * });
81- *
89+ *
8290 * // Using with pre-parsed request body
8391 * app.post('/mcp', (req, res) => {
8492 * transport.handleRequest(req, res, req.body);
8593 * });
8694 * ```
87- *
95+ *
8896 * In stateful mode:
8997 * - Session ID is generated and included in response headers
9098 * - Session ID is always included in initialization responses
9199 * - Requests with invalid session IDs are rejected with 404 Not Found
92100 * - Non-initialization requests without a session ID are rejected with 400 Bad Request
93101 * - State is maintained in-memory (connections, message history)
94- *
102+ *
95103 * In stateless mode:
96- * - Session ID is only included in initialization responses
104+ * - No initialization is required before handling requests
97105 * - No session validation is performed
106+ * - No state is maintained between requests
98107 */
99108export class StreamableHTTPServerTransport implements Transport {
100109 // when sessionId is not set (undefined), it means the transport is in stateless mode
@@ -108,6 +117,7 @@ export class StreamableHTTPServerTransport implements Transport {
108117 private _standaloneSseStreamId : string = '_GET_stream' ;
109118 private _eventStore ?: EventStore ;
110119 private _onsessioninitialized ?: ( sessionId : string ) => void ;
120+ private _statelessMode : boolean = false ;
111121
112122 sessionId ?: string | undefined ;
113123 onclose ?: ( ) => void ;
@@ -119,6 +129,12 @@ export class StreamableHTTPServerTransport implements Transport {
119129 this . _enableJsonResponse = options . enableJsonResponse ?? false ;
120130 this . _eventStore = options . eventStore ;
121131 this . _onsessioninitialized = options . onsessioninitialized ;
132+ this . _statelessMode = options . statelessMode ?? false ;
133+
134+ // In stateless mode, no initialization is required
135+ if ( this . _statelessMode ) {
136+ this . _initialized = true ;
137+ }
122138 }
123139
124140 /**
@@ -166,7 +182,7 @@ export class StreamableHTTPServerTransport implements Transport {
166182 }
167183
168184 // If an Mcp-Session-Id is returned by the server during initialization,
169- // clients using the Streamable HTTP transport MUST include it
185+ // clients using the Streamable HTTP transport MUST include it
170186 // in the Mcp-Session-Id header on all of their subsequent HTTP requests.
171187 if ( ! this . validateSession ( req , res ) ) {
172188 return ;
@@ -180,7 +196,7 @@ export class StreamableHTTPServerTransport implements Transport {
180196 }
181197 }
182198
183- // The server MUST either return Content-Type: text/event-stream in response to this HTTP GET,
199+ // The server MUST either return Content-Type: text/event-stream in response to this HTTP GET,
184200 // or else return HTTP 405 Method Not Allowed
185201 const headers : Record < string , string > = {
186202 "Content-Type" : "text/event-stream" ,
@@ -376,7 +392,7 @@ export class StreamableHTTPServerTransport implements Transport {
376392
377393 }
378394 // If an Mcp-Session-Id is returned by the server during initialization,
379- // clients using the Streamable HTTP transport MUST include it
395+ // clients using the Streamable HTTP transport MUST include it
380396 // in the Mcp-Session-Id header on all of their subsequent HTTP requests.
381397 if ( ! isInitializationRequest && ! this . validateSession ( req , res ) ) {
382398 return ;
@@ -475,11 +491,12 @@ export class StreamableHTTPServerTransport implements Transport {
475491 } ) ) ;
476492 return false ;
477493 }
478- if ( this . sessionId === undefined ) {
479- // If the session ID is not set, the session management is disabled
480- // and we don't need to validate the session ID
494+
495+ // If in stateless mode or the session ID is undefined, no session validation is needed
496+ if ( this . _statelessMode || this . sessionId === undefined ) {
481497 return true ;
482498 }
499+
483500 const sessionId = req . headers [ "mcp-session-id" ] ;
484501
485502 if ( ! sessionId ) {
0 commit comments