Skip to content

Commit 8f40e05

Browse files
committed
Merge remote-tracking branch 'origin/main' into devin/1733551277-capability-negotiation
2 parents 024f06c + 2eae823 commit 8f40e05

File tree

5 files changed

+35
-7
lines changed

5 files changed

+35
-7
lines changed

client/src/App.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ const DEFAULT_REQUEST_TIMEOUT_MSEC = 10000;
6262

6363
const params = new URLSearchParams(window.location.search);
6464
const PROXY_PORT = params.get("proxyPort") ?? "3000";
65-
const REQUEST_TIMEOUT = parseInt(params.get("timeout") ?? "") || DEFAULT_REQUEST_TIMEOUT_MSEC;
65+
const REQUEST_TIMEOUT =
66+
parseInt(params.get("timeout") ?? "") || DEFAULT_REQUEST_TIMEOUT_MSEC;
6667
const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
6768

6869
const App = () => {
@@ -221,6 +222,12 @@ const App = () => {
221222
rootsRef.current = roots;
222223
}, [roots]);
223224

225+
useEffect(() => {
226+
if (!window.location.hash) {
227+
window.location.hash = "resources";
228+
}
229+
}, []);
230+
224231
const pushHistory = (request: object, response?: object) => {
225232
setRequestHistory((prev) => [
226233
...prev,
@@ -255,10 +262,14 @@ const App = () => {
255262
response = await mcpClient.request(request, schema, {
256263
signal: abortController.signal,
257264
});
265+
pushHistory(request, response);
266+
} catch (error) {
267+
const errorMessage = error instanceof Error ? error.message : String(error);
268+
pushHistory(request, { error: errorMessage });
269+
throw error;
258270
} finally {
259271
clearTimeout(timeoutId);
260272
}
261-
pushHistory(request, response);
262273

263274
if (tabKey !== undefined) {
264275
clearError(tabKey);
@@ -494,12 +505,14 @@ const App = () => {
494505
{mcpClient ? (
495506
<Tabs
496507
defaultValue={
508+
window.location.hash.slice(1) ||
497509
serverCapabilities?.resources ? "resources" :
498510
serverCapabilities?.prompts ? "prompts" :
499511
serverCapabilities?.tools ? "tools" :
500512
"ping"
501513
}
502514
className="w-full p-4"
515+
onValueChange={(value) => (window.location.hash = value)}
503516
>
504517
<TabsList className="mb-4 p-0">
505518
<TabsTrigger value="resources" disabled={!serverCapabilities?.resources}>

client/src/components/ToolsTab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ const ToolsTab = ({
100100
return (
101101
<>
102102
<h4 className="font-semibold mb-2">Tool Result (Legacy):</h4>
103-
<pre className="bg-gray-50 p-4 rounded text-sm overflow-auto max-h-64">
103+
<pre className="bg-gray-50 dark:bg-gray-800 dark:text-gray-100 p-4 rounded text-sm overflow-auto max-h-64">
104104
{JSON.stringify(toolResult.toolResult, null, 2)}
105105
</pre>
106106
</>

package-lock.json

Lines changed: 15 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
"@modelcontextprotocol/inspector-client": "0.3.0",
3737
"@modelcontextprotocol/inspector-server": "0.3.0",
3838
"concurrently": "^9.0.1",
39+
"shell-quote": "^1.8.2",
3940
"spawn-rx": "^5.1.0",
4041
"ts-node": "^10.9.2"
4142
},
4243
"devDependencies": {
4344
"@types/node": "^22.7.5",
45+
"@types/shell-quote": "^1.7.5",
4446
"prettier": "3.3.3"
4547
}
4648
}

server/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import cors from "cors";
44
import EventSource from "eventsource";
55
import { parseArgs } from "node:util";
6+
import { parse as shellParseArgs } from "shell-quote";
67

78
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
89
import {
@@ -38,7 +39,7 @@ const createTransport = async (query: express.Request["query"]) => {
3839

3940
if (transportType === "stdio") {
4041
const command = query.command as string;
41-
const origArgs = (query.args as string).split(/\s+/);
42+
const origArgs = shellParseArgs(query.args as string) as string[];
4243
const env = query.env ? JSON.parse(query.env as string) : undefined;
4344

4445
const { cmd, args } = findActualExecutable(command, origArgs);

0 commit comments

Comments
 (0)