@modelcontextprotocol/inspector 2.0.0 → 2.1.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 +18 -14
- package/clients/cli/build/index.js +134 -36
- package/clients/tui/build/index.js +129 -33
- package/clients/web/build/index.js +24 -5
- package/clients/web/dist/assets/index-CyPh2pEE.js +300 -0
- package/clients/web/dist/assets/prism-light-CCFFzO_n.js +6 -0
- package/clients/web/dist/index.html +1 -1
- package/package.json +3 -3
- package/clients/web/dist/assets/index-wIMJi5MN.js +0 -300
- package/clients/web/dist/assets/prism-light-CVa8c8_p.js +0 -6
|
@@ -422,9 +422,13 @@ function loadMcpServersConfig(configPath, writable) {
|
|
|
422
422
|
return { ...config, mcpServers: normalizedServers };
|
|
423
423
|
} catch (error) {
|
|
424
424
|
if (error instanceof Error) {
|
|
425
|
-
throw new Error(`Error loading configuration: ${error.message}
|
|
425
|
+
throw new Error(`Error loading configuration: ${error.message}`, {
|
|
426
|
+
cause: error
|
|
427
|
+
});
|
|
426
428
|
}
|
|
427
|
-
throw new Error("Error loading configuration: Unknown error"
|
|
429
|
+
throw new Error("Error loading configuration: Unknown error", {
|
|
430
|
+
cause: error
|
|
431
|
+
});
|
|
428
432
|
}
|
|
429
433
|
}
|
|
430
434
|
function loadServerFromConfig(configPath, serverName, writable) {
|
|
@@ -994,7 +998,9 @@ function parseHttpUrl(value, label) {
|
|
|
994
998
|
return new URL(trimmed);
|
|
995
999
|
} catch (err) {
|
|
996
1000
|
const detail = err instanceof Error ? err.message : String(err);
|
|
997
|
-
throw new Error(`Invalid ${label}: "${trimmed}" (${detail})
|
|
1001
|
+
throw new Error(`Invalid ${label}: "${trimmed}" (${detail})`, {
|
|
1002
|
+
cause: err
|
|
1003
|
+
});
|
|
998
1004
|
}
|
|
999
1005
|
}
|
|
1000
1006
|
var parseOAuthCallbackParams = (location) => {
|
|
@@ -1734,7 +1740,7 @@ function parseRunnerOAuthCallbackUrl(cliCallbackUrl) {
|
|
|
1734
1740
|
url = new URL(raw);
|
|
1735
1741
|
} catch (err) {
|
|
1736
1742
|
const reason = err?.message ?? String(err);
|
|
1737
|
-
throw new Error(`Invalid OAuth callback URL: ${reason}
|
|
1743
|
+
throw new Error(`Invalid OAuth callback URL: ${reason}`, { cause: err });
|
|
1738
1744
|
}
|
|
1739
1745
|
if (url.protocol !== "http:") {
|
|
1740
1746
|
throw new Error("OAuth callback URL must use http scheme");
|
|
@@ -1779,6 +1785,7 @@ import { Client } from "@modelcontextprotocol/client";
|
|
|
1779
1785
|
|
|
1780
1786
|
// ../../core/json/xMcpHeader.ts
|
|
1781
1787
|
var X_MCP_HEADER_KEY = "x-mcp-header";
|
|
1788
|
+
var MCP_PARAM_HEADER_PREFIX = "Mcp-Param-";
|
|
1782
1789
|
var RFC9110_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
1783
1790
|
var PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
1784
1791
|
"string",
|
|
@@ -1868,6 +1875,66 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
1868
1875
|
const fault = visit(inputSchema, [], true);
|
|
1869
1876
|
return fault === void 0 ? { valid: true, declarations } : { valid: false, reason: fault };
|
|
1870
1877
|
}
|
|
1878
|
+
var BASE64_SENTINEL_PREFIX = "=?base64?";
|
|
1879
|
+
var BASE64_SENTINEL_SUFFIX = "?=";
|
|
1880
|
+
function mcpParamPrimitiveToString(value) {
|
|
1881
|
+
if (typeof value === "string") return value;
|
|
1882
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
1883
|
+
if (typeof value === "number") {
|
|
1884
|
+
if (!Number.isFinite(value)) return void 0;
|
|
1885
|
+
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
|
|
1886
|
+
return void 0;
|
|
1887
|
+
}
|
|
1888
|
+
return String(value);
|
|
1889
|
+
}
|
|
1890
|
+
return void 0;
|
|
1891
|
+
}
|
|
1892
|
+
function needsBase64(s) {
|
|
1893
|
+
if (s.length === 0) return true;
|
|
1894
|
+
if (s.startsWith(BASE64_SENTINEL_PREFIX) && s.endsWith(BASE64_SENTINEL_SUFFIX)) {
|
|
1895
|
+
return true;
|
|
1896
|
+
}
|
|
1897
|
+
if (s !== s.trim()) return true;
|
|
1898
|
+
for (let i = 0; i < s.length; i++) {
|
|
1899
|
+
const c = s.codePointAt(i);
|
|
1900
|
+
if (c === 9 || c >= 32 && c <= 126) continue;
|
|
1901
|
+
return true;
|
|
1902
|
+
}
|
|
1903
|
+
return false;
|
|
1904
|
+
}
|
|
1905
|
+
function utf8ToBase64(s) {
|
|
1906
|
+
const bytes = new TextEncoder().encode(s);
|
|
1907
|
+
let bin = "";
|
|
1908
|
+
for (const b of bytes) bin += String.fromCodePoint(b);
|
|
1909
|
+
return btoa(bin);
|
|
1910
|
+
}
|
|
1911
|
+
function encodeMcpParamValue(value) {
|
|
1912
|
+
return needsBase64(value) ? `${BASE64_SENTINEL_PREFIX}${utf8ToBase64(value)}${BASE64_SENTINEL_SUFFIX}` : value;
|
|
1913
|
+
}
|
|
1914
|
+
function valueAtPath(root, path3) {
|
|
1915
|
+
let node = root;
|
|
1916
|
+
for (const key of path3) {
|
|
1917
|
+
if (node === null || typeof node !== "object") return void 0;
|
|
1918
|
+
node = node[key];
|
|
1919
|
+
}
|
|
1920
|
+
return node;
|
|
1921
|
+
}
|
|
1922
|
+
function buildMcpParamHeaders(declarations, args) {
|
|
1923
|
+
const out = {};
|
|
1924
|
+
for (const decl of declarations) {
|
|
1925
|
+
const raw = valueAtPath(args, decl.path);
|
|
1926
|
+
if (raw === void 0 || raw === null) continue;
|
|
1927
|
+
const stringValue = mcpParamPrimitiveToString(raw);
|
|
1928
|
+
if (stringValue === void 0) continue;
|
|
1929
|
+
out[`${MCP_PARAM_HEADER_PREFIX}${decl.headerName}`] = encodeMcpParamValue(stringValue);
|
|
1930
|
+
}
|
|
1931
|
+
return out;
|
|
1932
|
+
}
|
|
1933
|
+
function mcpParamHeadersForTool(tool, args) {
|
|
1934
|
+
const scan = scanXMcpHeaderDeclarations(tool.inputSchema);
|
|
1935
|
+
if (!scan.valid || scan.declarations.length === 0) return {};
|
|
1936
|
+
return buildMcpParamHeaders(scan.declarations, args);
|
|
1937
|
+
}
|
|
1871
1938
|
|
|
1872
1939
|
// ../../core/mcp/messageTrackingTransport.ts
|
|
1873
1940
|
var MessageTrackingTransport = class {
|
|
@@ -2967,7 +3034,9 @@ function getAuthorizationServerUrl(serverUrl, resourceMetadata) {
|
|
|
2967
3034
|
return new URL("/", serverUrl);
|
|
2968
3035
|
} catch (err) {
|
|
2969
3036
|
const detail = err instanceof Error ? err.message : String(err);
|
|
2970
|
-
throw new Error(`Invalid MCP server URL: "${serverUrl}" (${detail})
|
|
3037
|
+
throw new Error(`Invalid MCP server URL: "${serverUrl}" (${detail})`, {
|
|
3038
|
+
cause: err
|
|
3039
|
+
});
|
|
2971
3040
|
}
|
|
2972
3041
|
}
|
|
2973
3042
|
|
|
@@ -4648,7 +4717,10 @@ var RemoteClientTransport = class {
|
|
|
4648
4717
|
message,
|
|
4649
4718
|
...options?.relatedRequestId != null && {
|
|
4650
4719
|
relatedRequestId: options.relatedRequestId
|
|
4651
|
-
}
|
|
4720
|
+
},
|
|
4721
|
+
// Forward per-send `Mcp-Param-*` headers (SEP-2243) for the backend to
|
|
4722
|
+
// apply to the upstream send; the browser can't set them cross-origin.
|
|
4723
|
+
...options?.headers != null && { headers: options.headers }
|
|
4652
4724
|
};
|
|
4653
4725
|
const res = await this.fetchFn(`${this.baseUrl}/api/mcp/send`, {
|
|
4654
4726
|
method: "POST",
|
|
@@ -6898,6 +6970,43 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
6898
6970
|
}
|
|
6899
6971
|
}
|
|
6900
6972
|
}
|
|
6973
|
+
/**
|
|
6974
|
+
* Coerce the string-valued entries of a tool's arguments to the types its
|
|
6975
|
+
* `inputSchema` declares (the Tools form hands everything over as text).
|
|
6976
|
+
* Shared by the two `tools/call` entry points — {@link attemptToolCall} and
|
|
6977
|
+
* {@link callToolStream} — so both put the SAME arguments on the wire.
|
|
6978
|
+
*/
|
|
6979
|
+
convertStringToolArgs(tool, args) {
|
|
6980
|
+
const stringArgs = {};
|
|
6981
|
+
for (const [key, value] of Object.entries(args)) {
|
|
6982
|
+
if (typeof value === "string") {
|
|
6983
|
+
stringArgs[key] = value;
|
|
6984
|
+
}
|
|
6985
|
+
}
|
|
6986
|
+
if (Object.keys(stringArgs).length === 0) return args;
|
|
6987
|
+
return { ...args, ...convertToolParameters(tool, stringArgs) };
|
|
6988
|
+
}
|
|
6989
|
+
/**
|
|
6990
|
+
* SEP-2243: mirror `x-mcp-header`-annotated arguments into `Mcp-Param-*`
|
|
6991
|
+
* headers on a modern connection. The SDK only does this inside
|
|
6992
|
+
* `client.callTool()` (and skips it in the browser), but we route
|
|
6993
|
+
* `tools/call` through `client.request()` for manual MRTR driving (#1704), so
|
|
6994
|
+
* we mirror ourselves. `Protocol.request` forwards `headers` (preserved
|
|
6995
|
+
* across MRTR retry legs) to the transport, and the remote transport relays
|
|
6996
|
+
* them to the backend's upstream send — issued server-side, where the browser
|
|
6997
|
+
* skip doesn't apply. No-op on legacy/stdio (no annotations).
|
|
6998
|
+
*
|
|
6999
|
+
* Applied by BOTH `tools/call` entry points: a plain call
|
|
7000
|
+
* ({@link attemptToolCall}) and a task-augmented one
|
|
7001
|
+
* ({@link callToolStream}) — a strict modern server rejects either with
|
|
7002
|
+
* `-32020` when the mirrored header is missing.
|
|
7003
|
+
*/
|
|
7004
|
+
applyMirroredParamHeaders(tool, convertedArgs, requestOptions) {
|
|
7005
|
+
if (this.protocolEra !== "modern") return;
|
|
7006
|
+
const paramHeaders = mcpParamHeadersForTool(tool, convertedArgs);
|
|
7007
|
+
if (Object.keys(paramHeaders).length === 0) return;
|
|
7008
|
+
requestOptions.headers = { ...requestOptions.headers, ...paramHeaders };
|
|
7009
|
+
}
|
|
6901
7010
|
/**
|
|
6902
7011
|
* Run a single tools/call attempt: convert args, issue the request, validate,
|
|
6903
7012
|
* and return a successful {@link ToolCallInvocation}. Throws on any error
|
|
@@ -6917,17 +7026,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
6917
7026
|
if (!client) {
|
|
6918
7027
|
throw new Error("Client is not connected");
|
|
6919
7028
|
}
|
|
6920
|
-
|
|
6921
|
-
const stringArgs = {};
|
|
6922
|
-
for (const [key, value] of Object.entries(args)) {
|
|
6923
|
-
if (typeof value === "string") {
|
|
6924
|
-
stringArgs[key] = value;
|
|
6925
|
-
}
|
|
6926
|
-
}
|
|
6927
|
-
if (Object.keys(stringArgs).length > 0) {
|
|
6928
|
-
const convertedStringArgs = convertToolParameters(tool, stringArgs);
|
|
6929
|
-
convertedArgs = { ...args, ...convertedStringArgs };
|
|
6930
|
-
}
|
|
7029
|
+
const convertedArgs = this.convertStringToolArgs(tool, args);
|
|
6931
7030
|
const callMetadata = generalMetadata || toolSpecificMetadata ? { ...generalMetadata || {}, ...toolSpecificMetadata || {} } : void 0;
|
|
6932
7031
|
const timestamp = /* @__PURE__ */ new Date();
|
|
6933
7032
|
const metadata = this.mergeMeta(callMetadata);
|
|
@@ -6943,6 +7042,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
6943
7042
|
metadata?.progressToken,
|
|
6944
7043
|
signal
|
|
6945
7044
|
);
|
|
7045
|
+
this.applyMirroredParamHeaders(tool, convertedArgs, requestOptions);
|
|
6946
7046
|
const rawResult = await this.invokeMcpClient(
|
|
6947
7047
|
() => this.requestWithInputRequired(
|
|
6948
7048
|
"tools/call",
|
|
@@ -7346,17 +7446,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
7346
7446
|
throw new Error("Client is not connected");
|
|
7347
7447
|
}
|
|
7348
7448
|
try {
|
|
7349
|
-
|
|
7350
|
-
const stringArgs = {};
|
|
7351
|
-
for (const [key, value] of Object.entries(args)) {
|
|
7352
|
-
if (typeof value === "string") {
|
|
7353
|
-
stringArgs[key] = value;
|
|
7354
|
-
}
|
|
7355
|
-
}
|
|
7356
|
-
if (Object.keys(stringArgs).length > 0) {
|
|
7357
|
-
const convertedStringArgs = convertToolParameters(tool, stringArgs);
|
|
7358
|
-
convertedArgs = { ...args, ...convertedStringArgs };
|
|
7359
|
-
}
|
|
7449
|
+
const convertedArgs = this.convertStringToolArgs(tool, args);
|
|
7360
7450
|
const callMetadata = generalMetadata || toolSpecificMetadata ? { ...generalMetadata || {}, ...toolSpecificMetadata || {} } : void 0;
|
|
7361
7451
|
const timestamp = /* @__PURE__ */ new Date();
|
|
7362
7452
|
const metadata = this.mergeMeta(callMetadata);
|
|
@@ -7374,6 +7464,7 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
7374
7464
|
let taskId;
|
|
7375
7465
|
let error;
|
|
7376
7466
|
const requestOptions = this.getRequestOptions(metadata?.progressToken);
|
|
7467
|
+
this.applyMirroredParamHeaders(tool, convertedArgs, requestOptions);
|
|
7377
7468
|
if (this.progress) {
|
|
7378
7469
|
const innerOnProgress = requestOptions.onprogress;
|
|
7379
7470
|
requestOptions.onprogress = (progress) => {
|
|
@@ -7479,7 +7570,8 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
7479
7570
|
);
|
|
7480
7571
|
} catch (resultError) {
|
|
7481
7572
|
throw new Error(
|
|
7482
|
-
`Tool call did not return a result: ${resultError instanceof Error ? resultError.message : String(resultError)}
|
|
7573
|
+
`Tool call did not return a result: ${resultError instanceof Error ? resultError.message : String(resultError)}`,
|
|
7574
|
+
{ cause: resultError }
|
|
7483
7575
|
);
|
|
7484
7576
|
}
|
|
7485
7577
|
}
|
|
@@ -7622,7 +7714,8 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
7622
7714
|
expandedUri = uriTemplate2.expand(params);
|
|
7623
7715
|
} catch (error) {
|
|
7624
7716
|
throw new Error(
|
|
7625
|
-
`Failed to expand URI template "${uriTemplate}": ${error instanceof Error ? error.message : String(error)}
|
|
7717
|
+
`Failed to expand URI template "${uriTemplate}": ${error instanceof Error ? error.message : String(error)}`,
|
|
7718
|
+
{ cause: error }
|
|
7626
7719
|
);
|
|
7627
7720
|
}
|
|
7628
7721
|
const readInvocation = await this.readResource(expandedUri, metadata);
|
|
@@ -7820,7 +7913,8 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
7820
7913
|
return { values: [] };
|
|
7821
7914
|
}
|
|
7822
7915
|
throw new Error(
|
|
7823
|
-
`Failed to get completions: ${error instanceof Error ? error.message : String(error)}
|
|
7916
|
+
`Failed to get completions: ${error instanceof Error ? error.message : String(error)}`,
|
|
7917
|
+
{ cause: error }
|
|
7824
7918
|
);
|
|
7825
7919
|
}
|
|
7826
7920
|
}
|
|
@@ -8222,7 +8316,8 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
8222
8316
|
this.dispatchSubscriptionsChange();
|
|
8223
8317
|
} catch (error) {
|
|
8224
8318
|
throw new Error(
|
|
8225
|
-
`Failed to subscribe to resource: ${error instanceof Error ? error.message : String(error)}
|
|
8319
|
+
`Failed to subscribe to resource: ${error instanceof Error ? error.message : String(error)}`,
|
|
8320
|
+
{ cause: error }
|
|
8226
8321
|
);
|
|
8227
8322
|
}
|
|
8228
8323
|
}
|
|
@@ -8266,7 +8361,8 @@ var InspectorClient = class _InspectorClient extends InspectorClientEventTarget
|
|
|
8266
8361
|
}
|
|
8267
8362
|
} catch (error) {
|
|
8268
8363
|
throw new Error(
|
|
8269
|
-
`Failed to unsubscribe from resource: ${error instanceof Error ? error.message : String(error)}
|
|
8364
|
+
`Failed to unsubscribe from resource: ${error instanceof Error ? error.message : String(error)}`,
|
|
8365
|
+
{ cause: error }
|
|
8270
8366
|
);
|
|
8271
8367
|
}
|
|
8272
8368
|
}
|
|
@@ -453,9 +453,13 @@ function loadMcpServersConfig(configPath, writable) {
|
|
|
453
453
|
return { ...config, mcpServers: normalizedServers };
|
|
454
454
|
} catch (error) {
|
|
455
455
|
if (error instanceof Error) {
|
|
456
|
-
throw new Error(`Error loading configuration: ${error.message}
|
|
456
|
+
throw new Error(`Error loading configuration: ${error.message}`, {
|
|
457
|
+
cause: error
|
|
458
|
+
});
|
|
457
459
|
}
|
|
458
|
-
throw new Error("Error loading configuration: Unknown error"
|
|
460
|
+
throw new Error("Error loading configuration: Unknown error", {
|
|
461
|
+
cause: error
|
|
462
|
+
});
|
|
459
463
|
}
|
|
460
464
|
}
|
|
461
465
|
function loadServerFromConfig(configPath, serverName, writable) {
|
|
@@ -1507,6 +1511,9 @@ function createTransportNode(config, options = {}) {
|
|
|
1507
1511
|
}
|
|
1508
1512
|
}
|
|
1509
1513
|
|
|
1514
|
+
// ../../core/json/xMcpHeader.ts
|
|
1515
|
+
var MCP_PARAM_HEADER_PREFIX = "Mcp-Param-";
|
|
1516
|
+
|
|
1510
1517
|
// ../../core/mcp/import/clientConfig.ts
|
|
1511
1518
|
function parseJsonObject(raw) {
|
|
1512
1519
|
let data;
|
|
@@ -1514,7 +1521,7 @@ function parseJsonObject(raw) {
|
|
|
1514
1521
|
data = JSON.parse(raw);
|
|
1515
1522
|
} catch (err) {
|
|
1516
1523
|
const detail = err instanceof Error ? err.message : String(err);
|
|
1517
|
-
throw new Error(`Invalid JSON: ${detail}
|
|
1524
|
+
throw new Error(`Invalid JSON: ${detail}`, { cause: err });
|
|
1518
1525
|
}
|
|
1519
1526
|
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
1520
1527
|
throw new Error("Expected a JSON object at the top level");
|
|
@@ -2347,6 +2354,16 @@ function requestIdForSendWait(message) {
|
|
|
2347
2354
|
}
|
|
2348
2355
|
return void 0;
|
|
2349
2356
|
}
|
|
2357
|
+
function mcpParamHeadersOnly(headers) {
|
|
2358
|
+
if (headers === null || typeof headers !== "object") return void 0;
|
|
2359
|
+
const out = {};
|
|
2360
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
2361
|
+
if (typeof value === "string" && key.toLowerCase().startsWith(MCP_PARAM_HEADER_PREFIX.toLowerCase())) {
|
|
2362
|
+
out[key] = value;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
2366
|
+
}
|
|
2350
2367
|
function createRemoteApp(options) {
|
|
2351
2368
|
const dangerouslyOmitAuth = !!options.dangerouslyOmitAuth;
|
|
2352
2369
|
const authToken = dangerouslyOmitAuth ? "" : options.authToken || process.env[API_SERVER_ENV_VARS.AUTH_TOKEN] || randomBytes(32).toString("hex");
|
|
@@ -2554,7 +2571,7 @@ function createRemoteApp(options) {
|
|
|
2554
2571
|
} catch {
|
|
2555
2572
|
return c.json({ error: "Invalid JSON body" }, 400);
|
|
2556
2573
|
}
|
|
2557
|
-
const { sessionId, message, relatedRequestId } = body;
|
|
2574
|
+
const { sessionId, message, relatedRequestId, headers } = body;
|
|
2558
2575
|
if (!sessionId || !message) {
|
|
2559
2576
|
return c.json({ error: "Missing sessionId or message" }, 400);
|
|
2560
2577
|
}
|
|
@@ -2575,8 +2592,10 @@ function createRemoteApp(options) {
|
|
|
2575
2592
|
});
|
|
2576
2593
|
}
|
|
2577
2594
|
try {
|
|
2595
|
+
const paramHeaders = mcpParamHeadersOnly(headers);
|
|
2578
2596
|
await session.transport.send(message, {
|
|
2579
|
-
relatedRequestId
|
|
2597
|
+
relatedRequestId,
|
|
2598
|
+
...paramHeaders && { headers: paramHeaders }
|
|
2580
2599
|
});
|
|
2581
2600
|
if (responseWait) {
|
|
2582
2601
|
await responseWait;
|