Skip to content

Commit 827d867

Browse files
authored
Merge branch 'main' into patch-1
2 parents ce81fb9 + 4d4bb91 commit 827d867

28 files changed

+5110
-328
lines changed

.github/workflows/main.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ jobs:
2525
# Working around https://github.com/npm/cli/issues/4828
2626
# - run: npm ci
2727
- run: npm install --no-package-lock
28+
29+
- name: Run client tests
30+
working-directory: ./client
31+
run: npm test
32+
2833
- run: npm run build
2934

3035
publish:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ server/build
44
client/dist
55
client/tsconfig.app.tsbuildinfo
66
client/tsconfig.node.tsbuildinfo
7+
.vscode

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Thanks for your interest in contributing! This guide explains how to get involve
77
1. Fork the repository and clone it locally
88
2. Install dependencies with `npm install`
99
3. Run `npm run dev` to start both client and server in development mode
10-
4. Use the web UI at http://localhost:5173 to interact with the inspector
10+
4. Use the web UI at http://127.0.0.1:5173 to interact with the inspector
1111

1212
## Development Process & Pull Requests
1313

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ For more details on ways to use the inspector, see the [Inspector section of the
4242

4343
The inspector supports bearer token authentication for SSE connections. Enter your token in the UI when connecting to an MCP server, and it will be sent in the Authorization header.
4444

45+
### Security Considerations
46+
47+
The MCP Inspector includes a proxy server that can run and communicate with local MCP processes. The proxy server should not be exposed to untrusted networks as it has permissions to spawn local processes and can connect to any specified MCP server.
48+
4549
### From this repository
4650

4751
If you're working on the inspector itself:

bin/cli.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,15 @@ async function main() {
2727
}
2828

2929
if (parsingFlags && arg === "-e" && i + 1 < args.length) {
30-
const [key, value] = args[++i].split("=");
31-
if (key && value) {
30+
const envVar = args[++i];
31+
const equalsIndex = envVar.indexOf("=");
32+
33+
if (equalsIndex !== -1) {
34+
const key = envVar.substring(0, equalsIndex);
35+
const value = envVar.substring(equalsIndex + 1);
3236
envVars[key] = value;
37+
} else {
38+
envVars[envVar] = "";
3339
}
3440
} else if (!command) {
3541
command = arg;
@@ -96,7 +102,7 @@ async function main() {
96102
await Promise.any([server, client, delay(2 * 1000)]);
97103
const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${SERVER_PORT}`;
98104
console.log(
99-
`\n🔍 MCP Inspector is up and running at http://localhost:${CLIENT_PORT}${portParam} 🚀`,
105+
`\n🔍 MCP Inspector is up and running at http://127.0.0.1:${CLIENT_PORT}${portParam} 🚀`,
100106
);
101107

102108
try {

client/jest.config.cjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module.exports = {
2+
preset: "ts-jest",
3+
testEnvironment: "jsdom",
4+
moduleNameMapper: {
5+
"^@/(.*)$": "<rootDir>/src/$1",
6+
"\\.css$": "<rootDir>/src/__mocks__/styleMock.js",
7+
},
8+
transform: {
9+
"^.+\\.tsx?$": [
10+
"ts-jest",
11+
{
12+
jsx: "react-jsx",
13+
tsconfig: "tsconfig.jest.json",
14+
},
15+
],
16+
},
17+
extensionsToTreatAsEsm: [".ts", ".tsx"],
18+
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
19+
// Exclude directories and files that don't need to be tested
20+
testPathIgnorePatterns: [
21+
"/node_modules/",
22+
"/dist/",
23+
"/bin/",
24+
"\\.config\\.(js|ts|cjs|mjs)$",
25+
],
26+
// Exclude the same patterns from coverage reports
27+
coveragePathIgnorePatterns: [
28+
"/node_modules/",
29+
"/dist/",
30+
"/bin/",
31+
"\\.config\\.(js|ts|cjs|mjs)$",
32+
],
33+
};

client/package.json

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@modelcontextprotocol/inspector-client",
3-
"version": "0.6.0",
3+
"version": "0.7.0",
44
"description": "Client-side application for the Model Context Protocol inspector",
55
"license": "MIT",
66
"author": "Anthropic, PBC (https://anthropic.com)",
@@ -18,12 +18,14 @@
1818
"dev": "vite",
1919
"build": "tsc -b && vite build",
2020
"lint": "eslint .",
21-
"preview": "vite preview"
21+
"preview": "vite preview",
22+
"test": "jest --config jest.config.cjs",
23+
"test:watch": "jest --config jest.config.cjs --watch"
2224
},
2325
"dependencies": {
2426
"@modelcontextprotocol/sdk": "^1.6.1",
25-
"@radix-ui/react-dialog": "^1.1.3",
2627
"@radix-ui/react-checkbox": "^1.1.4",
28+
"@radix-ui/react-dialog": "^1.1.3",
2729
"@radix-ui/react-icons": "^1.3.0",
2830
"@radix-ui/react-label": "^2.1.0",
2931
"@radix-ui/react-popover": "^1.1.3",
@@ -35,8 +37,8 @@
3537
"clsx": "^2.1.1",
3638
"cmdk": "^1.0.4",
3739
"lucide-react": "^0.447.0",
38-
"prismjs": "^1.29.0",
3940
"pkce-challenge": "^4.1.0",
41+
"prismjs": "^1.30.0",
4042
"react": "^18.3.1",
4143
"react-dom": "^18.3.1",
4244
"react-simple-code-editor": "^0.14.1",
@@ -48,18 +50,25 @@
4850
},
4951
"devDependencies": {
5052
"@eslint/js": "^9.11.1",
53+
"@testing-library/jest-dom": "^6.6.3",
54+
"@testing-library/react": "^16.2.0",
55+
"@types/jest": "^29.5.14",
5156
"@types/node": "^22.7.5",
5257
"@types/react": "^18.3.10",
5358
"@types/react-dom": "^18.3.0",
5459
"@types/serve-handler": "^6.1.4",
5560
"@vitejs/plugin-react": "^4.3.2",
5661
"autoprefixer": "^10.4.20",
62+
"co": "^4.6.0",
5763
"eslint": "^9.11.1",
5864
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
5965
"eslint-plugin-react-refresh": "^0.4.12",
6066
"globals": "^15.9.0",
67+
"jest": "^29.7.0",
68+
"jest-environment-jsdom": "^29.7.0",
6169
"postcss": "^8.4.47",
6270
"tailwindcss": "^3.4.13",
71+
"ts-jest": "^29.2.6",
6372
"typescript": "^5.5.3",
6473
"typescript-eslint": "^8.7.0",
6574
"vite": "^5.4.8"

client/src/App.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
Root,
1616
ServerNotification,
1717
Tool,
18+
LoggingLevel,
1819
} from "@modelcontextprotocol/sdk/types.js";
1920
import React, { Suspense, useEffect, useRef, useState } from "react";
2021
import { useConnection } from "./lib/hooks/useConnection";
@@ -47,7 +48,7 @@ import ToolsTab from "./components/ToolsTab";
4748

4849
const params = new URLSearchParams(window.location.search);
4950
const PROXY_PORT = params.get("proxyPort") ?? "3000";
50-
const PROXY_SERVER_URL = `http://localhost:${PROXY_PORT}`;
51+
const PROXY_SERVER_URL = `http://${window.location.hostname}:${PROXY_PORT}`;
5152

5253
const App = () => {
5354
// Handle OAuth callback route
@@ -91,6 +92,7 @@ const App = () => {
9192
(localStorage.getItem("lastTransportType") as "stdio" | "sse") || "stdio"
9293
);
9394
});
95+
const [logLevel, setLogLevel] = useState<LoggingLevel>("debug");
9496
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
9597
const [stdErrNotifications, setStdErrNotifications] = useState<
9698
StdErrNotification[]
@@ -412,6 +414,17 @@ const App = () => {
412414
await sendNotification({ method: "notifications/roots/list_changed" });
413415
};
414416

417+
const sendLogLevelRequest = async (level: LoggingLevel) => {
418+
await makeRequest(
419+
{
420+
method: "logging/setLevel" as const,
421+
params: { level },
422+
},
423+
z.object({}),
424+
);
425+
setLogLevel(level);
426+
};
427+
415428
return (
416429
<div className="flex h-screen bg-background">
417430
<Sidebar
@@ -430,6 +443,9 @@ const App = () => {
430443
setBearerToken={setBearerToken}
431444
onConnect={connectMcpServer}
432445
stdErrNotifications={stdErrNotifications}
446+
logLevel={logLevel}
447+
sendLogLevelRequest={sendLogLevelRequest}
448+
loggingSupported={!!serverCapabilities?.logging || false}
433449
/>
434450
<div className="flex-1 flex flex-col overflow-hidden">
435451
<div className="flex-1 overflow-auto">

client/src/__mocks__/styleMock.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

0 commit comments

Comments
 (0)