From 1b754f52ca2df7b7459fc35aeab08aceb0b814a9 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 28 Mar 2025 11:59:21 -0400 Subject: [PATCH 1/2] This fixes #214 where when the inspector is started, it can report that the inspector is up, when in fact it isn't because the address is already in use. It catches this condition, as well as the condition where the proxy server port is in use, reports it, and exits. * In bin/cli.js - in the delay function, have the setTimeout return a true value. - try the server's spawnPromise call and within the try block, use Promise.race to get the return value of the first promise to resolve. If the server is up, it will not resolve and the 2 second delay will resolve with true, telling us the server is ok. Any error will have been reported by the server startup process, so we will not pile on with more output in the catch block. - If the server started ok, then we will await the spawnPromise call for starting the client. If the client fails to start it will report and exit, otherwise we are done and both servers are running and have reported as much. If an error is caught and it isn't SIGINT or if process.env.DEBUG is true then the error will be thrown before exiting. * In client/bin/cli.js - add a "listening" handler to the server, logging that the MCP inspector is up at the given port - Add an "error" handler to the server that reports that the client port is in use if the error message includes "EADDRINUSE", otherwise throw the error so the entire contents can be seen. * In server/src/index.ts - add a "listening" handler to the server, logging that the Proxy server is up at the given port - Add an "error" handler to the server that reports that the server port is in use if the error message includes "EADDRINUSE", otherwise throw the error so the entire contents can be seen. * In package.json - in preview script - add --port 5173 to start the client on the proper port. This was useful in getting an instance of the client running before trying the start script. otherwise it starts on 4173 --- bin/cli.js | 75 +++++++++++++++++++++++---------------------- client/bin/cli.js | 16 +++++++++- client/package.json | 2 +- server/src/index.ts | 25 ++++++++------- 4 files changed, 69 insertions(+), 49 deletions(-) diff --git a/bin/cli.js b/bin/cli.js index 1b744ce..d559688 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -7,7 +7,7 @@ import { fileURLToPath } from "url"; const __dirname = dirname(fileURLToPath(import.meta.url)); function delay(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms, true)); } async function main() { @@ -73,42 +73,45 @@ async function main() { cancelled = true; abort.abort(); }); - - const server = spawnPromise( - "node", - [ - inspectorServerPath, - ...(command ? [`--env`, command] : []), - ...(mcpServerArgs ? [`--args=${mcpServerArgs.join(" ")}`] : []), - ], - { - env: { - ...process.env, - PORT: SERVER_PORT, - MCP_ENV_VARS: JSON.stringify(envVars), - }, - signal: abort.signal, - echoOutput: true, - }, - ); - - const client = spawnPromise("node", [inspectorClientPath], { - env: { ...process.env, PORT: CLIENT_PORT }, - signal: abort.signal, - echoOutput: true, - }); - - // Make sure our server/client didn't immediately fail - await Promise.any([server, client, delay(2 * 1000)]); - const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${SERVER_PORT}`; - console.log( - `\nšŸ” MCP Inspector is up and running at http://127.0.0.1:${CLIENT_PORT}${portParam} šŸš€`, - ); - + let server, serverOk; try { - await Promise.any([server, client]); - } catch (e) { - if (!cancelled || process.env.DEBUG) throw e; + + server = spawnPromise( + "node", + [ + inspectorServerPath, + ...(command ? [`--env`, command] : []), + ...(mcpServerArgs ? [`--args=${mcpServerArgs.join(" ")}`] : []), + ], + { + env: { + ...process.env, + PORT: SERVER_PORT, + MCP_ENV_VARS: JSON.stringify(envVars), + }, + signal: abort.signal, + echoOutput: true, + }, + ) + + // Make sure server started before starting client + serverOk = await Promise.race([server, delay(2 * 1000)]); + + } catch(error) {} + + if (serverOk) { + try { + + await spawnPromise("node", [inspectorClientPath], { + env: { ...process.env, PORT: CLIENT_PORT }, + signal: abort.signal, + echoOutput: true, + }); + + } catch (e) { + if (!cancelled || process.env.DEBUG) throw e; + } + } return 0; diff --git a/client/bin/cli.js b/client/bin/cli.js index 7dc93ea..9dbe796 100755 --- a/client/bin/cli.js +++ b/client/bin/cli.js @@ -16,4 +16,18 @@ const server = http.createServer((request, response) => { }); const port = process.env.PORT || 5173; -server.listen(port, () => {}); +server.on("listening", () => { + console.log( + `šŸ” MCP Inspector is up and running at http://127.0.0.1:${port} šŸš€`, + ); +}) +server.on("error", (err) => { + if (err.message.includes(`EADDRINUSE`)) { + console.error( + `āŒ MCP Inspector PORT IS IN USE at http://127.0.0.1:${port} āŒ `, + ); + } else { + throw err; + } +}) +server.listen(port); diff --git a/client/package.json b/client/package.json index 9eff88c..c268c33 100644 --- a/client/package.json +++ b/client/package.json @@ -18,7 +18,7 @@ "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint .", - "preview": "vite preview", + "preview": "vite preview --port 5173", "test": "jest --config jest.config.cjs", "test:watch": "jest --config jest.config.cjs --watch" }, diff --git a/server/src/index.ts b/server/src/index.ts index 2a4fe65..7e45de4 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -184,15 +184,18 @@ app.get("/config", (req, res) => { const PORT = process.env.PORT || 3000; -try { - const server = app.listen(PORT); - - server.on("listening", () => { - const addr = server.address(); - const port = typeof addr === "string" ? addr : addr?.port; - console.log(`Proxy server listening on port ${port}`); - }); -} catch (error) { - console.error("Failed to start server:", error); +const server = app.listen(PORT); +server.on("listening", () => { + console.log(`āš™ļø Proxy server listening on port ${PORT}`); +}); +server.on("error", (err) => { + if (err.message.includes(`EADDRINUSE`)) { + console.error( + `āŒ Proxy Server PORT IS IN USE at port ${PORT} āŒ `, + ); + } else { + console.error(err.message); + } process.exit(1); -} +}) + From 054741be03bbade7ef0bd09012bd2e8c3f3b2628 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Sat, 29 Mar 2025 12:36:03 -0400 Subject: [PATCH 2/2] Run prettier. --- bin/cli.js | 9 ++------- client/bin/cli.js | 4 ++-- server/src/index.ts | 7 ++----- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/bin/cli.js b/bin/cli.js index d559688..8c5e526 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -75,7 +75,6 @@ async function main() { }); let server, serverOk; try { - server = spawnPromise( "node", [ @@ -92,26 +91,22 @@ async function main() { signal: abort.signal, echoOutput: true, }, - ) + ); // Make sure server started before starting client serverOk = await Promise.race([server, delay(2 * 1000)]); - - } catch(error) {} + } catch (error) {} if (serverOk) { try { - await spawnPromise("node", [inspectorClientPath], { env: { ...process.env, PORT: CLIENT_PORT }, signal: abort.signal, echoOutput: true, }); - } catch (e) { if (!cancelled || process.env.DEBUG) throw e; } - } return 0; diff --git a/client/bin/cli.js b/client/bin/cli.js index 9dbe796..95b6429 100755 --- a/client/bin/cli.js +++ b/client/bin/cli.js @@ -20,7 +20,7 @@ server.on("listening", () => { console.log( `šŸ” MCP Inspector is up and running at http://127.0.0.1:${port} šŸš€`, ); -}) +}); server.on("error", (err) => { if (err.message.includes(`EADDRINUSE`)) { console.error( @@ -29,5 +29,5 @@ server.on("error", (err) => { } else { throw err; } -}) +}); server.listen(port); diff --git a/server/src/index.ts b/server/src/index.ts index 7e45de4..6c66de0 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -190,12 +190,9 @@ server.on("listening", () => { }); server.on("error", (err) => { if (err.message.includes(`EADDRINUSE`)) { - console.error( - `āŒ Proxy Server PORT IS IN USE at port ${PORT} āŒ `, - ); + console.error(`āŒ Proxy Server PORT IS IN USE at port ${PORT} āŒ `); } else { console.error(err.message); } process.exit(1); -}) - +});