Skip to content

Commit 0d17082

Browse files
authored
Merge branch 'main' into update-readme
2 parents ec73831 + cdf1f15 commit 0d17082

File tree

14 files changed

+783
-28
lines changed

14 files changed

+783
-28
lines changed

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

bin/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ async function main() {
102102
await Promise.any([server, client, delay(2 * 1000)]);
103103
const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${SERVER_PORT}`;
104104
console.log(
105-
`\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} 🚀`,
106106
);
107107

108108
try {

client/jest.config.cjs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@ module.exports = {
33
testEnvironment: "jsdom",
44
moduleNameMapper: {
55
"^@/(.*)$": "<rootDir>/src/$1",
6-
"^../components/DynamicJsonForm$":
7-
"<rootDir>/src/utils/__mocks__/DynamicJsonForm.ts",
8-
"^../../components/DynamicJsonForm$":
9-
"<rootDir>/src/utils/__mocks__/DynamicJsonForm.ts",
6+
"\\.css$": "<rootDir>/src/__mocks__/styleMock.js",
107
},
118
transform: {
129
"^.+\\.tsx?$": [
1310
"ts-jest",
1411
{
15-
useESM: true,
1612
jsx: "react-jsx",
1713
tsconfig: "tsconfig.jest.json",
1814
},

client/package.json

Lines changed: 5 additions & 3 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)",
@@ -24,8 +24,8 @@
2424
},
2525
"dependencies": {
2626
"@modelcontextprotocol/sdk": "^1.6.1",
27-
"@radix-ui/react-dialog": "^1.1.3",
2827
"@radix-ui/react-checkbox": "^1.1.4",
28+
"@radix-ui/react-dialog": "^1.1.3",
2929
"@radix-ui/react-icons": "^1.3.0",
3030
"@radix-ui/react-label": "^2.1.0",
3131
"@radix-ui/react-popover": "^1.1.3",
@@ -38,7 +38,7 @@
3838
"cmdk": "^1.0.4",
3939
"lucide-react": "^0.447.0",
4040
"pkce-challenge": "^4.1.0",
41-
"prismjs": "^1.29.0",
41+
"prismjs": "^1.30.0",
4242
"react": "^18.3.1",
4343
"react-dom": "^18.3.1",
4444
"react-simple-code-editor": "^0.14.1",
@@ -50,6 +50,8 @@
5050
},
5151
"devDependencies": {
5252
"@eslint/js": "^9.11.1",
53+
"@testing-library/jest-dom": "^6.6.3",
54+
"@testing-library/react": "^16.2.0",
5355
"@types/jest": "^29.5.14",
5456
"@types/node": "^22.7.5",
5557
"@types/react": "^18.3.10",

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 = {};

client/src/components/Sidebar.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,17 @@ const Sidebar = ({
187187
value={key}
188188
onChange={(e) => {
189189
const newKey = e.target.value;
190-
const newEnv = { ...env };
191-
delete newEnv[key];
192-
newEnv[newKey] = value;
190+
const newEnv = Object.entries(env).reduce(
191+
(acc, [k, v]) => {
192+
if (k === key) {
193+
acc[newKey] = value;
194+
} else {
195+
acc[k] = v;
196+
}
197+
return acc;
198+
},
199+
{} as Record<string, string>,
200+
);
193201
setEnv(newEnv);
194202
setShownEnvVars((prev) => {
195203
const next = new Set(prev);

client/src/components/ToolsTab.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ const ToolsTab = ({
233233
id={key}
234234
name={key}
235235
placeholder={prop.description}
236+
value={(params[key] as string) ?? ""}
236237
onChange={(e) =>
237238
setParams({
238239
...params,
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { render, screen, fireEvent } from "@testing-library/react";
2+
import { describe, it, expect, jest } from "@jest/globals";
3+
import DynamicJsonForm from "../DynamicJsonForm";
4+
import type { JsonSchemaType } from "../DynamicJsonForm";
5+
6+
describe("DynamicJsonForm String Fields", () => {
7+
const renderForm = (props = {}) => {
8+
const defaultProps = {
9+
schema: {
10+
type: "string" as const,
11+
description: "Test string field",
12+
} satisfies JsonSchemaType,
13+
value: undefined,
14+
onChange: jest.fn(),
15+
};
16+
return render(<DynamicJsonForm {...defaultProps} {...props} />);
17+
};
18+
19+
describe("Type Validation", () => {
20+
it("should handle numeric input as string type", () => {
21+
const onChange = jest.fn();
22+
renderForm({ onChange });
23+
24+
const input = screen.getByRole("textbox");
25+
fireEvent.change(input, { target: { value: "123321" } });
26+
27+
expect(onChange).toHaveBeenCalledWith("123321");
28+
// Verify the value is a string, not a number
29+
expect(typeof onChange.mock.calls[0][0]).toBe("string");
30+
});
31+
32+
it("should render as text input, not number input", () => {
33+
renderForm();
34+
const input = screen.getByRole("textbox");
35+
expect(input).toHaveProperty("type", "text");
36+
});
37+
});
38+
});
39+
40+
describe("DynamicJsonForm Integer Fields", () => {
41+
const renderForm = (props = {}) => {
42+
const defaultProps = {
43+
schema: {
44+
type: "integer" as const,
45+
description: "Test integer field",
46+
} satisfies JsonSchemaType,
47+
value: undefined,
48+
onChange: jest.fn(),
49+
};
50+
return render(<DynamicJsonForm {...defaultProps} {...props} />);
51+
};
52+
53+
describe("Basic Operations", () => {
54+
it("should render number input with step=1", () => {
55+
renderForm();
56+
const input = screen.getByRole("spinbutton");
57+
expect(input).toHaveProperty("type", "number");
58+
expect(input).toHaveProperty("step", "1");
59+
});
60+
61+
it("should pass integer values to onChange", () => {
62+
const onChange = jest.fn();
63+
renderForm({ onChange });
64+
65+
const input = screen.getByRole("spinbutton");
66+
fireEvent.change(input, { target: { value: "42" } });
67+
68+
expect(onChange).toHaveBeenCalledWith(42);
69+
// Verify the value is a number, not a string
70+
expect(typeof onChange.mock.calls[0][0]).toBe("number");
71+
});
72+
73+
it("should not pass string values to onChange", () => {
74+
const onChange = jest.fn();
75+
renderForm({ onChange });
76+
77+
const input = screen.getByRole("spinbutton");
78+
fireEvent.change(input, { target: { value: "abc" } });
79+
80+
expect(onChange).not.toHaveBeenCalled();
81+
});
82+
});
83+
84+
describe("Edge Cases", () => {
85+
it("should handle non-numeric input by not calling onChange", () => {
86+
const onChange = jest.fn();
87+
renderForm({ onChange });
88+
89+
const input = screen.getByRole("spinbutton");
90+
fireEvent.change(input, { target: { value: "abc" } });
91+
92+
expect(onChange).not.toHaveBeenCalled();
93+
});
94+
});
95+
});

0 commit comments

Comments
 (0)