diff --git a/bin/cli.js b/bin/cli.js index 460ce58..ca1958a 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,40 @@ 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 === "6277" ? "" : `?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; @@ -119,4 +117,4 @@ main() .catch((e) => { console.error(e); process.exit(1); - }); + }); \ No newline at end of file diff --git a/client/bin/cli.js b/client/bin/cli.js index 81b7bd1..d30cc70 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 || 6274; -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/client/src/components/Sidebar.tsx b/client/src/components/Sidebar.tsx index ca6d5fe..33e88a7 100644 --- a/client/src/components/Sidebar.tsx +++ b/client/src/components/Sidebar.tsx @@ -8,6 +8,7 @@ import { Github, Eye, EyeOff, + RotateCcw, Settings, } from "lucide-react"; import { Button } from "@/components/ui/button"; @@ -375,8 +376,17 @@ const Sidebar = ({
diff --git a/package-lock.json b/package-lock.json index 448edd6..c891d5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10777,9 +10777,9 @@ } }, "node_modules/vite": { - "version": "5.4.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.12.tgz", - "integrity": "sha512-KwUaKB27TvWwDJr1GjjWthLMATbGEbeWYZIbGZ5qFIsgPP3vWzLu4cVooqhm5/Z2SPDUMjyPVjTztm5tYKwQxA==", + "version": "5.4.15", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.15.tgz", + "integrity": "sha512-6ANcZRivqL/4WtwPGTKNaosuNJr5tWiftOC7liM7G9+rMb8+oeJeyzymDu4rTN93seySBmbjSfsS3Vzr19KNtA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/server/src/index.ts b/server/src/index.ts index fcb8295..ee33930 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -12,6 +12,7 @@ import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js"; +import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js"; import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js"; import express from "express"; import { findActualExecutable } from "spawn-rx"; @@ -98,12 +99,14 @@ const createTransport = async (req: express.Request) => { } }; +let backingServerTransport: Transport | undefined; + app.get("/sse", async (req, res) => { try { console.log("New SSE connection"); - let backingServerTransport; try { + await backingServerTransport?.close(); backingServerTransport = await createTransport(req); } catch (error) { if (error instanceof SseError && error.code === 401) { @@ -184,15 +187,15 @@ app.get("/config", (req, res) => { const PORT = process.env.PORT || 6277; -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); -} +});