@@ -117,9 +117,27 @@ export abstract class BaseMCPServer {
117117 await this . initializeToolsManager ( ) ;
118118
119119 const transport = new StdioServerTransport ( ) ;
120- await this . mcpServer . connect ( transport ) ;
121120
121+ try {
122+ await this . mcpServer . connect ( transport ) ;
123+ } catch ( error : unknown ) {
124+ const message = error instanceof Error ? error . message : String ( error ) ;
125+ console . error ( `Failed to connect MCP stdio transport: ${ message } ` ) ;
126+ throw new Error ( `Failed to initialize MCP stdio transport: ${ message } ` ) ;
127+ }
128+
129+ // Setup cleanup handlers
122130 process . stdin . on ( 'close' , ( ) => this . performCleanup ( ) ) ;
131+
132+ // Setup signal handlers for graceful shutdown
133+ const cleanup = ( ) => {
134+ console . error ( `${ this . config . name } shutting down...` ) ;
135+ this . performCleanup ( ) ;
136+ process . exit ( 0 ) ;
137+ } ;
138+
139+ process . once ( 'SIGINT' , cleanup ) ;
140+ process . once ( 'SIGTERM' , cleanup ) ;
123141 }
124142
125143 /**
@@ -149,6 +167,9 @@ export abstract class BaseMCPServer {
149167 const sessions = new Map < string , SessionData > ( ) ;
150168
151169 app . all ( '/mcp' , async ( req : Request , res : Response ) => {
170+ const startTime = Date . now ( ) ;
171+ const requestId = randomUUID ( ) . substring ( 0 , 8 ) ;
172+
152173 try {
153174 const rawSessionId = req . headers [ 'mcp-session-id' ] ;
154175 const sessionId = Array . isArray ( rawSessionId )
@@ -159,26 +180,42 @@ export abstract class BaseMCPServer {
159180 if ( ! session && req . method === 'POST' ) {
160181 // Check session limit to prevent DoS
161182 if ( sessions . size >= MAX_SESSIONS ) {
183+ console . error (
184+ `[${ new Date ( ) . toISOString ( ) } ] [${ requestId } ] Session limit reached: ${ sessions . size } /${ MAX_SESSIONS } ` ,
185+ ) ;
162186 res . status ( 503 ) . json ( {
163187 error : 'Too many active sessions' ,
164188 message : 'Server is at maximum capacity. Please try again later.' ,
165189 } ) ;
166190 return ;
167191 }
168192 session = await this . createHttpSession ( sessions ) ;
193+ console . log (
194+ `[${ new Date ( ) . toISOString ( ) } ] [${ requestId } ] New session created: ${ session . transport . sessionId } ` ,
195+ ) ;
169196 }
170197
171198 if ( session ) {
172199 session . lastAccessedAt = new Date ( ) ;
173200 await session . transport . handleRequest ( req , res , req . body ) ;
201+ const duration = Date . now ( ) - startTime ;
202+ console . log (
203+ `[${ new Date ( ) . toISOString ( ) } ] [${ requestId } ] Request completed in ${ duration } ms` ,
204+ ) ;
174205 } else {
206+ console . error (
207+ `[${ new Date ( ) . toISOString ( ) } ] [${ requestId } ] Invalid session or GET without session` ,
208+ ) ;
175209 res
176210 . status ( 400 )
177211 . json ( { error : 'Invalid session or GET without session' } ) ;
178212 }
179213 } catch ( error : unknown ) {
180214 const message = error instanceof Error ? error . message : String ( error ) ;
181- console . error ( 'MCP request error:' , message ) ;
215+ const duration = Date . now ( ) - startTime ;
216+ console . error (
217+ `[${ new Date ( ) . toISOString ( ) } ] [${ requestId } ] MCP request error after ${ duration } ms: ${ message } ` ,
218+ ) ;
182219 if ( ! res . headersSent ) {
183220 res . status ( 500 ) . json ( {
184221 error : 'Internal server error' ,
@@ -200,15 +237,11 @@ export abstract class BaseMCPServer {
200237 . on ( 'error' , ( error : NodeJS . ErrnoException ) => {
201238 if ( error . code === 'EADDRINUSE' ) {
202239 console . error (
203- `ERROR: Port ${ options . port } is already in use.\n` +
204- `Please try a different port: --port=<number>\n` +
205- `Example: --mode=http --port=${ options . port + 1 } ` ,
240+ `ERROR: Port ${ options . port } is already in use.\nPlease try a different port: --port=<number>\nExample: --mode=http --port=${ options . port + 1 } ` ,
206241 ) ;
207242 } else if ( error . code === 'EACCES' ) {
208243 console . error (
209- `ERROR: Permission denied to bind to port ${ options . port } .\n` +
210- `Ports below 1024 require root/admin privileges.\n` +
211- `Please use a port above 1024 or run with elevated privileges.` ,
244+ `ERROR: Permission denied to bind to port ${ options . port } .\nPorts below 1024 require root/admin privileges.\nPlease use a port above 1024 or run with elevated privileges.` ,
212245 ) ;
213246 } else {
214247 console . error (
@@ -238,22 +271,28 @@ export abstract class BaseMCPServer {
238271 createdAt : new Date ( ) ,
239272 lastAccessedAt : new Date ( ) ,
240273 } ) ;
241- console . log ( `Session ${ sid } created` ) ;
274+ console . log (
275+ `[${ new Date ( ) . toISOString ( ) } ] Session ${ sid } initialized (total: ${ sessions . size } )` ,
276+ ) ;
242277 } ,
243278 } ) ;
244279
245280 transport . onclose = ( ) => {
246281 if ( transport . sessionId ) {
247282 sessions . delete ( transport . sessionId ) ;
248- console . log ( `Session ${ transport . sessionId } closed` ) ;
283+ console . log (
284+ `[${ new Date ( ) . toISOString ( ) } ] Session ${ transport . sessionId } closed (remaining: ${ sessions . size } )` ,
285+ ) ;
249286 }
250287 } ;
251288
252289 try {
253290 await this . mcpServer . connect ( transport ) ;
254291 } catch ( error : unknown ) {
255292 const message = error instanceof Error ? error . message : String ( error ) ;
256- console . error ( `Failed to connect MCP transport: ${ message } ` ) ;
293+ console . error (
294+ `[${ new Date ( ) . toISOString ( ) } ] Failed to connect MCP transport: ${ message } ` ,
295+ ) ;
257296 // Clean up the failed transport
258297 if ( transport . sessionId ) {
259298 sessions . delete ( transport . sessionId ) ;
@@ -281,12 +320,14 @@ export abstract class BaseMCPServer {
281320 try {
282321 session . transport . close ( ) ;
283322 sessions . delete ( sid ) ;
284- console . log ( `Session ${ sid } cleaned up due to inactivity` ) ;
323+ console . log (
324+ `[${ new Date ( ) . toISOString ( ) } ] Session ${ sid } cleaned up due to inactivity (remaining: ${ sessions . size } )` ,
325+ ) ;
285326 } catch ( error : unknown ) {
286327 const message =
287328 error instanceof Error ? error . message : String ( error ) ;
288329 console . error (
289- `Failed to close session ${ sid } during cleanup: ${ message } ` ,
330+ `[ ${ new Date ( ) . toISOString ( ) } ] Failed to close session ${ sid } during cleanup: ${ message } ` ,
290331 ) ;
291332 // Still delete from map to prevent retry loops
292333 sessions . delete ( sid ) ;
@@ -313,21 +354,33 @@ export abstract class BaseMCPServer {
313354 try {
314355 session . transport . close ( ) ;
315356 } catch ( error : unknown ) {
316- const message = error instanceof Error ? error . message : String ( error ) ;
357+ const message =
358+ error instanceof Error ? error . message : String ( error ) ;
317359 console . error ( `Error closing session during shutdown: ${ message } ` ) ;
318360 }
319361 }
320362 sessions . clear ( ) ;
321363
322- // Close HTTP server
364+ // Close HTTP server gracefully
323365 try {
324- server . close ( ) ;
366+ server . close ( ( ) => {
367+ // Server closed callback - all connections finished
368+ this . performCleanup ( ) ;
369+ process . exit ( 0 ) ;
370+ } ) ;
371+
372+ // Set a timeout in case server.close() hangs
373+ setTimeout ( ( ) => {
374+ console . error ( 'Forcefully shutting down after timeout' ) ;
375+ this . performCleanup ( ) ;
376+ process . exit ( 1 ) ;
377+ } , 5000 ) ;
325378 } catch ( error : unknown ) {
326379 const message = error instanceof Error ? error . message : String ( error ) ;
327380 console . error ( `Error closing HTTP server: ${ message } ` ) ;
381+ this . performCleanup ( ) ;
382+ process . exit ( 1 ) ;
328383 }
329-
330- this . performCleanup ( ) ;
331384 } ;
332385
333386 // Use once() to prevent multiple registrations
0 commit comments