Merge branch 'main' into main

This commit is contained in:
Cliff Hall 2025-05-21 16:27:13 -04:00 • committed by GitHub
commit efa4959ec4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 111 additions and 52 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-cli",
"version": "0.12.0",
"version": "0.13.0",
"description": "CLI for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
@ -21,7 +21,7 @@
},
"devDependencies": {},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"commander": "^13.1.0",
"spawn-rx": "^5.1.2"
}

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-client",
"version": "0.12.0",
"version": "0.13.0",
"description": "Client-side application for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
@ -23,7 +23,7 @@
"test:watch": "jest --config jest.config.cjs --watch"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-icons": "^1.3.0",

View file

@ -234,7 +234,6 @@ const App = () => {
const onOAuthConnect = useCallback(
(serverUrl: string) => {
setSseUrl(serverUrl);
setTransportType("sse");
setIsAuthDebuggerVisible(false);
void connectMcpServer();
},

View file

@ -127,14 +127,14 @@ const Sidebar = ({
return {
type: "sse",
url: sseUrl,
note: "For SSE connections, add this URL directly in Client",
note: "For SSE connections, add this URL directly in your MCP Client",
};
}
if (transportType === "streamable-http") {
return {
type: "streamable-http",
url: sseUrl,
note: "For Streamable HTTP connections, add this URL directly in Client",
note: "For Streamable HTTP connections, add this URL directly in your MCP Client",
};
}
return {};
@ -172,7 +172,7 @@ const Sidebar = ({
description:
transportType === "stdio"
? "Server configuration has been copied to clipboard. Add this to your mcp.json inside the 'mcpServers' object with your preferred server name."
: "SSE URL has been copied. Use this URL in Cursor directly.",
: "SSE URL has been copied. Use this URL directly in your MCP Client.",
});
setTimeout(() => {

View file

@ -755,7 +755,7 @@ describe("Sidebar Environment Variables", () => {
{
type: "sse",
url: sseUrl,
note: "For SSE connections, add this URL directly in Client",
note: "For SSE connections, add this URL directly in your MCP Client",
},
null,
4,
@ -780,7 +780,7 @@ describe("Sidebar Environment Variables", () => {
"default-server": {
type: "sse",
url: sseUrl,
note: "For SSE connections, add this URL directly in Client",
note: "For SSE connections, add this URL directly in your MCP Client",
},
},
},
@ -805,7 +805,7 @@ describe("Sidebar Environment Variables", () => {
{
type: "streamable-http",
url: sseUrl,
note: "For Streamable HTTP connections, add this URL directly in Client",
note: "For Streamable HTTP connections, add this URL directly in your MCP Client",
},
null,
4,
@ -830,7 +830,7 @@ describe("Sidebar Environment Variables", () => {
"default-server": {
type: "streamable-http",
url: sseUrl,
note: "For Streamable HTTP connections, add this URL directly in Client",
note: "For Streamable HTTP connections, add this URL directly in your MCP Client",
},
},
},

View file

@ -249,9 +249,16 @@ export function useConnection({
}
};
const is401Error = (error: unknown): boolean => {
return (
(error instanceof SseError && error.code === 401) ||
(error instanceof Error && error.message.includes("401")) ||
(error instanceof Error && error.message.includes("Unauthorized"))
);
};
const handleAuthError = async (error: unknown) => {
if (error instanceof SseError && error.code === 401) {
// Create a new auth provider with the current server URL
if (is401Error(error)) {
const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
const result = await auth(serverAuthProvider, { serverUrl: sseUrl });
@ -330,7 +337,6 @@ export function useConnection({
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
mcpProxyServerUrl.searchParams.append("url", sseUrl);
transportOptions = {
authProvider: serverAuthProvider,
eventSourceInit: {
fetch: (
url: string | URL | globalThis.Request,
@ -347,7 +353,6 @@ export function useConnection({
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
mcpProxyServerUrl.searchParams.append("url", sseUrl);
transportOptions = {
authProvider: serverAuthProvider,
eventSourceInit: {
fetch: (
url: string | URL | globalThis.Request,
@ -425,13 +430,14 @@ export function useConnection({
`Failed to connect to MCP Server via the MCP Inspector Proxy: ${mcpProxyServerUrl}:`,
error,
);
const shouldRetry = await handleAuthError(error);
if (shouldRetry) {
return connect(undefined, retryCount + 1);
}
if (error instanceof SseError && error.code === 401) {
if (is401Error(error)) {
// Don't set error state if we're about to redirect for auth
return;
}
throw error;

91
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "@modelcontextprotocol/inspector",
"version": "0.12.0",
"version": "0.13.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@modelcontextprotocol/inspector",
"version": "0.12.0",
"version": "0.13.0",
"license": "MIT",
"workspaces": [
"client",
@ -14,10 +14,10 @@
"cli"
],
"dependencies": {
"@modelcontextprotocol/inspector-cli": "^0.12.0",
"@modelcontextprotocol/inspector-client": "^0.12.0",
"@modelcontextprotocol/inspector-server": "^0.12.0",
"@modelcontextprotocol/sdk": "^1.11.2",
"@modelcontextprotocol/inspector-cli": "^0.13.0",
"@modelcontextprotocol/inspector-client": "^0.13.0",
"@modelcontextprotocol/inspector-server": "^0.13.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"concurrently": "^9.0.1",
"open": "^10.1.0",
"shell-quote": "^1.8.2",
@ -40,10 +40,10 @@
},
"cli": {
"name": "@modelcontextprotocol/inspector-cli",
"version": "0.12.0",
"version": "0.13.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"commander": "^13.1.0",
"spawn-rx": "^5.1.2"
},
@ -63,10 +63,10 @@
},
"client": {
"name": "@modelcontextprotocol/inspector-client",
"version": "0.12.0",
"version": "0.13.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-dialog": "^1.1.3",
"@radix-ui/react-icons": "^1.3.0",
@ -2004,13 +2004,15 @@
"link": true
},
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.11.2",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz",
"integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==",
"version": "1.11.5",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.5.tgz",
"integrity": "sha512-gS7Q7IHpKxjVaNLMUZyTtatZ63ca3h418zPPntAhu/MvG5yfz/8HMcDAOpvpQfx3V3dsw9QQxk8RuFNrQhLlgA==",
"license": "MIT",
"dependencies": {
"ajv": "^8.17.1",
"content-type": "^1.0.5",
"cors": "^2.8.5",
"cross-spawn": "^7.0.3",
"cross-spawn": "^7.0.5",
"eventsource": "^3.0.2",
"express": "^5.0.1",
"express-rate-limit": "^7.5.0",
@ -2023,6 +2025,28 @@
"node": ">=18"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -5652,7 +5676,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true,
"license": "MIT"
},
"node_modules/fast-glob": {
@ -5697,6 +5720,22 @@
"dev": true,
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
@ -8407,15 +8446,6 @@
"node": "20 || >=22"
}
},
"node_modules/path-to-regexp": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
"license": "MIT",
"engines": {
"node": ">=16"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@ -9037,6 +9067,15 @@
"node": ">=0.10.0"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@ -10933,10 +10972,10 @@
},
"server": {
"name": "@modelcontextprotocol/inspector-server",
"version": "0.12.0",
"version": "0.13.0",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"cors": "^2.8.5",
"express": "^5.1.0",
"ws": "^8.18.0",

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector",
"version": "0.12.0",
"version": "0.13.0",
"description": "Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
@ -40,10 +40,10 @@
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
},
"dependencies": {
"@modelcontextprotocol/inspector-cli": "^0.12.0",
"@modelcontextprotocol/inspector-client": "^0.12.0",
"@modelcontextprotocol/inspector-server": "^0.12.0",
"@modelcontextprotocol/sdk": "^1.11.2",
"@modelcontextprotocol/inspector-cli": "^0.13.0",
"@modelcontextprotocol/inspector-client": "^0.13.0",
"@modelcontextprotocol/inspector-server": "^0.13.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"concurrently": "^9.0.1",
"open": "^10.1.0",
"shell-quote": "^1.8.2",

View file

@ -1,6 +1,6 @@
{
"name": "@modelcontextprotocol/inspector-server",
"version": "0.12.0",
"version": "0.13.0",
"description": "Server-side application for the Model Context Protocol inspector",
"license": "MIT",
"author": "Anthropic, PBC (https://anthropic.com)",
@ -27,7 +27,7 @@
"typescript": "^5.6.2"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.11.0",
"@modelcontextprotocol/sdk": "^1.11.5",
"cors": "^2.8.5",
"express": "^5.1.0",
"ws": "^8.18.0",

View file

@ -1,4 +1,5 @@
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
import { isJSONRPCRequest } from "@modelcontextprotocol/sdk/types.js";
function onClientError(error: Error) {
console.error("Error from inspector client:", error);
@ -19,7 +20,21 @@ export default function mcpProxy({
let transportToServerClosed = false;
transportToClient.onmessage = (message) => {
transportToServer.send(message).catch(onServerError);
transportToServer.send(message).catch((error) => {
// Send error response back to client if it was a request (has id) and connection is still open
if (isJSONRPCRequest(message) && !transportToClientClosed) {
const errorResponse = {
jsonrpc: "2.0" as const,
id: message.id,
error: {
code: -32001,
message: error.message,
data: error,
},
};
transportToClient.send(errorResponse).catch(onClientError);
}
});
};
transportToServer.onmessage = (message) => {