@@ -53,7 +53,7 @@ const serverTransports: Map<string, Transport> = new Map<string, Transport>(); /
53
53
54
54
const createTransport = async ( req : express . Request ) : Promise < Transport > => {
55
55
const query = req . query ;
56
- console . log ( "Query parameters:" , query ) ;
56
+ console . log ( "Query parameters:" , JSON . stringify ( query ) ) ;
57
57
58
58
const transportType = query . transportType as string ;
59
59
@@ -65,7 +65,7 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
65
65
66
66
const { cmd, args } = findActualExecutable ( command , origArgs ) ;
67
67
68
- console . log ( `Stdio transport: command=${ cmd } , args=${ args } ` ) ;
68
+ console . log ( `STDIO transport: command=${ cmd } , args=${ args } ` ) ;
69
69
70
70
const transport = new StdioClientTransport ( {
71
71
command : cmd ,
@@ -75,8 +75,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
75
75
} ) ;
76
76
77
77
await transport . start ( ) ;
78
-
79
- console . log ( "Spawned stdio transport" ) ;
80
78
return transport ;
81
79
} else if ( transportType === "sse" ) {
82
80
const url = query . url as string ;
@@ -104,8 +102,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
104
102
} ,
105
103
} ) ;
106
104
await transport . start ( ) ;
107
-
108
- console . log ( "Connected to SSE transport" ) ;
109
105
return transport ;
110
106
} else if ( transportType === "streamable - http ") {
111
107
const headers : HeadersInit = {
@@ -130,7 +126,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
130
126
} ,
131
127
) ;
132
128
await transport . start ( ) ;
133
- console . log ( "Connected to Streamable HTTP transport" ) ;
134
129
return transport ;
135
130
} else {
136
131
console . error ( `Invalid transport type: ${ transportType } ` ) ;
@@ -159,11 +154,10 @@ app.get("/mcp", async (req, res) => {
159
154
160
155
app . post ( "/mcp" , async ( req , res ) => {
161
156
const sessionId = req . headers [ "mcp-session-id" ] as string | undefined ;
162
- console . log ( `Received POST message for sessionId ${ sessionId } ` ) ;
163
157
let serverTransport : Transport | undefined ;
164
158
if ( ! sessionId ) {
165
159
try {
166
- console . log ( "New streamable-http connection" ) ;
160
+ console . log ( "New StreamableHttp connection request " ) ;
167
161
try {
168
162
serverTransport = await createTransport ( req ) ;
169
163
} catch ( error ) {
@@ -179,16 +173,17 @@ app.post("/mcp", async (req, res) => {
179
173
throw error ;
180
174
}
181
175
182
- console . log ( "Connected MCP client to server transport" ) ;
176
+ console . log ( "Created StreamableHttp server transport" ) ;
183
177
184
178
const webAppTransport = new StreamableHTTPServerTransport ( {
185
179
sessionIdGenerator : randomUUID ,
186
180
onsessioninitialized : ( sessionId ) => {
187
181
webAppTransports . set ( sessionId , webAppTransport ) ;
188
182
serverTransports . set ( sessionId , serverTransport ! ) ;
189
- console . log ( "Created streamable web app transport " + sessionId ) ;
183
+ console . log ( "New client <-> proxy server sessionId: " + sessionId ) ;
190
184
} ,
191
185
} ) ;
186
+ console . log ( "Created StreamableHttp client transport" ) ;
192
187
193
188
await webAppTransport . start ( ) ;
194
189
@@ -207,6 +202,7 @@ app.post("/mcp", async (req, res) => {
207
202
res . status ( 500 ) . json ( error ) ;
208
203
}
209
204
} else {
205
+ console . log ( `Received POST message for sessionId ${ sessionId } ` ) ;
210
206
try {
211
207
const transport = webAppTransports . get (
212
208
sessionId ,
@@ -255,15 +251,15 @@ app.delete("/mcp", async (req, res) => {
255
251
256
252
app . get ( "/stdio" , async ( req , res ) => {
257
253
try {
258
- console . log ( "New connection" ) ;
254
+ console . log ( "New STDIO connection request " ) ;
259
255
let serverTransport : Transport | undefined ;
260
256
try {
261
257
serverTransport = await createTransport ( req ) ;
258
+ console . log ( "Created server transport" ) ;
262
259
} catch ( error ) {
263
260
if ( error instanceof SseError && error . code === 401 ) {
264
261
console . error (
265
- "Received 401 Unauthorized from MCP server:" ,
266
- error . message ,
262
+ "Received 401 Unauthorized from MCP server. Authentication failure."
267
263
) ;
268
264
res . status ( 401 ) . json ( error ) ;
269
265
return ;
@@ -272,31 +268,44 @@ app.get("/stdio", async (req, res) => {
272
268
throw error ;
273
269
}
274
270
275
- console . log ( "Connected MCP client to backing server transport" ) ;
276
-
277
271
const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
272
+ console . log ( "Created client transport" ) ;
273
+
278
274
webAppTransports . set ( webAppTransport . sessionId , webAppTransport ) ;
279
275
serverTransports . set ( webAppTransport . sessionId , serverTransport ) ;
280
- console . log ( "Created client/server transports" ) ;
281
276
282
277
await webAppTransport . start ( ) ;
283
278
284
279
( serverTransport as StdioClientTransport ) . stderr ! . on ( "data" , ( chunk ) => {
285
- webAppTransport . send ( {
286
- jsonrpc : "2.0" ,
287
- method : "notifications/stderr" ,
288
- params : {
289
- content : chunk . toString ( ) ,
290
- } ,
291
- } ) ;
280
+ if ( chunk . toString ( ) . includes ( "MODULE_NOT_FOUND" ) ) {
281
+ webAppTransport . send ( {
282
+ jsonrpc : "2.0" ,
283
+ method : "notifications/stderr" ,
284
+ params : {
285
+ content : "Command not found, transports removed" ,
286
+ } ,
287
+ } ) ;
288
+ webAppTransport . close ( ) ;
289
+ serverTransport . close ( ) ;
290
+ webAppTransports . delete ( webAppTransport . sessionId ) ;
291
+ serverTransports . delete ( webAppTransport . sessionId ) ;
292
+ console . error ( "Command not found, transports removed" ) ;
293
+ } else {
294
+ webAppTransport . send ( {
295
+ jsonrpc : "2.0" ,
296
+ method : "notifications/stderr" ,
297
+ params : {
298
+ content : chunk . toString ( ) ,
299
+ } ,
300
+ } ) ;
301
+ }
292
302
} ) ;
293
303
294
304
mcpProxy ( {
295
305
transportToClient : webAppTransport ,
296
306
transportToServer : serverTransport ,
297
307
} ) ;
298
308
299
- console . log ( "Set up MCP proxy" ) ;
300
309
} catch ( error ) {
301
310
console . error ( "Error in /stdio route:" , error ) ;
302
311
res . status ( 500 ) . json ( error ) ;
@@ -306,40 +315,47 @@ app.get("/stdio", async (req, res) => {
306
315
app . get ( "/sse" , async ( req , res ) => {
307
316
try {
308
317
console . log (
309
- "New SSE connection. NOTE: The sse transport is deprecated and has been replaced by streamable-http " ,
318
+ "New SSE connection request . NOTE: The sse transport is deprecated and has been replaced by StreamableHttp " ,
310
319
) ;
311
320
let serverTransport : Transport | undefined ;
312
321
try {
313
322
serverTransport = await createTransport ( req ) ;
314
323
} catch ( error ) {
315
324
if ( error instanceof SseError && error . code === 401 ) {
316
325
console . error (
317
- "Received 401 Unauthorized from MCP server:" ,
318
- error . message ,
326
+ "Received 401 Unauthorized from MCP server. Authentication failure."
319
327
) ;
320
328
res . status ( 401 ) . json ( error ) ;
321
329
return ;
330
+ } else if ( error instanceof SseError && error . code === 404 ) {
331
+ console . error (
332
+ "Received 404 not found from MCP server. Does the MCP server support SSE?" ,
333
+ ) ;
334
+ res . status ( 404 ) . json ( error ) ;
335
+ return ;
336
+ } else if ( JSON . stringify ( error ) . includes ( "ECONNREFUSED" ) ) {
337
+ console . error ( "Connection refused. Is the MCP server running?" ) ;
338
+ res . status ( 500 ) . json ( error ) ;
339
+ } else {
340
+ throw error ;
322
341
}
323
-
324
- throw error ;
325
342
}
326
343
327
- console . log ( "Connected MCP client to backing server transport" ) ;
344
+ if ( serverTransport ) {
345
+ const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
346
+ webAppTransports . set ( webAppTransport . sessionId , webAppTransport ) ;
347
+ console . log ( "Created client transport" ) ;
348
+ serverTransports . set ( webAppTransport . sessionId , serverTransport ! ) ;
349
+ console . log ( "Created server transport" ) ;
328
350
329
- const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
330
- webAppTransports . set ( webAppTransport . sessionId , webAppTransport ) ;
331
- console . log ( "Created client transport" ) ;
332
- serverTransports . set ( webAppTransport . sessionId , serverTransport ) ;
333
- console . log ( "Created server transport" ) ;
334
-
335
- await webAppTransport . start ( ) ;
351
+ await webAppTransport . start ( ) ;
336
352
337
- mcpProxy ( {
338
- transportToClient : webAppTransport ,
339
- transportToServer : serverTransport ,
340
- } ) ;
353
+ mcpProxy ( {
354
+ transportToClient : webAppTransport ,
355
+ transportToServer : serverTransport ,
356
+ } ) ;
357
+ }
341
358
342
- console . log ( "Set up MCP proxy" ) ;
343
359
} catch ( error ) {
344
360
console . error ( "Error in /sse route:" , error ) ;
345
361
res . status ( 500 ) . json ( error ) ;
@@ -349,7 +365,7 @@ app.get("/sse", async (req, res) => {
349
365
app . post ( "/message" , async ( req , res ) => {
350
366
try {
351
367
const sessionId = req . query . sessionId ;
352
- console . log ( `Received message for sessionId ${ sessionId } ` ) ;
368
+ console . log ( `Received POST message for sessionId ${ sessionId } ` ) ;
353
369
354
370
const transport = webAppTransports . get (
355
371
sessionId as string ,
0 commit comments