diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed28e9d..72502f9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Thanks for your interest in contributing! This guide explains how to get involve 1. Fork the repository and clone it locally 2. Install dependencies with `npm install` 3. Run `npm run dev` to start both client and server in development mode -4. Use the web UI at http://127.0.0.1:5173 to interact with the inspector +4. Use the web UI at http://127.0.0.1:6274 to interact with the inspector ## Development Process & Pull Requests diff --git a/README.md b/README.md index 5fe3693..b0e18de 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ npx @modelcontextprotocol/inspector -e KEY=value -e KEY2=$VALUE2 node build/inde npx @modelcontextprotocol/inspector -e KEY=$VALUE -- node build/index.js -e server-flag ``` -The inspector runs both a client UI (default port 5173) and an MCP proxy server (default port 3000). Open the client UI in your browser to use the inspector. You can customize the ports if needed: +The inspector runs both an MCP Inspector (MCPI) client UI (default port 6274) and an MCP Proxy (MCPP) server (default port 6277). Open the MCPI client UI in your browser to use the inspector. (These ports are derived from the T9 dialpad mapping of MCPI and MCPP respectively, as a mnemonic). You can customize the ports if needed: ```bash CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector node build/index.js diff --git a/bin/cli.js b/bin/cli.js index 1b744ce..35edf0e 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() { @@ -61,8 +61,8 @@ async function main() { "cli.js", ); - const CLIENT_PORT = process.env.CLIENT_PORT ?? "5173"; - const SERVER_PORT = process.env.SERVER_PORT ?? "3000"; + const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274"; + const SERVER_PORT = process.env.SERVER_PORT ?? "6277"; console.log("Starting MCP inspector..."); @@ -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 === "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..d30cc70 100755 --- a/client/bin/cli.js +++ b/client/bin/cli.js @@ -15,5 +15,19 @@ const server = http.createServer((request, response) => { }); }); -const port = process.env.PORT || 5173; -server.listen(port, () => {}); +const port = process.env.PORT || 6274; +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..eb0091f 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 6274", "test": "jest --config jest.config.cjs", "test:watch": "jest --config jest.config.cjs --watch" }, diff --git a/client/src/App.tsx b/client/src/App.tsx index c29ef71..23c508f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -49,7 +49,7 @@ import { DEFAULT_INSPECTOR_CONFIG } from "./lib/constants"; import { InspectorConfig } from "./lib/configurationTypes"; const params = new URLSearchParams(window.location.search); -const PROXY_PORT = params.get("proxyPort") ?? "3000"; +const PROXY_PORT = params.get("proxyPort") ?? "6277"; const PROXY_SERVER_URL = `http://${window.location.hostname}:${PROXY_PORT}`; const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1"; 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..feb893f 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.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.16.tgz", + "integrity": "sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/server/src/index.ts b/server/src/index.ts index 2a4fe65..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) { @@ -182,17 +185,17 @@ app.get("/config", (req, res) => { } }); -const PORT = process.env.PORT || 3000; +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); -} +});