Skip to content

Commit 2df7238

Browse files
committed
Normalize the reporting of connection setup and connection errors. The logging is verbose and different for every server type. This is an attempt to make the console output cleaner and more readable.
* In server/index.js - in createTransport() - stringify query params to put them on one line - remove logging of transport creation (done in callers) - in /mcp POST handler - report POST request if session id is present - otherwise, report new StreamableHttp connection request - report creation of server transport - report creation of client transport - in /stdio GET handler - report new STDIO connection request - report creation of server transport - report creation of client transport - report 401 as authentication error without stack - in stderr data handler - if it includes "MODULE_NOT_FOUND" - report "Command not found" - remove transports - otherwise send to client as usual - in /sse GET handler - report SSE connection request - report 401 as authentication error without stack - report 404 as server that may not support SSE - report error with "ECONNREFUSED" as "Connection refused" without stack - only create, map, and proxy transports if serverTransport was successfully created - in /message POST handler - report received POST message * In mcpProxy.ts - in onServerError() - if error message includes 404 OR error.cause includes ECONNREFUSED, report "Connection refused."
1 parent 438390e commit 2df7238

File tree

2 files changed

+68
-45
lines changed

2 files changed

+68
-45
lines changed

server/src/index.ts

Lines changed: 60 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const serverTransports: Map<string, Transport> = new Map<string, Transport>(); /
5353

5454
const createTransport = async (req: express.Request): Promise<Transport> => {
5555
const query = req.query;
56-
console.log("Query parameters:", query);
56+
console.log("Query parameters:", JSON.stringify(query));
5757

5858
const transportType = query.transportType as string;
5959

@@ -65,7 +65,7 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
6565

6666
const { cmd, args } = findActualExecutable(command, origArgs);
6767

68-
console.log(`Stdio transport: command=${cmd}, args=${args}`);
68+
console.log(`STDIO transport: command=${cmd}, args=${args}`);
6969

7070
const transport = new StdioClientTransport({
7171
command: cmd,
@@ -75,8 +75,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
7575
});
7676

7777
await transport.start();
78-
79-
console.log("Spawned stdio transport");
8078
return transport;
8179
} else if (transportType === "sse") {
8280
const url = query.url as string;
@@ -104,8 +102,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
104102
},
105103
});
106104
await transport.start();
107-
108-
console.log("Connected to SSE transport");
109105
return transport;
110106
} else if (transportType === "streamable-http") {
111107
const headers: HeadersInit = {
@@ -130,7 +126,6 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
130126
},
131127
);
132128
await transport.start();
133-
console.log("Connected to Streamable HTTP transport");
134129
return transport;
135130
} else {
136131
console.error(`Invalid transport type: ${transportType}`);
@@ -159,11 +154,10 @@ app.get("/mcp", async (req, res) => {
159154

160155
app.post("/mcp", async (req, res) => {
161156
const sessionId = req.headers["mcp-session-id"] as string | undefined;
162-
console.log(`Received POST message for sessionId ${sessionId}`);
163157
let serverTransport: Transport | undefined;
164158
if (!sessionId) {
165159
try {
166-
console.log("New streamable-http connection");
160+
console.log("New StreamableHttp connection request");
167161
try {
168162
serverTransport = await createTransport(req);
169163
} catch (error) {
@@ -179,16 +173,17 @@ app.post("/mcp", async (req, res) => {
179173
throw error;
180174
}
181175

182-
console.log("Connected MCP client to server transport");
176+
console.log("Created StreamableHttp server transport");
183177

184178
const webAppTransport = new StreamableHTTPServerTransport({
185179
sessionIdGenerator: randomUUID,
186180
onsessioninitialized: (sessionId) => {
187181
webAppTransports.set(sessionId, webAppTransport);
188182
serverTransports.set(sessionId, serverTransport!);
189-
console.log("Created streamable web app transport " + sessionId);
183+
console.log("New client <-> proxy server sessionId: " + sessionId);
190184
},
191185
});
186+
console.log("Created StreamableHttp client transport");
192187

193188
await webAppTransport.start();
194189

@@ -207,6 +202,7 @@ app.post("/mcp", async (req, res) => {
207202
res.status(500).json(error);
208203
}
209204
} else {
205+
console.log(`Received POST message for sessionId ${sessionId}`);
210206
try {
211207
const transport = webAppTransports.get(
212208
sessionId,
@@ -255,15 +251,15 @@ app.delete("/mcp", async (req, res) => {
255251

256252
app.get("/stdio", async (req, res) => {
257253
try {
258-
console.log("New connection");
254+
console.log("New STDIO connection request");
259255
let serverTransport: Transport | undefined;
260256
try {
261257
serverTransport = await createTransport(req);
258+
console.log("Created server transport");
262259
} catch (error) {
263260
if (error instanceof SseError && error.code === 401) {
264261
console.error(
265-
"Received 401 Unauthorized from MCP server:",
266-
error.message,
262+
"Received 401 Unauthorized from MCP server. Authentication failure."
267263
);
268264
res.status(401).json(error);
269265
return;
@@ -272,31 +268,44 @@ app.get("/stdio", async (req, res) => {
272268
throw error;
273269
}
274270

275-
console.log("Connected MCP client to backing server transport");
276-
277271
const webAppTransport = new SSEServerTransport("/message", res);
272+
console.log("Created client transport");
273+
278274
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
279275
serverTransports.set(webAppTransport.sessionId, serverTransport);
280-
console.log("Created client/server transports");
281276

282277
await webAppTransport.start();
283278

284279
(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+
}
292302
});
293303

294304
mcpProxy({
295305
transportToClient: webAppTransport,
296306
transportToServer: serverTransport,
297307
});
298308

299-
console.log("Set up MCP proxy");
300309
} catch (error) {
301310
console.error("Error in /stdio route:", error);
302311
res.status(500).json(error);
@@ -306,40 +315,47 @@ app.get("/stdio", async (req, res) => {
306315
app.get("/sse", async (req, res) => {
307316
try {
308317
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",
310319
);
311320
let serverTransport: Transport | undefined;
312321
try {
313322
serverTransport = await createTransport(req);
314323
} catch (error) {
315324
if (error instanceof SseError && error.code === 401) {
316325
console.error(
317-
"Received 401 Unauthorized from MCP server:",
318-
error.message,
326+
"Received 401 Unauthorized from MCP server. Authentication failure."
319327
);
320328
res.status(401).json(error);
321329
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;
322341
}
323-
324-
throw error;
325342
}
326343

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");
328350

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();
336352

337-
mcpProxy({
338-
transportToClient: webAppTransport,
339-
transportToServer: serverTransport,
340-
});
353+
mcpProxy({
354+
transportToClient: webAppTransport,
355+
transportToServer: serverTransport,
356+
});
357+
}
341358

342-
console.log("Set up MCP proxy");
343359
} catch (error) {
344360
console.error("Error in /sse route:", error);
345361
res.status(500).json(error);
@@ -349,7 +365,7 @@ app.get("/sse", async (req, res) => {
349365
app.post("/message", async (req, res) => {
350366
try {
351367
const sessionId = req.query.sessionId;
352-
console.log(`Received message for sessionId ${sessionId}`);
368+
console.log(`Received POST message for sessionId ${sessionId}`);
353369

354370
const transport = webAppTransports.get(
355371
sessionId as string,

server/src/mcpProxy.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ function onClientError(error: Error) {
66
}
77

88
function onServerError(error: Error) {
9-
console.error("Error from MCP server:", error);
9+
if (
10+
(error?.message && error.message.includes("Error POSTing to endpoint (HTTP 404)")) ||
11+
(error?.cause && JSON.stringify(error.cause).includes('ECONNREFUSED'))
12+
) {
13+
console.error("Connection refused. Is the MCP server running?");
14+
} else {
15+
console.error("Error from MCP server:", error);
16+
}
1017
}
1118

1219
export default function mcpProxy({

0 commit comments

Comments
 (0)