@modelcontextprotocol/inspector 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -4
- package/bin/cli.js +31 -3
- package/client/dist/assets/OAuthCallback-HUNd2OJn.js +33 -0
- package/client/dist/assets/{index-BKN3G2r3.js → index-DjoEM10P.js} +1646 -701
- package/client/dist/assets/{index-DxcZhiGz.css → index-eOhPEcGC.css} +13 -11
- package/client/dist/index.html +2 -2
- package/package.json +3 -1
- package/server/build/index.js +43 -17
- package/server/build/mcpProxy.js +13 -7
|
@@ -835,7 +835,7 @@
|
|
|
835
835
|
--tw-contain-paint: ;
|
|
836
836
|
--tw-contain-style: ;
|
|
837
837
|
}/*
|
|
838
|
-
! tailwindcss v3.4.
|
|
838
|
+
! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com
|
|
839
839
|
*//*
|
|
840
840
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
841
841
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
@@ -1435,8 +1435,8 @@ video {
|
|
|
1435
1435
|
.w-9 {
|
|
1436
1436
|
width: 2.25rem;
|
|
1437
1437
|
}
|
|
1438
|
-
.w-\[
|
|
1439
|
-
width:
|
|
1438
|
+
.w-\[100px\] {
|
|
1439
|
+
width: 100px;
|
|
1440
1440
|
}
|
|
1441
1441
|
.w-full {
|
|
1442
1442
|
width: 100%;
|
|
@@ -1456,6 +1456,9 @@ video {
|
|
|
1456
1456
|
.flex-shrink-0 {
|
|
1457
1457
|
flex-shrink: 0;
|
|
1458
1458
|
}
|
|
1459
|
+
.shrink-0 {
|
|
1460
|
+
flex-shrink: 0;
|
|
1461
|
+
}
|
|
1459
1462
|
.transform {
|
|
1460
1463
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
1461
1464
|
}
|
|
@@ -1488,9 +1491,6 @@ video {
|
|
|
1488
1491
|
.grid-cols-3 {
|
|
1489
1492
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
1490
1493
|
}
|
|
1491
|
-
.grid-cols-\[1fr\2c auto\] {
|
|
1492
|
-
grid-template-columns: 1fr auto;
|
|
1493
|
-
}
|
|
1494
1494
|
.flex-col {
|
|
1495
1495
|
flex-direction: column;
|
|
1496
1496
|
}
|
|
@@ -1514,11 +1514,6 @@ video {
|
|
|
1514
1514
|
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
|
1515
1515
|
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
|
1516
1516
|
}
|
|
1517
|
-
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
|
|
1518
|
-
--tw-space-y-reverse: 0;
|
|
1519
|
-
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
|
|
1520
|
-
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
|
1521
|
-
}
|
|
1522
1517
|
.space-y-2 > :not([hidden]) ~ :not([hidden]) {
|
|
1523
1518
|
--tw-space-y-reverse: 0;
|
|
1524
1519
|
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
|
@@ -1707,6 +1702,9 @@ video {
|
|
|
1707
1702
|
padding-top: 1.5rem;
|
|
1708
1703
|
padding-bottom: 1.5rem;
|
|
1709
1704
|
}
|
|
1705
|
+
.pb-4 {
|
|
1706
|
+
padding-bottom: 1rem;
|
|
1707
|
+
}
|
|
1710
1708
|
.pl-2 {
|
|
1711
1709
|
padding-left: 0.5rem;
|
|
1712
1710
|
}
|
|
@@ -1793,6 +1791,10 @@ video {
|
|
|
1793
1791
|
--tw-text-opacity: 1;
|
|
1794
1792
|
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
|
|
1795
1793
|
}
|
|
1794
|
+
.text-gray-800 {
|
|
1795
|
+
--tw-text-opacity: 1;
|
|
1796
|
+
color: rgb(31 41 55 / var(--tw-text-opacity, 1));
|
|
1797
|
+
}
|
|
1796
1798
|
.text-gray-900 {
|
|
1797
1799
|
--tw-text-opacity: 1;
|
|
1798
1800
|
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
|
package/client/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/mcp.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>MCP Inspector</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DjoEM10P.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-eOhPEcGC.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/inspector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Model Context Protocol inspector",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
|
@@ -36,11 +36,13 @@
|
|
|
36
36
|
"@modelcontextprotocol/inspector-client": "0.3.0",
|
|
37
37
|
"@modelcontextprotocol/inspector-server": "0.3.0",
|
|
38
38
|
"concurrently": "^9.0.1",
|
|
39
|
+
"shell-quote": "^1.8.2",
|
|
39
40
|
"spawn-rx": "^5.1.0",
|
|
40
41
|
"ts-node": "^10.9.2"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/node": "^22.7.5",
|
|
45
|
+
"@types/shell-quote": "^1.7.5",
|
|
44
46
|
"prettier": "3.3.3"
|
|
45
47
|
}
|
|
46
48
|
}
|
package/server/build/index.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cors from "cors";
|
|
3
|
-
import EventSource from "eventsource";
|
|
4
3
|
import { parseArgs } from "node:util";
|
|
5
|
-
import {
|
|
4
|
+
import { parse as shellParseArgs } from "shell-quote";
|
|
5
|
+
import { SSEClientTransport, SseError, } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
6
6
|
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
7
7
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
8
8
|
import express from "express";
|
|
9
|
-
import mcpProxy from "./mcpProxy.js";
|
|
10
9
|
import { findActualExecutable } from "spawn-rx";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
import mcpProxy from "./mcpProxy.js";
|
|
11
|
+
const SSE_HEADERS_PASSTHROUGH = ["authorization"];
|
|
12
|
+
const defaultEnvironment = {
|
|
13
|
+
...getDefaultEnvironment(),
|
|
14
|
+
...(process.env.MCP_ENV_VARS ? JSON.parse(process.env.MCP_ENV_VARS) : {}),
|
|
15
|
+
};
|
|
14
16
|
const { values } = parseArgs({
|
|
15
17
|
args: process.argv.slice(2),
|
|
16
18
|
options: {
|
|
@@ -21,15 +23,17 @@ const { values } = parseArgs({
|
|
|
21
23
|
const app = express();
|
|
22
24
|
app.use(cors());
|
|
23
25
|
let webAppTransports = [];
|
|
24
|
-
const createTransport = async (
|
|
26
|
+
const createTransport = async (req) => {
|
|
27
|
+
const query = req.query;
|
|
25
28
|
console.log("Query parameters:", query);
|
|
26
29
|
const transportType = query.transportType;
|
|
27
30
|
if (transportType === "stdio") {
|
|
28
31
|
const command = query.command;
|
|
29
|
-
const origArgs = query.args
|
|
30
|
-
const
|
|
32
|
+
const origArgs = shellParseArgs(query.args);
|
|
33
|
+
const queryEnv = query.env ? JSON.parse(query.env) : {};
|
|
34
|
+
const env = { ...process.env, ...defaultEnvironment, ...queryEnv };
|
|
31
35
|
const { cmd, args } = findActualExecutable(command, origArgs);
|
|
32
|
-
console.log(`Stdio transport: command=${cmd}, args=${args}
|
|
36
|
+
console.log(`Stdio transport: command=${cmd}, args=${args}`);
|
|
33
37
|
const transport = new StdioClientTransport({
|
|
34
38
|
command: cmd,
|
|
35
39
|
args,
|
|
@@ -42,8 +46,23 @@ const createTransport = async (query) => {
|
|
|
42
46
|
}
|
|
43
47
|
else if (transportType === "sse") {
|
|
44
48
|
const url = query.url;
|
|
45
|
-
|
|
46
|
-
const
|
|
49
|
+
const headers = {};
|
|
50
|
+
for (const key of SSE_HEADERS_PASSTHROUGH) {
|
|
51
|
+
if (req.headers[key] === undefined) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const value = req.headers[key];
|
|
55
|
+
headers[key] = Array.isArray(value) ? value[value.length - 1] : value;
|
|
56
|
+
}
|
|
57
|
+
console.log(`SSE transport: url=${url}, headers=${Object.keys(headers)}`);
|
|
58
|
+
const transport = new SSEClientTransport(new URL(url), {
|
|
59
|
+
eventSourceInit: {
|
|
60
|
+
fetch: (url, init) => fetch(url, { ...init, headers }),
|
|
61
|
+
},
|
|
62
|
+
requestInit: {
|
|
63
|
+
headers,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
47
66
|
await transport.start();
|
|
48
67
|
console.log("Connected to SSE transport");
|
|
49
68
|
return transport;
|
|
@@ -56,7 +75,18 @@ const createTransport = async (query) => {
|
|
|
56
75
|
app.get("/sse", async (req, res) => {
|
|
57
76
|
try {
|
|
58
77
|
console.log("New SSE connection");
|
|
59
|
-
|
|
78
|
+
let backingServerTransport;
|
|
79
|
+
try {
|
|
80
|
+
backingServerTransport = await createTransport(req);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof SseError && error.code === 401) {
|
|
84
|
+
console.error("Received 401 Unauthorized from MCP server:", error.message);
|
|
85
|
+
res.status(401).json(error);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
60
90
|
console.log("Connected MCP client to backing server transport");
|
|
61
91
|
const webAppTransport = new SSEServerTransport("/message", res);
|
|
62
92
|
console.log("Created web app transport");
|
|
@@ -77,9 +107,6 @@ app.get("/sse", async (req, res) => {
|
|
|
77
107
|
mcpProxy({
|
|
78
108
|
transportToClient: webAppTransport,
|
|
79
109
|
transportToServer: backingServerTransport,
|
|
80
|
-
onerror: (error) => {
|
|
81
|
-
console.error(error);
|
|
82
|
-
},
|
|
83
110
|
});
|
|
84
111
|
console.log("Set up MCP proxy");
|
|
85
112
|
}
|
|
@@ -106,7 +133,6 @@ app.post("/message", async (req, res) => {
|
|
|
106
133
|
});
|
|
107
134
|
app.get("/config", (req, res) => {
|
|
108
135
|
try {
|
|
109
|
-
const defaultEnvironment = getDefaultEnvironment();
|
|
110
136
|
res.json({
|
|
111
137
|
defaultEnvironment,
|
|
112
138
|
defaultCommand: values.env,
|
package/server/build/mcpProxy.js
CHANGED
|
@@ -1,26 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
function onClientError(error) {
|
|
2
|
+
console.error("Error from inspector client:", error);
|
|
3
|
+
}
|
|
4
|
+
function onServerError(error) {
|
|
5
|
+
console.error("Error from MCP server:", error);
|
|
6
|
+
}
|
|
7
|
+
export default function mcpProxy({ transportToClient, transportToServer, }) {
|
|
2
8
|
let transportToClientClosed = false;
|
|
3
9
|
let transportToServerClosed = false;
|
|
4
10
|
transportToClient.onmessage = (message) => {
|
|
5
|
-
transportToServer.send(message).catch(
|
|
11
|
+
transportToServer.send(message).catch(onServerError);
|
|
6
12
|
};
|
|
7
13
|
transportToServer.onmessage = (message) => {
|
|
8
|
-
transportToClient.send(message).catch(
|
|
14
|
+
transportToClient.send(message).catch(onClientError);
|
|
9
15
|
};
|
|
10
16
|
transportToClient.onclose = () => {
|
|
11
17
|
if (transportToServerClosed) {
|
|
12
18
|
return;
|
|
13
19
|
}
|
|
14
20
|
transportToClientClosed = true;
|
|
15
|
-
transportToServer.close().catch(
|
|
21
|
+
transportToServer.close().catch(onServerError);
|
|
16
22
|
};
|
|
17
23
|
transportToServer.onclose = () => {
|
|
18
24
|
if (transportToClientClosed) {
|
|
19
25
|
return;
|
|
20
26
|
}
|
|
21
27
|
transportToServerClosed = true;
|
|
22
|
-
transportToClient.close().catch(
|
|
28
|
+
transportToClient.close().catch(onClientError);
|
|
23
29
|
};
|
|
24
|
-
transportToClient.onerror =
|
|
25
|
-
transportToServer.onerror =
|
|
30
|
+
transportToClient.onerror = onClientError;
|
|
31
|
+
transportToServer.onerror = onServerError;
|
|
26
32
|
}
|