Merge remote-tracking branch 'origin/main' into devin/1733551277-capability-negotiation
This commit is contained in:
@@ -62,7 +62,8 @@ const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000;
|
|||||||
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const PROXY_PORT = params.get("proxyPort") ?? "3000";
|
const PROXY_PORT = params.get("proxyPort") ?? "3000";
|
||||||
const REQUEST_TIMEOUT = parseInt(params.get("timeout") ?? "") || DEFAULT_REQUEST_TIMEOUT_MSEC;
|
const REQUEST_TIMEOUT =
|
||||||
|
parseInt(params.get("timeout") ?? "") || DEFAULT_REQUEST_TIMEOUT_MSEC;
|
||||||
const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
|
const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@@ -221,6 +222,12 @@ const App = () => {
|
|||||||
rootsRef.current = roots;
|
rootsRef.current = roots;
|
||||||
}, [roots]);
|
}, [roots]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!window.location.hash) {
|
||||||
|
window.location.hash = "resources";
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const pushHistory = (request: object, response?: object) => {
|
const pushHistory = (request: object, response?: object) => {
|
||||||
setRequestHistory((prev) => [
|
setRequestHistory((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
@@ -255,10 +262,14 @@ const App = () => {
|
|||||||
response = await mcpClient.request(request, schema, {
|
response = await mcpClient.request(request, schema, {
|
||||||
signal: abortController.signal,
|
signal: abortController.signal,
|
||||||
});
|
});
|
||||||
|
pushHistory(request, response);
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||||
|
pushHistory(request, { error: errorMessage });
|
||||||
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
}
|
}
|
||||||
pushHistory(request, response);
|
|
||||||
|
|
||||||
if (tabKey !== undefined) {
|
if (tabKey !== undefined) {
|
||||||
clearError(tabKey);
|
clearError(tabKey);
|
||||||
@@ -494,12 +505,14 @@ const App = () => {
|
|||||||
{mcpClient ? (
|
{mcpClient ? (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue={
|
defaultValue={
|
||||||
|
window.location.hash.slice(1) ||
|
||||||
serverCapabilities?.resources ? "resources" :
|
serverCapabilities?.resources ? "resources" :
|
||||||
serverCapabilities?.prompts ? "prompts" :
|
serverCapabilities?.prompts ? "prompts" :
|
||||||
serverCapabilities?.tools ? "tools" :
|
serverCapabilities?.tools ? "tools" :
|
||||||
"ping"
|
"ping"
|
||||||
}
|
}
|
||||||
className="w-full p-4"
|
className="w-full p-4"
|
||||||
|
onValueChange={(value) => (window.location.hash = value)}
|
||||||
>
|
>
|
||||||
<TabsList className="mb-4 p-0">
|
<TabsList className="mb-4 p-0">
|
||||||
<TabsTrigger value="resources" disabled={!serverCapabilities?.resources}>
|
<TabsTrigger value="resources" disabled={!serverCapabilities?.resources}>
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ const ToolsTab = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h4 className="font-semibold mb-2">Tool Result (Legacy):</h4>
|
<h4 className="font-semibold mb-2">Tool Result (Legacy):</h4>
|
||||||
<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 p-4 rounded text-sm overflow-auto max-h-64">
|
||||||
{JSON.stringify(toolResult.toolResult, null, 2)}
|
{JSON.stringify(toolResult.toolResult, null, 2)}
|
||||||
</pre>
|
</pre>
|
||||||
</>
|
</>
|
||||||
|
|||||||
18
package-lock.json
generated
18
package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"@modelcontextprotocol/inspector-client": "0.3.0",
|
"@modelcontextprotocol/inspector-client": "0.3.0",
|
||||||
"@modelcontextprotocol/inspector-server": "0.3.0",
|
"@modelcontextprotocol/inspector-server": "0.3.0",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
|
"shell-quote": "^1.8.2",
|
||||||
"spawn-rx": "^5.1.0",
|
"spawn-rx": "^5.1.0",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
},
|
},
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.7.5",
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
"prettier": "3.3.3"
|
"prettier": "3.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2393,6 +2395,13 @@
|
|||||||
"@types/send": "*"
|
"@types/send": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/shell-quote": {
|
||||||
|
"version": "1.7.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/shell-quote/-/shell-quote-1.7.5.tgz",
|
||||||
|
"integrity": "sha512-+UE8GAGRPbJVQDdxi16dgadcBfQ+KG2vgZhV1+3A1XmHbmwcdwhCUwIdy+d3pAGrbvgRoVSjeI9vOWyq376Yzw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.13",
|
"version": "8.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||||
@@ -5688,10 +5697,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shell-quote": {
|
"node_modules/shell-quote": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
|
||||||
"integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
|
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,13 @@
|
|||||||
"@modelcontextprotocol/inspector-client": "0.3.0",
|
"@modelcontextprotocol/inspector-client": "0.3.0",
|
||||||
"@modelcontextprotocol/inspector-server": "0.3.0",
|
"@modelcontextprotocol/inspector-server": "0.3.0",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
|
"shell-quote": "^1.8.2",
|
||||||
"spawn-rx": "^5.1.0",
|
"spawn-rx": "^5.1.0",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.7.5",
|
||||||
|
"@types/shell-quote": "^1.7.5",
|
||||||
"prettier": "3.3.3"
|
"prettier": "3.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import EventSource from "eventsource";
|
import EventSource from "eventsource";
|
||||||
import { parseArgs } from "node:util";
|
import { parseArgs } from "node:util";
|
||||||
|
import { parse as shellParseArgs } from "shell-quote";
|
||||||
|
|
||||||
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
||||||
import {
|
import {
|
||||||
@@ -38,7 +39,7 @@ const createTransport = async (query: express.Request["query"]) => {
|
|||||||
|
|
||||||
if (transportType === "stdio") {
|
if (transportType === "stdio") {
|
||||||
const command = query.command as string;
|
const command = query.command as string;
|
||||||
const origArgs = (query.args as string).split(/\s+/);
|
const origArgs = shellParseArgs(query.args as string) as string[];
|
||||||
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
const env = query.env ? JSON.parse(query.env as string) : undefined;
|
||||||
|
|
||||||
const { cmd, args } = findActualExecutable(command, origArgs);
|
const { cmd, args } = findActualExecutable(command, origArgs);
|
||||||
|
|||||||
Reference in New Issue
Block a user