@modelcontextprotocol/inspector 0.15.0 → 0.16.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 +3 -3
- package/client/bin/client.js +11 -6
- package/client/bin/start.js +64 -28
- package/client/dist/assets/{OAuthCallback-CaW3Hcqw.js → OAuthCallback-DMQy4ibj.js} +1 -1
- package/client/dist/assets/{OAuthDebugCallback-DiBt_oxh.js → OAuthDebugCallback-9JxBAysc.js} +1 -1
- package/client/dist/assets/{index-C1MLjTGf.css → index-BwWj6LL9.css} +0 -4
- package/client/dist/assets/{index-BNqYF5Na.js → index-DI7JCTeu.js} +317 -102
- package/client/dist/index.html +3 -3
- package/package.json +7 -4
- package/server/build/index.js +8 -12
- package/server/build/mcpProxy.js +4 -3
package/README.md
CHANGED
|
@@ -168,20 +168,20 @@ DANGEROUSLY_OMIT_AUTH=true npm start
|
|
|
168
168
|
|
|
169
169
|
#### Local-only Binding
|
|
170
170
|
|
|
171
|
-
By default, the MCP Inspector proxy server
|
|
171
|
+
By default, both the MCP Inspector proxy server and client bind only to `localhost` to prevent network access. This ensures they are not accessible from other devices on the network. If you need to bind to all interfaces for development purposes, you can override this with the `HOST` environment variable:
|
|
172
172
|
|
|
173
173
|
```bash
|
|
174
174
|
HOST=0.0.0.0 npm start
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
**Warning:** Only bind to all interfaces in trusted network environments, as this exposes the proxy server's ability to execute local processes.
|
|
177
|
+
**Warning:** Only bind to all interfaces in trusted network environments, as this exposes the proxy server's ability to execute local processes and both services to network access.
|
|
178
178
|
|
|
179
179
|
#### DNS Rebinding Protection
|
|
180
180
|
|
|
181
181
|
To prevent DNS rebinding attacks, the MCP Inspector validates the `Origin` header on incoming requests. By default, only requests from the client origin are allowed (respects `CLIENT_PORT` if set, defaulting to port 6274). You can configure additional allowed origins by setting the `ALLOWED_ORIGINS` environment variable (comma-separated list):
|
|
182
182
|
|
|
183
183
|
```bash
|
|
184
|
-
ALLOWED_ORIGINS=http://localhost:6274,http://
|
|
184
|
+
ALLOWED_ORIGINS=http://localhost:6274,http://localhost:8000 npm start
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
### Configuration
|
package/client/bin/client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import open from "open";
|
|
3
4
|
import { join, dirname } from "path";
|
|
4
5
|
import { fileURLToPath } from "url";
|
|
5
6
|
import handler from "serve-handler";
|
|
@@ -39,19 +40,23 @@ const server = http.createServer((request, response) => {
|
|
|
39
40
|
return handler(request, response, handlerOptions);
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
const port = process.env.
|
|
43
|
+
const port = parseInt(process.env.CLIENT_PORT || "6274", 10);
|
|
44
|
+
const host = process.env.HOST || "localhost";
|
|
43
45
|
server.on("listening", () => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
46
|
+
const url = process.env.INSPECTOR_URL || `http://${host}:${port}`;
|
|
47
|
+
console.log(`\n🚀 MCP Inspector is up and running at:\n ${url}\n`);
|
|
48
|
+
if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
|
|
49
|
+
console.log(`🌐 Opening browser...`);
|
|
50
|
+
open(url);
|
|
51
|
+
}
|
|
47
52
|
});
|
|
48
53
|
server.on("error", (err) => {
|
|
49
54
|
if (err.message.includes(`EADDRINUSE`)) {
|
|
50
55
|
console.error(
|
|
51
|
-
`❌ MCP Inspector PORT IS IN USE at http
|
|
56
|
+
`❌ MCP Inspector PORT IS IN USE at http://${host}:${port} ❌ `,
|
|
52
57
|
);
|
|
53
58
|
} else {
|
|
54
59
|
throw err;
|
|
55
60
|
}
|
|
56
61
|
});
|
|
57
|
-
server.listen(port);
|
|
62
|
+
server.listen(port, host);
|
package/client/bin/start.js
CHANGED
|
@@ -7,11 +7,26 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
import { randomBytes } from "crypto";
|
|
8
8
|
|
|
9
9
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const DEFAULT_MCP_PROXY_LISTEN_PORT = "6277";
|
|
10
11
|
|
|
11
12
|
function delay(ms) {
|
|
12
13
|
return new Promise((resolve) => setTimeout(resolve, ms, true));
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
function getClientUrl(port, authDisabled, sessionToken, serverPort) {
|
|
17
|
+
const host = process.env.HOST || "localhost";
|
|
18
|
+
const baseUrl = `http://${host}:${port}`;
|
|
19
|
+
|
|
20
|
+
const params = new URLSearchParams();
|
|
21
|
+
if (serverPort && serverPort !== DEFAULT_MCP_PROXY_LISTEN_PORT) {
|
|
22
|
+
params.set("MCP_PROXY_PORT", serverPort);
|
|
23
|
+
}
|
|
24
|
+
if (!authDisabled) {
|
|
25
|
+
params.set("MCP_PROXY_AUTH_TOKEN", sessionToken);
|
|
26
|
+
}
|
|
27
|
+
return params.size > 0 ? `${baseUrl}/?${params.toString()}` : baseUrl;
|
|
28
|
+
}
|
|
29
|
+
|
|
15
30
|
async function startDevServer(serverOptions) {
|
|
16
31
|
const { SERVER_PORT, CLIENT_PORT, sessionToken, envVars, abort } =
|
|
17
32
|
serverOptions;
|
|
@@ -23,8 +38,8 @@ async function startDevServer(serverOptions) {
|
|
|
23
38
|
cwd: resolve(__dirname, "../..", "server"),
|
|
24
39
|
env: {
|
|
25
40
|
...process.env,
|
|
26
|
-
|
|
27
|
-
CLIENT_PORT
|
|
41
|
+
SERVER_PORT,
|
|
42
|
+
CLIENT_PORT,
|
|
28
43
|
MCP_PROXY_TOKEN: sessionToken,
|
|
29
44
|
MCP_ENV_VARS: JSON.stringify(envVars),
|
|
30
45
|
},
|
|
@@ -82,8 +97,8 @@ async function startProdServer(serverOptions) {
|
|
|
82
97
|
{
|
|
83
98
|
env: {
|
|
84
99
|
...process.env,
|
|
85
|
-
|
|
86
|
-
CLIENT_PORT
|
|
100
|
+
SERVER_PORT,
|
|
101
|
+
CLIENT_PORT,
|
|
87
102
|
MCP_PROXY_TOKEN: sessionToken,
|
|
88
103
|
MCP_ENV_VARS: JSON.stringify(envVars),
|
|
89
104
|
},
|
|
@@ -99,30 +114,40 @@ async function startProdServer(serverOptions) {
|
|
|
99
114
|
}
|
|
100
115
|
|
|
101
116
|
async function startDevClient(clientOptions) {
|
|
102
|
-
const {
|
|
103
|
-
|
|
117
|
+
const {
|
|
118
|
+
CLIENT_PORT,
|
|
119
|
+
SERVER_PORT,
|
|
120
|
+
authDisabled,
|
|
121
|
+
sessionToken,
|
|
122
|
+
abort,
|
|
123
|
+
cancelled,
|
|
124
|
+
} = clientOptions;
|
|
104
125
|
const clientCommand = "npx";
|
|
105
|
-
const
|
|
126
|
+
const host = process.env.HOST || "localhost";
|
|
127
|
+
const clientArgs = ["vite", "--port", CLIENT_PORT, "--host", host];
|
|
106
128
|
|
|
107
129
|
const client = spawn(clientCommand, clientArgs, {
|
|
108
130
|
cwd: resolve(__dirname, ".."),
|
|
109
|
-
env: { ...process.env,
|
|
131
|
+
env: { ...process.env, CLIENT_PORT },
|
|
110
132
|
signal: abort.signal,
|
|
111
133
|
echoOutput: true,
|
|
112
134
|
});
|
|
113
135
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
136
|
+
const url = getClientUrl(
|
|
137
|
+
CLIENT_PORT,
|
|
138
|
+
authDisabled,
|
|
139
|
+
sessionToken,
|
|
140
|
+
SERVER_PORT,
|
|
141
|
+
);
|
|
119
142
|
|
|
120
|
-
|
|
121
|
-
|
|
143
|
+
// Give vite time to start before opening or logging the URL
|
|
144
|
+
setTimeout(() => {
|
|
145
|
+
console.log(`\n🚀 MCP Inspector is up and running at:\n ${url}\n`);
|
|
146
|
+
if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
|
|
147
|
+
console.log("🌐 Opening browser...");
|
|
122
148
|
open(url);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
149
|
+
}
|
|
150
|
+
}, 3000);
|
|
126
151
|
|
|
127
152
|
await new Promise((resolve) => {
|
|
128
153
|
client.subscribe({
|
|
@@ -139,7 +164,14 @@ async function startDevClient(clientOptions) {
|
|
|
139
164
|
}
|
|
140
165
|
|
|
141
166
|
async function startProdClient(clientOptions) {
|
|
142
|
-
const {
|
|
167
|
+
const {
|
|
168
|
+
CLIENT_PORT,
|
|
169
|
+
SERVER_PORT,
|
|
170
|
+
authDisabled,
|
|
171
|
+
sessionToken,
|
|
172
|
+
abort,
|
|
173
|
+
cancelled,
|
|
174
|
+
} = clientOptions;
|
|
143
175
|
const inspectorClientPath = resolve(
|
|
144
176
|
__dirname,
|
|
145
177
|
"../..",
|
|
@@ -148,16 +180,19 @@ async function startProdClient(clientOptions) {
|
|
|
148
180
|
"client.js",
|
|
149
181
|
);
|
|
150
182
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
183
|
+
const url = getClientUrl(
|
|
184
|
+
CLIENT_PORT,
|
|
185
|
+
authDisabled,
|
|
186
|
+
sessionToken,
|
|
187
|
+
SERVER_PORT,
|
|
188
|
+
);
|
|
158
189
|
|
|
159
190
|
await spawnPromise("node", [inspectorClientPath], {
|
|
160
|
-
env: {
|
|
191
|
+
env: {
|
|
192
|
+
...process.env,
|
|
193
|
+
CLIENT_PORT,
|
|
194
|
+
INSPECTOR_URL: url,
|
|
195
|
+
},
|
|
161
196
|
signal: abort.signal,
|
|
162
197
|
echoOutput: true,
|
|
163
198
|
});
|
|
@@ -204,7 +239,7 @@ async function main() {
|
|
|
204
239
|
}
|
|
205
240
|
|
|
206
241
|
const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274";
|
|
207
|
-
const SERVER_PORT = process.env.SERVER_PORT ??
|
|
242
|
+
const SERVER_PORT = process.env.SERVER_PORT ?? DEFAULT_MCP_PROXY_LISTEN_PORT;
|
|
208
243
|
|
|
209
244
|
console.log(
|
|
210
245
|
isDev
|
|
@@ -249,6 +284,7 @@ async function main() {
|
|
|
249
284
|
try {
|
|
250
285
|
const clientOptions = {
|
|
251
286
|
CLIENT_PORT,
|
|
287
|
+
SERVER_PORT,
|
|
252
288
|
authDisabled,
|
|
253
289
|
sessionToken,
|
|
254
290
|
abort,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useToast, r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-
|
|
1
|
+
import { u as useToast, r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-DI7JCTeu.js";
|
|
2
2
|
import { p as parseOAuthCallbackParams, g as generateOAuthErrorDescription } from "./oauthUtils-DTcoXpSP.js";
|
|
3
3
|
const OAuthCallback = ({ onConnect }) => {
|
|
4
4
|
const { toast } = useToast();
|
package/client/dist/assets/{OAuthDebugCallback-DiBt_oxh.js → OAuthDebugCallback-9JxBAysc.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, S as SESSION_KEYS, j as jsxRuntimeExports } from "./index-
|
|
1
|
+
import { r as reactExports, S as SESSION_KEYS, j as jsxRuntimeExports } from "./index-DI7JCTeu.js";
|
|
2
2
|
import { p as parseOAuthCallbackParams, g as generateOAuthErrorDescription } from "./oauthUtils-DTcoXpSP.js";
|
|
3
3
|
const OAuthDebugCallback = ({ onConnect }) => {
|
|
4
4
|
reactExports.useEffect(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/OAuthCallback-DMQy4ibj.js","assets/oauthUtils-DTcoXpSP.js","assets/OAuthDebugCallback-9JxBAysc.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
function _mergeNamespaces(n, m2) {
|
|
3
3
|
for (var i = 0; i < m2.length; i++) {
|
|
4
4
|
const e = m2[i];
|
|
@@ -11612,8 +11612,9 @@ class ZodError extends Error {
|
|
|
11612
11612
|
const formErrors = [];
|
|
11613
11613
|
for (const sub of this.issues) {
|
|
11614
11614
|
if (sub.path.length > 0) {
|
|
11615
|
-
|
|
11616
|
-
fieldErrors[
|
|
11615
|
+
const firstEl = sub.path[0];
|
|
11616
|
+
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
|
|
11617
|
+
fieldErrors[firstEl].push(mapper(sub));
|
|
11617
11618
|
} else {
|
|
11618
11619
|
formErrors.push(mapper(sub));
|
|
11619
11620
|
}
|
|
@@ -11689,6 +11690,8 @@ const errorMap = (issue, _ctx) => {
|
|
|
11689
11690
|
message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
|
|
11690
11691
|
else if (issue.type === "number")
|
|
11691
11692
|
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
11693
|
+
else if (issue.type === "bigint")
|
|
11694
|
+
message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
|
|
11692
11695
|
else if (issue.type === "date")
|
|
11693
11696
|
message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
|
|
11694
11697
|
else
|
|
@@ -12241,6 +12244,8 @@ function isValidJWT(jwt, alg) {
|
|
|
12241
12244
|
return false;
|
|
12242
12245
|
try {
|
|
12243
12246
|
const [header] = jwt.split(".");
|
|
12247
|
+
if (!header)
|
|
12248
|
+
return false;
|
|
12244
12249
|
const base64 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
|
|
12245
12250
|
const decoded = JSON.parse(atob(base64));
|
|
12246
12251
|
if (typeof decoded !== "object" || decoded === null)
|
|
@@ -15913,7 +15918,7 @@ const ElicitResultSchema = ResultSchema.extend({
|
|
|
15913
15918
|
/**
|
|
15914
15919
|
* The user's response action.
|
|
15915
15920
|
*/
|
|
15916
|
-
action: enumType(["accept", "
|
|
15921
|
+
action: enumType(["accept", "decline", "cancel"]),
|
|
15917
15922
|
/**
|
|
15918
15923
|
* The collected user input content (only present if action is "accept").
|
|
15919
15924
|
*/
|
|
@@ -16505,7 +16510,11 @@ async function fetchWithCorsRetry(url, headers) {
|
|
|
16505
16510
|
return await fetch(url, { headers });
|
|
16506
16511
|
} catch (error) {
|
|
16507
16512
|
if (error instanceof TypeError) {
|
|
16508
|
-
|
|
16513
|
+
if (headers) {
|
|
16514
|
+
return fetchWithCorsRetry(url);
|
|
16515
|
+
} else {
|
|
16516
|
+
return void 0;
|
|
16517
|
+
}
|
|
16509
16518
|
}
|
|
16510
16519
|
throw error;
|
|
16511
16520
|
}
|
|
@@ -16524,7 +16533,7 @@ async function tryMetadataDiscovery(url, protocolVersion) {
|
|
|
16524
16533
|
return await fetchWithCorsRetry(url, headers);
|
|
16525
16534
|
}
|
|
16526
16535
|
function shouldAttemptFallback(response, pathname) {
|
|
16527
|
-
return response.status === 404 && pathname !== "/";
|
|
16536
|
+
return !response || response.status === 404 && pathname !== "/";
|
|
16528
16537
|
}
|
|
16529
16538
|
async function discoverOAuthMetadata(authorizationServerUrl, opts) {
|
|
16530
16539
|
var _a;
|
|
@@ -16534,16 +16543,10 @@ async function discoverOAuthMetadata(authorizationServerUrl, opts) {
|
|
|
16534
16543
|
const pathAwareUrl = new URL(wellKnownPath, issuer);
|
|
16535
16544
|
let response = await tryMetadataDiscovery(pathAwareUrl, protocolVersion);
|
|
16536
16545
|
if (shouldAttemptFallback(response, issuer.pathname)) {
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
return void 0;
|
|
16542
|
-
}
|
|
16543
|
-
} catch (_b) {
|
|
16544
|
-
return void 0;
|
|
16545
|
-
}
|
|
16546
|
-
} else if (response.status === 404) {
|
|
16546
|
+
const rootUrl = new URL("/.well-known/oauth-authorization-server", issuer);
|
|
16547
|
+
response = await tryMetadataDiscovery(rootUrl, protocolVersion);
|
|
16548
|
+
}
|
|
16549
|
+
if (!response || response.status === 404) {
|
|
16547
16550
|
return void 0;
|
|
16548
16551
|
}
|
|
16549
16552
|
if (!response.ok) {
|
|
@@ -22908,38 +22911,44 @@ function validateToolOutput(toolName, structuredContent) {
|
|
|
22908
22911
|
function hasOutputSchema(toolName) {
|
|
22909
22912
|
return toolOutputValidators.has(toolName);
|
|
22910
22913
|
}
|
|
22911
|
-
function generateDefaultValue(schema) {
|
|
22912
|
-
if ("default" in schema) {
|
|
22914
|
+
function generateDefaultValue(schema, propertyName, parentSchema) {
|
|
22915
|
+
if ("default" in schema && schema.default !== void 0) {
|
|
22913
22916
|
return schema.default;
|
|
22914
22917
|
}
|
|
22915
|
-
|
|
22916
|
-
if (schema.type === "array") return [];
|
|
22917
|
-
if (schema.type === "object") return {};
|
|
22918
|
-
return void 0;
|
|
22919
|
-
}
|
|
22918
|
+
const isRequired = propertyName && parentSchema ? isPropertyRequired(propertyName, parentSchema) : false;
|
|
22920
22919
|
switch (schema.type) {
|
|
22921
22920
|
case "string":
|
|
22922
|
-
return "";
|
|
22921
|
+
return isRequired ? "" : void 0;
|
|
22923
22922
|
case "number":
|
|
22924
22923
|
case "integer":
|
|
22925
|
-
return 0;
|
|
22924
|
+
return isRequired ? 0 : void 0;
|
|
22926
22925
|
case "boolean":
|
|
22927
|
-
return false;
|
|
22926
|
+
return isRequired ? false : void 0;
|
|
22928
22927
|
case "array":
|
|
22929
22928
|
return [];
|
|
22930
22929
|
case "object": {
|
|
22931
22930
|
if (!schema.properties) return {};
|
|
22932
22931
|
const obj = {};
|
|
22933
|
-
Object.entries(schema.properties).
|
|
22934
|
-
|
|
22935
|
-
|
|
22932
|
+
Object.entries(schema.properties).forEach(([key, prop]) => {
|
|
22933
|
+
if (isPropertyRequired(key, schema)) {
|
|
22934
|
+
const value = generateDefaultValue(prop, key, schema);
|
|
22935
|
+
if (value !== void 0) {
|
|
22936
|
+
obj[key] = value;
|
|
22937
|
+
}
|
|
22938
|
+
}
|
|
22936
22939
|
});
|
|
22937
22940
|
return obj;
|
|
22938
22941
|
}
|
|
22939
|
-
|
|
22942
|
+
case "null":
|
|
22940
22943
|
return null;
|
|
22944
|
+
default:
|
|
22945
|
+
return void 0;
|
|
22941
22946
|
}
|
|
22942
22947
|
}
|
|
22948
|
+
function isPropertyRequired(propertyName, schema) {
|
|
22949
|
+
var _a;
|
|
22950
|
+
return ((_a = schema.required) == null ? void 0 : _a.includes(propertyName)) ?? false;
|
|
22951
|
+
}
|
|
22943
22952
|
const DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
22944
22953
|
class Protocol {
|
|
22945
22954
|
constructor(_options) {
|
|
@@ -23900,6 +23909,7 @@ class SSEClientTransport {
|
|
|
23900
23909
|
this._eventSourceInit = opts === null || opts === void 0 ? void 0 : opts.eventSourceInit;
|
|
23901
23910
|
this._requestInit = opts === null || opts === void 0 ? void 0 : opts.requestInit;
|
|
23902
23911
|
this._authProvider = opts === null || opts === void 0 ? void 0 : opts.authProvider;
|
|
23912
|
+
this._fetch = opts === null || opts === void 0 ? void 0 : opts.fetch;
|
|
23903
23913
|
}
|
|
23904
23914
|
async _authThenStart() {
|
|
23905
23915
|
var _a;
|
|
@@ -23935,8 +23945,8 @@ class SSEClientTransport {
|
|
|
23935
23945
|
return headers;
|
|
23936
23946
|
}
|
|
23937
23947
|
_startOrAuth() {
|
|
23938
|
-
var _a;
|
|
23939
|
-
const fetchImpl = ((_a = this === null || this === void 0 ? void 0 : this._eventSourceInit) === null || _a === void 0 ? void 0 : _a.fetch)
|
|
23948
|
+
var _a, _b, _c;
|
|
23949
|
+
const fetchImpl = (_c = (_b = (_a = this === null || this === void 0 ? void 0 : this._eventSourceInit) === null || _a === void 0 ? void 0 : _a.fetch) !== null && _b !== void 0 ? _b : this._fetch) !== null && _c !== void 0 ? _c : fetch;
|
|
23940
23950
|
return new Promise((resolve, reject) => {
|
|
23941
23951
|
this._eventSource = new EventSource(this._url.href, {
|
|
23942
23952
|
...this._eventSourceInit,
|
|
@@ -23985,7 +23995,7 @@ class SSEClientTransport {
|
|
|
23985
23995
|
resolve();
|
|
23986
23996
|
});
|
|
23987
23997
|
this._eventSource.onmessage = (event) => {
|
|
23988
|
-
var _a2,
|
|
23998
|
+
var _a2, _b2;
|
|
23989
23999
|
const messageEvent = event;
|
|
23990
24000
|
let message;
|
|
23991
24001
|
try {
|
|
@@ -23994,7 +24004,7 @@ class SSEClientTransport {
|
|
|
23994
24004
|
(_a2 = this.onerror) === null || _a2 === void 0 ? void 0 : _a2.call(this, error);
|
|
23995
24005
|
return;
|
|
23996
24006
|
}
|
|
23997
|
-
(
|
|
24007
|
+
(_b2 = this.onmessage) === null || _b2 === void 0 ? void 0 : _b2.call(this, message);
|
|
23998
24008
|
};
|
|
23999
24009
|
});
|
|
24000
24010
|
}
|
|
@@ -24023,7 +24033,7 @@ class SSEClientTransport {
|
|
|
24023
24033
|
(_c = this.onclose) === null || _c === void 0 ? void 0 : _c.call(this);
|
|
24024
24034
|
}
|
|
24025
24035
|
async send(message) {
|
|
24026
|
-
var _a, _b;
|
|
24036
|
+
var _a, _b, _c;
|
|
24027
24037
|
if (!this._endpoint) {
|
|
24028
24038
|
throw new Error("Not connected");
|
|
24029
24039
|
}
|
|
@@ -24038,7 +24048,7 @@ class SSEClientTransport {
|
|
|
24038
24048
|
body: JSON.stringify(message),
|
|
24039
24049
|
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal
|
|
24040
24050
|
};
|
|
24041
|
-
const response = await fetch(this._endpoint, init);
|
|
24051
|
+
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._endpoint, init);
|
|
24042
24052
|
if (!response.ok) {
|
|
24043
24053
|
if (response.status === 401 && this._authProvider) {
|
|
24044
24054
|
this._resourceMetadataUrl = extractResourceMetadataUrl(response);
|
|
@@ -24052,7 +24062,7 @@ class SSEClientTransport {
|
|
|
24052
24062
|
throw new Error(`Error POSTing to endpoint (HTTP ${response.status}): ${text}`);
|
|
24053
24063
|
}
|
|
24054
24064
|
} catch (error) {
|
|
24055
|
-
(
|
|
24065
|
+
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
|
24056
24066
|
throw error;
|
|
24057
24067
|
}
|
|
24058
24068
|
}
|
|
@@ -24101,6 +24111,7 @@ class StreamableHTTPClientTransport {
|
|
|
24101
24111
|
this._resourceMetadataUrl = void 0;
|
|
24102
24112
|
this._requestInit = opts === null || opts === void 0 ? void 0 : opts.requestInit;
|
|
24103
24113
|
this._authProvider = opts === null || opts === void 0 ? void 0 : opts.authProvider;
|
|
24114
|
+
this._fetch = opts === null || opts === void 0 ? void 0 : opts.fetch;
|
|
24104
24115
|
this._sessionId = opts === null || opts === void 0 ? void 0 : opts.sessionId;
|
|
24105
24116
|
this._reconnectionOptions = (_a = opts === null || opts === void 0 ? void 0 : opts.reconnectionOptions) !== null && _a !== void 0 ? _a : DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
|
24106
24117
|
}
|
|
@@ -24136,10 +24147,14 @@ class StreamableHTTPClientTransport {
|
|
|
24136
24147
|
if (this._protocolVersion) {
|
|
24137
24148
|
headers["mcp-protocol-version"] = this._protocolVersion;
|
|
24138
24149
|
}
|
|
24139
|
-
|
|
24150
|
+
const extraHeaders = this._normalizeHeaders((_a = this._requestInit) === null || _a === void 0 ? void 0 : _a.headers);
|
|
24151
|
+
return new Headers({
|
|
24152
|
+
...headers,
|
|
24153
|
+
...extraHeaders
|
|
24154
|
+
});
|
|
24140
24155
|
}
|
|
24141
24156
|
async _startOrAuthSse(options) {
|
|
24142
|
-
var _a, _b;
|
|
24157
|
+
var _a, _b, _c;
|
|
24143
24158
|
const { resumptionToken } = options;
|
|
24144
24159
|
try {
|
|
24145
24160
|
const headers = await this._commonHeaders();
|
|
@@ -24147,10 +24162,10 @@ class StreamableHTTPClientTransport {
|
|
|
24147
24162
|
if (resumptionToken) {
|
|
24148
24163
|
headers.set("last-event-id", resumptionToken);
|
|
24149
24164
|
}
|
|
24150
|
-
const response = await fetch(this._url, {
|
|
24165
|
+
const response = await ((_a = this._fetch) !== null && _a !== void 0 ? _a : fetch)(this._url, {
|
|
24151
24166
|
method: "GET",
|
|
24152
24167
|
headers,
|
|
24153
|
-
signal: (
|
|
24168
|
+
signal: (_b = this._abortController) === null || _b === void 0 ? void 0 : _b.signal
|
|
24154
24169
|
});
|
|
24155
24170
|
if (!response.ok) {
|
|
24156
24171
|
if (response.status === 401 && this._authProvider) {
|
|
@@ -24163,7 +24178,7 @@ class StreamableHTTPClientTransport {
|
|
|
24163
24178
|
}
|
|
24164
24179
|
this._handleSseStream(response.body, options);
|
|
24165
24180
|
} catch (error) {
|
|
24166
|
-
(
|
|
24181
|
+
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
|
24167
24182
|
throw error;
|
|
24168
24183
|
}
|
|
24169
24184
|
}
|
|
@@ -24179,6 +24194,17 @@ class StreamableHTTPClientTransport {
|
|
|
24179
24194
|
const maxDelay = this._reconnectionOptions.maxReconnectionDelay;
|
|
24180
24195
|
return Math.min(initialDelay * Math.pow(growFactor, attempt), maxDelay);
|
|
24181
24196
|
}
|
|
24197
|
+
_normalizeHeaders(headers) {
|
|
24198
|
+
if (!headers)
|
|
24199
|
+
return {};
|
|
24200
|
+
if (headers instanceof Headers) {
|
|
24201
|
+
return Object.fromEntries(headers.entries());
|
|
24202
|
+
}
|
|
24203
|
+
if (Array.isArray(headers)) {
|
|
24204
|
+
return Object.fromEntries(headers);
|
|
24205
|
+
}
|
|
24206
|
+
return { ...headers };
|
|
24207
|
+
}
|
|
24182
24208
|
/**
|
|
24183
24209
|
* Schedule a reconnection attempt with exponential backoff
|
|
24184
24210
|
*
|
|
@@ -24275,7 +24301,7 @@ class StreamableHTTPClientTransport {
|
|
|
24275
24301
|
(_b = this.onclose) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
24276
24302
|
}
|
|
24277
24303
|
async send(message, options) {
|
|
24278
|
-
var _a, _b, _c;
|
|
24304
|
+
var _a, _b, _c, _d;
|
|
24279
24305
|
try {
|
|
24280
24306
|
const { resumptionToken, onresumptiontoken } = options || {};
|
|
24281
24307
|
if (resumptionToken) {
|
|
@@ -24295,7 +24321,7 @@ class StreamableHTTPClientTransport {
|
|
|
24295
24321
|
body: JSON.stringify(message),
|
|
24296
24322
|
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal
|
|
24297
24323
|
};
|
|
24298
|
-
const response = await fetch(this._url, init);
|
|
24324
|
+
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._url, init);
|
|
24299
24325
|
const sessionId = response.headers.get("mcp-session-id");
|
|
24300
24326
|
if (sessionId) {
|
|
24301
24327
|
this._sessionId = sessionId;
|
|
@@ -24331,14 +24357,14 @@ class StreamableHTTPClientTransport {
|
|
|
24331
24357
|
const data2 = await response.json();
|
|
24332
24358
|
const responseMessages = Array.isArray(data2) ? data2.map((msg) => JSONRPCMessageSchema.parse(msg)) : [JSONRPCMessageSchema.parse(data2)];
|
|
24333
24359
|
for (const msg of responseMessages) {
|
|
24334
|
-
(
|
|
24360
|
+
(_c = this.onmessage) === null || _c === void 0 ? void 0 : _c.call(this, msg);
|
|
24335
24361
|
}
|
|
24336
24362
|
} else {
|
|
24337
24363
|
throw new StreamableHTTPError(-1, `Unexpected content type: ${contentType}`);
|
|
24338
24364
|
}
|
|
24339
24365
|
}
|
|
24340
24366
|
} catch (error) {
|
|
24341
|
-
(
|
|
24367
|
+
(_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, error);
|
|
24342
24368
|
throw error;
|
|
24343
24369
|
}
|
|
24344
24370
|
}
|
|
@@ -24357,7 +24383,7 @@ class StreamableHTTPClientTransport {
|
|
|
24357
24383
|
* the server does not allow clients to terminate sessions.
|
|
24358
24384
|
*/
|
|
24359
24385
|
async terminateSession() {
|
|
24360
|
-
var _a, _b;
|
|
24386
|
+
var _a, _b, _c;
|
|
24361
24387
|
if (!this._sessionId) {
|
|
24362
24388
|
return;
|
|
24363
24389
|
}
|
|
@@ -24369,13 +24395,13 @@ class StreamableHTTPClientTransport {
|
|
|
24369
24395
|
headers,
|
|
24370
24396
|
signal: (_a = this._abortController) === null || _a === void 0 ? void 0 : _a.signal
|
|
24371
24397
|
};
|
|
24372
|
-
const response = await fetch(this._url, init);
|
|
24398
|
+
const response = await ((_b = this._fetch) !== null && _b !== void 0 ? _b : fetch)(this._url, init);
|
|
24373
24399
|
if (!response.ok && response.status !== 405) {
|
|
24374
24400
|
throw new StreamableHTTPError(response.status, `Failed to terminate session: ${response.statusText}`);
|
|
24375
24401
|
}
|
|
24376
24402
|
this._sessionId = void 0;
|
|
24377
24403
|
} catch (error) {
|
|
24378
|
-
(
|
|
24404
|
+
(_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
|
|
24379
24405
|
throw error;
|
|
24380
24406
|
}
|
|
24381
24407
|
}
|
|
@@ -24395,16 +24421,26 @@ const StdErrNotificationSchema = NotificationSchema.extend({
|
|
|
24395
24421
|
ClientNotificationSchema.or(
|
|
24396
24422
|
StdErrNotificationSchema
|
|
24397
24423
|
).or(ServerNotificationSchema).or(NotificationSchema);
|
|
24398
|
-
const version$1 = "0.
|
|
24424
|
+
const version$1 = "0.16.0";
|
|
24399
24425
|
const packageJson = {
|
|
24400
24426
|
version: version$1
|
|
24401
24427
|
};
|
|
24428
|
+
const getSearchParam = (key) => {
|
|
24429
|
+
try {
|
|
24430
|
+
const url = new URL(window.location.href);
|
|
24431
|
+
return url.searchParams.get(key);
|
|
24432
|
+
} catch {
|
|
24433
|
+
return null;
|
|
24434
|
+
}
|
|
24435
|
+
};
|
|
24402
24436
|
const getMCPProxyAddress = (config) => {
|
|
24403
|
-
|
|
24437
|
+
let proxyFullAddress = config.MCP_PROXY_FULL_ADDRESS.value;
|
|
24404
24438
|
if (proxyFullAddress) {
|
|
24439
|
+
proxyFullAddress = proxyFullAddress.replace(/\/+$/, "");
|
|
24405
24440
|
return proxyFullAddress;
|
|
24406
24441
|
}
|
|
24407
|
-
|
|
24442
|
+
const proxyPort = getSearchParam("MCP_PROXY_PORT") || DEFAULT_MCP_PROXY_LISTEN_PORT;
|
|
24443
|
+
return `${window.location.protocol}//${window.location.hostname}:${proxyPort}`;
|
|
24408
24444
|
};
|
|
24409
24445
|
const getMCPServerRequestTimeout = (config) => {
|
|
24410
24446
|
return config.MCP_SERVER_REQUEST_TIMEOUT.value;
|
|
@@ -24421,14 +24457,6 @@ const getMCPProxyAuthToken = (config) => {
|
|
|
24421
24457
|
header: "X-MCP-Proxy-Auth"
|
|
24422
24458
|
};
|
|
24423
24459
|
};
|
|
24424
|
-
const getSearchParam = (key) => {
|
|
24425
|
-
try {
|
|
24426
|
-
const url = new URL(window.location.href);
|
|
24427
|
-
return url.searchParams.get(key);
|
|
24428
|
-
} catch {
|
|
24429
|
-
return null;
|
|
24430
|
-
}
|
|
24431
|
-
};
|
|
24432
24460
|
const getInitialTransportType = () => {
|
|
24433
24461
|
const param = getSearchParam("transport");
|
|
24434
24462
|
if (param === "stdio" || param === "sse" || param === "streamable-http") {
|
|
@@ -26864,7 +26892,9 @@ const HistoryAndNotifications = ({
|
|
|
26864
26892
|
"div",
|
|
26865
26893
|
{
|
|
26866
26894
|
className: "flex justify-between items-center cursor-pointer",
|
|
26867
|
-
onClick: () => toggleNotificationExpansion(
|
|
26895
|
+
onClick: () => toggleNotificationExpansion(
|
|
26896
|
+
serverNotifications.length - 1 - index2
|
|
26897
|
+
),
|
|
26868
26898
|
children: [
|
|
26869
26899
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "font-mono", children: [
|
|
26870
26900
|
serverNotifications.length - index2,
|
|
@@ -26872,11 +26902,11 @@ const HistoryAndNotifications = ({
|
|
|
26872
26902
|
" ",
|
|
26873
26903
|
notification.method
|
|
26874
26904
|
] }),
|
|
26875
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expandedNotifications[index2] ? "▼" : "▶" })
|
|
26905
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expandedNotifications[serverNotifications.length - 1 - index2] ? "▼" : "▶" })
|
|
26876
26906
|
]
|
|
26877
26907
|
}
|
|
26878
26908
|
),
|
|
26879
|
-
expandedNotifications[index2] && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
|
|
26909
|
+
expandedNotifications[serverNotifications.length - 1 - index2] && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2", children: [
|
|
26880
26910
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-between items-center mb-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-purple-600", children: "Details:" }) }),
|
|
26881
26911
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
26882
26912
|
JsonView,
|
|
@@ -31455,9 +31485,9 @@ const PromptsTab = ({
|
|
|
31455
31485
|
setSelectedPrompt(prompt);
|
|
31456
31486
|
setPromptArgs({});
|
|
31457
31487
|
},
|
|
31458
|
-
renderItem: (prompt) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
31488
|
+
renderItem: (prompt) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-start", children: [
|
|
31459
31489
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1", children: prompt.name }),
|
|
31460
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-500", children: prompt.description })
|
|
31490
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-500 text-left", children: prompt.description })
|
|
31461
31491
|
] }),
|
|
31462
31492
|
title: "Prompts",
|
|
31463
31493
|
buttonText: nextCursor ? "List More Prompts" : "List Prompts",
|
|
@@ -33916,10 +33946,37 @@ const JsonEditor = ({
|
|
|
33916
33946
|
const isSimpleObject = (schema) => {
|
|
33917
33947
|
const supportedTypes = ["string", "number", "integer", "boolean", "null"];
|
|
33918
33948
|
if (supportedTypes.includes(schema.type)) return true;
|
|
33919
|
-
if (schema.type
|
|
33920
|
-
|
|
33921
|
-
|
|
33922
|
-
|
|
33949
|
+
if (schema.type === "object") {
|
|
33950
|
+
return Object.values(schema.properties ?? {}).every(
|
|
33951
|
+
(prop) => supportedTypes.includes(prop.type)
|
|
33952
|
+
);
|
|
33953
|
+
}
|
|
33954
|
+
if (schema.type === "array") {
|
|
33955
|
+
return !!schema.items && isSimpleObject(schema.items);
|
|
33956
|
+
}
|
|
33957
|
+
return false;
|
|
33958
|
+
};
|
|
33959
|
+
const getArrayItemDefault = (schema) => {
|
|
33960
|
+
if ("default" in schema && schema.default !== void 0) {
|
|
33961
|
+
return schema.default;
|
|
33962
|
+
}
|
|
33963
|
+
switch (schema.type) {
|
|
33964
|
+
case "string":
|
|
33965
|
+
return "";
|
|
33966
|
+
case "number":
|
|
33967
|
+
case "integer":
|
|
33968
|
+
return 0;
|
|
33969
|
+
case "boolean":
|
|
33970
|
+
return false;
|
|
33971
|
+
case "array":
|
|
33972
|
+
return [];
|
|
33973
|
+
case "object":
|
|
33974
|
+
return {};
|
|
33975
|
+
case "null":
|
|
33976
|
+
return null;
|
|
33977
|
+
default:
|
|
33978
|
+
return null;
|
|
33979
|
+
}
|
|
33923
33980
|
};
|
|
33924
33981
|
const DynamicJsonForm = ({
|
|
33925
33982
|
schema,
|
|
@@ -33930,6 +33987,8 @@ const DynamicJsonForm = ({
|
|
|
33930
33987
|
const isOnlyJSON = !isSimpleObject(schema);
|
|
33931
33988
|
const [isJsonMode, setIsJsonMode] = reactExports.useState(isOnlyJSON);
|
|
33932
33989
|
const [jsonError, setJsonError] = reactExports.useState();
|
|
33990
|
+
const [copiedJson, setCopiedJson] = reactExports.useState(false);
|
|
33991
|
+
const { toast: toast2 } = useToast();
|
|
33933
33992
|
const [rawJsonValue, setRawJsonValue] = reactExports.useState(
|
|
33934
33993
|
JSON.stringify(value ?? generateDefaultValue(schema), null, 2)
|
|
33935
33994
|
);
|
|
@@ -33987,13 +34046,14 @@ const DynamicJsonForm = ({
|
|
|
33987
34046
|
setJsonError(err instanceof Error ? err.message : "Invalid JSON");
|
|
33988
34047
|
}
|
|
33989
34048
|
};
|
|
33990
|
-
const renderFormFields = (propSchema, currentValue, path = [], depth = 0) => {
|
|
34049
|
+
const renderFormFields = (propSchema, currentValue, path = [], depth = 0, parentSchema, propertyName) => {
|
|
34050
|
+
var _a, _b, _c;
|
|
33991
34051
|
if (depth >= maxDepth && (propSchema.type === "object" || propSchema.type === "array")) {
|
|
33992
34052
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
33993
34053
|
JsonEditor,
|
|
33994
34054
|
{
|
|
33995
34055
|
value: JSON.stringify(
|
|
33996
|
-
currentValue ?? generateDefaultValue(propSchema),
|
|
34056
|
+
currentValue ?? generateDefaultValue(propSchema, propertyName, parentSchema),
|
|
33997
34057
|
null,
|
|
33998
34058
|
2
|
|
33999
34059
|
),
|
|
@@ -34010,6 +34070,7 @@ const DynamicJsonForm = ({
|
|
|
34010
34070
|
}
|
|
34011
34071
|
);
|
|
34012
34072
|
}
|
|
34073
|
+
const isRequired = ((_a = parentSchema == null ? void 0 : parentSchema.required) == null ? void 0 : _a.includes(propertyName || "")) ?? false;
|
|
34013
34074
|
switch (propSchema.type) {
|
|
34014
34075
|
case "string":
|
|
34015
34076
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -34019,14 +34080,10 @@ const DynamicJsonForm = ({
|
|
|
34019
34080
|
value: currentValue ?? "",
|
|
34020
34081
|
onChange: (e) => {
|
|
34021
34082
|
const val = e.target.value;
|
|
34022
|
-
|
|
34023
|
-
handleFieldChange(path, void 0);
|
|
34024
|
-
} else {
|
|
34025
|
-
handleFieldChange(path, val);
|
|
34026
|
-
}
|
|
34083
|
+
handleFieldChange(path, val);
|
|
34027
34084
|
},
|
|
34028
34085
|
placeholder: propSchema.description,
|
|
34029
|
-
required:
|
|
34086
|
+
required: isRequired
|
|
34030
34087
|
}
|
|
34031
34088
|
);
|
|
34032
34089
|
case "number":
|
|
@@ -34037,7 +34094,7 @@ const DynamicJsonForm = ({
|
|
|
34037
34094
|
value: (currentValue == null ? void 0 : currentValue.toString()) ?? "",
|
|
34038
34095
|
onChange: (e) => {
|
|
34039
34096
|
const val = e.target.value;
|
|
34040
|
-
if (!val && !
|
|
34097
|
+
if (!val && !isRequired) {
|
|
34041
34098
|
handleFieldChange(path, void 0);
|
|
34042
34099
|
} else {
|
|
34043
34100
|
const num = Number(val);
|
|
@@ -34047,7 +34104,7 @@ const DynamicJsonForm = ({
|
|
|
34047
34104
|
}
|
|
34048
34105
|
},
|
|
34049
34106
|
placeholder: propSchema.description,
|
|
34050
|
-
required:
|
|
34107
|
+
required: isRequired
|
|
34051
34108
|
}
|
|
34052
34109
|
);
|
|
34053
34110
|
case "integer":
|
|
@@ -34059,7 +34116,7 @@ const DynamicJsonForm = ({
|
|
|
34059
34116
|
value: (currentValue == null ? void 0 : currentValue.toString()) ?? "",
|
|
34060
34117
|
onChange: (e) => {
|
|
34061
34118
|
const val = e.target.value;
|
|
34062
|
-
if (!val && !
|
|
34119
|
+
if (!val && !isRequired) {
|
|
34063
34120
|
handleFieldChange(path, void 0);
|
|
34064
34121
|
} else {
|
|
34065
34122
|
const num = Number(val);
|
|
@@ -34069,7 +34126,7 @@ const DynamicJsonForm = ({
|
|
|
34069
34126
|
}
|
|
34070
34127
|
},
|
|
34071
34128
|
placeholder: propSchema.description,
|
|
34072
|
-
required:
|
|
34129
|
+
required: isRequired
|
|
34073
34130
|
}
|
|
34074
34131
|
);
|
|
34075
34132
|
case "boolean":
|
|
@@ -34080,9 +34137,116 @@ const DynamicJsonForm = ({
|
|
|
34080
34137
|
checked: currentValue ?? false,
|
|
34081
34138
|
onChange: (e) => handleFieldChange(path, e.target.checked),
|
|
34082
34139
|
className: "w-4 h-4",
|
|
34083
|
-
required:
|
|
34140
|
+
required: isRequired
|
|
34141
|
+
}
|
|
34142
|
+
);
|
|
34143
|
+
case "object":
|
|
34144
|
+
if (!propSchema.properties) {
|
|
34145
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34146
|
+
JsonEditor,
|
|
34147
|
+
{
|
|
34148
|
+
value: JSON.stringify(currentValue ?? {}, null, 2),
|
|
34149
|
+
onChange: (newValue) => {
|
|
34150
|
+
try {
|
|
34151
|
+
const parsed = JSON.parse(newValue);
|
|
34152
|
+
handleFieldChange(path, parsed);
|
|
34153
|
+
setJsonError(void 0);
|
|
34154
|
+
} catch (err) {
|
|
34155
|
+
setJsonError(
|
|
34156
|
+
err instanceof Error ? err.message : "Invalid JSON"
|
|
34157
|
+
);
|
|
34158
|
+
}
|
|
34159
|
+
},
|
|
34160
|
+
error: jsonError
|
|
34161
|
+
}
|
|
34162
|
+
);
|
|
34163
|
+
}
|
|
34164
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 border rounded p-3", children: Object.entries(propSchema.properties).map(([key, subSchema]) => {
|
|
34165
|
+
var _a2;
|
|
34166
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
34167
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium mb-1", children: [
|
|
34168
|
+
key,
|
|
34169
|
+
((_a2 = propSchema.required) == null ? void 0 : _a2.includes(key)) && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
34170
|
+
] }),
|
|
34171
|
+
renderFormFields(
|
|
34172
|
+
subSchema,
|
|
34173
|
+
currentValue == null ? void 0 : currentValue[key],
|
|
34174
|
+
[...path, key],
|
|
34175
|
+
depth + 1,
|
|
34176
|
+
propSchema,
|
|
34177
|
+
key
|
|
34178
|
+
)
|
|
34179
|
+
] }, key);
|
|
34180
|
+
}) });
|
|
34181
|
+
case "array": {
|
|
34182
|
+
const arrayValue = Array.isArray(currentValue) ? currentValue : [];
|
|
34183
|
+
if (!propSchema.items) return null;
|
|
34184
|
+
if (isSimpleObject(propSchema.items)) {
|
|
34185
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
34186
|
+
propSchema.description && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600", children: propSchema.description }),
|
|
34187
|
+
((_b = propSchema.items) == null ? void 0 : _b.description) && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-sm text-gray-500", children: [
|
|
34188
|
+
"Items: ",
|
|
34189
|
+
propSchema.items.description
|
|
34190
|
+
] }),
|
|
34191
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
|
|
34192
|
+
arrayValue.map((item, index2) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
34193
|
+
renderFormFields(
|
|
34194
|
+
propSchema.items,
|
|
34195
|
+
item,
|
|
34196
|
+
[...path, index2.toString()],
|
|
34197
|
+
depth + 1
|
|
34198
|
+
),
|
|
34199
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34200
|
+
Button,
|
|
34201
|
+
{
|
|
34202
|
+
variant: "outline",
|
|
34203
|
+
size: "sm",
|
|
34204
|
+
onClick: () => {
|
|
34205
|
+
const newArray = [...arrayValue];
|
|
34206
|
+
newArray.splice(index2, 1);
|
|
34207
|
+
handleFieldChange(path, newArray);
|
|
34208
|
+
},
|
|
34209
|
+
children: "Remove"
|
|
34210
|
+
}
|
|
34211
|
+
)
|
|
34212
|
+
] }, index2)),
|
|
34213
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34214
|
+
Button,
|
|
34215
|
+
{
|
|
34216
|
+
variant: "outline",
|
|
34217
|
+
size: "sm",
|
|
34218
|
+
onClick: () => {
|
|
34219
|
+
const defaultValue = getArrayItemDefault(
|
|
34220
|
+
propSchema.items
|
|
34221
|
+
);
|
|
34222
|
+
handleFieldChange(path, [...arrayValue, defaultValue]);
|
|
34223
|
+
},
|
|
34224
|
+
title: ((_c = propSchema.items) == null ? void 0 : _c.description) ? `Add new ${propSchema.items.description}` : "Add new item",
|
|
34225
|
+
children: "Add Item"
|
|
34226
|
+
}
|
|
34227
|
+
)
|
|
34228
|
+
] })
|
|
34229
|
+
] });
|
|
34230
|
+
}
|
|
34231
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34232
|
+
JsonEditor,
|
|
34233
|
+
{
|
|
34234
|
+
value: JSON.stringify(currentValue ?? [], null, 2),
|
|
34235
|
+
onChange: (newValue) => {
|
|
34236
|
+
try {
|
|
34237
|
+
const parsed = JSON.parse(newValue);
|
|
34238
|
+
handleFieldChange(path, parsed);
|
|
34239
|
+
setJsonError(void 0);
|
|
34240
|
+
} catch (err) {
|
|
34241
|
+
setJsonError(
|
|
34242
|
+
err instanceof Error ? err.message : "Invalid JSON"
|
|
34243
|
+
);
|
|
34244
|
+
}
|
|
34245
|
+
},
|
|
34246
|
+
error: jsonError
|
|
34084
34247
|
}
|
|
34085
34248
|
);
|
|
34249
|
+
}
|
|
34086
34250
|
default:
|
|
34087
34251
|
return null;
|
|
34088
34252
|
}
|
|
@@ -34106,18 +34270,57 @@ const DynamicJsonForm = ({
|
|
|
34106
34270
|
setIsJsonMode(true);
|
|
34107
34271
|
}
|
|
34108
34272
|
}, [shouldUseJsonMode, isJsonMode]);
|
|
34273
|
+
const handleCopyJson = reactExports.useCallback(() => {
|
|
34274
|
+
const copyToClipboard = async () => {
|
|
34275
|
+
try {
|
|
34276
|
+
await navigator.clipboard.writeText(
|
|
34277
|
+
JSON.stringify(value, null, 2) ?? "[]"
|
|
34278
|
+
);
|
|
34279
|
+
setCopiedJson(true);
|
|
34280
|
+
toast2({
|
|
34281
|
+
title: "JSON copied",
|
|
34282
|
+
description: "The JSON data has been successfully copied to your clipboard."
|
|
34283
|
+
});
|
|
34284
|
+
setTimeout(() => {
|
|
34285
|
+
setCopiedJson(false);
|
|
34286
|
+
}, 2e3);
|
|
34287
|
+
} catch (error) {
|
|
34288
|
+
toast2({
|
|
34289
|
+
title: "Error",
|
|
34290
|
+
description: `Failed to copy JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
34291
|
+
variant: "destructive"
|
|
34292
|
+
});
|
|
34293
|
+
}
|
|
34294
|
+
};
|
|
34295
|
+
copyToClipboard();
|
|
34296
|
+
}, [toast2, value]);
|
|
34109
34297
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
|
|
34110
34298
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end space-x-2", children: [
|
|
34111
|
-
isJsonMode && /* @__PURE__ */ jsxRuntimeExports.
|
|
34112
|
-
|
|
34113
|
-
|
|
34114
|
-
|
|
34115
|
-
|
|
34116
|
-
|
|
34117
|
-
|
|
34118
|
-
|
|
34119
|
-
|
|
34120
|
-
|
|
34299
|
+
isJsonMode && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
34300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
34301
|
+
Button,
|
|
34302
|
+
{
|
|
34303
|
+
type: "button",
|
|
34304
|
+
variant: "outline",
|
|
34305
|
+
size: "sm",
|
|
34306
|
+
onClick: handleCopyJson,
|
|
34307
|
+
children: [
|
|
34308
|
+
copiedJson ? /* @__PURE__ */ jsxRuntimeExports.jsx(CheckCheck, { className: "h-4 w-4 mr-2" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-4 w-4 mr-2" }),
|
|
34309
|
+
"Copy JSON"
|
|
34310
|
+
]
|
|
34311
|
+
}
|
|
34312
|
+
),
|
|
34313
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
34314
|
+
Button,
|
|
34315
|
+
{
|
|
34316
|
+
type: "button",
|
|
34317
|
+
variant: "outline",
|
|
34318
|
+
size: "sm",
|
|
34319
|
+
onClick: formatJson,
|
|
34320
|
+
children: "Format JSON"
|
|
34321
|
+
}
|
|
34322
|
+
)
|
|
34323
|
+
] }),
|
|
34121
34324
|
!isOnlyJSON && /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", size: "sm", onClick: handleSwitchToFormMode, children: isJsonMode ? "Switch to Form" : "Switch to JSON" })
|
|
34122
34325
|
] }),
|
|
34123
34326
|
isJsonMode ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -35595,7 +35798,7 @@ const useTheme = () => {
|
|
|
35595
35798
|
[theme, setThemeWithSideEffect]
|
|
35596
35799
|
);
|
|
35597
35800
|
};
|
|
35598
|
-
const version = "0.
|
|
35801
|
+
const version = "0.16.0";
|
|
35599
35802
|
var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
|
|
35600
35803
|
createPopperScope
|
|
35601
35804
|
]);
|
|
@@ -37204,7 +37407,11 @@ const ToolsTab = ({
|
|
|
37204
37407
|
(selectedTool == null ? void 0 : selectedTool.inputSchema.properties) ?? []
|
|
37205
37408
|
).map(([key, value]) => [
|
|
37206
37409
|
key,
|
|
37207
|
-
generateDefaultValue(
|
|
37410
|
+
generateDefaultValue(
|
|
37411
|
+
value,
|
|
37412
|
+
key,
|
|
37413
|
+
selectedTool == null ? void 0 : selectedTool.inputSchema
|
|
37414
|
+
)
|
|
37208
37415
|
]);
|
|
37209
37416
|
setParams(Object.fromEntries(params2));
|
|
37210
37417
|
}, [selectedTool]);
|
|
@@ -37235,13 +37442,18 @@ const ToolsTab = ({
|
|
|
37235
37442
|
Object.entries(selectedTool.inputSchema.properties ?? []).map(
|
|
37236
37443
|
([key, value]) => {
|
|
37237
37444
|
const prop = value;
|
|
37445
|
+
const inputSchema = selectedTool.inputSchema;
|
|
37446
|
+
const required2 = isPropertyRequired(key, inputSchema);
|
|
37238
37447
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
37239
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
37448
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37240
37449
|
Label$1,
|
|
37241
37450
|
{
|
|
37242
37451
|
htmlFor: key,
|
|
37243
37452
|
className: "block text-sm font-medium text-gray-700 dark:text-gray-300",
|
|
37244
|
-
children:
|
|
37453
|
+
children: [
|
|
37454
|
+
key,
|
|
37455
|
+
required2 && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" })
|
|
37456
|
+
]
|
|
37245
37457
|
}
|
|
37246
37458
|
),
|
|
37247
37459
|
prop.type === "boolean" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2 mt-2", children: [
|
|
@@ -37303,10 +37515,13 @@ const ToolsTab = ({
|
|
|
37303
37515
|
name: key,
|
|
37304
37516
|
placeholder: prop.description,
|
|
37305
37517
|
value: params[key] ?? "",
|
|
37306
|
-
onChange: (e) =>
|
|
37307
|
-
|
|
37308
|
-
|
|
37309
|
-
|
|
37518
|
+
onChange: (e) => {
|
|
37519
|
+
const value2 = e.target.value;
|
|
37520
|
+
setParams({
|
|
37521
|
+
...params,
|
|
37522
|
+
[key]: value2 === "" ? "" : Number(value2)
|
|
37523
|
+
});
|
|
37524
|
+
},
|
|
37310
37525
|
className: "mt-1"
|
|
37311
37526
|
}
|
|
37312
37527
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -37816,13 +38031,13 @@ const App = () => {
|
|
|
37816
38031
|
) });
|
|
37817
38032
|
if (window.location.pathname === "/oauth/callback") {
|
|
37818
38033
|
const OAuthCallback = React.lazy(
|
|
37819
|
-
() => __vitePreload(() => import("./OAuthCallback-
|
|
38034
|
+
() => __vitePreload(() => import("./OAuthCallback-DMQy4ibj.js"), true ? __vite__mapDeps([0,1]) : void 0)
|
|
37820
38035
|
);
|
|
37821
38036
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
|
|
37822
38037
|
}
|
|
37823
38038
|
if (window.location.pathname === "/oauth/callback/debug") {
|
|
37824
38039
|
const OAuthDebugCallback = React.lazy(
|
|
37825
|
-
() => __vitePreload(() => import("./OAuthDebugCallback-
|
|
38040
|
+
() => __vitePreload(() => import("./OAuthDebugCallback-9JxBAysc.js"), true ? __vite__mapDeps([2,1]) : void 0)
|
|
37826
38041
|
);
|
|
37827
38042
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
|
|
37828
38043
|
}
|
package/client/dist/index.html
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
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-DI7JCTeu.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BwWj6LL9.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
|
-
<div id="root"></div>
|
|
12
|
+
<div id="root" class="w-full"></div>
|
|
13
13
|
</body>
|
|
14
14
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/inspector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Model Context Protocol inspector",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"check-version": "node scripts/check-version-consistency.js"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/inspector-cli": "^0.
|
|
48
|
-
"@modelcontextprotocol/inspector-client": "^0.
|
|
49
|
-
"@modelcontextprotocol/inspector-server": "^0.
|
|
47
|
+
"@modelcontextprotocol/inspector-cli": "^0.16.0",
|
|
48
|
+
"@modelcontextprotocol/inspector-client": "^0.16.0",
|
|
49
|
+
"@modelcontextprotocol/inspector-server": "^0.16.0",
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.13.1",
|
|
51
51
|
"concurrently": "^9.0.1",
|
|
52
52
|
"open": "^10.1.0",
|
|
@@ -64,5 +64,8 @@
|
|
|
64
64
|
"prettier": "3.3.3",
|
|
65
65
|
"rimraf": "^6.0.1",
|
|
66
66
|
"typescript": "^5.4.2"
|
|
67
|
+
},
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=22.7.5"
|
|
67
70
|
}
|
|
68
71
|
}
|
package/server/build/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import express from "express";
|
|
|
11
11
|
import { findActualExecutable } from "spawn-rx";
|
|
12
12
|
import mcpProxy from "./mcpProxy.js";
|
|
13
13
|
import { randomUUID, randomBytes, timingSafeEqual } from "node:crypto";
|
|
14
|
+
const DEFAULT_MCP_PROXY_LISTEN_PORT = "6277";
|
|
14
15
|
const SSE_HEADERS_PASSTHROUGH = ["authorization"];
|
|
15
16
|
const STREAMABLE_HTTP_HEADERS_PASSTHROUGH = [
|
|
16
17
|
"authorization",
|
|
@@ -73,11 +74,10 @@ const originValidationMiddleware = (req, res, next) => {
|
|
|
73
74
|
const origin = req.headers.origin;
|
|
74
75
|
// Default origins based on CLIENT_PORT or use environment variable
|
|
75
76
|
const clientPort = process.env.CLIENT_PORT || "6274";
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const defaultOrigin = `http://localhost:${clientPort}`;
|
|
78
|
+
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",") || [
|
|
79
|
+
defaultOrigin,
|
|
79
80
|
];
|
|
80
|
-
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(",") || defaultOrigins;
|
|
81
81
|
if (origin && !allowedOrigins.includes(origin)) {
|
|
82
82
|
console.error(`Invalid origin: ${origin}`);
|
|
83
83
|
res.status(403).json({
|
|
@@ -405,18 +405,14 @@ app.get("/config", originValidationMiddleware, authMiddleware, (req, res) => {
|
|
|
405
405
|
res.status(500).json(error);
|
|
406
406
|
}
|
|
407
407
|
});
|
|
408
|
-
const PORT = parseInt(process.env.
|
|
409
|
-
const HOST = process.env.HOST || "
|
|
408
|
+
const PORT = parseInt(process.env.SERVER_PORT || DEFAULT_MCP_PROXY_LISTEN_PORT, 10);
|
|
409
|
+
const HOST = process.env.HOST || "localhost";
|
|
410
410
|
const server = app.listen(PORT, HOST);
|
|
411
411
|
server.on("listening", () => {
|
|
412
412
|
console.log(`⚙️ Proxy server listening on ${HOST}:${PORT}`);
|
|
413
413
|
if (!authDisabled) {
|
|
414
|
-
console.log(`🔑 Session token: ${sessionToken}`
|
|
415
|
-
|
|
416
|
-
// Display clickable URL with pre-filled token
|
|
417
|
-
const clientPort = process.env.CLIENT_PORT || "6274";
|
|
418
|
-
const clientUrl = `http://localhost:${clientPort}/?MCP_PROXY_AUTH_TOKEN=${sessionToken}`;
|
|
419
|
-
console.log(`\n🔗 Open inspector with token pre-filled:\n ${clientUrl}\n`);
|
|
414
|
+
console.log(`🔑 Session token: ${sessionToken}\n ` +
|
|
415
|
+
`Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth`);
|
|
420
416
|
}
|
|
421
417
|
else {
|
|
422
418
|
console.log(`⚠️ WARNING: Authentication is disabled. This is not recommended.`);
|
package/server/build/mcpProxy.js
CHANGED
|
@@ -3,11 +3,12 @@ function onClientError(error) {
|
|
|
3
3
|
console.error("Error from inspector client:", error);
|
|
4
4
|
}
|
|
5
5
|
function onServerError(error) {
|
|
6
|
-
if (
|
|
7
|
-
error.message.includes("Error POSTing to endpoint (HTTP 404)")) ||
|
|
8
|
-
(error?.cause && JSON.stringify(error.cause).includes("ECONNREFUSED"))) {
|
|
6
|
+
if (error?.cause && JSON.stringify(error.cause).includes("ECONNREFUSED")) {
|
|
9
7
|
console.error("Connection refused. Is the MCP server running?");
|
|
10
8
|
}
|
|
9
|
+
else if (error.message && error.message.includes("404")) {
|
|
10
|
+
console.error("Error accessing endpoint (HTTP 404)");
|
|
11
|
+
}
|
|
11
12
|
else {
|
|
12
13
|
console.error("Error from MCP server:", error);
|
|
13
14
|
}
|