Merge pull request #79 from modelcontextprotocol/ani/fix-windows
Fix launch issues on Windows
This commit is contained in:
123
bin/cli.js
123
bin/cli.js
@@ -1,65 +1,82 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import { join, dirname } from "path";
|
import { resolve, dirname } from "path";
|
||||||
|
import { spawnPromise } from "spawn-rx";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
import concurrently from "concurrently";
|
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
// Get command line arguments
|
function delay(ms) {
|
||||||
const [, , command, ...mcpServerArgs] = process.argv;
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
const inspectorServerPath = join(__dirname, "../server/build/index.js");
|
|
||||||
|
|
||||||
// Path to the client entry point
|
|
||||||
const inspectorClientPath = join(__dirname, "../client/bin/cli.js");
|
|
||||||
|
|
||||||
console.log("Starting MCP inspector...");
|
|
||||||
|
|
||||||
function escapeArg(arg) {
|
|
||||||
if (arg.includes(" ") || arg.includes("'") || arg.includes('"')) {
|
|
||||||
return `\\"${arg.replace(/"/g, '\\\\\\"')}\\"`;
|
|
||||||
}
|
|
||||||
return arg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverCommand = [
|
async function main() {
|
||||||
`node`,
|
// Get command line arguments
|
||||||
inspectorServerPath,
|
const [, , command, ...mcpServerArgs] = process.argv;
|
||||||
command ? `--env ${escapeArg(command)}` : "",
|
|
||||||
mcpServerArgs.length
|
|
||||||
? `--args="${mcpServerArgs.map(escapeArg).join(" ")}"`
|
|
||||||
: "",
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(" ");
|
|
||||||
|
|
||||||
const CLIENT_PORT = process.env.CLIENT_PORT ?? "";
|
const inspectorServerPath = resolve(
|
||||||
const SERVER_PORT = process.env.SERVER_PORT ?? "";
|
__dirname,
|
||||||
|
"..",
|
||||||
|
"server",
|
||||||
|
"build",
|
||||||
|
"index.js",
|
||||||
|
);
|
||||||
|
|
||||||
const { result } = concurrently(
|
// Path to the client entry point
|
||||||
[
|
const inspectorClientPath = resolve(
|
||||||
{
|
__dirname,
|
||||||
command: `PORT=${SERVER_PORT} ${serverCommand}`,
|
"..",
|
||||||
name: "server",
|
"client",
|
||||||
},
|
"bin",
|
||||||
{
|
"cli.js",
|
||||||
command: `PORT=${CLIENT_PORT} node ${inspectorClientPath}`,
|
);
|
||||||
name: "client",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
{
|
|
||||||
prefix: "name",
|
|
||||||
killOthers: ["failure", "success"],
|
|
||||||
restartTries: 3,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(
|
const CLIENT_PORT = process.env.CLIENT_PORT ?? "5173";
|
||||||
`\n🔍 MCP Inspector is up and running at http://localhost:${CLIENT_PORT || 5173} 🚀`,
|
const SERVER_PORT = process.env.SERVER_PORT ?? "3000";
|
||||||
);
|
|
||||||
|
|
||||||
result.catch((err) => {
|
console.log("Starting MCP inspector...");
|
||||||
console.error("An error occurred:", err);
|
|
||||||
process.exit(1);
|
const abort = new AbortController();
|
||||||
});
|
|
||||||
|
let cancelled = false;
|
||||||
|
process.on("SIGINT", () => {
|
||||||
|
cancelled = true;
|
||||||
|
abort.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
const server = spawnPromise(
|
||||||
|
"node",
|
||||||
|
[
|
||||||
|
inspectorServerPath,
|
||||||
|
...(command ? [`--env`, command] : []),
|
||||||
|
...(mcpServerArgs ? ["--args", mcpServerArgs.join(" ")] : []),
|
||||||
|
],
|
||||||
|
{ env: { ...process.env, PORT: SERVER_PORT }, signal: abort.signal },
|
||||||
|
);
|
||||||
|
|
||||||
|
const client = spawnPromise("node", [inspectorClientPath], {
|
||||||
|
env: { ...process.env, PORT: CLIENT_PORT },
|
||||||
|
signal: abort.signal,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure our server/client didn't immediately fail
|
||||||
|
await Promise.any([server, client, delay(2 * 1000)]);
|
||||||
|
console.log(
|
||||||
|
`\n🔍 MCP Inspector is up and running at http://localhost:${CLIENT_PORT} 🚀`,
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.any([server, client]);
|
||||||
|
} catch (e) {
|
||||||
|
if (!cancelled || process.env.DEBUG) throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then((_) => process.exit(0))
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "0.7.0",
|
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.1.0",
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
"@radix-ui/react-select": "^2.1.2",
|
"@radix-ui/react-select": "^2.1.2",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
import animate from "tailwindcss-animate";
|
||||||
export default {
|
export default {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||||
@@ -53,5 +54,5 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("tailwindcss-animate")],
|
plugins: [animate],
|
||||||
};
|
};
|
||||||
|
|||||||
2425
package-lock.json
generated
2425
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -27,7 +27,7 @@
|
|||||||
"build": "npm run build-server && npm run build-client",
|
"build": "npm run build-server && npm run build-client",
|
||||||
"start-server": "cd server && npm run start",
|
"start-server": "cd server && npm run start",
|
||||||
"start-client": "cd client && npm run preview",
|
"start-client": "cd client && npm run preview",
|
||||||
"start": "./bin/cli.js",
|
"start": "node ./bin/cli.js",
|
||||||
"prepare": "npm run build",
|
"prepare": "npm run build",
|
||||||
"prettier-fix": "prettier --write .",
|
"prettier-fix": "prettier --write .",
|
||||||
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
|
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
|
||||||
@@ -35,10 +35,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/inspector-client": "0.2.1",
|
"@modelcontextprotocol/inspector-client": "0.2.1",
|
||||||
"@modelcontextprotocol/inspector-server": "0.2.1",
|
"@modelcontextprotocol/inspector-server": "0.2.1",
|
||||||
"concurrently": "^9.0.1"
|
"concurrently": "^9.0.1",
|
||||||
|
"spawn-rx": "^5.0.4",
|
||||||
|
"ts-node": "^10.9.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "3.3.3",
|
"@types/node": "^22.7.5",
|
||||||
"@types/node": "^22.7.5"
|
"prettier": "3.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"typescript": "^5.6.2"
|
"typescript": "^5.6.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "0.7.0",
|
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"eventsource": "^2.0.2",
|
"eventsource": "^2.0.2",
|
||||||
"express": "^4.21.0",
|
"express": "^4.21.0",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ const createTransport = async (query: express.Request["query"]) => {
|
|||||||
const command = query.command as string;
|
const command = query.command as string;
|
||||||
const args = (query.args as string).split(/\s+/);
|
const args = (query.args as string).split(/\s+/);
|
||||||
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Stdio transport: command=${command}, args=${args}, env=${JSON.stringify(env)}`,
|
`Stdio transport: command=${command}, args=${args}, env=${JSON.stringify(env)}`,
|
||||||
);
|
);
|
||||||
@@ -48,14 +49,18 @@ const createTransport = async (query: express.Request["query"]) => {
|
|||||||
env,
|
env,
|
||||||
stderr: "pipe",
|
stderr: "pipe",
|
||||||
});
|
});
|
||||||
|
|
||||||
await transport.start();
|
await transport.start();
|
||||||
|
|
||||||
console.log("Spawned stdio transport");
|
console.log("Spawned stdio transport");
|
||||||
return transport;
|
return transport;
|
||||||
} else if (transportType === "sse") {
|
} else if (transportType === "sse") {
|
||||||
const url = query.url as string;
|
const url = query.url as string;
|
||||||
console.log(`SSE transport: url=${url}`);
|
console.log(`SSE transport: url=${url}`);
|
||||||
|
|
||||||
const transport = new SSEClientTransport(new URL(url));
|
const transport = new SSEClientTransport(new URL(url));
|
||||||
await transport.start();
|
await transport.start();
|
||||||
|
|
||||||
console.log("Connected to SSE transport");
|
console.log("Connected to SSE transport");
|
||||||
return transport;
|
return transport;
|
||||||
} else {
|
} else {
|
||||||
@@ -99,6 +104,7 @@ app.get("/sse", async (req, res) => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Set up MCP proxy");
|
console.log("Set up MCP proxy");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error in /sse route:", error);
|
console.error("Error in /sse route:", error);
|
||||||
@@ -126,6 +132,7 @@ app.post("/message", async (req, res) => {
|
|||||||
app.get("/config", (req, res) => {
|
app.get("/config", (req, res) => {
|
||||||
try {
|
try {
|
||||||
const defaultEnvironment = getDefaultEnvironment();
|
const defaultEnvironment = getDefaultEnvironment();
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
defaultCommand: values.env,
|
defaultCommand: values.env,
|
||||||
@@ -138,4 +145,4 @@ app.get("/config", (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
app.listen(PORT, () => { });
|
app.listen(PORT, () => {});
|
||||||
|
|||||||
Reference in New Issue
Block a user