33 *
44 * Each example MCP App server is mounted at its own path, sharing the same
55 * OAuth authentication as the main MCP server.
6+ *
7+ * These servers run in STATELESS mode - each request creates a fresh server
8+ * instance without maintaining session state across requests.
69 */
710
811import { Router , Request , Response , NextFunction } from 'express' ;
912import cors from 'cors' ;
1013import { BearerAuthMiddlewareOptions , requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js' ;
1114import { getOAuthProtectedResourceMetadataUrl } from '@modelcontextprotocol/sdk/server/auth/router.js' ;
1215import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js' ;
13- import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js' ;
14- import { randomUUID } from 'crypto' ;
1516import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' ;
1617import { ITokenValidator } from '../../interfaces/auth-validator.js' ;
1718import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js' ;
@@ -59,13 +60,6 @@ export interface ExampleAppsConfig {
5960 baseUri : string ;
6061}
6162
62- // Session store: maps sessionId to { transport, server } per slug
63- const sessions = new Map < string , {
64- transport : StreamableHTTPServerTransport ;
65- server : McpServer ;
66- slug : string ;
67- } > ( ) ;
68-
6963export class ExampleAppsModule {
7064 private router : Router ;
7165
@@ -83,7 +77,7 @@ export class ExampleAppsModule {
8377 private setupRouter ( ) : Router {
8478 const router = Router ( ) ;
8579
86- // CORS configuration
80+ // CORS configuration - intentionally permissive for public MCP reference server
8781 const corsOptions = {
8882 origin : true ,
8983 methods : [ 'GET' , 'POST' , 'DELETE' ] ,
@@ -106,72 +100,31 @@ export class ExampleAppsModule {
106100 } ;
107101 const bearerAuth = requireBearerAuth ( bearerAuthOptions ) ;
108102
109- // Handler for /:slug/mcp
103+ // Handler for /:slug/mcp - stateless: each request creates a fresh server
110104 const handleExampleMcp = async ( req : Request , res : Response ) => {
111105 const { slug } = req . params ;
112106 const createServer = EXAMPLE_SERVERS [ slug ] ;
113107
114108 if ( ! createServer ) {
115109 res . status ( 404 ) . json ( {
116110 jsonrpc : "2.0" ,
117- error : { code : - 32001 , message : ` Unknown example server: ${ slug } ` } ,
111+ error : { code : - 32001 , message : " Unknown example server" } ,
118112 id : null ,
119113 } ) ;
120114 return ;
121115 }
122116
123- let transport : StreamableHTTPServerTransport | undefined ;
124-
125117 try {
126- const sessionId = req . headers [ 'mcp-session-id' ] as string | undefined ;
127-
128- // Check for existing session
129- if ( sessionId ) {
130- const session = sessions . get ( sessionId ) ;
131- if ( session && session . slug === slug ) {
132- await session . transport . handleRequest ( req , res , req . body ) ;
133- return ;
134- } else if ( session ) {
135- res . status ( 400 ) . json ( {
136- jsonrpc : "2.0" ,
137- error : { code : - 32000 , message : "Session belongs to different server" } ,
138- id : null ,
139- } ) ;
140- return ;
141- }
142- }
143-
144- // New session - must be initialize request
145- if ( ! isInitializeRequest ( req . body ) ) {
146- res . status ( 400 ) . json ( {
147- jsonrpc : "2.0" ,
148- error : { code : - 32000 , message : "Bad request: not initialized" } ,
149- id : null ,
150- } ) ;
151- return ;
152- }
153-
154- // Create new server instance
118+ // Create fresh server and transport for each request (stateless mode)
155119 const server = createServer ( ) ;
156- const newSessionId = randomUUID ( ) ;
157-
158- transport = new StreamableHTTPServerTransport ( {
159- sessionIdGenerator : ( ) => newSessionId ,
160- onsessioninitialized : ( id ) => {
161- sessions . set ( id , { transport : transport ! , server, slug } ) ;
162- } ,
120+ const transport = new StreamableHTTPServerTransport ( {
121+ sessionIdGenerator : undefined , // Stateless: no session management
163122 } ) ;
164123
165- transport . onclose = ( ) => {
166- if ( transport ?. sessionId ) {
167- sessions . delete ( transport . sessionId ) ;
168- }
169- } ;
170-
171124 await server . connect ( transport ) ;
172125 await transport . handleRequest ( req , res , req . body ) ;
173126 } catch ( error ) {
174- console . error ( ` Error handling ${ slug } MCP request:` , error ) ;
127+ console . error ( ' Error handling MCP request:' , error ) ;
175128 if ( ! res . headersSent ) {
176129 res . status ( 500 ) . json ( {
177130 jsonrpc : "2.0" ,
0 commit comments