Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
576ff0043a | ||
|
|
18dc4d0a99 | ||
|
|
f04b161411 | ||
|
|
bd6a63603a | ||
|
|
b845444fab | ||
|
|
ace94c4d37 | ||
|
|
50640bc9cc | ||
|
|
cc17ba8d56 | ||
|
|
764f02310d | ||
|
|
945299181d | ||
|
|
79344bd495 | ||
|
|
295ccac27e | ||
|
|
f3f424f21e | ||
|
|
6b6eeb8dcd | ||
|
|
3110cf9343 | ||
|
|
2c04fa31e8 | ||
|
|
e700bc713a | ||
|
|
bea86af65b | ||
|
|
68a6130b17 | ||
|
|
853a3b4faf | ||
|
|
6f62066d34 | ||
|
|
c770d217e7 | ||
|
|
98470a12f9 | ||
|
|
a00564fafa | ||
|
|
62546dec58 | ||
|
|
886ac5fc7b | ||
|
|
722df4d798 | ||
|
|
407e304585 | ||
|
|
60578314aa | ||
|
|
fbac5b78bc | ||
|
|
f876b1ec0d | ||
|
|
aecfa21d47 | ||
|
|
a3d542c0a3 |
@@ -26,6 +26,8 @@ The inspector runs both a client UI (default port 5173) and an MCP proxy server
|
||||
CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector build/index.js
|
||||
```
|
||||
|
||||
For more details on ways to use the inspector, see the [Inspector section of the MCP docs site](https://modelcontextprotocol.io/docs/tools/inspector).
|
||||
|
||||
### From this repository
|
||||
|
||||
If you're working on the inspector itself:
|
||||
|
||||
12
bin/cli.js
12
bin/cli.js
@@ -49,20 +49,26 @@ async function main() {
|
||||
[
|
||||
inspectorServerPath,
|
||||
...(command ? [`--env`, command] : []),
|
||||
...(mcpServerArgs ? ["--args", mcpServerArgs.join(" ")] : []),
|
||||
...(mcpServerArgs ? [`--args=${mcpServerArgs.join(" ")}`] : []),
|
||||
],
|
||||
{ env: { ...process.env, PORT: SERVER_PORT }, signal: abort.signal },
|
||||
{
|
||||
env: { ...process.env, PORT: SERVER_PORT },
|
||||
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://localhost:${CLIENT_PORT} 🚀`,
|
||||
`\n🔍 MCP Inspector is up and running at http://localhost:${CLIENT_PORT}${portParam} 🚀`,
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@modelcontextprotocol/inspector-client",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"description": "Client-side application for the Model Context Protocol inspector",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
@@ -21,7 +21,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||
"@modelcontextprotocol/sdk": "^1.0.3",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
|
||||
@@ -57,6 +57,11 @@ import ToolsTab from "./components/ToolsTab";
|
||||
|
||||
const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000;
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const PROXY_PORT = params.get("proxyPort") ?? "3000";
|
||||
const REQUEST_TIMEOUT = parseInt(params.get("timeout") ?? "") || DEFAULT_REQUEST_TIMEOUT_MSEC;
|
||||
const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
|
||||
|
||||
const App = () => {
|
||||
const [connectionStatus, setConnectionStatus] = useState<
|
||||
"disconnected" | "connected" | "error"
|
||||
@@ -82,7 +87,8 @@ const App = () => {
|
||||
const [args, setArgs] = useState<string>(() => {
|
||||
return localStorage.getItem("lastArgs") || "";
|
||||
});
|
||||
const [url, setUrl] = useState<string>("http://localhost:3001/sse");
|
||||
|
||||
const [sseUrl, setSseUrl] = useState<string>("http://localhost:3001/sse");
|
||||
const [transportType, setTransportType] = useState<"stdio" | "sse">("stdio");
|
||||
const [requestHistory, setRequestHistory] = useState<
|
||||
{ request: string; response?: string }[]
|
||||
@@ -191,7 +197,7 @@ const App = () => {
|
||||
}, [args]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch("http://localhost:3000/config")
|
||||
fetch(`${PROXY_SERVER_URL}/config`)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
setEnv(data.defaultEnvironment);
|
||||
@@ -238,7 +244,7 @@ const App = () => {
|
||||
const abortController = new AbortController();
|
||||
const timeoutId = setTimeout(() => {
|
||||
abortController.abort("Request timed out");
|
||||
}, DEFAULT_REQUEST_TIMEOUT_MSEC);
|
||||
}, REQUEST_TIMEOUT);
|
||||
|
||||
let response;
|
||||
try {
|
||||
@@ -404,7 +410,7 @@ const App = () => {
|
||||
},
|
||||
);
|
||||
|
||||
const backendUrl = new URL("http://localhost:3000/sse");
|
||||
const backendUrl = new URL(`${PROXY_SERVER_URL}/sse`);
|
||||
|
||||
backendUrl.searchParams.append("transportType", transportType);
|
||||
if (transportType === "stdio") {
|
||||
@@ -412,7 +418,7 @@ const App = () => {
|
||||
backendUrl.searchParams.append("args", args);
|
||||
backendUrl.searchParams.append("env", JSON.stringify(env));
|
||||
} else {
|
||||
backendUrl.searchParams.append("url", url);
|
||||
backendUrl.searchParams.append("url", sseUrl);
|
||||
}
|
||||
|
||||
const clientTransport = new SSEClientTransport(backendUrl);
|
||||
@@ -469,8 +475,8 @@ const App = () => {
|
||||
setCommand={setCommand}
|
||||
args={args}
|
||||
setArgs={setArgs}
|
||||
url={url}
|
||||
setUrl={setUrl}
|
||||
sseUrl={sseUrl}
|
||||
setSseUrl={setSseUrl}
|
||||
env={env}
|
||||
setEnv={setEnv}
|
||||
onConnect={connectMcpServer}
|
||||
@@ -520,10 +526,18 @@ const App = () => {
|
||||
clearError("resources");
|
||||
listResources();
|
||||
}}
|
||||
clearResources={() => {
|
||||
setResources([]);
|
||||
setNextResourceCursor(undefined);
|
||||
}}
|
||||
listResourceTemplates={() => {
|
||||
clearError("resources");
|
||||
listResourceTemplates();
|
||||
}}
|
||||
clearResourceTemplates={() => {
|
||||
setResourceTemplates([]);
|
||||
setNextResourceTemplateCursor(undefined);
|
||||
}}
|
||||
readResource={(uri) => {
|
||||
clearError("resources");
|
||||
readResource(uri);
|
||||
@@ -544,6 +558,10 @@ const App = () => {
|
||||
clearError("prompts");
|
||||
listPrompts();
|
||||
}}
|
||||
clearPrompts={() => {
|
||||
setPrompts([]);
|
||||
setNextPromptCursor(undefined);
|
||||
}}
|
||||
getPrompt={(name, args) => {
|
||||
clearError("prompts");
|
||||
getPrompt(name, args);
|
||||
@@ -563,6 +581,10 @@ const App = () => {
|
||||
clearError("tools");
|
||||
listTools();
|
||||
}}
|
||||
clearTools={() => {
|
||||
setTools([]);
|
||||
setNextToolCursor(undefined);
|
||||
}}
|
||||
callTool={(name, params) => {
|
||||
clearError("tools");
|
||||
callTool(name, params);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Button } from "./ui/button";
|
||||
type ListPaneProps<T> = {
|
||||
items: T[];
|
||||
listItems: () => void;
|
||||
clearItems: () => void;
|
||||
setSelectedItem: (item: T) => void;
|
||||
renderItem: (item: T) => React.ReactNode;
|
||||
title: string;
|
||||
@@ -13,6 +14,7 @@ type ListPaneProps<T> = {
|
||||
const ListPane = <T extends object>({
|
||||
items,
|
||||
listItems,
|
||||
clearItems,
|
||||
setSelectedItem,
|
||||
renderItem,
|
||||
title,
|
||||
@@ -32,6 +34,14 @@ const ListPane = <T extends object>({
|
||||
>
|
||||
{buttonText}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="w-full mb-4"
|
||||
onClick={clearItems}
|
||||
disabled={items.length === 0}
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
<div className="space-y-2 overflow-y-auto max-h-96">
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
|
||||
@@ -22,6 +22,7 @@ export type Prompt = {
|
||||
const PromptsTab = ({
|
||||
prompts,
|
||||
listPrompts,
|
||||
clearPrompts,
|
||||
getPrompt,
|
||||
selectedPrompt,
|
||||
setSelectedPrompt,
|
||||
@@ -31,6 +32,7 @@ const PromptsTab = ({
|
||||
}: {
|
||||
prompts: Prompt[];
|
||||
listPrompts: () => void;
|
||||
clearPrompts: () => void;
|
||||
getPrompt: (name: string, args: Record<string, string>) => void;
|
||||
selectedPrompt: Prompt | null;
|
||||
setSelectedPrompt: (prompt: Prompt) => void;
|
||||
@@ -55,6 +57,7 @@ const PromptsTab = ({
|
||||
<ListPane
|
||||
items={prompts}
|
||||
listItems={listPrompts}
|
||||
clearItems={clearPrompts}
|
||||
setSelectedItem={(prompt) => {
|
||||
setSelectedPrompt(prompt);
|
||||
setPromptArgs({});
|
||||
|
||||
@@ -16,7 +16,9 @@ const ResourcesTab = ({
|
||||
resources,
|
||||
resourceTemplates,
|
||||
listResources,
|
||||
clearResources,
|
||||
listResourceTemplates,
|
||||
clearResourceTemplates,
|
||||
readResource,
|
||||
selectedResource,
|
||||
setSelectedResource,
|
||||
@@ -28,7 +30,9 @@ const ResourcesTab = ({
|
||||
resources: Resource[];
|
||||
resourceTemplates: ResourceTemplate[];
|
||||
listResources: () => void;
|
||||
clearResources: () => void;
|
||||
listResourceTemplates: () => void;
|
||||
clearResourceTemplates: () => void;
|
||||
readResource: (uri: string) => void;
|
||||
selectedResource: Resource | null;
|
||||
setSelectedResource: (resource: Resource | null) => void;
|
||||
@@ -68,6 +72,7 @@ const ResourcesTab = ({
|
||||
<ListPane
|
||||
items={resources}
|
||||
listItems={listResources}
|
||||
clearItems={clearResources}
|
||||
setSelectedItem={(resource) => {
|
||||
setSelectedResource(resource);
|
||||
readResource(resource.uri);
|
||||
@@ -90,6 +95,7 @@ const ResourcesTab = ({
|
||||
<ListPane
|
||||
items={resourceTemplates}
|
||||
listItems={listResourceTemplates}
|
||||
clearItems={clearResourceTemplates}
|
||||
setSelectedItem={(template) => {
|
||||
setSelectedTemplate(template);
|
||||
setSelectedResource(null);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { Play, ChevronDown, ChevronRight } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
import { StdErrNotification } from "@/lib/notificationTypes";
|
||||
|
||||
import useTheme from "../lib/useTheme";
|
||||
import { version } from "../../../package.json";
|
||||
|
||||
interface SidebarProps {
|
||||
connectionStatus: "disconnected" | "connected" | "error";
|
||||
@@ -22,8 +22,8 @@ interface SidebarProps {
|
||||
setCommand: (command: string) => void;
|
||||
args: string;
|
||||
setArgs: (args: string) => void;
|
||||
url: string;
|
||||
setUrl: (url: string) => void;
|
||||
sseUrl: string;
|
||||
setSseUrl: (url: string) => void;
|
||||
env: Record<string, string>;
|
||||
setEnv: (env: Record<string, string>) => void;
|
||||
onConnect: () => void;
|
||||
@@ -38,8 +38,8 @@ const Sidebar = ({
|
||||
setCommand,
|
||||
args,
|
||||
setArgs,
|
||||
url,
|
||||
setUrl,
|
||||
sseUrl,
|
||||
setSseUrl,
|
||||
env,
|
||||
setEnv,
|
||||
onConnect,
|
||||
@@ -52,7 +52,9 @@ const Sidebar = ({
|
||||
<div className="w-80 bg-card border-r border-border flex flex-col h-full">
|
||||
<div className="flex items-center justify-between p-4 border-b border-gray-200">
|
||||
<div className="flex items-center">
|
||||
<h1 className="ml-2 text-lg font-semibold">MCP Inspector</h1>
|
||||
<h1 className="ml-2 text-lg font-semibold">
|
||||
MCP Inspector v{version}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,6 +77,7 @@ const Sidebar = ({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{transportType === "stdio" ? (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
@@ -99,8 +102,8 @@ const Sidebar = ({
|
||||
<label className="text-sm font-medium">URL</label>
|
||||
<Input
|
||||
placeholder="URL"
|
||||
value={url}
|
||||
onChange={(e) => setUrl(e.target.value)}
|
||||
value={sseUrl}
|
||||
onChange={(e) => setSseUrl(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -5,9 +5,9 @@ import { Label } from "@/components/ui/label";
|
||||
import { TabsContent } from "@/components/ui/tabs";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import {
|
||||
CallToolResult,
|
||||
ListToolsResult,
|
||||
Tool,
|
||||
CallToolResultSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import { AlertCircle, Send } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
@@ -18,6 +18,7 @@ import { CompatibilityCallToolResult } from "@modelcontextprotocol/sdk/types.js"
|
||||
const ToolsTab = ({
|
||||
tools,
|
||||
listTools,
|
||||
clearTools,
|
||||
callTool,
|
||||
selectedTool,
|
||||
setSelectedTool,
|
||||
@@ -27,6 +28,7 @@ const ToolsTab = ({
|
||||
}: {
|
||||
tools: Tool[];
|
||||
listTools: () => void;
|
||||
clearTools: () => void;
|
||||
callTool: (name: string, params: Record<string, unknown>) => void;
|
||||
selectedTool: Tool | null;
|
||||
setSelectedTool: (tool: Tool) => void;
|
||||
@@ -40,7 +42,27 @@ const ToolsTab = ({
|
||||
if (!toolResult) return null;
|
||||
|
||||
if ("content" in toolResult) {
|
||||
const structuredResult = toolResult as CallToolResult;
|
||||
const parsedResult = CallToolResultSchema.safeParse(toolResult);
|
||||
if (!parsedResult.success) {
|
||||
return (
|
||||
<>
|
||||
<h4 className="font-semibold mb-2">Invalid Tool Result:</h4>
|
||||
<pre className="bg-gray-50 dark:bg-gray-800 dark:text-gray-100 p-4 rounded text-sm overflow-auto max-h-64">
|
||||
{JSON.stringify(toolResult, null, 2)}
|
||||
</pre>
|
||||
<h4 className="font-semibold mb-2">Errors:</h4>
|
||||
{parsedResult.error.errors.map((error, idx) => (
|
||||
<pre
|
||||
key={idx}
|
||||
className="bg-gray-50 dark:bg-gray-800 dark:text-gray-100 p-4 rounded text-sm overflow-auto max-h-64"
|
||||
>
|
||||
{JSON.stringify(error, null, 2)}
|
||||
</pre>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
const structuredResult = parsedResult.data;
|
||||
const isError = structuredResult.isError ?? false;
|
||||
|
||||
return (
|
||||
@@ -63,7 +85,7 @@ const ToolsTab = ({
|
||||
/>
|
||||
)}
|
||||
{item.type === "resource" && (
|
||||
<pre className="bg-gray-50 p-4 rounded text-sm overflow-auto max-h-64">
|
||||
<pre className="bg-gray-50 dark:bg-gray-800 dark:text-gray-100 whitespace-pre-wrap break-words p-4 rounded text-sm overflow-auto max-h-64">
|
||||
{JSON.stringify(item.resource, null, 2)}
|
||||
</pre>
|
||||
)}
|
||||
@@ -88,6 +110,7 @@ const ToolsTab = ({
|
||||
<ListPane
|
||||
items={tools}
|
||||
listItems={listTools}
|
||||
clearItems={clearTools}
|
||||
setSelectedItem={setSelectedTool}
|
||||
renderItem={(tool) => (
|
||||
<>
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -10,4 +10,12 @@ export default defineConfig({
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
minify: false,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
31
package-lock.json
generated
31
package-lock.json
generated
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"name": "@modelcontextprotocol/inspector",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@modelcontextprotocol/inspector",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"client",
|
||||
"server"
|
||||
],
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/inspector-client": "0.2.3",
|
||||
"@modelcontextprotocol/inspector-server": "0.2.3",
|
||||
"@modelcontextprotocol/inspector-client": "0.3.0",
|
||||
"@modelcontextprotocol/inspector-server": "0.3.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"spawn-rx": "^5.0.4",
|
||||
"spawn-rx": "^5.1.0",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"bin": {
|
||||
@@ -29,10 +29,10 @@
|
||||
},
|
||||
"client": {
|
||||
"name": "@modelcontextprotocol/inspector-client",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||
"@modelcontextprotocol/sdk": "^1.0.3",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-select": "^2.1.2",
|
||||
@@ -1203,10 +1203,9 @@
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.0.1.tgz",
|
||||
"integrity": "sha512-slLdFaxQJ9AlRg+hw28iiTtGvShAOgOKXcD0F91nUcRYiOMuS9ZBYjcdNZRXW9G5JQ511GRTdUy1zQVZDpJ+4w==",
|
||||
"license": "MIT",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.0.3.tgz",
|
||||
"integrity": "sha512-2as3cX/VJ0YBHGmdv3GFyTpoM8q2gqE98zh3Vf1NwnsSY0h3mvoO07MUzfygCKkWsFjcZm4otIiqD6Xh7kiSBQ==",
|
||||
"dependencies": {
|
||||
"content-type": "^1.0.5",
|
||||
"raw-body": "^3.0.0",
|
||||
@@ -5737,9 +5736,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/spawn-rx": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-5.0.4.tgz",
|
||||
"integrity": "sha512-Do11ahkHLlqN9G/J6fs10gdx25BU33NrpkyN3/DFXIIUVojBiJysl12nC0iGUkE+msJAPflzyfpLWWHGHw/6Xg==",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/spawn-rx/-/spawn-rx-5.1.0.tgz",
|
||||
"integrity": "sha512-b4HX44hI0usMiHu6LNaZUVg0BGqHuBcl+81iEhZwhvKHz1efTqD/CHBcUbm/uIe5TARy9pJolxU2NMfh6GuQBA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.7",
|
||||
@@ -6926,10 +6925,10 @@
|
||||
},
|
||||
"server": {
|
||||
"name": "@modelcontextprotocol/inspector-server",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||
"@modelcontextprotocol/sdk": "^1.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"eventsource": "^2.0.2",
|
||||
"express": "^4.21.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@modelcontextprotocol/inspector",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"description": "Model Context Protocol inspector",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
@@ -33,10 +33,10 @@
|
||||
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/inspector-client": "0.2.3",
|
||||
"@modelcontextprotocol/inspector-server": "0.2.3",
|
||||
"@modelcontextprotocol/inspector-client": "0.3.0",
|
||||
"@modelcontextprotocol/inspector-server": "0.3.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"spawn-rx": "^5.0.4",
|
||||
"spawn-rx": "^5.1.0",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@modelcontextprotocol/inspector-server",
|
||||
"version": "0.2.3",
|
||||
"version": "0.3.0",
|
||||
"description": "Server-side application for the Model Context Protocol inspector",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
@@ -27,7 +27,7 @@
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.1",
|
||||
"@modelcontextprotocol/sdk": "^1.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"eventsource": "^2.0.2",
|
||||
"express": "^4.21.0",
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
||||
import express from "express";
|
||||
import mcpProxy from "./mcpProxy.js";
|
||||
import { findActualExecutable } from "spawn-rx";
|
||||
|
||||
// Polyfill EventSource for an SSE client in Node.js
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -37,14 +38,17 @@ const createTransport = async (query: express.Request["query"]) => {
|
||||
|
||||
if (transportType === "stdio") {
|
||||
const command = query.command as string;
|
||||
const args = (query.args as string).split(/\s+/);
|
||||
const origArgs = (query.args as string).split(/\s+/);
|
||||
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
||||
|
||||
const { cmd, args } = findActualExecutable(command, origArgs);
|
||||
|
||||
console.log(
|
||||
`Stdio transport: command=${command}, args=${args}, env=${JSON.stringify(env)}`,
|
||||
`Stdio transport: command=${cmd}, args=${args}, env=${JSON.stringify(env)}`,
|
||||
);
|
||||
|
||||
const transport = new StdioClientTransport({
|
||||
command,
|
||||
command: cmd,
|
||||
args,
|
||||
env,
|
||||
stderr: "pipe",
|
||||
|
||||
Reference in New Issue
Block a user