Merge branch 'main' into add_proxy_config

This commit is contained in:
Pulkit Sharma
2025-04-02 13:43:42 +05:30
committed by GitHub
10 changed files with 83 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "@modelcontextprotocol/inspector-client", "name": "@modelcontextprotocol/inspector-client",
"version": "0.7.0", "version": "0.8.0",
"description": "Client-side application for the Model Context Protocol inspector", "description": "Client-side application for the Model Context Protocol inspector",
"license": "MIT", "license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)", "author": "Anthropic, PBC (https://anthropic.com)",

View File

@@ -152,6 +152,7 @@ const App = () => {
handleCompletion, handleCompletion,
completionsSupported, completionsSupported,
connect: connectMcpServer, connect: connectMcpServer,
disconnect: disconnectMcpServer,
} = useConnection({ } = useConnection({
transportType, transportType,
command, command,
@@ -466,6 +467,7 @@ const App = () => {
bearerToken={bearerToken} bearerToken={bearerToken}
setBearerToken={setBearerToken} setBearerToken={setBearerToken}
onConnect={connectMcpServer} onConnect={connectMcpServer}
onDisconnect={disconnectMcpServer}
stdErrNotifications={stdErrNotifications} stdErrNotifications={stdErrNotifications}
logLevel={logLevel} logLevel={logLevel}
sendLogLevelRequest={sendLogLevelRequest} sendLogLevelRequest={sendLogLevelRequest}

View File

@@ -11,6 +11,7 @@ import {
RotateCcw, RotateCcw,
Settings, Settings,
HelpCircle, HelpCircle,
RefreshCwOff,
} from "lucide-react"; } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
@@ -51,6 +52,7 @@ interface SidebarProps {
bearerToken: string; bearerToken: string;
setBearerToken: (token: string) => void; setBearerToken: (token: string) => void;
onConnect: () => void; onConnect: () => void;
onDisconnect: () => void;
stdErrNotifications: StdErrNotification[]; stdErrNotifications: StdErrNotification[];
logLevel: LoggingLevel; logLevel: LoggingLevel;
sendLogLevelRequest: (level: LoggingLevel) => void; sendLogLevelRequest: (level: LoggingLevel) => void;
@@ -74,6 +76,7 @@ const Sidebar = ({
bearerToken, bearerToken,
setBearerToken, setBearerToken,
onConnect, onConnect,
onDisconnect,
stdErrNotifications, stdErrNotifications,
logLevel, logLevel,
sendLogLevelRequest, sendLogLevelRequest,
@@ -393,23 +396,24 @@ const Sidebar = ({
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Button {connectionStatus === "connected" && (
data-testid="connect-button" <div className="grid grid-cols-2 gap-4">
className="w-full" <Button data-testid="connect-button" onClick={onConnect}>
onClick={onConnect}
>
{connectionStatus === "connected" ? (
<>
<RotateCcw className="w-4 h-4 mr-2" /> <RotateCcw className="w-4 h-4 mr-2" />
{transportType === "stdio" ? "Restart" : "Reconnect"} {transportType === "stdio" ? "Restart" : "Reconnect"}
</> </Button>
) : ( <Button onClick={onDisconnect}>
<> <RefreshCwOff className="w-4 h-4 mr-2" />
<Play className="w-4 h-4 mr-2" /> Disconnect
Connect </Button>
</> </div>
)} )}
</Button> {connectionStatus !== "connected" && (
<Button className="w-full" onClick={onConnect}>
<Play className="w-4 h-4 mr-2" />
Connect
</Button>
)}
<div className="flex items-center justify-center space-x-2 mb-4"> <div className="flex items-center justify-center space-x-2 mb-4">
<div <div

View File

@@ -1,4 +1,4 @@
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox"; import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
@@ -13,7 +13,7 @@ import {
ListToolsResult, ListToolsResult,
Tool, Tool,
} from "@modelcontextprotocol/sdk/types.js"; } from "@modelcontextprotocol/sdk/types.js";
import { AlertCircle, Send } from "lucide-react"; import { Send } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ListPane from "./ListPane"; import ListPane from "./ListPane";
import JsonView from "./JsonView"; import JsonView from "./JsonView";
@@ -27,7 +27,6 @@ const ToolsTab = ({
setSelectedTool, setSelectedTool,
toolResult, toolResult,
nextCursor, nextCursor,
error,
}: { }: {
tools: Tool[]; tools: Tool[];
listTools: () => void; listTools: () => void;
@@ -147,13 +146,7 @@ const ToolsTab = ({
</h3> </h3>
</div> </div>
<div className="p-4"> <div className="p-4">
{error ? ( {selectedTool ? (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>{error}</AlertDescription>
</Alert>
) : selectedTool ? (
<div className="space-y-4"> <div className="space-y-4">
<p className="text-sm text-gray-600"> <p className="text-sm text-gray-600">
{selectedTool.description} {selectedTool.description}
@@ -226,7 +219,11 @@ const ToolsTab = ({
</div> </div>
) : ( ) : (
<Input <Input
type={prop.type === "number" ? "number" : "text"} type={
prop.type === "number" || prop.type === "integer"
? "number"
: "text"
}
id={key} id={key}
name={key} name={key}
placeholder={prop.description} placeholder={prop.description}
@@ -235,7 +232,8 @@ const ToolsTab = ({
setParams({ setParams({
...params, ...params,
[key]: [key]:
prop.type === "number" prop.type === "number" ||
prop.type === "integer"
? Number(e.target.value) ? Number(e.target.value)
: e.target.value, : e.target.value,
}) })

View File

@@ -27,6 +27,7 @@ describe("Sidebar Environment Variables", () => {
bearerToken: "", bearerToken: "",
setBearerToken: jest.fn(), setBearerToken: jest.fn(),
onConnect: jest.fn(), onConnect: jest.fn(),
onDisconnect: jest.fn(),
stdErrNotifications: [], stdErrNotifications: [],
logLevel: "info" as const, logLevel: "info" as const,
sendLogLevelRequest: jest.fn(), sendLogLevelRequest: jest.fn(),

View File

@@ -1,5 +1,6 @@
import { render, screen, fireEvent } from "@testing-library/react"; import { render, screen, fireEvent } from "@testing-library/react";
import { describe, it, expect, jest } from "@jest/globals"; import { describe, it, expect, jest } from "@jest/globals";
import "@testing-library/jest-dom";
import ToolsTab from "../ToolsTab"; import ToolsTab from "../ToolsTab";
import { Tool } from "@modelcontextprotocol/sdk/types.js"; import { Tool } from "@modelcontextprotocol/sdk/types.js";
import { Tabs } from "@/components/ui/tabs"; import { Tabs } from "@/components/ui/tabs";
@@ -16,6 +17,16 @@ describe("ToolsTab", () => {
}, },
}, },
}, },
{
name: "tool3",
description: "Integer tool",
inputSchema: {
type: "object" as const,
properties: {
count: { type: "integer" as const },
},
},
},
{ {
name: "tool2", name: "tool2",
description: "Second tool", description: "Second tool",
@@ -61,7 +72,7 @@ describe("ToolsTab", () => {
// Switch to second tool // Switch to second tool
rerender( rerender(
<Tabs defaultValue="tools"> <Tabs defaultValue="tools">
<ToolsTab {...defaultProps} selectedTool={mockTools[1]} /> <ToolsTab {...defaultProps} selectedTool={mockTools[2]} />
</Tabs>, </Tabs>,
); );
@@ -69,4 +80,23 @@ describe("ToolsTab", () => {
const newInput = screen.getByRole("spinbutton") as HTMLInputElement; const newInput = screen.getByRole("spinbutton") as HTMLInputElement;
expect(newInput.value).toBe(""); expect(newInput.value).toBe("");
}); });
it("should handle integer type inputs", () => {
renderToolsTab({
selectedTool: mockTools[1], // Use the tool with integer type
});
const input = screen.getByRole("spinbutton", {
name: /count/i,
}) as HTMLInputElement;
expect(input).toHaveProperty("type", "number");
fireEvent.change(input, { target: { value: "42" } });
expect(input.value).toBe("42");
const submitButton = screen.getByRole("button", { name: /run tool/i });
fireEvent.click(submitButton);
expect(defaultProps.callTool).toHaveBeenCalledWith(mockTools[1].name, {
count: 42,
});
});
}); });

View File

@@ -342,6 +342,14 @@ export function useConnection({
} }
}; };
const disconnect = async () => {
await mcpClient?.close();
setMcpClient(null);
setConnectionStatus("disconnected");
setCompletionsSupported(false);
setServerCapabilities(null);
};
return { return {
connectionStatus, connectionStatus,
serverCapabilities, serverCapabilities,
@@ -352,5 +360,6 @@ export function useConnection({
handleCompletion, handleCompletion,
completionsSupported, completionsSupported,
connect, connect,
disconnect,
}; };
} }

12
package-lock.json generated
View File

@@ -1,20 +1,20 @@
{ {
"name": "@modelcontextprotocol/inspector", "name": "@modelcontextprotocol/inspector",
"version": "0.7.0", "version": "0.8.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@modelcontextprotocol/inspector", "name": "@modelcontextprotocol/inspector",
"version": "0.7.0", "version": "0.8.0",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"client", "client",
"server" "server"
], ],
"dependencies": { "dependencies": {
"@modelcontextprotocol/inspector-client": "^0.7.0", "@modelcontextprotocol/inspector-client": "^0.8.0",
"@modelcontextprotocol/inspector-server": "^0.7.0", "@modelcontextprotocol/inspector-server": "^0.8.0",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"shell-quote": "^1.8.2", "shell-quote": "^1.8.2",
"spawn-rx": "^5.1.2", "spawn-rx": "^5.1.2",
@@ -32,7 +32,7 @@
}, },
"client": { "client": {
"name": "@modelcontextprotocol/inspector-client", "name": "@modelcontextprotocol/inspector-client",
"version": "0.7.0", "version": "0.8.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.6.1", "@modelcontextprotocol/sdk": "^1.6.1",
@@ -11810,7 +11810,7 @@
}, },
"server": { "server": {
"name": "@modelcontextprotocol/inspector-server", "name": "@modelcontextprotocol/inspector-server",
"version": "0.7.0", "version": "0.8.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "^1.6.1", "@modelcontextprotocol/sdk": "^1.6.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@modelcontextprotocol/inspector", "name": "@modelcontextprotocol/inspector",
"version": "0.7.0", "version": "0.8.0",
"description": "Model Context Protocol inspector", "description": "Model Context Protocol inspector",
"license": "MIT", "license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)", "author": "Anthropic, PBC (https://anthropic.com)",
@@ -36,8 +36,8 @@
"publish-all": "npm publish --workspaces --access public && npm publish --access public" "publish-all": "npm publish --workspaces --access public && npm publish --access public"
}, },
"dependencies": { "dependencies": {
"@modelcontextprotocol/inspector-client": "^0.7.0", "@modelcontextprotocol/inspector-client": "^0.8.0",
"@modelcontextprotocol/inspector-server": "^0.7.0", "@modelcontextprotocol/inspector-server": "^0.8.0",
"concurrently": "^9.0.1", "concurrently": "^9.0.1",
"shell-quote": "^1.8.2", "shell-quote": "^1.8.2",
"spawn-rx": "^5.1.2", "spawn-rx": "^5.1.2",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@modelcontextprotocol/inspector-server", "name": "@modelcontextprotocol/inspector-server",
"version": "0.7.0", "version": "0.8.0",
"description": "Server-side application for the Model Context Protocol inspector", "description": "Server-side application for the Model Context Protocol inspector",
"license": "MIT", "license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)", "author": "Anthropic, PBC (https://anthropic.com)",