@modelcontextprotocol/inspector 0.16.4 → 0.16.6
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 +24 -0
- package/cli/build/cli.js +34 -3
- package/cli/build/client/prompts.js +16 -1
- package/cli/build/client/tools.js +12 -2
- package/cli/build/index.js +32 -4
- package/cli/build/transport.js +17 -3
- package/cli/build/utils/awaitable-log.js +7 -0
- package/client/dist/assets/{OAuthCallback-DyaAiF-O.js → OAuthCallback-Cmffn8om.js} +1 -1
- package/client/dist/assets/{OAuthDebugCallback-BD-zJllm.js → OAuthDebugCallback-BhzcPtuF.js} +9 -1
- package/client/dist/assets/{index-MFoeZZBS.js → index-B_qh-Btq.js} +159 -105
- package/client/dist/assets/{index-BWZfLo5E.css → index-C217Ot8c.css} +4 -10
- package/client/dist/index.html +2 -2
- package/package.json +13 -6
- package/server/build/index.js +71 -12
package/README.md
CHANGED
|
@@ -29,6 +29,14 @@ npx @modelcontextprotocol/inspector
|
|
|
29
29
|
|
|
30
30
|
The server will start up and the UI will be accessible at `http://localhost:6274`.
|
|
31
31
|
|
|
32
|
+
### Docker Container
|
|
33
|
+
|
|
34
|
+
You can also start it in a Docker container with the following command:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
docker run --rm --network host -p 6274:6274 -p 6277:6277 ghcr.io/modelcontextprotocol/inspector:latest
|
|
38
|
+
```
|
|
39
|
+
|
|
32
40
|
### From an MCP server repository
|
|
33
41
|
|
|
34
42
|
To inspect an MCP server implementation, there's no need to clone this repo. Instead, use `npx`. For example, if your server is built at `build/index.js`:
|
|
@@ -166,6 +174,16 @@ If you need to disable authentication (NOT RECOMMENDED), you can set the `DANGER
|
|
|
166
174
|
DANGEROUSLY_OMIT_AUTH=true npm start
|
|
167
175
|
```
|
|
168
176
|
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
**🚨 WARNING 🚨**
|
|
180
|
+
|
|
181
|
+
Disabling authentication with `DANGEROUSLY_OMIT_AUTH` is incredibly dangerous! Disabling auth leaves your machine open to attack not just when exposed to the public internet, but also **via your web browser**. Meaning, visiting a malicious website OR viewing a malicious advertizement could allow an attacker to remotely compromise your computer. Do not disable this feature unless you truly understand the risks.
|
|
182
|
+
|
|
183
|
+
Read more about the risks of this vulnerability on Oligo's blog: [Critical RCE Vulnerability in Anthropic MCP Inspector - CVE-2025-49596](https://www.oligo.security/blog/critical-rce-vulnerability-in-anthropic-mcp-inspector-cve-2025-49596)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
169
187
|
You can also set the token via the `MCP_PROXY_AUTH_TOKEN` environment variable when starting the server:
|
|
170
188
|
|
|
171
189
|
```bash
|
|
@@ -377,6 +395,9 @@ npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/lis
|
|
|
377
395
|
# Call a specific tool
|
|
378
396
|
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/call --tool-name mytool --tool-arg key=value --tool-arg another=value2
|
|
379
397
|
|
|
398
|
+
# Call a tool with JSON arguments
|
|
399
|
+
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/call --tool-name mytool --tool-arg 'options={"format": "json", "max_tokens": 100}'
|
|
400
|
+
|
|
380
401
|
# List available resources
|
|
381
402
|
npx @modelcontextprotocol/inspector --cli node build/index.js --method resources/list
|
|
382
403
|
|
|
@@ -389,6 +410,9 @@ npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com
|
|
|
389
410
|
# Connect to a remote MCP server (with Streamable HTTP transport)
|
|
390
411
|
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http --method tools/list
|
|
391
412
|
|
|
413
|
+
# Connect to a remote MCP server (with custom headers)
|
|
414
|
+
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http --method tools/list --header "X-API-Key: your-api-key"
|
|
415
|
+
|
|
392
416
|
# Call a tool on a remote server
|
|
393
417
|
npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
|
|
394
418
|
|
package/cli/build/cli.js
CHANGED
|
@@ -54,6 +54,10 @@ async function runWebClient(args) {
|
|
|
54
54
|
await spawnPromise("node", [inspectorClientPath, ...startArgs], {
|
|
55
55
|
signal: abort.signal,
|
|
56
56
|
echoOutput: true,
|
|
57
|
+
// pipe the stdout through here, prevents issues with buffering and
|
|
58
|
+
// dropping the end of console.out after 8192 chars due to node
|
|
59
|
+
// closing the stdout pipe before the output has finished flushing
|
|
60
|
+
stdio: "inherit",
|
|
57
61
|
});
|
|
58
62
|
}
|
|
59
63
|
catch (e) {
|
|
@@ -73,18 +77,28 @@ async function runCli(args) {
|
|
|
73
77
|
try {
|
|
74
78
|
// Build CLI arguments
|
|
75
79
|
const cliArgs = [cliPath];
|
|
80
|
+
// Add target URL/command first
|
|
81
|
+
cliArgs.push(args.command, ...args.args);
|
|
76
82
|
// Add transport flag if specified
|
|
77
83
|
if (args.transport && args.transport !== "stdio") {
|
|
78
84
|
// Convert streamable-http back to http for CLI mode
|
|
79
85
|
const cliTransport = args.transport === "streamable-http" ? "http" : args.transport;
|
|
80
86
|
cliArgs.push("--transport", cliTransport);
|
|
81
87
|
}
|
|
82
|
-
// Add
|
|
83
|
-
|
|
88
|
+
// Add headers if specified
|
|
89
|
+
if (args.headers) {
|
|
90
|
+
for (const [key, value] of Object.entries(args.headers)) {
|
|
91
|
+
cliArgs.push("--header", `${key}: ${value}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
84
94
|
await spawnPromise("node", cliArgs, {
|
|
85
95
|
env: { ...process.env, ...args.envArgs },
|
|
86
96
|
signal: abort.signal,
|
|
87
97
|
echoOutput: true,
|
|
98
|
+
// pipe the stdout through here, prevents issues with buffering and
|
|
99
|
+
// dropping the end of console.out after 8192 chars due to node
|
|
100
|
+
// closing the stdout pipe before the output has finished flushing
|
|
101
|
+
stdio: "inherit",
|
|
88
102
|
});
|
|
89
103
|
}
|
|
90
104
|
catch (e) {
|
|
@@ -126,6 +140,18 @@ function parseKeyValuePair(value, previous = {}) {
|
|
|
126
140
|
}
|
|
127
141
|
return { ...previous, [key]: val };
|
|
128
142
|
}
|
|
143
|
+
function parseHeaderPair(value, previous = {}) {
|
|
144
|
+
const colonIndex = value.indexOf(":");
|
|
145
|
+
if (colonIndex === -1) {
|
|
146
|
+
throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
|
|
147
|
+
}
|
|
148
|
+
const key = value.slice(0, colonIndex).trim();
|
|
149
|
+
const val = value.slice(colonIndex + 1).trim();
|
|
150
|
+
if (key === "" || val === "") {
|
|
151
|
+
throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
|
|
152
|
+
}
|
|
153
|
+
return { ...previous, [key]: val };
|
|
154
|
+
}
|
|
129
155
|
function parseArgs() {
|
|
130
156
|
const program = new Command();
|
|
131
157
|
const argSeparatorIndex = process.argv.indexOf("--");
|
|
@@ -144,7 +170,8 @@ function parseArgs() {
|
|
|
144
170
|
.option("--server <n>", "server name from config file")
|
|
145
171
|
.option("--cli", "enable CLI mode")
|
|
146
172
|
.option("--transport <type>", "transport type (stdio, sse, http)")
|
|
147
|
-
.option("--server-url <url>", "server URL for SSE/HTTP transport")
|
|
173
|
+
.option("--server-url <url>", "server URL for SSE/HTTP transport")
|
|
174
|
+
.option("--header <headers...>", 'HTTP headers as "HeaderName: Value" pairs (for HTTP/SSE transports)', parseHeaderPair, {});
|
|
148
175
|
// Parse only the arguments before --
|
|
149
176
|
program.parse(preArgs);
|
|
150
177
|
const options = program.opts();
|
|
@@ -186,6 +213,7 @@ function parseArgs() {
|
|
|
186
213
|
envArgs: { ...(config.env || {}), ...(options.e || {}) },
|
|
187
214
|
cli: options.cli || false,
|
|
188
215
|
transport: "stdio",
|
|
216
|
+
headers: options.header,
|
|
189
217
|
};
|
|
190
218
|
}
|
|
191
219
|
else if (config.type === "sse" || config.type === "streamable-http") {
|
|
@@ -196,6 +224,7 @@ function parseArgs() {
|
|
|
196
224
|
cli: options.cli || false,
|
|
197
225
|
transport: config.type,
|
|
198
226
|
serverUrl: config.url,
|
|
227
|
+
headers: options.header,
|
|
199
228
|
};
|
|
200
229
|
}
|
|
201
230
|
else {
|
|
@@ -206,6 +235,7 @@ function parseArgs() {
|
|
|
206
235
|
envArgs: { ...(config.env || {}), ...(options.e || {}) },
|
|
207
236
|
cli: options.cli || false,
|
|
208
237
|
transport: "stdio",
|
|
238
|
+
headers: options.header,
|
|
209
239
|
};
|
|
210
240
|
}
|
|
211
241
|
}
|
|
@@ -224,6 +254,7 @@ function parseArgs() {
|
|
|
224
254
|
cli: options.cli || false,
|
|
225
255
|
transport: transport,
|
|
226
256
|
serverUrl: options.serverUrl,
|
|
257
|
+
headers: options.header,
|
|
227
258
|
};
|
|
228
259
|
}
|
|
229
260
|
async function main() {
|
|
@@ -11,9 +11,24 @@ export async function listPrompts(client) {
|
|
|
11
11
|
// Get a prompt
|
|
12
12
|
export async function getPrompt(client, name, args) {
|
|
13
13
|
try {
|
|
14
|
+
// Convert all arguments to strings for prompt arguments
|
|
15
|
+
const stringArgs = {};
|
|
16
|
+
if (args) {
|
|
17
|
+
for (const [key, value] of Object.entries(args)) {
|
|
18
|
+
if (typeof value === "string") {
|
|
19
|
+
stringArgs[key] = value;
|
|
20
|
+
}
|
|
21
|
+
else if (value === null || value === undefined) {
|
|
22
|
+
stringArgs[key] = String(value);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
stringArgs[key] = JSON.stringify(value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
14
29
|
const response = await client.getPrompt({
|
|
15
30
|
name,
|
|
16
|
-
arguments:
|
|
31
|
+
arguments: stringArgs,
|
|
17
32
|
});
|
|
18
33
|
return response;
|
|
19
34
|
}
|
|
@@ -49,8 +49,18 @@ export async function callTool(client, name, args) {
|
|
|
49
49
|
const tool = tools.find((t) => t.name === name);
|
|
50
50
|
let convertedArgs = args;
|
|
51
51
|
if (tool) {
|
|
52
|
-
// Convert parameters based on the tool's schema
|
|
53
|
-
|
|
52
|
+
// Convert parameters based on the tool's schema, but only for string values
|
|
53
|
+
// since we now accept pre-parsed values from the CLI
|
|
54
|
+
const stringArgs = {};
|
|
55
|
+
for (const [key, value] of Object.entries(args)) {
|
|
56
|
+
if (typeof value === "string") {
|
|
57
|
+
stringArgs[key] = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (Object.keys(stringArgs).length > 0) {
|
|
61
|
+
const convertedStringArgs = convertParameters(tool, stringArgs);
|
|
62
|
+
convertedArgs = { ...args, ...convertedStringArgs };
|
|
63
|
+
}
|
|
54
64
|
}
|
|
55
65
|
const response = await client.callTool({
|
|
56
66
|
name: name,
|
package/cli/build/index.js
CHANGED
|
@@ -4,7 +4,8 @@ import { Command } from "commander";
|
|
|
4
4
|
import { callTool, connect, disconnect, getPrompt, listPrompts, listResources, listResourceTemplates, listTools, readResource, setLoggingLevel, validLogLevels, } from "./client/index.js";
|
|
5
5
|
import { handleError } from "./error-handler.js";
|
|
6
6
|
import { createTransport } from "./transport.js";
|
|
7
|
-
|
|
7
|
+
import { awaitableLog } from "./utils/awaitable-log.js";
|
|
8
|
+
function createTransportOptions(target, transport, headers) {
|
|
8
9
|
if (target.length === 0) {
|
|
9
10
|
throw new Error("Target is required. Specify a URL or a command to execute.");
|
|
10
11
|
}
|
|
@@ -46,10 +47,11 @@ function createTransportOptions(target, transport) {
|
|
|
46
47
|
command: isUrl ? undefined : command,
|
|
47
48
|
args: isUrl ? undefined : commandArgs,
|
|
48
49
|
url: isUrl ? command : undefined,
|
|
50
|
+
headers,
|
|
49
51
|
};
|
|
50
52
|
}
|
|
51
53
|
async function callMethod(args) {
|
|
52
|
-
const transportOptions = createTransportOptions(args.target, args.transport);
|
|
54
|
+
const transportOptions = createTransportOptions(args.target, args.transport, args.headers);
|
|
53
55
|
const transport = createTransport(transportOptions);
|
|
54
56
|
const client = new Client({
|
|
55
57
|
name: "inspector-cli",
|
|
@@ -101,7 +103,7 @@ async function callMethod(args) {
|
|
|
101
103
|
else {
|
|
102
104
|
throw new Error(`Unsupported method: ${args.method}. Supported methods include: tools/list, tools/call, resources/list, resources/read, resources/templates/list, prompts/list, prompts/get, logging/setLevel`);
|
|
103
105
|
}
|
|
104
|
-
|
|
106
|
+
await awaitableLog(JSON.stringify(result, null, 2));
|
|
105
107
|
}
|
|
106
108
|
finally {
|
|
107
109
|
try {
|
|
@@ -119,6 +121,27 @@ function parseKeyValuePair(value, previous = {}) {
|
|
|
119
121
|
if (val === undefined || val === "") {
|
|
120
122
|
throw new Error(`Invalid parameter format: ${value}. Use key=value format.`);
|
|
121
123
|
}
|
|
124
|
+
// Try to parse as JSON first
|
|
125
|
+
let parsedValue;
|
|
126
|
+
try {
|
|
127
|
+
parsedValue = JSON.parse(val);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// If JSON parsing fails, keep as string
|
|
131
|
+
parsedValue = val;
|
|
132
|
+
}
|
|
133
|
+
return { ...previous, [key]: parsedValue };
|
|
134
|
+
}
|
|
135
|
+
function parseHeaderPair(value, previous = {}) {
|
|
136
|
+
const colonIndex = value.indexOf(":");
|
|
137
|
+
if (colonIndex === -1) {
|
|
138
|
+
throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
|
|
139
|
+
}
|
|
140
|
+
const key = value.slice(0, colonIndex).trim();
|
|
141
|
+
const val = value.slice(colonIndex + 1).trim();
|
|
142
|
+
if (key === "" || val === "") {
|
|
143
|
+
throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
|
|
144
|
+
}
|
|
122
145
|
return { ...previous, [key]: val };
|
|
123
146
|
}
|
|
124
147
|
function parseArgs() {
|
|
@@ -171,7 +194,11 @@ function parseArgs() {
|
|
|
171
194
|
throw new Error(`Invalid transport type: ${value}. Valid types are: ${validTransports.join(", ")}`);
|
|
172
195
|
}
|
|
173
196
|
return value;
|
|
174
|
-
})
|
|
197
|
+
})
|
|
198
|
+
//
|
|
199
|
+
// HTTP headers
|
|
200
|
+
//
|
|
201
|
+
.option("--header <headers...>", 'HTTP headers as "HeaderName: Value" pairs (for HTTP/SSE transports)', parseHeaderPair, {});
|
|
175
202
|
// Parse only the arguments before --
|
|
176
203
|
program.parse(preArgs);
|
|
177
204
|
const options = program.opts();
|
|
@@ -184,6 +211,7 @@ function parseArgs() {
|
|
|
184
211
|
return {
|
|
185
212
|
target: finalArgs,
|
|
186
213
|
...options,
|
|
214
|
+
headers: options.header, // commander.js uses 'header' field, map to 'headers'
|
|
187
215
|
};
|
|
188
216
|
}
|
|
189
217
|
async function main() {
|
package/cli/build/transport.js
CHANGED
|
@@ -15,8 +15,8 @@ function createStdioTransport(options) {
|
|
|
15
15
|
}
|
|
16
16
|
const defaultEnv = getDefaultEnvironment();
|
|
17
17
|
const env = {
|
|
18
|
-
...processEnv,
|
|
19
18
|
...defaultEnv,
|
|
19
|
+
...processEnv,
|
|
20
20
|
};
|
|
21
21
|
const { cmd: actualCommand, args: actualArgs } = findActualExecutable(options.command ?? "", args);
|
|
22
22
|
return new StdioClientTransport({
|
|
@@ -38,10 +38,24 @@ export function createTransport(options) {
|
|
|
38
38
|
}
|
|
39
39
|
const url = new URL(options.url);
|
|
40
40
|
if (transportType === "sse") {
|
|
41
|
-
|
|
41
|
+
const transportOptions = options.headers
|
|
42
|
+
? {
|
|
43
|
+
requestInit: {
|
|
44
|
+
headers: options.headers,
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
: undefined;
|
|
48
|
+
return new SSEClientTransport(url, transportOptions);
|
|
42
49
|
}
|
|
43
50
|
if (transportType === "http") {
|
|
44
|
-
|
|
51
|
+
const transportOptions = options.headers
|
|
52
|
+
? {
|
|
53
|
+
requestInit: {
|
|
54
|
+
headers: options.headers,
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
: undefined;
|
|
58
|
+
return new StreamableHTTPClientTransport(url, transportOptions);
|
|
45
59
|
}
|
|
46
60
|
throw new Error(`Unsupported transport type: ${transportType}`);
|
|
47
61
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-
|
|
1
|
+
import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-B_qh-Btq.js";
|
|
2
2
|
const OAuthCallback = ({ onConnect }) => {
|
|
3
3
|
const { toast } = useToast();
|
|
4
4
|
const hasProcessedRef = reactExports.useRef(false);
|
package/client/dist/assets/{OAuthDebugCallback-BD-zJllm.js → OAuthDebugCallback-BhzcPtuF.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-
|
|
1
|
+
import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-B_qh-Btq.js";
|
|
2
2
|
const OAuthDebugCallback = ({ onConnect }) => {
|
|
3
3
|
reactExports.useEffect(() => {
|
|
4
4
|
let isProcessed = false;
|
|
@@ -21,6 +21,14 @@ const OAuthDebugCallback = ({ onConnect }) => {
|
|
|
21
21
|
if (storedState) {
|
|
22
22
|
try {
|
|
23
23
|
restoredState = JSON.parse(storedState);
|
|
24
|
+
if (restoredState && typeof restoredState.resource === "string") {
|
|
25
|
+
restoredState.resource = new URL(restoredState.resource);
|
|
26
|
+
}
|
|
27
|
+
if (restoredState && typeof restoredState.authorizationUrl === "string") {
|
|
28
|
+
restoredState.authorizationUrl = new URL(
|
|
29
|
+
restoredState.authorizationUrl
|
|
30
|
+
);
|
|
31
|
+
}
|
|
24
32
|
sessionStorage.removeItem(SESSION_KEYS.AUTH_DEBUGGER_STATE);
|
|
25
33
|
} catch (e) {
|
|
26
34
|
console.error("Failed to parse stored auth state:", e);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1
4
|
function _mergeNamespaces(n, m2) {
|
|
2
5
|
for (var i = 0; i < m2.length; i++) {
|
|
3
6
|
const e = m2[i];
|
|
@@ -15118,6 +15121,7 @@ const enumType = ZodEnum.create;
|
|
|
15118
15121
|
ZodPromise.create;
|
|
15119
15122
|
const optionalType = ZodOptional.create;
|
|
15120
15123
|
ZodNullable.create;
|
|
15124
|
+
const NEVER = INVALID;
|
|
15121
15125
|
const LATEST_PROTOCOL_VERSION = "2025-06-18";
|
|
15122
15126
|
const SUPPORTED_PROTOCOL_VERSIONS = [
|
|
15123
15127
|
LATEST_PROTOCOL_VERSION,
|
|
@@ -16020,7 +16024,7 @@ unionType([
|
|
|
16020
16024
|
CallToolRequestSchema,
|
|
16021
16025
|
ListToolsRequestSchema
|
|
16022
16026
|
]);
|
|
16023
|
-
|
|
16027
|
+
unionType([
|
|
16024
16028
|
CancelledNotificationSchema,
|
|
16025
16029
|
ProgressNotificationSchema,
|
|
16026
16030
|
InitializedNotificationSchema,
|
|
@@ -16038,7 +16042,7 @@ unionType([
|
|
|
16038
16042
|
ElicitRequestSchema,
|
|
16039
16043
|
ListRootsRequestSchema
|
|
16040
16044
|
]);
|
|
16041
|
-
|
|
16045
|
+
unionType([
|
|
16042
16046
|
CancelledNotificationSchema,
|
|
16043
16047
|
ProgressNotificationSchema,
|
|
16044
16048
|
LoggingMessageNotificationSchema,
|
|
@@ -16067,9 +16071,22 @@ class McpError extends Error {
|
|
|
16067
16071
|
this.name = "McpError";
|
|
16068
16072
|
}
|
|
16069
16073
|
}
|
|
16074
|
+
const SafeUrlSchema = stringType().url().superRefine((val, ctx) => {
|
|
16075
|
+
if (!URL.canParse(val)) {
|
|
16076
|
+
ctx.addIssue({
|
|
16077
|
+
code: ZodIssueCode.custom,
|
|
16078
|
+
message: "URL must be parseable",
|
|
16079
|
+
fatal: true
|
|
16080
|
+
});
|
|
16081
|
+
return NEVER;
|
|
16082
|
+
}
|
|
16083
|
+
}).refine((url) => {
|
|
16084
|
+
const u2 = new URL(url);
|
|
16085
|
+
return u2.protocol !== "javascript:" && u2.protocol !== "data:" && u2.protocol !== "vbscript:";
|
|
16086
|
+
}, { message: "URL cannot use javascript:, data:, or vbscript: scheme" });
|
|
16070
16087
|
const OAuthProtectedResourceMetadataSchema = objectType({
|
|
16071
16088
|
resource: stringType().url(),
|
|
16072
|
-
authorization_servers: arrayType(
|
|
16089
|
+
authorization_servers: arrayType(SafeUrlSchema).optional(),
|
|
16073
16090
|
jwks_uri: stringType().url().optional(),
|
|
16074
16091
|
scopes_supported: arrayType(stringType()).optional(),
|
|
16075
16092
|
bearer_methods_supported: arrayType(stringType()).optional(),
|
|
@@ -16085,17 +16102,17 @@ const OAuthProtectedResourceMetadataSchema = objectType({
|
|
|
16085
16102
|
}).passthrough();
|
|
16086
16103
|
const OAuthMetadataSchema = objectType({
|
|
16087
16104
|
issuer: stringType(),
|
|
16088
|
-
authorization_endpoint:
|
|
16089
|
-
token_endpoint:
|
|
16090
|
-
registration_endpoint:
|
|
16105
|
+
authorization_endpoint: SafeUrlSchema,
|
|
16106
|
+
token_endpoint: SafeUrlSchema,
|
|
16107
|
+
registration_endpoint: SafeUrlSchema.optional(),
|
|
16091
16108
|
scopes_supported: arrayType(stringType()).optional(),
|
|
16092
16109
|
response_types_supported: arrayType(stringType()),
|
|
16093
16110
|
response_modes_supported: arrayType(stringType()).optional(),
|
|
16094
16111
|
grant_types_supported: arrayType(stringType()).optional(),
|
|
16095
16112
|
token_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
|
|
16096
16113
|
token_endpoint_auth_signing_alg_values_supported: arrayType(stringType()).optional(),
|
|
16097
|
-
service_documentation:
|
|
16098
|
-
revocation_endpoint:
|
|
16114
|
+
service_documentation: SafeUrlSchema.optional(),
|
|
16115
|
+
revocation_endpoint: SafeUrlSchema.optional(),
|
|
16099
16116
|
revocation_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
|
|
16100
16117
|
revocation_endpoint_auth_signing_alg_values_supported: arrayType(stringType()).optional(),
|
|
16101
16118
|
introspection_endpoint: stringType().optional(),
|
|
@@ -16105,11 +16122,11 @@ const OAuthMetadataSchema = objectType({
|
|
|
16105
16122
|
}).passthrough();
|
|
16106
16123
|
const OpenIdProviderMetadataSchema = objectType({
|
|
16107
16124
|
issuer: stringType(),
|
|
16108
|
-
authorization_endpoint:
|
|
16109
|
-
token_endpoint:
|
|
16110
|
-
userinfo_endpoint:
|
|
16111
|
-
jwks_uri:
|
|
16112
|
-
registration_endpoint:
|
|
16125
|
+
authorization_endpoint: SafeUrlSchema,
|
|
16126
|
+
token_endpoint: SafeUrlSchema,
|
|
16127
|
+
userinfo_endpoint: SafeUrlSchema.optional(),
|
|
16128
|
+
jwks_uri: SafeUrlSchema,
|
|
16129
|
+
registration_endpoint: SafeUrlSchema.optional(),
|
|
16113
16130
|
scopes_supported: arrayType(stringType()).optional(),
|
|
16114
16131
|
response_types_supported: arrayType(stringType()),
|
|
16115
16132
|
response_modes_supported: arrayType(stringType()).optional(),
|
|
@@ -16137,8 +16154,8 @@ const OpenIdProviderMetadataSchema = objectType({
|
|
|
16137
16154
|
request_parameter_supported: booleanType().optional(),
|
|
16138
16155
|
request_uri_parameter_supported: booleanType().optional(),
|
|
16139
16156
|
require_request_uri_registration: booleanType().optional(),
|
|
16140
|
-
op_policy_uri:
|
|
16141
|
-
op_tos_uri:
|
|
16157
|
+
op_policy_uri: SafeUrlSchema.optional(),
|
|
16158
|
+
op_tos_uri: SafeUrlSchema.optional()
|
|
16142
16159
|
}).passthrough();
|
|
16143
16160
|
const OpenIdProviderDiscoveryMetadataSchema = OpenIdProviderMetadataSchema.merge(OAuthMetadataSchema.pick({
|
|
16144
16161
|
code_challenge_methods_supported: true
|
|
@@ -16158,18 +16175,18 @@ const OAuthErrorResponseSchema = objectType({
|
|
|
16158
16175
|
error_uri: stringType().optional()
|
|
16159
16176
|
});
|
|
16160
16177
|
const OAuthClientMetadataSchema = objectType({
|
|
16161
|
-
redirect_uris: arrayType(
|
|
16178
|
+
redirect_uris: arrayType(SafeUrlSchema),
|
|
16162
16179
|
token_endpoint_auth_method: stringType().optional(),
|
|
16163
16180
|
grant_types: arrayType(stringType()).optional(),
|
|
16164
16181
|
response_types: arrayType(stringType()).optional(),
|
|
16165
16182
|
client_name: stringType().optional(),
|
|
16166
|
-
client_uri:
|
|
16167
|
-
logo_uri:
|
|
16183
|
+
client_uri: SafeUrlSchema.optional(),
|
|
16184
|
+
logo_uri: SafeUrlSchema.optional(),
|
|
16168
16185
|
scope: stringType().optional(),
|
|
16169
16186
|
contacts: arrayType(stringType()).optional(),
|
|
16170
|
-
tos_uri:
|
|
16187
|
+
tos_uri: SafeUrlSchema.optional(),
|
|
16171
16188
|
policy_uri: stringType().optional(),
|
|
16172
|
-
jwks_uri:
|
|
16189
|
+
jwks_uri: SafeUrlSchema.optional(),
|
|
16173
16190
|
jwks: anyType().optional(),
|
|
16174
16191
|
software_id: stringType().optional(),
|
|
16175
16192
|
software_version: stringType().optional(),
|
|
@@ -16629,7 +16646,7 @@ async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
|
|
|
16629
16646
|
return await fetchWithCorsRetry(url, headers, fetchFn);
|
|
16630
16647
|
}
|
|
16631
16648
|
function shouldAttemptFallback(response, pathname) {
|
|
16632
|
-
return !response || response.status
|
|
16649
|
+
return !response || response.status >= 400 && response.status < 500 && pathname !== "/";
|
|
16633
16650
|
}
|
|
16634
16651
|
async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
|
|
16635
16652
|
var _a, _b;
|
|
@@ -16885,6 +16902,19 @@ const generateOAuthErrorDescription = (params) => {
|
|
|
16885
16902
|
errorUri ? `More info: ${errorUri}.` : ""
|
|
16886
16903
|
].filter(Boolean).join("\n");
|
|
16887
16904
|
};
|
|
16905
|
+
function validateRedirectUrl(url) {
|
|
16906
|
+
try {
|
|
16907
|
+
const parsedUrl = new URL(url);
|
|
16908
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
16909
|
+
throw new Error("Authorization URL must be HTTP or HTTPS");
|
|
16910
|
+
}
|
|
16911
|
+
} catch (error) {
|
|
16912
|
+
if (error instanceof Error && error.message === "Authorization URL must be HTTP or HTTPS") {
|
|
16913
|
+
throw error;
|
|
16914
|
+
}
|
|
16915
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
16916
|
+
}
|
|
16917
|
+
}
|
|
16888
16918
|
const discoverScopes = async (serverUrl, resourceMetadata) => {
|
|
16889
16919
|
try {
|
|
16890
16920
|
const metadata = await discoverAuthorizationServerMetadata(
|
|
@@ -16935,8 +16965,10 @@ const clearClientInformationFromSessionStorage = ({
|
|
|
16935
16965
|
sessionStorage.removeItem(key);
|
|
16936
16966
|
};
|
|
16937
16967
|
class InspectorOAuthClientProvider {
|
|
16938
|
-
constructor(serverUrl) {
|
|
16968
|
+
constructor(serverUrl, scope) {
|
|
16969
|
+
__publicField(this, "scope");
|
|
16939
16970
|
this.serverUrl = serverUrl;
|
|
16971
|
+
this.scope = scope;
|
|
16940
16972
|
sessionStorage.setItem(SESSION_KEYS.SERVER_URL, serverUrl);
|
|
16941
16973
|
}
|
|
16942
16974
|
get redirectUrl() {
|
|
@@ -16949,7 +16981,8 @@ class InspectorOAuthClientProvider {
|
|
|
16949
16981
|
grant_types: ["authorization_code", "refresh_token"],
|
|
16950
16982
|
response_types: ["code"],
|
|
16951
16983
|
client_name: "MCP Inspector",
|
|
16952
|
-
client_uri: "https://github.com/modelcontextprotocol/inspector"
|
|
16984
|
+
client_uri: "https://github.com/modelcontextprotocol/inspector",
|
|
16985
|
+
scope: this.scope ?? ""
|
|
16953
16986
|
};
|
|
16954
16987
|
}
|
|
16955
16988
|
state() {
|
|
@@ -16990,9 +17023,7 @@ class InspectorOAuthClientProvider {
|
|
|
16990
17023
|
sessionStorage.setItem(key, JSON.stringify(tokens));
|
|
16991
17024
|
}
|
|
16992
17025
|
redirectToAuthorization(authorizationUrl) {
|
|
16993
|
-
|
|
16994
|
-
throw new Error("Authorization URL must be HTTP or HTTPS");
|
|
16995
|
-
}
|
|
17026
|
+
validateRedirectUrl(authorizationUrl.href);
|
|
16996
17027
|
window.location.href = authorizationUrl.href;
|
|
16997
17028
|
}
|
|
16998
17029
|
saveCodeVerifier(codeVerifier) {
|
|
@@ -17179,7 +17210,7 @@ const oauthTransitions = {
|
|
|
17179
17210
|
authorizationCode: context.state.authorizationCode,
|
|
17180
17211
|
codeVerifier,
|
|
17181
17212
|
redirectUri: context.provider.redirectUrl,
|
|
17182
|
-
resource: context.state.resource
|
|
17213
|
+
resource: context.state.resource ? context.state.resource instanceof URL ? context.state.resource : new URL(context.state.resource) : void 0
|
|
17183
17214
|
});
|
|
17184
17215
|
context.provider.saveTokens(tokens);
|
|
17185
17216
|
context.updateState({
|
|
@@ -24047,7 +24078,7 @@ function splitLines(chunk) {
|
|
|
24047
24078
|
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
|
24048
24079
|
`, searchIndex);
|
|
24049
24080
|
let lineEnd = -1;
|
|
24050
|
-
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
|
24081
|
+
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
|
24051
24082
|
incompleteLine = chunk.slice(searchIndex);
|
|
24052
24083
|
break;
|
|
24053
24084
|
} else {
|
|
@@ -24835,16 +24866,7 @@ class StreamableHTTPClientTransport {
|
|
|
24835
24866
|
return this._protocolVersion;
|
|
24836
24867
|
}
|
|
24837
24868
|
}
|
|
24838
|
-
const
|
|
24839
|
-
method: literalType("notifications/stderr"),
|
|
24840
|
-
params: objectType({
|
|
24841
|
-
content: stringType()
|
|
24842
|
-
})
|
|
24843
|
-
});
|
|
24844
|
-
ClientNotificationSchema.or(
|
|
24845
|
-
StdErrNotificationSchema
|
|
24846
|
-
).or(ServerNotificationSchema).or(NotificationSchema);
|
|
24847
|
-
const version$1 = "0.16.4";
|
|
24869
|
+
const version$1 = "0.16.6";
|
|
24848
24870
|
const packageJson = {
|
|
24849
24871
|
version: version$1
|
|
24850
24872
|
};
|
|
@@ -24976,7 +24998,6 @@ function useConnection({
|
|
|
24976
24998
|
oauthScope,
|
|
24977
24999
|
config,
|
|
24978
25000
|
onNotification,
|
|
24979
|
-
onStdErrNotification,
|
|
24980
25001
|
onPendingRequest,
|
|
24981
25002
|
onElicitationRequest,
|
|
24982
25003
|
getRoots,
|
|
@@ -25030,7 +25051,7 @@ function useConnection({
|
|
|
25030
25051
|
mcpRequestOptions.onprogress = (params) => {
|
|
25031
25052
|
if (onNotification) {
|
|
25032
25053
|
onNotification({
|
|
25033
|
-
method: "
|
|
25054
|
+
method: "notifications/progress",
|
|
25034
25055
|
params
|
|
25035
25056
|
});
|
|
25036
25057
|
}
|
|
@@ -25147,7 +25168,6 @@ function useConnection({
|
|
|
25147
25168
|
};
|
|
25148
25169
|
const handleAuthError = async (error) => {
|
|
25149
25170
|
if (is401Error(error)) {
|
|
25150
|
-
const serverAuthProvider = new InspectorOAuthClientProvider(sseUrl);
|
|
25151
25171
|
let scope = oauthScope == null ? void 0 : oauthScope.trim();
|
|
25152
25172
|
if (!scope) {
|
|
25153
25173
|
let resourceMetadata;
|
|
@@ -25159,6 +25179,10 @@ function useConnection({
|
|
|
25159
25179
|
}
|
|
25160
25180
|
scope = await discoverScopes(sseUrl, resourceMetadata);
|
|
25161
25181
|
}
|
|
25182
|
+
const serverAuthProvider = new InspectorOAuthClientProvider(
|
|
25183
|
+
sseUrl,
|
|
25184
|
+
scope
|
|
25185
|
+
);
|
|
25162
25186
|
const result = await auth(serverAuthProvider, {
|
|
25163
25187
|
serverUrl: sseUrl,
|
|
25164
25188
|
scope
|
|
@@ -25212,11 +25236,18 @@ function useConnection({
|
|
|
25212
25236
|
let transportOptions;
|
|
25213
25237
|
let mcpProxyServerUrl;
|
|
25214
25238
|
switch (transportType) {
|
|
25215
|
-
case "stdio":
|
|
25239
|
+
case "stdio": {
|
|
25216
25240
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/stdio`);
|
|
25217
25241
|
mcpProxyServerUrl.searchParams.append("command", command);
|
|
25218
25242
|
mcpProxyServerUrl.searchParams.append("args", args);
|
|
25219
25243
|
mcpProxyServerUrl.searchParams.append("env", JSON.stringify(env));
|
|
25244
|
+
const proxyFullAddress = config.MCP_PROXY_FULL_ADDRESS.value;
|
|
25245
|
+
if (proxyFullAddress) {
|
|
25246
|
+
mcpProxyServerUrl.searchParams.append(
|
|
25247
|
+
"proxyFullAddress",
|
|
25248
|
+
proxyFullAddress
|
|
25249
|
+
);
|
|
25250
|
+
}
|
|
25220
25251
|
transportOptions = {
|
|
25221
25252
|
authProvider: serverAuthProvider,
|
|
25222
25253
|
eventSourceInit: {
|
|
@@ -25230,9 +25261,17 @@ function useConnection({
|
|
|
25230
25261
|
}
|
|
25231
25262
|
};
|
|
25232
25263
|
break;
|
|
25233
|
-
|
|
25264
|
+
}
|
|
25265
|
+
case "sse": {
|
|
25234
25266
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/sse`);
|
|
25235
25267
|
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
|
25268
|
+
const proxyFullAddressSSE = config.MCP_PROXY_FULL_ADDRESS.value;
|
|
25269
|
+
if (proxyFullAddressSSE) {
|
|
25270
|
+
mcpProxyServerUrl.searchParams.append(
|
|
25271
|
+
"proxyFullAddress",
|
|
25272
|
+
proxyFullAddressSSE
|
|
25273
|
+
);
|
|
25274
|
+
}
|
|
25236
25275
|
transportOptions = {
|
|
25237
25276
|
eventSourceInit: {
|
|
25238
25277
|
fetch: (url, init) => fetch(url, {
|
|
@@ -25245,6 +25284,7 @@ function useConnection({
|
|
|
25245
25284
|
}
|
|
25246
25285
|
};
|
|
25247
25286
|
break;
|
|
25287
|
+
}
|
|
25248
25288
|
case "streamable-http":
|
|
25249
25289
|
mcpProxyServerUrl = new URL(`${getMCPProxyAddress(config)}/mcp`);
|
|
25250
25290
|
mcpProxyServerUrl.searchParams.append("url", sseUrl);
|
|
@@ -25288,12 +25328,6 @@ function useConnection({
|
|
|
25288
25328
|
return Promise.resolve();
|
|
25289
25329
|
};
|
|
25290
25330
|
}
|
|
25291
|
-
if (onStdErrNotification) {
|
|
25292
|
-
client2.setNotificationHandler(
|
|
25293
|
-
StdErrNotificationSchema,
|
|
25294
|
-
onStdErrNotification
|
|
25295
|
-
);
|
|
25296
|
-
}
|
|
25297
25331
|
let capabilities;
|
|
25298
25332
|
try {
|
|
25299
25333
|
const transport = transportType === "streamable-http" ? new StreamableHTTPClientTransport(mcpProxyServerUrl, {
|
|
@@ -25354,6 +25388,15 @@ function useConnection({
|
|
|
25354
25388
|
if ((capabilities == null ? void 0 : capabilities.logging) && defaultLoggingLevel) {
|
|
25355
25389
|
lastRequest = "logging/setLevel";
|
|
25356
25390
|
await client2.setLoggingLevel(defaultLoggingLevel);
|
|
25391
|
+
pushHistory(
|
|
25392
|
+
{
|
|
25393
|
+
method: "logging/setLevel",
|
|
25394
|
+
params: {
|
|
25395
|
+
level: defaultLoggingLevel
|
|
25396
|
+
}
|
|
25397
|
+
},
|
|
25398
|
+
{}
|
|
25399
|
+
);
|
|
25357
25400
|
lastRequest = "";
|
|
25358
25401
|
}
|
|
25359
25402
|
if (onElicitationRequest) {
|
|
@@ -26558,6 +26601,7 @@ const OAuthFlowProgress = ({
|
|
|
26558
26601
|
updateAuthState,
|
|
26559
26602
|
proceedToNextStep
|
|
26560
26603
|
}) => {
|
|
26604
|
+
const { toast: toast2 } = useToast();
|
|
26561
26605
|
const provider = reactExports.useMemo(
|
|
26562
26606
|
() => new DebugInspectorOAuthClientProvider(serverUrl),
|
|
26563
26607
|
[serverUrl]
|
|
@@ -26688,11 +26732,24 @@ const OAuthFlowProgress = ({
|
|
|
26688
26732
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26689
26733
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs break-all", children: authState.authorizationUrl }),
|
|
26690
26734
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
26691
|
-
"
|
|
26735
|
+
"button",
|
|
26692
26736
|
{
|
|
26693
|
-
|
|
26694
|
-
|
|
26695
|
-
|
|
26737
|
+
onClick: () => {
|
|
26738
|
+
try {
|
|
26739
|
+
validateRedirectUrl(authState.authorizationUrl);
|
|
26740
|
+
window.open(
|
|
26741
|
+
authState.authorizationUrl,
|
|
26742
|
+
"_blank",
|
|
26743
|
+
"noopener noreferrer"
|
|
26744
|
+
);
|
|
26745
|
+
} catch (error) {
|
|
26746
|
+
toast2({
|
|
26747
|
+
title: "Invalid URL",
|
|
26748
|
+
description: error instanceof Error ? error.message : "The authorization URL is not valid",
|
|
26749
|
+
variant: "destructive"
|
|
26750
|
+
});
|
|
26751
|
+
}
|
|
26752
|
+
},
|
|
26696
26753
|
className: "flex items-center text-blue-500 hover:text-blue-700",
|
|
26697
26754
|
"aria-label": "Open authorization URL in new tab",
|
|
26698
26755
|
title: "Open authorization URL",
|
|
@@ -26778,7 +26835,18 @@ const OAuthFlowProgress = ({
|
|
|
26778
26835
|
Button,
|
|
26779
26836
|
{
|
|
26780
26837
|
variant: "outline",
|
|
26781
|
-
onClick: () =>
|
|
26838
|
+
onClick: () => {
|
|
26839
|
+
try {
|
|
26840
|
+
validateRedirectUrl(authState.authorizationUrl);
|
|
26841
|
+
window.open(authState.authorizationUrl, "_blank");
|
|
26842
|
+
} catch (error) {
|
|
26843
|
+
toast2({
|
|
26844
|
+
title: "Invalid URL",
|
|
26845
|
+
description: error instanceof Error ? error.message : "The authorization URL is not valid",
|
|
26846
|
+
variant: "destructive"
|
|
26847
|
+
});
|
|
26848
|
+
}
|
|
26849
|
+
},
|
|
26782
26850
|
children: "Open in New Tab"
|
|
26783
26851
|
}
|
|
26784
26852
|
)
|
|
@@ -26906,6 +26974,20 @@ const AuthDebugger = ({
|
|
|
26906
26974
|
while (currentState.oauthStep !== "complete") {
|
|
26907
26975
|
await oauthMachine.executeStep(currentState);
|
|
26908
26976
|
if (currentState.oauthStep === "authorization_code" && currentState.authorizationUrl) {
|
|
26977
|
+
try {
|
|
26978
|
+
validateRedirectUrl(currentState.authorizationUrl);
|
|
26979
|
+
} catch (error) {
|
|
26980
|
+
updateAuthState({
|
|
26981
|
+
...currentState,
|
|
26982
|
+
isInitiatingAuth: false,
|
|
26983
|
+
latestError: error instanceof Error ? error : new Error(String(error)),
|
|
26984
|
+
statusMessage: {
|
|
26985
|
+
type: "error",
|
|
26986
|
+
message: `Invalid authorization URL: ${error instanceof Error ? error.message : String(error)}`
|
|
26987
|
+
}
|
|
26988
|
+
});
|
|
26989
|
+
return;
|
|
26990
|
+
}
|
|
26909
26991
|
sessionStorage.setItem(
|
|
26910
26992
|
SESSION_KEYS.AUTH_DEBUGGER_STATE,
|
|
26911
26993
|
JSON.stringify(currentState)
|
|
@@ -30313,15 +30395,9 @@ function getWindowScrollBarX(element, rect) {
|
|
|
30313
30395
|
}
|
|
30314
30396
|
return rect.left + leftScroll;
|
|
30315
30397
|
}
|
|
30316
|
-
function getHTMLOffset(documentElement, scroll
|
|
30317
|
-
if (ignoreScrollbarX === void 0) {
|
|
30318
|
-
ignoreScrollbarX = false;
|
|
30319
|
-
}
|
|
30398
|
+
function getHTMLOffset(documentElement, scroll) {
|
|
30320
30399
|
const htmlRect = documentElement.getBoundingClientRect();
|
|
30321
|
-
const x = htmlRect.left + scroll.scrollLeft - (
|
|
30322
|
-
// RTL <body> scrollbar.
|
|
30323
|
-
getWindowScrollBarX(documentElement, htmlRect)
|
|
30324
|
-
));
|
|
30400
|
+
const x = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
|
|
30325
30401
|
const y = htmlRect.top + scroll.scrollTop;
|
|
30326
30402
|
return {
|
|
30327
30403
|
x,
|
|
@@ -30359,7 +30435,7 @@ function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
|
|
|
30359
30435
|
offsets.y = offsetRect.y + offsetParent.clientTop;
|
|
30360
30436
|
}
|
|
30361
30437
|
}
|
|
30362
|
-
const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll
|
|
30438
|
+
const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
|
|
30363
30439
|
return {
|
|
30364
30440
|
width: rect.width * scale.x,
|
|
30365
30441
|
height: rect.height * scale.y,
|
|
@@ -30388,6 +30464,7 @@ function getDocumentRect(element) {
|
|
|
30388
30464
|
y
|
|
30389
30465
|
};
|
|
30390
30466
|
}
|
|
30467
|
+
const SCROLLBAR_MAX = 25;
|
|
30391
30468
|
function getViewportRect(element, strategy) {
|
|
30392
30469
|
const win = getWindow(element);
|
|
30393
30470
|
const html = getDocumentElement(element);
|
|
@@ -30405,6 +30482,19 @@ function getViewportRect(element, strategy) {
|
|
|
30405
30482
|
y = visualViewport.offsetTop;
|
|
30406
30483
|
}
|
|
30407
30484
|
}
|
|
30485
|
+
const windowScrollbarX = getWindowScrollBarX(html);
|
|
30486
|
+
if (windowScrollbarX <= 0) {
|
|
30487
|
+
const doc = html.ownerDocument;
|
|
30488
|
+
const body = doc.body;
|
|
30489
|
+
const bodyStyles = getComputedStyle(body);
|
|
30490
|
+
const bodyMarginInline = doc.compatMode === "CSS1Compat" ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
|
|
30491
|
+
const clippingStableScrollbarWidth = Math.abs(html.clientWidth - body.clientWidth - bodyMarginInline);
|
|
30492
|
+
if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
|
|
30493
|
+
width -= clippingStableScrollbarWidth;
|
|
30494
|
+
}
|
|
30495
|
+
} else if (windowScrollbarX <= SCROLLBAR_MAX) {
|
|
30496
|
+
width += windowScrollbarX;
|
|
30497
|
+
}
|
|
30408
30498
|
return {
|
|
30409
30499
|
width,
|
|
30410
30500
|
height,
|
|
@@ -36382,7 +36472,7 @@ const useTheme = () => {
|
|
|
36382
36472
|
[theme, setThemeWithSideEffect]
|
|
36383
36473
|
);
|
|
36384
36474
|
};
|
|
36385
|
-
const version = "0.16.
|
|
36475
|
+
const version = "0.16.6";
|
|
36386
36476
|
var [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [
|
|
36387
36477
|
createPopperScope
|
|
36388
36478
|
]);
|
|
@@ -36887,8 +36977,6 @@ const Sidebar = ({
|
|
|
36887
36977
|
setOauthScope,
|
|
36888
36978
|
onConnect,
|
|
36889
36979
|
onDisconnect,
|
|
36890
|
-
stdErrNotifications,
|
|
36891
|
-
clearStdErrNotifications,
|
|
36892
36980
|
logLevel,
|
|
36893
36981
|
sendLogLevelRequest,
|
|
36894
36982
|
loggingSupported,
|
|
@@ -37030,6 +37118,7 @@ const Sidebar = ({
|
|
|
37030
37118
|
placeholder: "Command",
|
|
37031
37119
|
value: command,
|
|
37032
37120
|
onChange: (e) => setCommand(e.target.value),
|
|
37121
|
+
onBlur: (e) => setCommand(e.target.value.trim()),
|
|
37033
37122
|
className: "font-mono"
|
|
37034
37123
|
}
|
|
37035
37124
|
)
|
|
@@ -37499,30 +37588,7 @@ const Sidebar = ({
|
|
|
37499
37588
|
]
|
|
37500
37589
|
}
|
|
37501
37590
|
)
|
|
37502
|
-
] })
|
|
37503
|
-
stdErrNotifications.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 border-t border-gray-200 pt-4", children: [
|
|
37504
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
37505
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium", children: "Error output from MCP server" }),
|
|
37506
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37507
|
-
Button,
|
|
37508
|
-
{
|
|
37509
|
-
variant: "outline",
|
|
37510
|
-
size: "sm",
|
|
37511
|
-
onClick: clearStdErrNotifications,
|
|
37512
|
-
className: "h-8 px-2",
|
|
37513
|
-
children: "Clear"
|
|
37514
|
-
}
|
|
37515
|
-
)
|
|
37516
|
-
] }),
|
|
37517
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 max-h-80 overflow-y-auto", children: stdErrNotifications.map((notification, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
37518
|
-
"div",
|
|
37519
|
-
{
|
|
37520
|
-
className: "text-sm text-red-500 font-mono py-2 border-b border-gray-200 last:border-b-0",
|
|
37521
|
-
children: notification.params.content
|
|
37522
|
-
},
|
|
37523
|
-
index2
|
|
37524
|
-
)) })
|
|
37525
|
-
] }) })
|
|
37591
|
+
] })
|
|
37526
37592
|
] })
|
|
37527
37593
|
] }) }),
|
|
37528
37594
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 border-t", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
@@ -38512,7 +38578,6 @@ const App = () => {
|
|
|
38512
38578
|
const [transportType, setTransportType] = reactExports.useState(getInitialTransportType);
|
|
38513
38579
|
const [logLevel, setLogLevel] = reactExports.useState("debug");
|
|
38514
38580
|
const [notifications, setNotifications] = reactExports.useState([]);
|
|
38515
|
-
const [stdErrNotifications, setStdErrNotifications] = reactExports.useState([]);
|
|
38516
38581
|
const [roots, setRoots] = reactExports.useState([]);
|
|
38517
38582
|
const [env, setEnv] = reactExports.useState({});
|
|
38518
38583
|
const [config, setConfig] = reactExports.useState(
|
|
@@ -38591,12 +38656,6 @@ const App = () => {
|
|
|
38591
38656
|
onNotification: (notification) => {
|
|
38592
38657
|
setNotifications((prev) => [...prev, notification]);
|
|
38593
38658
|
},
|
|
38594
|
-
onStdErrNotification: (notification) => {
|
|
38595
|
-
setStdErrNotifications((prev) => [
|
|
38596
|
-
...prev,
|
|
38597
|
-
notification
|
|
38598
|
-
]);
|
|
38599
|
-
},
|
|
38600
38659
|
onPendingRequest: (request, resolve, reject) => {
|
|
38601
38660
|
setPendingSampleRequests((prev) => [
|
|
38602
38661
|
...prev,
|
|
@@ -39034,9 +39093,6 @@ const App = () => {
|
|
|
39034
39093
|
);
|
|
39035
39094
|
setLogLevel(level);
|
|
39036
39095
|
};
|
|
39037
|
-
const clearStdErrNotifications = () => {
|
|
39038
|
-
setStdErrNotifications([]);
|
|
39039
|
-
};
|
|
39040
39096
|
const AuthDebuggerWrapper = () => /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "auth", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
39041
39097
|
AuthDebugger,
|
|
39042
39098
|
{
|
|
@@ -39048,13 +39104,13 @@ const App = () => {
|
|
|
39048
39104
|
) });
|
|
39049
39105
|
if (window.location.pathname === "/oauth/callback") {
|
|
39050
39106
|
const OAuthCallback = React.lazy(
|
|
39051
|
-
() => __vitePreload(() => import("./OAuthCallback-
|
|
39107
|
+
() => __vitePreload(() => import("./OAuthCallback-Cmffn8om.js"), true ? [] : void 0)
|
|
39052
39108
|
);
|
|
39053
39109
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
|
|
39054
39110
|
}
|
|
39055
39111
|
if (window.location.pathname === "/oauth/callback/debug") {
|
|
39056
39112
|
const OAuthDebugCallback = React.lazy(
|
|
39057
|
-
() => __vitePreload(() => import("./OAuthDebugCallback-
|
|
39113
|
+
() => __vitePreload(() => import("./OAuthDebugCallback-BhzcPtuF.js"), true ? [] : void 0)
|
|
39058
39114
|
);
|
|
39059
39115
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
|
|
39060
39116
|
}
|
|
@@ -39096,11 +39152,9 @@ const App = () => {
|
|
|
39096
39152
|
setOauthScope,
|
|
39097
39153
|
onConnect: connectMcpServer,
|
|
39098
39154
|
onDisconnect: disconnectMcpServer,
|
|
39099
|
-
stdErrNotifications,
|
|
39100
39155
|
logLevel,
|
|
39101
39156
|
sendLogLevelRequest,
|
|
39102
|
-
loggingSupported: !!(serverCapabilities == null ? void 0 : serverCapabilities.logging) || false
|
|
39103
|
-
clearStdErrNotifications
|
|
39157
|
+
loggingSupported: !!(serverCapabilities == null ? void 0 : serverCapabilities.logging) || false
|
|
39104
39158
|
}
|
|
39105
39159
|
),
|
|
39106
39160
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -944,9 +944,6 @@ video {
|
|
|
944
944
|
.h-screen {
|
|
945
945
|
height: 100vh;
|
|
946
946
|
}
|
|
947
|
-
.max-h-80 {
|
|
948
|
-
max-height: 20rem;
|
|
949
|
-
}
|
|
950
947
|
.max-h-96 {
|
|
951
948
|
max-height: 24rem;
|
|
952
949
|
}
|
|
@@ -1407,9 +1404,6 @@ video {
|
|
|
1407
1404
|
.pr-8 {
|
|
1408
1405
|
padding-right: 2rem;
|
|
1409
1406
|
}
|
|
1410
|
-
.pt-4 {
|
|
1411
|
-
padding-top: 1rem;
|
|
1412
|
-
}
|
|
1413
1407
|
.text-left {
|
|
1414
1408
|
text-align: left;
|
|
1415
1409
|
}
|
|
@@ -1625,6 +1619,10 @@ video {
|
|
|
1625
1619
|
.ring-offset-background {
|
|
1626
1620
|
--tw-ring-offset-color: hsl(var(--background));
|
|
1627
1621
|
}
|
|
1622
|
+
.blur {
|
|
1623
|
+
--tw-blur: blur(8px);
|
|
1624
|
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
1625
|
+
}
|
|
1628
1626
|
.filter {
|
|
1629
1627
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
1630
1628
|
}
|
|
@@ -1768,10 +1766,6 @@ h1 {
|
|
|
1768
1766
|
color: hsl(var(--muted-foreground));
|
|
1769
1767
|
}
|
|
1770
1768
|
|
|
1771
|
-
.last\:border-b-0:last-child {
|
|
1772
|
-
border-bottom-width: 0px;
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
1769
|
.hover\:border-\[\#646cff\]:hover {
|
|
1776
1770
|
--tw-border-opacity: 1;
|
|
1777
1771
|
border-color: rgb(100 108 255 / var(--tw-border-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-B_qh-Btq.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-C217Ot8c.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root" class="w-full"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modelcontextprotocol/inspector",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.6",
|
|
4
4
|
"description": "Model Context Protocol inspector",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Anthropic, PBC (https://anthropic.com)",
|
|
@@ -41,16 +41,16 @@
|
|
|
41
41
|
"prettier-fix": "prettier --write .",
|
|
42
42
|
"prettier-check": "prettier --check .",
|
|
43
43
|
"lint": "prettier --check . && cd client && npm run lint",
|
|
44
|
-
"prepare": "npm run build",
|
|
44
|
+
"prepare": "husky && npm run build",
|
|
45
45
|
"publish-all": "npm publish --workspaces --access public && npm publish --access public",
|
|
46
46
|
"update-version": "node scripts/update-version.js",
|
|
47
47
|
"check-version": "node scripts/check-version-consistency.js"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@modelcontextprotocol/inspector-cli": "^0.16.
|
|
51
|
-
"@modelcontextprotocol/inspector-client": "^0.16.
|
|
52
|
-
"@modelcontextprotocol/inspector-server": "^0.16.
|
|
53
|
-
"@modelcontextprotocol/sdk": "^1.17.
|
|
50
|
+
"@modelcontextprotocol/inspector-cli": "^0.16.6",
|
|
51
|
+
"@modelcontextprotocol/inspector-client": "^0.16.6",
|
|
52
|
+
"@modelcontextprotocol/inspector-server": "^0.16.6",
|
|
53
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
54
54
|
"concurrently": "^9.2.0",
|
|
55
55
|
"open": "^10.2.0",
|
|
56
56
|
"shell-quote": "^1.8.3",
|
|
@@ -63,12 +63,19 @@
|
|
|
63
63
|
"@types/jest": "^29.5.14",
|
|
64
64
|
"@types/node": "^22.17.0",
|
|
65
65
|
"@types/shell-quote": "^1.7.5",
|
|
66
|
+
"husky": "^9.1.7",
|
|
66
67
|
"jest-fixed-jsdom": "^0.0.9",
|
|
68
|
+
"lint-staged": "^16.1.5",
|
|
67
69
|
"prettier": "^3.6.2",
|
|
68
70
|
"rimraf": "^6.0.1",
|
|
69
71
|
"typescript": "^5.4.2"
|
|
70
72
|
},
|
|
71
73
|
"engines": {
|
|
72
74
|
"node": ">=22.7.5"
|
|
75
|
+
},
|
|
76
|
+
"lint-staged": {
|
|
77
|
+
"**/*.{js,ts,jsx,tsx,json,md}": [
|
|
78
|
+
"prettier --write"
|
|
79
|
+
]
|
|
73
80
|
}
|
|
74
81
|
}
|
package/server/build/index.js
CHANGED
|
@@ -131,10 +131,10 @@ const createTransport = async (req) => {
|
|
|
131
131
|
console.log("Query parameters:", JSON.stringify(query));
|
|
132
132
|
const transportType = query.transportType;
|
|
133
133
|
if (transportType === "stdio") {
|
|
134
|
-
const command = query.command;
|
|
134
|
+
const command = query.command.trim();
|
|
135
135
|
const origArgs = shellParseArgs(query.args);
|
|
136
136
|
const queryEnv = query.env ? JSON.parse(query.env) : {};
|
|
137
|
-
const env = { ...process.env, ...
|
|
137
|
+
const env = { ...defaultEnvironment, ...process.env, ...queryEnv };
|
|
138
138
|
const { cmd, args } = findActualExecutable(command, origArgs);
|
|
139
139
|
console.log(`STDIO transport: command=${cmd}, args=${args}`);
|
|
140
140
|
const transport = new StdioClientTransport({
|
|
@@ -280,7 +280,6 @@ app.get("/stdio", originValidationMiddleware, authMiddleware, async (req, res) =
|
|
|
280
280
|
let serverTransport;
|
|
281
281
|
try {
|
|
282
282
|
serverTransport = await createTransport(req);
|
|
283
|
-
console.log("Created server transport");
|
|
284
283
|
}
|
|
285
284
|
catch (error) {
|
|
286
285
|
if (error instanceof SseError && error.code === 401) {
|
|
@@ -290,32 +289,89 @@ app.get("/stdio", originValidationMiddleware, authMiddleware, async (req, res) =
|
|
|
290
289
|
}
|
|
291
290
|
throw error;
|
|
292
291
|
}
|
|
293
|
-
const
|
|
294
|
-
|
|
292
|
+
const proxyFullAddress = req.query.proxyFullAddress || "";
|
|
293
|
+
const prefix = proxyFullAddress || "";
|
|
294
|
+
const endpoint = `${prefix}/message`;
|
|
295
|
+
const webAppTransport = new SSEServerTransport(endpoint, res);
|
|
295
296
|
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
|
297
|
+
console.log("Created client transport");
|
|
296
298
|
serverTransports.set(webAppTransport.sessionId, serverTransport);
|
|
299
|
+
console.log("Created server transport");
|
|
297
300
|
await webAppTransport.start();
|
|
298
301
|
serverTransport.stderr.on("data", (chunk) => {
|
|
299
302
|
if (chunk.toString().includes("MODULE_NOT_FOUND")) {
|
|
303
|
+
// Server command not found, remove transports
|
|
304
|
+
const message = "Command not found, transports removed";
|
|
300
305
|
webAppTransport.send({
|
|
301
306
|
jsonrpc: "2.0",
|
|
302
|
-
method: "notifications/
|
|
307
|
+
method: "notifications/message",
|
|
303
308
|
params: {
|
|
304
|
-
|
|
309
|
+
level: "emergency",
|
|
310
|
+
logger: "proxy",
|
|
311
|
+
data: {
|
|
312
|
+
message,
|
|
313
|
+
},
|
|
305
314
|
},
|
|
306
315
|
});
|
|
307
316
|
webAppTransport.close();
|
|
308
317
|
serverTransport.close();
|
|
309
318
|
webAppTransports.delete(webAppTransport.sessionId);
|
|
310
319
|
serverTransports.delete(webAppTransport.sessionId);
|
|
311
|
-
console.error(
|
|
320
|
+
console.error(message);
|
|
312
321
|
}
|
|
313
322
|
else {
|
|
323
|
+
// Inspect message and attempt to assign a RFC 5424 Syslog Protocol level
|
|
324
|
+
let level;
|
|
325
|
+
let message = chunk.toString().trim();
|
|
326
|
+
let ucMsg = chunk.toString().toUpperCase();
|
|
327
|
+
if (ucMsg.includes("DEBUG")) {
|
|
328
|
+
level = "debug";
|
|
329
|
+
}
|
|
330
|
+
else if (ucMsg.includes("INFO")) {
|
|
331
|
+
level = "info";
|
|
332
|
+
}
|
|
333
|
+
else if (ucMsg.includes("NOTICE")) {
|
|
334
|
+
level = "notice";
|
|
335
|
+
}
|
|
336
|
+
else if (ucMsg.includes("WARN")) {
|
|
337
|
+
level = "warning";
|
|
338
|
+
}
|
|
339
|
+
else if (ucMsg.includes("ERROR")) {
|
|
340
|
+
level = "error";
|
|
341
|
+
}
|
|
342
|
+
else if (ucMsg.includes("CRITICAL")) {
|
|
343
|
+
level = "critical";
|
|
344
|
+
}
|
|
345
|
+
else if (ucMsg.includes("ALERT")) {
|
|
346
|
+
level = "alert";
|
|
347
|
+
}
|
|
348
|
+
else if (ucMsg.includes("EMERGENCY")) {
|
|
349
|
+
level = "emergency";
|
|
350
|
+
}
|
|
351
|
+
else if (ucMsg.includes("SIGINT")) {
|
|
352
|
+
message = "SIGINT received. Server shutdown.";
|
|
353
|
+
level = "emergency";
|
|
354
|
+
}
|
|
355
|
+
else if (ucMsg.includes("SIGHUP")) {
|
|
356
|
+
message = "SIGHUP received. Server shutdown.";
|
|
357
|
+
level = "emergency";
|
|
358
|
+
}
|
|
359
|
+
else if (ucMsg.includes("SIGTERM")) {
|
|
360
|
+
message = "SIGTERM received. Server shutdown.";
|
|
361
|
+
level = "emergency";
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
level = "info";
|
|
365
|
+
}
|
|
314
366
|
webAppTransport.send({
|
|
315
367
|
jsonrpc: "2.0",
|
|
316
|
-
method: "notifications/
|
|
368
|
+
method: "notifications/message",
|
|
317
369
|
params: {
|
|
318
|
-
|
|
370
|
+
level,
|
|
371
|
+
logger: "stdio",
|
|
372
|
+
data: {
|
|
373
|
+
message,
|
|
374
|
+
},
|
|
319
375
|
},
|
|
320
376
|
});
|
|
321
377
|
}
|
|
@@ -332,7 +388,7 @@ app.get("/stdio", originValidationMiddleware, authMiddleware, async (req, res) =
|
|
|
332
388
|
});
|
|
333
389
|
app.get("/sse", originValidationMiddleware, authMiddleware, async (req, res) => {
|
|
334
390
|
try {
|
|
335
|
-
console.log("New SSE connection request. NOTE: The
|
|
391
|
+
console.log("New SSE connection request. NOTE: The SSE transport is deprecated and has been replaced by StreamableHttp");
|
|
336
392
|
let serverTransport;
|
|
337
393
|
try {
|
|
338
394
|
serverTransport = await createTransport(req);
|
|
@@ -357,7 +413,10 @@ app.get("/sse", originValidationMiddleware, authMiddleware, async (req, res) =>
|
|
|
357
413
|
}
|
|
358
414
|
}
|
|
359
415
|
if (serverTransport) {
|
|
360
|
-
const
|
|
416
|
+
const proxyFullAddress = req.query.proxyFullAddress || "";
|
|
417
|
+
const prefix = proxyFullAddress || "";
|
|
418
|
+
const endpoint = `${prefix}/message`;
|
|
419
|
+
const webAppTransport = new SSEServerTransport(endpoint, res);
|
|
361
420
|
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
|
|
362
421
|
console.log("Created client transport");
|
|
363
422
|
serverTransports.set(webAppTransport.sessionId, serverTransport);
|