Merge branch 'main' of https://github.com/modelcontextprotocol/inspector
This commit is contained in:
30
README.md
30
README.md
@@ -122,12 +122,13 @@ The MCP Inspector includes a proxy server that can run and communicate with loca
|
|||||||
|
|
||||||
The MCP Inspector supports the following configuration settings. To change them, click on the `Configuration` button in the MCP Inspector UI:
|
The MCP Inspector supports the following configuration settings. To change them, click on the `Configuration` button in the MCP Inspector UI:
|
||||||
|
|
||||||
| Setting | Description | Default |
|
| Setting | Description | Default |
|
||||||
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------- |
|
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------- |
|
||||||
| `MCP_SERVER_REQUEST_TIMEOUT` | Timeout for requests to the MCP server (ms) | 10000 |
|
| `MCP_SERVER_REQUEST_TIMEOUT` | Timeout for requests to the MCP server (ms) | 10000 |
|
||||||
| `MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS` | Reset timeout on progress notifications | true |
|
| `MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS` | Reset timeout on progress notifications | true |
|
||||||
| `MCP_REQUEST_MAX_TOTAL_TIMEOUT` | Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications) | 60000 |
|
| `MCP_REQUEST_MAX_TOTAL_TIMEOUT` | Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications) | 60000 |
|
||||||
| `MCP_PROXY_FULL_ADDRESS` | Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577 | "" |
|
| `MCP_PROXY_FULL_ADDRESS` | Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577 | "" |
|
||||||
|
| `MCP_AUTO_OPEN_ENABLED` | Enable automatic browser opening when inspector starts. Only as environment var, not configurable in browser. | true |
|
||||||
|
|
||||||
These settings can be adjusted in real-time through the UI and will persist across sessions.
|
These settings can be adjusted in real-time through the UI and will persist across sessions.
|
||||||
|
|
||||||
@@ -160,9 +161,24 @@ Example server configuration file:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Tip:** You can easily generate this configuration format using the **Server Entry** and **Servers File** buttons in the Inspector UI, as described in the Servers File Export section above.
|
> **Tip:** You can easily generate this configuration format using the **Server Entry** and **Servers File** buttons in the Inspector UI, as described in the Servers File Export section above.
|
||||||
|
|
||||||
|
You can also set the initial `transport` type, `serverUrl`, `serverCommand`, and `serverArgs` via query params, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:6274/?transport=sse&serverUrl=http://localhost:8787/sse
|
||||||
|
http://localhost:6274/?transport=streamable-http&serverUrl=http://localhost:8787/mcp
|
||||||
|
http://localhost:6274/?transport=stdio&serverCommand=npx&serverArgs=arg1%20arg2
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also set initial config settings via query params, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:6274/?MCP_SERVER_REQUEST_TIMEOUT=10000&MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS=false&MCP_PROXY_FULL_ADDRESS=http://10.1.1.22:5577
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that if both the query param and the corresponding localStorage item are set, the query param will take precedence.
|
||||||
|
|
||||||
### From this repository
|
### From this repository
|
||||||
|
|
||||||
If you're working on the inspector itself:
|
If you're working on the inspector itself:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@modelcontextprotocol/inspector-cli",
|
"name": "@modelcontextprotocol/inspector-cli",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"description": "CLI for the Model Context Protocol inspector",
|
"description": "CLI for the Model Context Protocol inspector",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import open from "open";
|
||||||
import { resolve, dirname } from "path";
|
import { resolve, dirname } from "path";
|
||||||
import { spawnPromise } from "spawn-rx";
|
import { spawnPromise } from "spawn-rx";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
@@ -99,6 +100,9 @@ async function main() {
|
|||||||
|
|
||||||
if (serverOk) {
|
if (serverOk) {
|
||||||
try {
|
try {
|
||||||
|
if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
|
||||||
|
open(`http://127.0.0.1:${CLIENT_PORT}`);
|
||||||
|
}
|
||||||
await spawnPromise("node", [inspectorClientPath], {
|
await spawnPromise("node", [inspectorClientPath], {
|
||||||
env: { ...process.env, PORT: CLIENT_PORT },
|
env: { ...process.env, PORT: CLIENT_PORT },
|
||||||
signal: abort.signal,
|
signal: abort.signal,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@modelcontextprotocol/inspector-client",
|
"name": "@modelcontextprotocol/inspector-client",
|
||||||
"version": "0.11.0",
|
"version": "0.12.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)",
|
||||||
|
|||||||
@@ -49,9 +49,15 @@ import RootsTab from "./components/RootsTab";
|
|||||||
import SamplingTab, { PendingRequest } from "./components/SamplingTab";
|
import SamplingTab, { PendingRequest } from "./components/SamplingTab";
|
||||||
import Sidebar from "./components/Sidebar";
|
import Sidebar from "./components/Sidebar";
|
||||||
import ToolsTab from "./components/ToolsTab";
|
import ToolsTab from "./components/ToolsTab";
|
||||||
import { DEFAULT_INSPECTOR_CONFIG } from "./lib/constants";
|
|
||||||
import { InspectorConfig } from "./lib/configurationTypes";
|
import { InspectorConfig } from "./lib/configurationTypes";
|
||||||
import { getMCPProxyAddress } from "./utils/configUtils";
|
import {
|
||||||
|
getMCPProxyAddress,
|
||||||
|
getInitialSseUrl,
|
||||||
|
getInitialTransportType,
|
||||||
|
getInitialCommand,
|
||||||
|
getInitialArgs,
|
||||||
|
initializeInspectorConfig,
|
||||||
|
} from "./utils/configUtils";
|
||||||
|
|
||||||
const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
|
const CONFIG_LOCAL_STORAGE_KEY = "inspectorConfig_v1";
|
||||||
|
|
||||||
@@ -71,26 +77,13 @@ const App = () => {
|
|||||||
prompts: null,
|
prompts: null,
|
||||||
tools: null,
|
tools: null,
|
||||||
});
|
});
|
||||||
const [command, setCommand] = useState<string>(() => {
|
const [command, setCommand] = useState<string>(getInitialCommand);
|
||||||
return localStorage.getItem("lastCommand") || "mcp-server-everything";
|
const [args, setArgs] = useState<string>(getInitialArgs);
|
||||||
});
|
|
||||||
const [args, setArgs] = useState<string>(() => {
|
|
||||||
return localStorage.getItem("lastArgs") || "";
|
|
||||||
});
|
|
||||||
|
|
||||||
const [sseUrl, setSseUrl] = useState<string>(() => {
|
const [sseUrl, setSseUrl] = useState<string>(getInitialSseUrl);
|
||||||
return localStorage.getItem("lastSseUrl") || "http://localhost:3001/sse";
|
|
||||||
});
|
|
||||||
const [transportType, setTransportType] = useState<
|
const [transportType, setTransportType] = useState<
|
||||||
"stdio" | "sse" | "streamable-http"
|
"stdio" | "sse" | "streamable-http"
|
||||||
>(() => {
|
>(getInitialTransportType);
|
||||||
return (
|
|
||||||
(localStorage.getItem("lastTransportType") as
|
|
||||||
| "stdio"
|
|
||||||
| "sse"
|
|
||||||
| "streamable-http") || "stdio"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
const [logLevel, setLogLevel] = useState<LoggingLevel>("debug");
|
const [logLevel, setLogLevel] = useState<LoggingLevel>("debug");
|
||||||
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
|
const [notifications, setNotifications] = useState<ServerNotification[]>([]);
|
||||||
const [stdErrNotifications, setStdErrNotifications] = useState<
|
const [stdErrNotifications, setStdErrNotifications] = useState<
|
||||||
@@ -99,27 +92,9 @@ const App = () => {
|
|||||||
const [roots, setRoots] = useState<Root[]>([]);
|
const [roots, setRoots] = useState<Root[]>([]);
|
||||||
const [env, setEnv] = useState<Record<string, string>>({});
|
const [env, setEnv] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
const [config, setConfig] = useState<InspectorConfig>(() => {
|
const [config, setConfig] = useState<InspectorConfig>(() =>
|
||||||
const savedConfig = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY);
|
initializeInspectorConfig(CONFIG_LOCAL_STORAGE_KEY),
|
||||||
if (savedConfig) {
|
);
|
||||||
// merge default config with saved config
|
|
||||||
const mergedConfig = {
|
|
||||||
...DEFAULT_INSPECTOR_CONFIG,
|
|
||||||
...JSON.parse(savedConfig),
|
|
||||||
} as InspectorConfig;
|
|
||||||
|
|
||||||
// update description of keys to match the new description (in case of any updates to the default config description)
|
|
||||||
Object.entries(mergedConfig).forEach(([key, value]) => {
|
|
||||||
mergedConfig[key as keyof InspectorConfig] = {
|
|
||||||
...value,
|
|
||||||
label: DEFAULT_INSPECTOR_CONFIG[key as keyof InspectorConfig].label,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return mergedConfig;
|
|
||||||
}
|
|
||||||
return DEFAULT_INSPECTOR_CONFIG;
|
|
||||||
});
|
|
||||||
const [bearerToken, setBearerToken] = useState<string>(() => {
|
const [bearerToken, setBearerToken] = useState<string>(() => {
|
||||||
return localStorage.getItem("lastBearerToken") || "";
|
return localStorage.getItem("lastBearerToken") || "";
|
||||||
});
|
});
|
||||||
@@ -575,11 +550,24 @@ const App = () => {
|
|||||||
{!serverCapabilities?.resources &&
|
{!serverCapabilities?.resources &&
|
||||||
!serverCapabilities?.prompts &&
|
!serverCapabilities?.prompts &&
|
||||||
!serverCapabilities?.tools ? (
|
!serverCapabilities?.tools ? (
|
||||||
<div className="flex items-center justify-center p-4">
|
<>
|
||||||
<p className="text-lg text-gray-500">
|
<div className="flex items-center justify-center p-4">
|
||||||
The connected server does not support any MCP capabilities
|
<p className="text-lg text-gray-500">
|
||||||
</p>
|
The connected server does not support any MCP
|
||||||
</div>
|
capabilities
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<PingTab
|
||||||
|
onPingClick={() => {
|
||||||
|
void sendMCPRequest(
|
||||||
|
{
|
||||||
|
method: "ping" as const,
|
||||||
|
},
|
||||||
|
EmptyResultSchema,
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<ResourcesTab
|
<ResourcesTab
|
||||||
|
|||||||
@@ -133,12 +133,12 @@ const ToolsTab = ({
|
|||||||
}}
|
}}
|
||||||
setSelectedItem={setSelectedTool}
|
setSelectedItem={setSelectedTool}
|
||||||
renderItem={(tool) => (
|
renderItem={(tool) => (
|
||||||
<>
|
<div className="flex flex-col items-start">
|
||||||
<span className="flex-1">{tool.name}</span>
|
<span className="flex-1">{tool.name}</span>
|
||||||
<span className="text-sm text-gray-500 text-right">
|
<span className="text-sm text-gray-500 text-left">
|
||||||
{tool.description}
|
{tool.description}
|
||||||
</span>
|
</span>
|
||||||
</>
|
</div>
|
||||||
)}
|
)}
|
||||||
title="Tools"
|
title="Tools"
|
||||||
buttonText={nextCursor ? "List More Tools" : "List Tools"}
|
buttonText={nextCursor ? "List More Tools" : "List Tools"}
|
||||||
|
|||||||
@@ -2,8 +2,12 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|||||||
import {
|
import {
|
||||||
SSEClientTransport,
|
SSEClientTransport,
|
||||||
SseError,
|
SseError,
|
||||||
|
SSEClientTransportOptions,
|
||||||
} from "@modelcontextprotocol/sdk/client/sse.js";
|
} from "@modelcontextprotocol/sdk/client/sse.js";
|
||||||
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
import {
|
||||||
|
StreamableHTTPClientTransport,
|
||||||
|
StreamableHTTPClientTransportOptions,
|
||||||
|
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
||||||
import {
|
import {
|
||||||
ClientNotification,
|
ClientNotification,
|
||||||
ClientRequest,
|
ClientRequest,
|
||||||
@@ -279,29 +283,6 @@ export function useConnection({
|
|||||||
setConnectionStatus("error-connecting-to-proxy");
|
setConnectionStatus("error-connecting-to-proxy");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mcpProxyServerUrl;
|
|
||||||
switch (transportType) {
|
|
||||||
case "stdio":
|
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/stdio`);
|
|
||||||
mcpProxyServerUrl.searchParams.append("command", command);
|
|
||||||
mcpProxyServerUrl.searchParams.append("args", args);
|
|
||||||
mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "sse":
|
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
|
|
||||||
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "streamable-http":
|
|
||||||
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
|
|
||||||
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
(mcpProxyServerUrl as URL).searchParams.append(
|
|
||||||
"transportType",
|
|
||||||
transportType,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Inject auth manually instead of using SSEClientTransport, because we're
|
// Inject auth manually instead of using SSEClientTransport, because we're
|
||||||
@@ -320,21 +301,82 @@ export function useConnection({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create appropriate transport
|
// Create appropriate transport
|
||||||
const transportOptions = {
|
let transportOptions:
|
||||||
eventSourceInit: {
|
| StreamableHTTPClientTransportOptions
|
||||||
fetch: (
|
| SSEClientTransportOptions;
|
||||||
url: string | URL | globalThis.Request,
|
|
||||||
init: RequestInit | undefined,
|
let mcpProxyServerUrl;
|
||||||
) => fetch(url, { ...init, headers }),
|
switch (transportType) {
|
||||||
},
|
case "stdio":
|
||||||
requestInit: {
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/stdio`);
|
||||||
headers,
|
mcpProxyServerUrl.searchParams.append("command", command);
|
||||||
},
|
mcpProxyServerUrl.searchParams.append("args", args);
|
||||||
};
|
mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env));
|
||||||
|
transportOptions = {
|
||||||
|
authProvider: serverAuthProvider,
|
||||||
|
eventSourceInit: {
|
||||||
|
fetch: (
|
||||||
|
url: string | URL | globalThis.Request,
|
||||||
|
init: RequestInit | undefined,
|
||||||
|
) => fetch(url, { ...init, headers }),
|
||||||
|
},
|
||||||
|
requestInit: {
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "sse":
|
||||||
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
|
||||||
|
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
||||||
|
transportOptions = {
|
||||||
|
authProvider: serverAuthProvider,
|
||||||
|
eventSourceInit: {
|
||||||
|
fetch: (
|
||||||
|
url: string | URL | globalThis.Request,
|
||||||
|
init: RequestInit | undefined,
|
||||||
|
) => fetch(url, { ...init, headers }),
|
||||||
|
},
|
||||||
|
requestInit: {
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "streamable-http":
|
||||||
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
|
||||||
|
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
||||||
|
transportOptions = {
|
||||||
|
authProvider: serverAuthProvider,
|
||||||
|
eventSourceInit: {
|
||||||
|
fetch: (
|
||||||
|
url: string | URL | globalThis.Request,
|
||||||
|
init: RequestInit | undefined,
|
||||||
|
) => fetch(url, { ...init, headers }),
|
||||||
|
},
|
||||||
|
requestInit: {
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
// TODO these should be configurable...
|
||||||
|
reconnectionOptions: {
|
||||||
|
maxReconnectionDelay: 30000,
|
||||||
|
initialReconnectionDelay: 1000,
|
||||||
|
reconnectionDelayGrowFactor: 1.5,
|
||||||
|
maxRetries: 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(mcpProxyServerUrl as URL).searchParams.append(
|
||||||
|
"transportType",
|
||||||
|
transportType,
|
||||||
|
);
|
||||||
|
|
||||||
const clientTransport =
|
const clientTransport =
|
||||||
transportType === "streamable-http"
|
transportType === "streamable-http"
|
||||||
? new StreamableHTTPClientTransport(mcpProxyServerUrl as URL, {
|
? new StreamableHTTPClientTransport(mcpProxyServerUrl as URL, {
|
||||||
sessionId: undefined,
|
sessionId: undefined,
|
||||||
|
...transportOptions,
|
||||||
})
|
})
|
||||||
: new SSEClientTransport(mcpProxyServerUrl as URL, transportOptions);
|
: new SSEClientTransport(mcpProxyServerUrl as URL, transportOptions);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { InspectorConfig } from "@/lib/configurationTypes";
|
import { InspectorConfig } from "@/lib/configurationTypes";
|
||||||
import { DEFAULT_MCP_PROXY_LISTEN_PORT } from "@/lib/constants";
|
import {
|
||||||
|
DEFAULT_MCP_PROXY_LISTEN_PORT,
|
||||||
|
DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
} from "@/lib/constants";
|
||||||
|
|
||||||
export const getMCPProxyAddress = (config: InspectorConfig): string => {
|
export const getMCPProxyAddress = (config: InspectorConfig): string => {
|
||||||
const proxyFullAddress = config.MCP_PROXY_FULL_ADDRESS.value as string;
|
const proxyFullAddress = config.MCP_PROXY_FULL_ADDRESS.value as string;
|
||||||
@@ -24,3 +27,100 @@ export const getMCPServerRequestMaxTotalTimeout = (
|
|||||||
): number => {
|
): number => {
|
||||||
return config.MCP_REQUEST_MAX_TOTAL_TIMEOUT.value as number;
|
return config.MCP_REQUEST_MAX_TOTAL_TIMEOUT.value as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSearchParam = (key: string): string | null => {
|
||||||
|
try {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
return url.searchParams.get(key);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInitialTransportType = ():
|
||||||
|
| "stdio"
|
||||||
|
| "sse"
|
||||||
|
| "streamable-http" => {
|
||||||
|
const param = getSearchParam("transport");
|
||||||
|
if (param === "stdio" || param === "sse" || param === "streamable-http") {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(localStorage.getItem("lastTransportType") as
|
||||||
|
| "stdio"
|
||||||
|
| "sse"
|
||||||
|
| "streamable-http") || "stdio"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInitialSseUrl = (): string => {
|
||||||
|
const param = getSearchParam("serverUrl");
|
||||||
|
if (param) return param;
|
||||||
|
return localStorage.getItem("lastSseUrl") || "http://localhost:3001/sse";
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInitialCommand = (): string => {
|
||||||
|
const param = getSearchParam("serverCommand");
|
||||||
|
if (param) return param;
|
||||||
|
return localStorage.getItem("lastCommand") || "mcp-server-everything";
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInitialArgs = (): string => {
|
||||||
|
const param = getSearchParam("serverArgs");
|
||||||
|
if (param) return param;
|
||||||
|
return localStorage.getItem("lastArgs") || "";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns a map of config key -> value from query params if present
|
||||||
|
export const getConfigOverridesFromQueryParams = (
|
||||||
|
defaultConfig: InspectorConfig,
|
||||||
|
): Partial<InspectorConfig> => {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
const overrides: Partial<InspectorConfig> = {};
|
||||||
|
for (const key of Object.keys(defaultConfig)) {
|
||||||
|
const param = url.searchParams.get(key);
|
||||||
|
if (param !== null) {
|
||||||
|
// Try to coerce to correct type based on default value
|
||||||
|
const defaultValue = defaultConfig[key as keyof InspectorConfig].value;
|
||||||
|
let value: string | number | boolean = param;
|
||||||
|
if (typeof defaultValue === "number") {
|
||||||
|
value = Number(param);
|
||||||
|
} else if (typeof defaultValue === "boolean") {
|
||||||
|
value = param === "true";
|
||||||
|
}
|
||||||
|
overrides[key as keyof InspectorConfig] = {
|
||||||
|
...defaultConfig[key as keyof InspectorConfig],
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return overrides;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initializeInspectorConfig = (
|
||||||
|
localStorageKey: string,
|
||||||
|
): InspectorConfig => {
|
||||||
|
const savedConfig = localStorage.getItem(localStorageKey);
|
||||||
|
let baseConfig: InspectorConfig;
|
||||||
|
if (savedConfig) {
|
||||||
|
// merge default config with saved config
|
||||||
|
const mergedConfig = {
|
||||||
|
...DEFAULT_INSPECTOR_CONFIG,
|
||||||
|
...JSON.parse(savedConfig),
|
||||||
|
} as InspectorConfig;
|
||||||
|
|
||||||
|
// update description of keys to match the new description (in case of any updates to the default config description)
|
||||||
|
for (const [key, value] of Object.entries(mergedConfig)) {
|
||||||
|
mergedConfig[key as keyof InspectorConfig] = {
|
||||||
|
...value,
|
||||||
|
label: DEFAULT_INSPECTOR_CONFIG[key as keyof InspectorConfig].label,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
baseConfig = mergedConfig;
|
||||||
|
} else {
|
||||||
|
baseConfig = DEFAULT_INSPECTOR_CONFIG;
|
||||||
|
}
|
||||||
|
// Apply query param overrides
|
||||||
|
const overrides = getConfigOverridesFromQueryParams(DEFAULT_INSPECTOR_CONFIG);
|
||||||
|
return { ...baseConfig, ...overrides };
|
||||||
|
};
|
||||||
|
|||||||
157
package-lock.json
generated
157
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@modelcontextprotocol/inspector",
|
"name": "@modelcontextprotocol/inspector",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@modelcontextprotocol/inspector",
|
"name": "@modelcontextprotocol/inspector",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"client",
|
"client",
|
||||||
@@ -14,11 +14,12 @@
|
|||||||
"cli"
|
"cli"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/inspector-cli": "^0.11.0",
|
"@modelcontextprotocol/inspector-cli": "^0.12.0",
|
||||||
"@modelcontextprotocol/inspector-client": "^0.11.0",
|
"@modelcontextprotocol/inspector-client": "^0.12.0",
|
||||||
"@modelcontextprotocol/inspector-server": "^0.11.0",
|
"@modelcontextprotocol/inspector-server": "^0.12.0",
|
||||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
"@modelcontextprotocol/sdk": "^1.11.0",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
|
"open": "^10.1.0",
|
||||||
"shell-quote": "^1.8.2",
|
"shell-quote": "^1.8.2",
|
||||||
"spawn-rx": "^5.1.2",
|
"spawn-rx": "^5.1.2",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
},
|
},
|
||||||
"cli": {
|
"cli": {
|
||||||
"name": "@modelcontextprotocol/inspector-cli",
|
"name": "@modelcontextprotocol/inspector-cli",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.10.2",
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
||||||
@@ -62,7 +63,7 @@
|
|||||||
},
|
},
|
||||||
"client": {
|
"client": {
|
||||||
"name": "@modelcontextprotocol/inspector-client",
|
"name": "@modelcontextprotocol/inspector-client",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.10.2",
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
||||||
@@ -4376,6 +4377,21 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/bundle-name": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"run-applescript": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@@ -4929,6 +4945,46 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/default-browser": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bundle-name": "^4.1.0",
|
||||||
|
"default-browser-id": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/default-browser-id": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-lazy-prop": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/delayed-stream": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
@@ -6341,6 +6397,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-docker": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"is-docker": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-extglob": {
|
"node_modules/is-extglob": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
@@ -6381,6 +6452,24 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-inside-container": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-docker": "^3.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"is-inside-container": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-number": {
|
"node_modules/is-number": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
@@ -6416,6 +6505,21 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-wsl": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-inside-container": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@@ -8098,6 +8202,24 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/open": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"default-browser": "^5.2.1",
|
||||||
|
"define-lazy-prop": "^3.0.0",
|
||||||
|
"is-inside-container": "^1.0.0",
|
||||||
|
"is-wsl": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
@@ -9132,6 +9254,25 @@
|
|||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/router/node_modules/path-to-regexp": {
|
||||||
|
"version": "8.2.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-applescript": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/run-parallel": {
|
"node_modules/run-parallel": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||||
@@ -10793,7 +10934,7 @@
|
|||||||
},
|
},
|
||||||
"server": {
|
"server": {
|
||||||
"name": "@modelcontextprotocol/inspector-server",
|
"name": "@modelcontextprotocol/inspector-server",
|
||||||
"version": "0.11.0",
|
"version": "0.12.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.10.2",
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@modelcontextprotocol/inspector",
|
"name": "@modelcontextprotocol/inspector",
|
||||||
"version": "0.11.0",
|
"version": "0.12.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)",
|
||||||
@@ -40,11 +40,12 @@
|
|||||||
"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-cli": "^0.11.0",
|
"@modelcontextprotocol/inspector-cli": "^0.12.0",
|
||||||
"@modelcontextprotocol/inspector-client": "^0.11.0",
|
"@modelcontextprotocol/inspector-client": "^0.12.0",
|
||||||
"@modelcontextprotocol/inspector-server": "^0.11.0",
|
"@modelcontextprotocol/inspector-server": "^0.12.0",
|
||||||
"@modelcontextprotocol/sdk": "^1.11.0",
|
"@modelcontextprotocol/sdk": "^1.11.0",
|
||||||
"concurrently": "^9.0.1",
|
"concurrently": "^9.0.1",
|
||||||
|
"open": "^10.1.0",
|
||||||
"shell-quote": "^1.8.2",
|
"shell-quote": "^1.8.2",
|
||||||
"spawn-rx": "^5.1.2",
|
"spawn-rx": "^5.1.2",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@modelcontextprotocol/inspector-server",
|
"name": "@modelcontextprotocol/inspector-server",
|
||||||
"version": "0.11.0",
|
"version": "0.12.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)",
|
||||||
|
|||||||
Reference in New Issue
Block a user