@modelcontextprotocol/inspector 0.10.2 → 0.12.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/client/bin/client.js +26 -2
- package/client/dist/assets/{OAuthCallback-DsrZ1Q5-.js → OAuthCallback-FfoeB75N.js} +1 -1
- package/client/dist/assets/{index-CMyU_PZH.js → index-CHwMp9hp.js} +5370 -4637
- package/client/dist/index.html +1 -1
- package/package.json +9 -5
- package/server/build/index.js +147 -15
package/client/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
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-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CHwMp9hp.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-D5WIP3OH.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/inspector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Model Context Protocol inspector",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"build-server": "cd server && npm run build",
|
|
27
27
|
"build-client": "cd client && npm run build",
|
|
28
28
|
"build-cli": "cd cli && npm run build",
|
|
29
|
+
"clean": "rimraf ./node_modules ./client/node_modules ./cli/node_modules ./build ./client/dist ./server/build ./cli/build ./package-lock.json && npm install",
|
|
29
30
|
"dev": "concurrently \"cd client && npm run dev\" \"cd server && npm run dev\"",
|
|
30
31
|
"dev:windows": "concurrently \"cd client && npm run dev\" \"cd server && npm run dev:windows\"",
|
|
31
32
|
"start": "node client/bin/start.js",
|
|
@@ -35,13 +36,14 @@
|
|
|
35
36
|
"test-cli": "cd cli && npm run test",
|
|
36
37
|
"prettier-fix": "prettier --write .",
|
|
37
38
|
"prettier-check": "prettier --check .",
|
|
39
|
+
"prepare": "npm run build",
|
|
38
40
|
"publish-all": "npm publish --workspaces --access public && npm publish --access public"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
|
-
"@modelcontextprotocol/inspector-cli": "^0.
|
|
42
|
-
"@modelcontextprotocol/inspector-client": "^0.
|
|
43
|
-
"@modelcontextprotocol/inspector-server": "^0.
|
|
44
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
43
|
+
"@modelcontextprotocol/inspector-cli": "^0.12.0",
|
|
44
|
+
"@modelcontextprotocol/inspector-client": "^0.12.0",
|
|
45
|
+
"@modelcontextprotocol/inspector-server": "^0.12.0",
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.11.0",
|
|
45
47
|
"concurrently": "^9.0.1",
|
|
46
48
|
"shell-quote": "^1.8.2",
|
|
47
49
|
"spawn-rx": "^5.1.2",
|
|
@@ -52,7 +54,9 @@
|
|
|
52
54
|
"@types/jest": "^29.5.14",
|
|
53
55
|
"@types/node": "^22.7.5",
|
|
54
56
|
"@types/shell-quote": "^1.7.5",
|
|
57
|
+
"jest-fixed-jsdom": "^0.0.9",
|
|
55
58
|
"prettier": "3.3.3",
|
|
59
|
+
"rimraf": "^6.0.1",
|
|
56
60
|
"typescript": "^5.4.2"
|
|
57
61
|
}
|
|
58
62
|
}
|
package/server/build/index.js
CHANGED
|
@@ -4,11 +4,19 @@ import { parseArgs } from "node:util";
|
|
|
4
4
|
import { parse as shellParseArgs } from "shell-quote";
|
|
5
5
|
import { SSEClientTransport, SseError, } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
6
6
|
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
7
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
8
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
7
9
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
8
10
|
import express from "express";
|
|
9
11
|
import { findActualExecutable } from "spawn-rx";
|
|
10
12
|
import mcpProxy from "./mcpProxy.js";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
11
14
|
const SSE_HEADERS_PASSTHROUGH = ["authorization"];
|
|
15
|
+
const STREAMABLE_HTTP_HEADERS_PASSTHROUGH = [
|
|
16
|
+
"authorization",
|
|
17
|
+
"mcp-session-id",
|
|
18
|
+
"last-event-id",
|
|
19
|
+
];
|
|
12
20
|
const defaultEnvironment = {
|
|
13
21
|
...getDefaultEnvironment(),
|
|
14
22
|
...(process.env.MCP_ENV_VARS ? JSON.parse(process.env.MCP_ENV_VARS) : {}),
|
|
@@ -22,7 +30,11 @@ const { values } = parseArgs({
|
|
|
22
30
|
});
|
|
23
31
|
const app = express();
|
|
24
32
|
app.use(cors());
|
|
25
|
-
|
|
33
|
+
app.use((req, res, next) => {
|
|
34
|
+
res.header("Access-Control-Expose-Headers", "mcp-session-id");
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
37
|
+
const webAppTransports = new Map(); // Transports by sessionId
|
|
26
38
|
const createTransport = async (req) => {
|
|
27
39
|
const query = req.query;
|
|
28
40
|
console.log("Query parameters:", query);
|
|
@@ -69,15 +81,107 @@ const createTransport = async (req) => {
|
|
|
69
81
|
console.log("Connected to SSE transport");
|
|
70
82
|
return transport;
|
|
71
83
|
}
|
|
84
|
+
else if (transportType === "streamable-http") {
|
|
85
|
+
const headers = {
|
|
86
|
+
Accept: "text/event-stream, application/json",
|
|
87
|
+
};
|
|
88
|
+
for (const key of STREAMABLE_HTTP_HEADERS_PASSTHROUGH) {
|
|
89
|
+
if (req.headers[key] === undefined) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const value = req.headers[key];
|
|
93
|
+
headers[key] = Array.isArray(value) ? value[value.length - 1] : value;
|
|
94
|
+
}
|
|
95
|
+
const transport = new StreamableHTTPClientTransport(new URL(query.url), {
|
|
96
|
+
requestInit: {
|
|
97
|
+
headers,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
await transport.start();
|
|
101
|
+
console.log("Connected to Streamable HTTP transport");
|
|
102
|
+
return transport;
|
|
103
|
+
}
|
|
72
104
|
else {
|
|
73
105
|
console.error(`Invalid transport type: ${transportType}`);
|
|
74
106
|
throw new Error("Invalid transport type specified");
|
|
75
107
|
}
|
|
76
108
|
};
|
|
77
109
|
let backingServerTransport;
|
|
78
|
-
app.get("/
|
|
110
|
+
app.get("/mcp", async (req, res) => {
|
|
111
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
112
|
+
console.log(`Received GET message for sessionId ${sessionId}`);
|
|
79
113
|
try {
|
|
80
|
-
|
|
114
|
+
const transport = webAppTransports.get(sessionId);
|
|
115
|
+
if (!transport) {
|
|
116
|
+
res.status(404).end("Session not found");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
await transport.handleRequest(req, res);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error("Error in /mcp route:", error);
|
|
125
|
+
res.status(500).json(error);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
app.post("/mcp", async (req, res) => {
|
|
129
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
130
|
+
console.log(`Received POST message for sessionId ${sessionId}`);
|
|
131
|
+
if (!sessionId) {
|
|
132
|
+
try {
|
|
133
|
+
console.log("New streamable-http connection");
|
|
134
|
+
try {
|
|
135
|
+
await backingServerTransport?.close();
|
|
136
|
+
backingServerTransport = await createTransport(req);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (error instanceof SseError && error.code === 401) {
|
|
140
|
+
console.error("Received 401 Unauthorized from MCP server:", error.message);
|
|
141
|
+
res.status(401).json(error);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
console.log("Connected MCP client to backing server transport");
|
|
147
|
+
const webAppTransport = new StreamableHTTPServerTransport({
|
|
148
|
+
sessionIdGenerator: randomUUID,
|
|
149
|
+
onsessioninitialized: (sessionId) => {
|
|
150
|
+
webAppTransports.set(sessionId, webAppTransport);
|
|
151
|
+
console.log("Created streamable web app transport " + sessionId);
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
await webAppTransport.start();
|
|
155
|
+
mcpProxy({
|
|
156
|
+
transportToClient: webAppTransport,
|
|
157
|
+
transportToServer: backingServerTransport,
|
|
158
|
+
});
|
|
159
|
+
await webAppTransport.handleRequest(req, res, req.body);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error("Error in /mcp POST route:", error);
|
|
163
|
+
res.status(500).json(error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
try {
|
|
168
|
+
const transport = webAppTransports.get(sessionId);
|
|
169
|
+
if (!transport) {
|
|
170
|
+
res.status(404).end("Transport not found for sessionId " + sessionId);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
await transport.handleRequest(req, res);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.error("Error in /mcp route:", error);
|
|
178
|
+
res.status(500).json(error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
app.get("/stdio", async (req, res) => {
|
|
183
|
+
try {
|
|
184
|
+
console.log("New connection");
|
|
81
185
|
try {
|
|
82
186
|
await backingServerTransport?.close();
|
|
83
187
|
backingServerTransport = await createTransport(req);
|
|
@@ -92,21 +196,49 @@ app.get("/sse", async (req, res) => {
|
|
|
92
196
|
}
|
|
93
197
|
console.log("Connected MCP client to backing server transport");
|
|
94
198
|
const webAppTransport = new SSEServerTransport("/message", res);
|
|
95
|
-
|
|
96
|
-
webAppTransports.push(webAppTransport);
|
|
199
|
+
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
|
97
200
|
console.log("Created web app transport");
|
|
98
201
|
await webAppTransport.start();
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
},
|
|
107
|
-
});
|
|
202
|
+
backingServerTransport.stderr.on("data", (chunk) => {
|
|
203
|
+
webAppTransport.send({
|
|
204
|
+
jsonrpc: "2.0",
|
|
205
|
+
method: "notifications/stderr",
|
|
206
|
+
params: {
|
|
207
|
+
content: chunk.toString(),
|
|
208
|
+
},
|
|
108
209
|
});
|
|
210
|
+
});
|
|
211
|
+
mcpProxy({
|
|
212
|
+
transportToClient: webAppTransport,
|
|
213
|
+
transportToServer: backingServerTransport,
|
|
214
|
+
});
|
|
215
|
+
console.log("Set up MCP proxy");
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.error("Error in /stdio route:", error);
|
|
219
|
+
res.status(500).json(error);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
app.get("/sse", async (req, res) => {
|
|
223
|
+
try {
|
|
224
|
+
console.log("New SSE connection. NOTE: The sse transport is deprecated and has been replaced by streamable-http");
|
|
225
|
+
try {
|
|
226
|
+
await backingServerTransport?.close();
|
|
227
|
+
backingServerTransport = await createTransport(req);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (error instanceof SseError && error.code === 401) {
|
|
231
|
+
console.error("Received 401 Unauthorized from MCP server:", error.message);
|
|
232
|
+
res.status(401).json(error);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
throw error;
|
|
109
236
|
}
|
|
237
|
+
console.log("Connected MCP client to backing server transport");
|
|
238
|
+
const webAppTransport = new SSEServerTransport("/message", res);
|
|
239
|
+
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
|
240
|
+
console.log("Created web app transport");
|
|
241
|
+
await webAppTransport.start();
|
|
110
242
|
mcpProxy({
|
|
111
243
|
transportToClient: webAppTransport,
|
|
112
244
|
transportToServer: backingServerTransport,
|
|
@@ -122,7 +254,7 @@ app.post("/message", async (req, res) => {
|
|
|
122
254
|
try {
|
|
123
255
|
const sessionId = req.query.sessionId;
|
|
124
256
|
console.log(`Received message for sessionId ${sessionId}`);
|
|
125
|
-
const transport = webAppTransports.
|
|
257
|
+
const transport = webAppTransports.get(sessionId);
|
|
126
258
|
if (!transport) {
|
|
127
259
|
res.status(404).end("Session not found");
|
|
128
260
|
return;
|