@ai-ecoverse/mcpcat 0.20.3 → 0.20.4
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/dist/host/mcpcat.mjs +204 -100
- package/dist/kernel/mcpcat.mjs +204 -100
- package/package.json +3 -3
package/dist/host/mcpcat.mjs
CHANGED
|
@@ -7691,7 +7691,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7691
7691
|
let dataLines = [];
|
|
7692
7692
|
let dataBytes = 0;
|
|
7693
7693
|
const maxEventBytes = options.maxEventBytes ?? DEFAULT_MAX_MESSAGE_BYTES;
|
|
7694
|
-
const
|
|
7694
|
+
const dispatch2 = () => {
|
|
7695
7695
|
if (dataLines.length === 0) {
|
|
7696
7696
|
eventName = void 0;
|
|
7697
7697
|
eventId = void 0;
|
|
@@ -7707,7 +7707,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7707
7707
|
const processLine = (rawLine) => {
|
|
7708
7708
|
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
7709
7709
|
if (line === "") {
|
|
7710
|
-
|
|
7710
|
+
dispatch2();
|
|
7711
7711
|
return;
|
|
7712
7712
|
}
|
|
7713
7713
|
if (line.startsWith(":"))
|
|
@@ -7748,7 +7748,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7748
7748
|
buffered += decoder3.decode();
|
|
7749
7749
|
if (buffered)
|
|
7750
7750
|
processLine(buffered);
|
|
7751
|
-
|
|
7751
|
+
dispatch2();
|
|
7752
7752
|
} finally {
|
|
7753
7753
|
reader.releaseLock();
|
|
7754
7754
|
}
|
|
@@ -8352,18 +8352,118 @@ var PlatformStdioTransport = class {
|
|
|
8352
8352
|
}
|
|
8353
8353
|
};
|
|
8354
8354
|
|
|
8355
|
+
// src/client/modern.ts
|
|
8356
|
+
var MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
8357
|
+
var META_PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
|
|
8358
|
+
var META_CLIENT_INFO = "io.modelcontextprotocol/clientInfo";
|
|
8359
|
+
var META_CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
8360
|
+
var META_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
|
|
8361
|
+
var HEADER_MISMATCH = -32020;
|
|
8362
|
+
var MISSING_REQUIRED_CLIENT_CAPABILITY = -32021;
|
|
8363
|
+
var UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
8364
|
+
var MODERN_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
8365
|
+
HEADER_MISMATCH,
|
|
8366
|
+
MISSING_REQUIRED_CLIENT_CAPABILITY,
|
|
8367
|
+
UNSUPPORTED_PROTOCOL_VERSION
|
|
8368
|
+
]);
|
|
8369
|
+
function isModernErrorCode(code2) {
|
|
8370
|
+
return MODERN_ERROR_CODES.has(code2);
|
|
8371
|
+
}
|
|
8372
|
+
function modernRequestMeta(protocolVersion, clientInfo) {
|
|
8373
|
+
return {
|
|
8374
|
+
[META_PROTOCOL_VERSION]: protocolVersion,
|
|
8375
|
+
[META_CLIENT_INFO]: clientInfo,
|
|
8376
|
+
[META_CLIENT_CAPABILITIES]: {}
|
|
8377
|
+
};
|
|
8378
|
+
}
|
|
8379
|
+
function modernRequestParams(params, protocolVersion, clientInfo) {
|
|
8380
|
+
const { _inputResponses, ...rest } = params;
|
|
8381
|
+
const out = { ...rest };
|
|
8382
|
+
if (_inputResponses) out.inputResponses = _inputResponses;
|
|
8383
|
+
out._meta = modernRequestMeta(protocolVersion, clientInfo);
|
|
8384
|
+
return out;
|
|
8385
|
+
}
|
|
8386
|
+
var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
8387
|
+
function base64Utf8(value) {
|
|
8388
|
+
const bytes = new TextEncoder().encode(value);
|
|
8389
|
+
let out = "";
|
|
8390
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
8391
|
+
const a = bytes[i];
|
|
8392
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
8393
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
8394
|
+
const n = a << 16 | b << 8 | c;
|
|
8395
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63];
|
|
8396
|
+
out += i + 1 < bytes.length ? B64[n >> 6 & 63] : "=";
|
|
8397
|
+
out += i + 2 < bytes.length ? B64[n & 63] : "=";
|
|
8398
|
+
}
|
|
8399
|
+
return out;
|
|
8400
|
+
}
|
|
8401
|
+
function encodeHeaderValue(value) {
|
|
8402
|
+
const safe = /^[\x20-\x7e\t]*$/.test(value) && value.trim() === value && !(value.startsWith("=?base64?") && value.endsWith("?="));
|
|
8403
|
+
return safe ? value : `=?base64?${base64Utf8(value)}?=`;
|
|
8404
|
+
}
|
|
8405
|
+
function isModernRequest(params) {
|
|
8406
|
+
if (!params || typeof params !== "object") return false;
|
|
8407
|
+
const meta = Object.getOwnPropertyDescriptor(params, "_meta")?.value;
|
|
8408
|
+
if (!meta || typeof meta !== "object") return false;
|
|
8409
|
+
return typeof Object.getOwnPropertyDescriptor(meta, META_PROTOCOL_VERSION)?.value === "string";
|
|
8410
|
+
}
|
|
8411
|
+
function completeModernOutcome(outcome, params) {
|
|
8412
|
+
if (outcome.status !== 200 || !isModernRequest(params)) return outcome;
|
|
8413
|
+
const frame = JSON.parse(outcome.body);
|
|
8414
|
+
const result = frame.result;
|
|
8415
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return outcome;
|
|
8416
|
+
if (Object.hasOwn(result, "resultType")) return outcome;
|
|
8417
|
+
frame.result = { resultType: "complete", ...result };
|
|
8418
|
+
return { ...outcome, body: JSON.stringify(frame) };
|
|
8419
|
+
}
|
|
8420
|
+
function modernDiscoverResult(supportedVersions, capabilities, serverInfo, instructions) {
|
|
8421
|
+
return {
|
|
8422
|
+
resultType: "complete",
|
|
8423
|
+
supportedVersions,
|
|
8424
|
+
capabilities,
|
|
8425
|
+
serverInfo,
|
|
8426
|
+
...instructions ? { instructions } : {},
|
|
8427
|
+
_meta: { [META_SERVER_INFO]: serverInfo }
|
|
8428
|
+
};
|
|
8429
|
+
}
|
|
8430
|
+
|
|
8355
8431
|
// src/client/stateless-connection.ts
|
|
8356
|
-
var STATELESS_PROTOCOL_VERSION =
|
|
8432
|
+
var STATELESS_PROTOCOL_VERSION = MODERN_PROTOCOL_VERSION;
|
|
8357
8433
|
var StatelessRpcError = class extends Error {
|
|
8358
8434
|
code;
|
|
8359
8435
|
data;
|
|
8360
|
-
|
|
8436
|
+
httpStatus;
|
|
8437
|
+
constructor(code2, message, data, httpStatus) {
|
|
8361
8438
|
super(`MCP RPC error ${code2}: ${message}`);
|
|
8362
8439
|
this.name = "StatelessRpcError";
|
|
8363
8440
|
this.code = code2;
|
|
8364
8441
|
this.data = data;
|
|
8442
|
+
this.httpStatus = httpStatus;
|
|
8443
|
+
}
|
|
8444
|
+
};
|
|
8445
|
+
var UnsupportedModernVersionError = class extends Error {
|
|
8446
|
+
constructor(version, supported) {
|
|
8447
|
+
super(`Server does not support ${version} (advertised: ${supported.join(", ") || "none"})`);
|
|
8448
|
+
this.name = "UnsupportedModernVersionError";
|
|
8365
8449
|
}
|
|
8366
8450
|
};
|
|
8451
|
+
function supportedList(data) {
|
|
8452
|
+
const list = data?.supported;
|
|
8453
|
+
return Array.isArray(list) ? list.filter((v) => typeof v === "string") : void 0;
|
|
8454
|
+
}
|
|
8455
|
+
function indicatesLegacyServer(err, http) {
|
|
8456
|
+
if (err instanceof UnsupportedModernVersionError) return true;
|
|
8457
|
+
if (http && err instanceof StatelessHttpError) return err.status >= 400 && err.status < 500;
|
|
8458
|
+
if (!(err instanceof StatelessRpcError)) return false;
|
|
8459
|
+
if (err.code === UNSUPPORTED_PROTOCOL_VERSION) {
|
|
8460
|
+
const supported = supportedList(err.data);
|
|
8461
|
+
return !!supported && !supported.includes(STATELESS_PROTOCOL_VERSION);
|
|
8462
|
+
}
|
|
8463
|
+
if (isModernErrorCode(err.code)) return false;
|
|
8464
|
+
if (!http || err.code === -32601) return true;
|
|
8465
|
+
return err.httpStatus !== void 0 && err.httpStatus >= 400 && err.httpStatus < 500;
|
|
8466
|
+
}
|
|
8367
8467
|
var StatelessHttpError = class extends Error {
|
|
8368
8468
|
status;
|
|
8369
8469
|
constructor(status, statusText, method, snippet) {
|
|
@@ -8475,11 +8575,16 @@ function logHeaders(verbose, dir, entries) {
|
|
|
8475
8575
|
else verbose.headerIn(k, v);
|
|
8476
8576
|
}
|
|
8477
8577
|
}
|
|
8578
|
+
function discoverServerInfo(discoverResult2) {
|
|
8579
|
+
const meta = discoverResult2?._meta;
|
|
8580
|
+
return meta?.[META_SERVER_INFO] ?? discoverResult2?.serverInfo;
|
|
8581
|
+
}
|
|
8478
8582
|
function buildServerInfo(discoverResult2) {
|
|
8583
|
+
const serverInfo = discoverServerInfo(discoverResult2);
|
|
8479
8584
|
return {
|
|
8480
|
-
name:
|
|
8481
|
-
version:
|
|
8482
|
-
title:
|
|
8585
|
+
name: serverInfo?.name,
|
|
8586
|
+
version: serverInfo?.version,
|
|
8587
|
+
title: serverInfo?.title,
|
|
8483
8588
|
protocolVersion: STATELESS_PROTOCOL_VERSION,
|
|
8484
8589
|
capabilities: discoverResult2?.capabilities ?? {},
|
|
8485
8590
|
instructions: discoverResult2?.instructions
|
|
@@ -8562,17 +8667,17 @@ async function createStatelessConnection(options) {
|
|
|
8562
8667
|
redact: redact2 = (text) => text
|
|
8563
8668
|
} = options;
|
|
8564
8669
|
let nextId2 = 1;
|
|
8565
|
-
|
|
8670
|
+
const protocolVersion = STATELESS_PROTOCOL_VERSION;
|
|
8566
8671
|
function buildHeaders(method, params, token) {
|
|
8567
8672
|
const h = {
|
|
8568
8673
|
"Content-Type": "application/json",
|
|
8569
8674
|
Accept: "application/json, text/event-stream",
|
|
8675
|
+
"MCP-Protocol-Version": protocolVersion,
|
|
8570
8676
|
"Mcp-Method": method,
|
|
8571
8677
|
...extraHeaders
|
|
8572
8678
|
};
|
|
8573
8679
|
const n = mcpNameForMethod(method, params);
|
|
8574
|
-
if (n) h["Mcp-Name"] = n;
|
|
8575
|
-
if (negotiatedVersion) h["Mcp-Protocol-Version"] = negotiatedVersion;
|
|
8680
|
+
if (n) h["Mcp-Name"] = encodeHeaderValue(n);
|
|
8576
8681
|
if (token) h["Authorization"] = `Bearer ${token}`;
|
|
8577
8682
|
return h;
|
|
8578
8683
|
}
|
|
@@ -8592,7 +8697,7 @@ async function createStatelessConnection(options) {
|
|
|
8592
8697
|
if (p.error && typeof p.error.code === "number") rpc = p.error;
|
|
8593
8698
|
} catch {
|
|
8594
8699
|
}
|
|
8595
|
-
if (rpc) throw new StatelessRpcError(rpc.code, rpc.message, rpc.data);
|
|
8700
|
+
if (rpc) throw new StatelessRpcError(rpc.code, rpc.message, rpc.data, res.status);
|
|
8596
8701
|
throw new StatelessHttpError(res.status, res.statusText, method, redact2(text).slice(0, 512));
|
|
8597
8702
|
}
|
|
8598
8703
|
async function doFetch(method, params, body) {
|
|
@@ -8635,7 +8740,12 @@ async function createStatelessConnection(options) {
|
|
|
8635
8740
|
}
|
|
8636
8741
|
if (verbose?.enabled) verbose.response(JSON.stringify(frame));
|
|
8637
8742
|
if (frame.error) {
|
|
8638
|
-
throw new StatelessRpcError(
|
|
8743
|
+
throw new StatelessRpcError(
|
|
8744
|
+
frame.error.code,
|
|
8745
|
+
frame.error.message,
|
|
8746
|
+
frame.error.data,
|
|
8747
|
+
res.status
|
|
8748
|
+
);
|
|
8639
8749
|
}
|
|
8640
8750
|
return frame.result;
|
|
8641
8751
|
}
|
|
@@ -8654,23 +8764,10 @@ async function createStatelessConnection(options) {
|
|
|
8654
8764
|
}
|
|
8655
8765
|
}
|
|
8656
8766
|
async function request(method, params) {
|
|
8657
|
-
const
|
|
8658
|
-
const meta = {
|
|
8659
|
-
protocolVersion: negotiatedVersion ?? STATELESS_PROTOCOL_VERSION,
|
|
8660
|
-
clientInfo
|
|
8661
|
-
};
|
|
8662
|
-
const cleanParams = { ...params };
|
|
8663
|
-
if (cleanParams._inputResponses) {
|
|
8664
|
-
meta.inputResponses = cleanParams._inputResponses;
|
|
8665
|
-
delete cleanParams._inputResponses;
|
|
8666
|
-
}
|
|
8667
|
-
const body = JSON.stringify({
|
|
8668
|
-
jsonrpc: "2.0",
|
|
8669
|
-
id,
|
|
8670
|
-
method,
|
|
8671
|
-
params: { ...cleanParams, _meta: meta }
|
|
8672
|
-
});
|
|
8767
|
+
const wireParams = modernRequestParams(params, protocolVersion, clientInfo);
|
|
8673
8768
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
8769
|
+
const id = nextId2++;
|
|
8770
|
+
const body = JSON.stringify({ jsonrpc: "2.0", id, method, params: wireParams });
|
|
8674
8771
|
const { res, token, detach } = await doFetch(method, params, body);
|
|
8675
8772
|
let retry;
|
|
8676
8773
|
try {
|
|
@@ -8690,16 +8787,11 @@ async function createStatelessConnection(options) {
|
|
|
8690
8787
|
}
|
|
8691
8788
|
throw new McpAuthError(401, url);
|
|
8692
8789
|
}
|
|
8693
|
-
const discoverResult2 = await request("server/discover", {
|
|
8694
|
-
protocolVersion: STATELESS_PROTOCOL_VERSION
|
|
8695
|
-
});
|
|
8790
|
+
const discoverResult2 = await request("server/discover", {});
|
|
8696
8791
|
const supported = discoverResult2?.supportedVersions?.filter((v) => typeof v === "string") ?? [];
|
|
8697
8792
|
if (!supported.includes(STATELESS_PROTOCOL_VERSION)) {
|
|
8698
|
-
throw new
|
|
8699
|
-
`Server does not support ${STATELESS_PROTOCOL_VERSION} (advertised: ${supported.join(", ") || "none"})`
|
|
8700
|
-
);
|
|
8793
|
+
throw new UnsupportedModernVersionError(STATELESS_PROTOCOL_VERSION, supported);
|
|
8701
8794
|
}
|
|
8702
|
-
negotiatedVersion = STATELESS_PROTOCOL_VERSION;
|
|
8703
8795
|
const extra = buildStatelessMethods(request, discoverResult2);
|
|
8704
8796
|
return {
|
|
8705
8797
|
...extra,
|
|
@@ -8846,14 +8938,13 @@ async function createPiConnection(options) {
|
|
|
8846
8938
|
}
|
|
8847
8939
|
|
|
8848
8940
|
// src/client/stdio-stateless.ts
|
|
8849
|
-
var PROTOCOL_VERSION =
|
|
8941
|
+
var PROTOCOL_VERSION = MODERN_PROTOCOL_VERSION;
|
|
8850
8942
|
function createStdioJsonRpc(proc, platform2, options) {
|
|
8851
8943
|
const encoder2 = new TextEncoder();
|
|
8852
8944
|
const decoder3 = new TextDecoder();
|
|
8853
8945
|
let nextId2 = 1;
|
|
8854
8946
|
let readBuffer = "";
|
|
8855
8947
|
const reader = proc.stdout.getReader();
|
|
8856
|
-
let negotiatedVersion;
|
|
8857
8948
|
const { version = "0.0.0", timeoutMs = 6e4, signal: externalSignal, verbose } = options;
|
|
8858
8949
|
async function readLine2() {
|
|
8859
8950
|
while (true) {
|
|
@@ -8893,20 +8984,11 @@ function createStdioJsonRpc(proc, platform2, options) {
|
|
|
8893
8984
|
}
|
|
8894
8985
|
async function request(method, params) {
|
|
8895
8986
|
const id = nextId2++;
|
|
8896
|
-
const meta = {
|
|
8897
|
-
protocolVersion: negotiatedVersion ?? PROTOCOL_VERSION,
|
|
8898
|
-
clientInfo: { name: "mcpcat", version }
|
|
8899
|
-
};
|
|
8900
|
-
const cleanParams = { ...params };
|
|
8901
|
-
if (cleanParams._inputResponses) {
|
|
8902
|
-
meta.inputResponses = cleanParams._inputResponses;
|
|
8903
|
-
delete cleanParams._inputResponses;
|
|
8904
|
-
}
|
|
8905
8987
|
const body = JSON.stringify({
|
|
8906
8988
|
jsonrpc: "2.0",
|
|
8907
8989
|
id,
|
|
8908
8990
|
method,
|
|
8909
|
-
params:
|
|
8991
|
+
params: modernRequestParams(params, PROTOCOL_VERSION, { name: "mcpcat", version })
|
|
8910
8992
|
});
|
|
8911
8993
|
if (verbose?.enabled) verbose.request(method, body);
|
|
8912
8994
|
await send(body);
|
|
@@ -8940,10 +9022,11 @@ function createStdioJsonRpc(proc, platform2, options) {
|
|
|
8940
9022
|
};
|
|
8941
9023
|
}
|
|
8942
9024
|
function buildServerInfo2(discoverResult2) {
|
|
9025
|
+
const serverInfo = discoverServerInfo(discoverResult2);
|
|
8943
9026
|
return {
|
|
8944
|
-
name:
|
|
8945
|
-
version:
|
|
8946
|
-
title:
|
|
9027
|
+
name: serverInfo?.name,
|
|
9028
|
+
version: serverInfo?.version,
|
|
9029
|
+
title: serverInfo?.title,
|
|
8947
9030
|
protocolVersion: PROTOCOL_VERSION,
|
|
8948
9031
|
capabilities: discoverResult2?.capabilities ?? {},
|
|
8949
9032
|
instructions: discoverResult2?.instructions
|
|
@@ -9017,25 +9100,27 @@ async function probeStdioStateless(options) {
|
|
|
9017
9100
|
});
|
|
9018
9101
|
let discoverRaw;
|
|
9019
9102
|
try {
|
|
9020
|
-
discoverRaw = await rpc.request("server/discover", {
|
|
9021
|
-
protocolVersion: PROTOCOL_VERSION
|
|
9022
|
-
});
|
|
9103
|
+
discoverRaw = await rpc.request("server/discover", {});
|
|
9023
9104
|
} catch (err) {
|
|
9024
9105
|
const pending = rpc.pendingBuffer();
|
|
9025
9106
|
rpc.close();
|
|
9026
9107
|
return { proc, pendingStdout: pending, error: err };
|
|
9027
9108
|
}
|
|
9028
|
-
void readStderr(proc, options.verbose);
|
|
9029
9109
|
const discoverResult2 = discoverRaw;
|
|
9030
|
-
const
|
|
9110
|
+
const advertised = discoverResult2?.supportedVersions;
|
|
9111
|
+
const supported = (Array.isArray(advertised) ? advertised : []).filter(
|
|
9031
9112
|
(v) => typeof v === "string"
|
|
9032
9113
|
);
|
|
9033
9114
|
if (!supported.includes(PROTOCOL_VERSION)) {
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9115
|
+
const pending = rpc.pendingBuffer();
|
|
9116
|
+
rpc.close();
|
|
9117
|
+
return {
|
|
9118
|
+
proc,
|
|
9119
|
+
pendingStdout: pending,
|
|
9120
|
+
error: new UnsupportedModernVersionError(PROTOCOL_VERSION, supported)
|
|
9121
|
+
};
|
|
9038
9122
|
}
|
|
9123
|
+
void readStderr(proc, options.verbose);
|
|
9039
9124
|
return buildConnectionMethods(rpc, discoverResult2, proc);
|
|
9040
9125
|
}
|
|
9041
9126
|
async function readStderr(proc, verbose) {
|
|
@@ -9079,16 +9164,7 @@ async function connect(platform2, options) {
|
|
|
9079
9164
|
verbose: options.verbose
|
|
9080
9165
|
});
|
|
9081
9166
|
if (!("proc" in result)) return result;
|
|
9082
|
-
|
|
9083
|
-
const isUnsupported = result.error.message.includes("does not support");
|
|
9084
|
-
if (options.protocolVersion?.startsWith("2026")) {
|
|
9085
|
-
try {
|
|
9086
|
-
await result.proc.kill("SIGTERM");
|
|
9087
|
-
} catch {
|
|
9088
|
-
}
|
|
9089
|
-
throw result.error;
|
|
9090
|
-
}
|
|
9091
|
-
if (!isMethodNotFound && !isUnsupported) {
|
|
9167
|
+
if (options.protocolVersion?.startsWith("2026") || !indicatesLegacyServer(result.error, false)) {
|
|
9092
9168
|
try {
|
|
9093
9169
|
await result.proc.kill("SIGTERM");
|
|
9094
9170
|
} catch {
|
|
@@ -9131,12 +9207,11 @@ async function connect(platform2, options) {
|
|
|
9131
9207
|
redact: options.redact
|
|
9132
9208
|
});
|
|
9133
9209
|
} catch (err) {
|
|
9134
|
-
const isMethodNotFound = err instanceof StatelessRpcError && err.code === -32601 || err instanceof StatelessHttpError && err.status >= 400 && err.status < 500;
|
|
9135
9210
|
if (options.protocolVersion?.startsWith("2026")) throw err;
|
|
9136
9211
|
if (err instanceof McpAuthError || err instanceof AuthStepUpError) throw err;
|
|
9137
9212
|
if (err instanceof TransportRefusalError) throw err;
|
|
9138
9213
|
if (err.name === "McpOAuthAuthorizationRequiredError") throw err;
|
|
9139
|
-
if (
|
|
9214
|
+
if (indicatesLegacyServer(err, true)) {
|
|
9140
9215
|
return createPiConnection({
|
|
9141
9216
|
url: options.url,
|
|
9142
9217
|
headers: options.headers,
|
|
@@ -10887,11 +10962,21 @@ async function probeLinkHeaders(fetcher, targetUrl, origin, page, userUrlIsPriva
|
|
|
10887
10962
|
}
|
|
10888
10963
|
return events;
|
|
10889
10964
|
}
|
|
10965
|
+
function sseResponse(text, id) {
|
|
10966
|
+
for (const block of text.replace(/\r\n?/g, "\n").split("\n\n")) {
|
|
10967
|
+
const data = block.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).replace(/^ /, "")).join("\n");
|
|
10968
|
+
const parsed = tryParseJson(data);
|
|
10969
|
+
if (isRecord4(parsed) && parsed.id === id) return parsed;
|
|
10970
|
+
}
|
|
10971
|
+
return void 0;
|
|
10972
|
+
}
|
|
10890
10973
|
function mcpJsonRpc(method, params, id = 1) {
|
|
10891
10974
|
return JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
10892
10975
|
}
|
|
10893
10976
|
function parseServerInfo(result) {
|
|
10894
|
-
const
|
|
10977
|
+
const meta = isRecord4(result._meta) ? result._meta : void 0;
|
|
10978
|
+
const fromMeta = meta && isRecord4(meta[META_SERVER_INFO]) ? meta[META_SERVER_INFO] : void 0;
|
|
10979
|
+
const si = fromMeta ?? (isRecord4(result.serverInfo) ? result.serverInfo : void 0);
|
|
10895
10980
|
if (!si) return void 0;
|
|
10896
10981
|
return {
|
|
10897
10982
|
name: typeof si.name === "string" ? si.name : void 0,
|
|
@@ -10907,7 +10992,7 @@ function checkAuthResponse(resp) {
|
|
|
10907
10992
|
async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
10908
10993
|
const headers = {
|
|
10909
10994
|
"Content-Type": "application/json",
|
|
10910
|
-
Accept: "application/json",
|
|
10995
|
+
Accept: "application/json, text/event-stream",
|
|
10911
10996
|
...extraHeaders
|
|
10912
10997
|
};
|
|
10913
10998
|
try {
|
|
@@ -10922,7 +11007,8 @@ async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
|
10922
11007
|
if (authSignal) return { url, trust: [authSignal] };
|
|
10923
11008
|
if (resp.status === 200) {
|
|
10924
11009
|
const text = await resp.text();
|
|
10925
|
-
const
|
|
11010
|
+
const sse = (resp.headers.get("content-type") ?? "").includes("text/event-stream");
|
|
11011
|
+
const parsed = sse ? sseResponse(text, tryParseJson(body)?.id) : tryParseJson(text);
|
|
10926
11012
|
if (isRecord4(parsed) && isRecord4(parsed.result)) {
|
|
10927
11013
|
return { url, serverInfo: parseServerInfo(parsed.result), trust: [] };
|
|
10928
11014
|
}
|
|
@@ -10933,18 +11019,22 @@ async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
|
10933
11019
|
}
|
|
10934
11020
|
async function probeMcpEndpoint(fetcher, url) {
|
|
10935
11021
|
const discoverBody = mcpJsonRpc("server/discover", {
|
|
10936
|
-
|
|
10937
|
-
clientInfo: { name: "mcpcat", version: "0.0.0" }
|
|
11022
|
+
_meta: modernRequestMeta(MODERN_PROTOCOL_VERSION, { name: "mcpcat", version: "0.0.0" })
|
|
10938
11023
|
});
|
|
10939
11024
|
const hit = await tryMcpPost(fetcher, url, discoverBody, {
|
|
11025
|
+
"MCP-Protocol-Version": MODERN_PROTOCOL_VERSION,
|
|
10940
11026
|
"Mcp-Method": "server/discover"
|
|
10941
11027
|
});
|
|
10942
11028
|
if (hit) return hit;
|
|
10943
|
-
const initBody = mcpJsonRpc(
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
11029
|
+
const initBody = mcpJsonRpc(
|
|
11030
|
+
"initialize",
|
|
11031
|
+
{
|
|
11032
|
+
protocolVersion: "2025-11-25",
|
|
11033
|
+
clientInfo: { name: "mcpcat", version: "0.0.0" },
|
|
11034
|
+
capabilities: {}
|
|
11035
|
+
},
|
|
11036
|
+
2
|
|
11037
|
+
);
|
|
10948
11038
|
return tryMcpPost(fetcher, url, initBody);
|
|
10949
11039
|
}
|
|
10950
11040
|
async function probeMcp(fetcher, origin, page, targetUrl) {
|
|
@@ -12073,6 +12163,12 @@ async function handleJsonRpc(raw, source, call, serverName, serverVersion) {
|
|
|
12073
12163
|
if (!hasOwn(parsed, "id")) return { status: 202, contentType: "text/plain", body: "" };
|
|
12074
12164
|
const id = readId(parsed);
|
|
12075
12165
|
const params = Object.getOwnPropertyDescriptor(parsed, "params")?.value;
|
|
12166
|
+
return completeModernOutcome(
|
|
12167
|
+
await dispatch(id, method, params, source, call, serverName, serverVersion),
|
|
12168
|
+
params
|
|
12169
|
+
);
|
|
12170
|
+
}
|
|
12171
|
+
async function dispatch(id, method, params, source, call, serverName, serverVersion) {
|
|
12076
12172
|
if (method === "initialize")
|
|
12077
12173
|
return rpcOk(id, initializeResult(params, serverName, serverVersion));
|
|
12078
12174
|
if (method === "server/discover") return rpcOk(id, discoverResult(serverName, serverVersion));
|
|
@@ -12127,12 +12223,11 @@ function initializeResult(params, serverName, serverVersion) {
|
|
|
12127
12223
|
};
|
|
12128
12224
|
}
|
|
12129
12225
|
function discoverResult(serverName, serverVersion) {
|
|
12130
|
-
return
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
};
|
|
12226
|
+
return modernDiscoverResult(
|
|
12227
|
+
PROTOCOL_VERSIONS,
|
|
12228
|
+
{ tools: { listChanged: false } },
|
|
12229
|
+
{ name: serverName, version: serverVersion }
|
|
12230
|
+
);
|
|
12136
12231
|
}
|
|
12137
12232
|
function cap(value) {
|
|
12138
12233
|
if (value.length <= OUTPUT_CAP) return value;
|
|
@@ -12268,15 +12363,18 @@ function translateCapabilities(info) {
|
|
|
12268
12363
|
if (info.capabilities.prompts) caps.prompts = { listChanged: false };
|
|
12269
12364
|
return caps;
|
|
12270
12365
|
}
|
|
12366
|
+
function proxyServerInfo(info) {
|
|
12367
|
+
return {
|
|
12368
|
+
name: info.name ?? "mcpcat-proxy",
|
|
12369
|
+
version: info.version ?? "0.0.0",
|
|
12370
|
+
...info.title ? { title: info.title } : {}
|
|
12371
|
+
};
|
|
12372
|
+
}
|
|
12271
12373
|
function buildServerResult(info, protocolVersion) {
|
|
12272
12374
|
return {
|
|
12273
12375
|
protocolVersion,
|
|
12274
12376
|
capabilities: translateCapabilities(info),
|
|
12275
|
-
serverInfo:
|
|
12276
|
-
name: info.name ?? "mcpcat-proxy",
|
|
12277
|
-
version: info.version ?? "0.0.0",
|
|
12278
|
-
...info.title ? { title: info.title } : {}
|
|
12279
|
-
},
|
|
12377
|
+
serverInfo: proxyServerInfo(info),
|
|
12280
12378
|
...info.instructions ? { instructions: info.instructions } : {}
|
|
12281
12379
|
};
|
|
12282
12380
|
}
|
|
@@ -12324,10 +12422,16 @@ function createProxyHandler(options) {
|
|
|
12324
12422
|
return scrubOk(id, buildServerResult(cachedInfo, pv));
|
|
12325
12423
|
}
|
|
12326
12424
|
function handleDiscover(id) {
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12425
|
+
const info = cachedInfo;
|
|
12426
|
+
return scrubOk(
|
|
12427
|
+
id,
|
|
12428
|
+
modernDiscoverResult(
|
|
12429
|
+
PROTOCOL_VERSIONS2,
|
|
12430
|
+
translateCapabilities(info),
|
|
12431
|
+
proxyServerInfo(info),
|
|
12432
|
+
info.instructions
|
|
12433
|
+
)
|
|
12434
|
+
);
|
|
12331
12435
|
}
|
|
12332
12436
|
async function forwardWithRetry(method, doForward, id) {
|
|
12333
12437
|
try {
|
|
@@ -12354,7 +12458,7 @@ function createProxyHandler(options) {
|
|
|
12354
12458
|
return scrubErr(id, -32e3, err.message);
|
|
12355
12459
|
}
|
|
12356
12460
|
}
|
|
12357
|
-
async function
|
|
12461
|
+
async function dispatch2(method, id, params) {
|
|
12358
12462
|
try {
|
|
12359
12463
|
await getConnection();
|
|
12360
12464
|
} catch (err) {
|
|
@@ -12391,7 +12495,7 @@ function createProxyHandler(options) {
|
|
|
12391
12495
|
if (!hasOwn2(parsed, "id")) return { status: 202, contentType: "text/plain", body: "" };
|
|
12392
12496
|
const id = readId2(parsed);
|
|
12393
12497
|
const params = Object.getOwnPropertyDescriptor(parsed, "params")?.value;
|
|
12394
|
-
return
|
|
12498
|
+
return completeModernOutcome(await dispatch2(method, id, params), params);
|
|
12395
12499
|
}
|
|
12396
12500
|
async function shutdown() {
|
|
12397
12501
|
if (conn) {
|
|
@@ -17579,5 +17683,5 @@ try {
|
|
|
17579
17683
|
});
|
|
17580
17684
|
} catch {
|
|
17581
17685
|
}
|
|
17582
|
-
var code = await run(platform, "0.20.
|
|
17686
|
+
var code = await run(platform, "0.20.4", args);
|
|
17583
17687
|
process.exit(code);
|
package/dist/kernel/mcpcat.mjs
CHANGED
|
@@ -7312,7 +7312,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7312
7312
|
let dataLines = [];
|
|
7313
7313
|
let dataBytes = 0;
|
|
7314
7314
|
const maxEventBytes = options.maxEventBytes ?? DEFAULT_MAX_MESSAGE_BYTES;
|
|
7315
|
-
const
|
|
7315
|
+
const dispatch2 = () => {
|
|
7316
7316
|
if (dataLines.length === 0) {
|
|
7317
7317
|
eventName = void 0;
|
|
7318
7318
|
eventId = void 0;
|
|
@@ -7328,7 +7328,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7328
7328
|
const processLine = (rawLine) => {
|
|
7329
7329
|
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
7330
7330
|
if (line === "") {
|
|
7331
|
-
|
|
7331
|
+
dispatch2();
|
|
7332
7332
|
return;
|
|
7333
7333
|
}
|
|
7334
7334
|
if (line.startsWith(":"))
|
|
@@ -7369,7 +7369,7 @@ async function consumeSseStream(stream, options) {
|
|
|
7369
7369
|
buffered += decoder3.decode();
|
|
7370
7370
|
if (buffered)
|
|
7371
7371
|
processLine(buffered);
|
|
7372
|
-
|
|
7372
|
+
dispatch2();
|
|
7373
7373
|
} finally {
|
|
7374
7374
|
reader.releaseLock();
|
|
7375
7375
|
}
|
|
@@ -7973,18 +7973,118 @@ var PlatformStdioTransport = class {
|
|
|
7973
7973
|
}
|
|
7974
7974
|
};
|
|
7975
7975
|
|
|
7976
|
+
// src/client/modern.ts
|
|
7977
|
+
var MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
7978
|
+
var META_PROTOCOL_VERSION = "io.modelcontextprotocol/protocolVersion";
|
|
7979
|
+
var META_CLIENT_INFO = "io.modelcontextprotocol/clientInfo";
|
|
7980
|
+
var META_CLIENT_CAPABILITIES = "io.modelcontextprotocol/clientCapabilities";
|
|
7981
|
+
var META_SERVER_INFO = "io.modelcontextprotocol/serverInfo";
|
|
7982
|
+
var HEADER_MISMATCH = -32020;
|
|
7983
|
+
var MISSING_REQUIRED_CLIENT_CAPABILITY = -32021;
|
|
7984
|
+
var UNSUPPORTED_PROTOCOL_VERSION = -32022;
|
|
7985
|
+
var MODERN_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
7986
|
+
HEADER_MISMATCH,
|
|
7987
|
+
MISSING_REQUIRED_CLIENT_CAPABILITY,
|
|
7988
|
+
UNSUPPORTED_PROTOCOL_VERSION
|
|
7989
|
+
]);
|
|
7990
|
+
function isModernErrorCode(code) {
|
|
7991
|
+
return MODERN_ERROR_CODES.has(code);
|
|
7992
|
+
}
|
|
7993
|
+
function modernRequestMeta(protocolVersion, clientInfo) {
|
|
7994
|
+
return {
|
|
7995
|
+
[META_PROTOCOL_VERSION]: protocolVersion,
|
|
7996
|
+
[META_CLIENT_INFO]: clientInfo,
|
|
7997
|
+
[META_CLIENT_CAPABILITIES]: {}
|
|
7998
|
+
};
|
|
7999
|
+
}
|
|
8000
|
+
function modernRequestParams(params, protocolVersion, clientInfo) {
|
|
8001
|
+
const { _inputResponses, ...rest } = params;
|
|
8002
|
+
const out = { ...rest };
|
|
8003
|
+
if (_inputResponses) out.inputResponses = _inputResponses;
|
|
8004
|
+
out._meta = modernRequestMeta(protocolVersion, clientInfo);
|
|
8005
|
+
return out;
|
|
8006
|
+
}
|
|
8007
|
+
var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
8008
|
+
function base64Utf8(value) {
|
|
8009
|
+
const bytes = new TextEncoder().encode(value);
|
|
8010
|
+
let out = "";
|
|
8011
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
8012
|
+
const a = bytes[i];
|
|
8013
|
+
const b = i + 1 < bytes.length ? bytes[i + 1] : 0;
|
|
8014
|
+
const c = i + 2 < bytes.length ? bytes[i + 2] : 0;
|
|
8015
|
+
const n = a << 16 | b << 8 | c;
|
|
8016
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63];
|
|
8017
|
+
out += i + 1 < bytes.length ? B64[n >> 6 & 63] : "=";
|
|
8018
|
+
out += i + 2 < bytes.length ? B64[n & 63] : "=";
|
|
8019
|
+
}
|
|
8020
|
+
return out;
|
|
8021
|
+
}
|
|
8022
|
+
function encodeHeaderValue(value) {
|
|
8023
|
+
const safe = /^[\x20-\x7e\t]*$/.test(value) && value.trim() === value && !(value.startsWith("=?base64?") && value.endsWith("?="));
|
|
8024
|
+
return safe ? value : `=?base64?${base64Utf8(value)}?=`;
|
|
8025
|
+
}
|
|
8026
|
+
function isModernRequest(params) {
|
|
8027
|
+
if (!params || typeof params !== "object") return false;
|
|
8028
|
+
const meta = Object.getOwnPropertyDescriptor(params, "_meta")?.value;
|
|
8029
|
+
if (!meta || typeof meta !== "object") return false;
|
|
8030
|
+
return typeof Object.getOwnPropertyDescriptor(meta, META_PROTOCOL_VERSION)?.value === "string";
|
|
8031
|
+
}
|
|
8032
|
+
function completeModernOutcome(outcome, params) {
|
|
8033
|
+
if (outcome.status !== 200 || !isModernRequest(params)) return outcome;
|
|
8034
|
+
const frame = JSON.parse(outcome.body);
|
|
8035
|
+
const result = frame.result;
|
|
8036
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return outcome;
|
|
8037
|
+
if (Object.hasOwn(result, "resultType")) return outcome;
|
|
8038
|
+
frame.result = { resultType: "complete", ...result };
|
|
8039
|
+
return { ...outcome, body: JSON.stringify(frame) };
|
|
8040
|
+
}
|
|
8041
|
+
function modernDiscoverResult(supportedVersions, capabilities, serverInfo, instructions) {
|
|
8042
|
+
return {
|
|
8043
|
+
resultType: "complete",
|
|
8044
|
+
supportedVersions,
|
|
8045
|
+
capabilities,
|
|
8046
|
+
serverInfo,
|
|
8047
|
+
...instructions ? { instructions } : {},
|
|
8048
|
+
_meta: { [META_SERVER_INFO]: serverInfo }
|
|
8049
|
+
};
|
|
8050
|
+
}
|
|
8051
|
+
|
|
7976
8052
|
// src/client/stateless-connection.ts
|
|
7977
|
-
var STATELESS_PROTOCOL_VERSION =
|
|
8053
|
+
var STATELESS_PROTOCOL_VERSION = MODERN_PROTOCOL_VERSION;
|
|
7978
8054
|
var StatelessRpcError = class extends Error {
|
|
7979
8055
|
code;
|
|
7980
8056
|
data;
|
|
7981
|
-
|
|
8057
|
+
httpStatus;
|
|
8058
|
+
constructor(code, message, data, httpStatus) {
|
|
7982
8059
|
super(`MCP RPC error ${code}: ${message}`);
|
|
7983
8060
|
this.name = "StatelessRpcError";
|
|
7984
8061
|
this.code = code;
|
|
7985
8062
|
this.data = data;
|
|
8063
|
+
this.httpStatus = httpStatus;
|
|
8064
|
+
}
|
|
8065
|
+
};
|
|
8066
|
+
var UnsupportedModernVersionError = class extends Error {
|
|
8067
|
+
constructor(version, supported) {
|
|
8068
|
+
super(`Server does not support ${version} (advertised: ${supported.join(", ") || "none"})`);
|
|
8069
|
+
this.name = "UnsupportedModernVersionError";
|
|
7986
8070
|
}
|
|
7987
8071
|
};
|
|
8072
|
+
function supportedList(data) {
|
|
8073
|
+
const list = data?.supported;
|
|
8074
|
+
return Array.isArray(list) ? list.filter((v) => typeof v === "string") : void 0;
|
|
8075
|
+
}
|
|
8076
|
+
function indicatesLegacyServer(err, http) {
|
|
8077
|
+
if (err instanceof UnsupportedModernVersionError) return true;
|
|
8078
|
+
if (http && err instanceof StatelessHttpError) return err.status >= 400 && err.status < 500;
|
|
8079
|
+
if (!(err instanceof StatelessRpcError)) return false;
|
|
8080
|
+
if (err.code === UNSUPPORTED_PROTOCOL_VERSION) {
|
|
8081
|
+
const supported = supportedList(err.data);
|
|
8082
|
+
return !!supported && !supported.includes(STATELESS_PROTOCOL_VERSION);
|
|
8083
|
+
}
|
|
8084
|
+
if (isModernErrorCode(err.code)) return false;
|
|
8085
|
+
if (!http || err.code === -32601) return true;
|
|
8086
|
+
return err.httpStatus !== void 0 && err.httpStatus >= 400 && err.httpStatus < 500;
|
|
8087
|
+
}
|
|
7988
8088
|
var StatelessHttpError = class extends Error {
|
|
7989
8089
|
status;
|
|
7990
8090
|
constructor(status, statusText, method, snippet) {
|
|
@@ -8096,11 +8196,16 @@ function logHeaders(verbose, dir, entries) {
|
|
|
8096
8196
|
else verbose.headerIn(k, v);
|
|
8097
8197
|
}
|
|
8098
8198
|
}
|
|
8199
|
+
function discoverServerInfo(discoverResult2) {
|
|
8200
|
+
const meta = discoverResult2?._meta;
|
|
8201
|
+
return meta?.[META_SERVER_INFO] ?? discoverResult2?.serverInfo;
|
|
8202
|
+
}
|
|
8099
8203
|
function buildServerInfo(discoverResult2) {
|
|
8204
|
+
const serverInfo = discoverServerInfo(discoverResult2);
|
|
8100
8205
|
return {
|
|
8101
|
-
name:
|
|
8102
|
-
version:
|
|
8103
|
-
title:
|
|
8206
|
+
name: serverInfo?.name,
|
|
8207
|
+
version: serverInfo?.version,
|
|
8208
|
+
title: serverInfo?.title,
|
|
8104
8209
|
protocolVersion: STATELESS_PROTOCOL_VERSION,
|
|
8105
8210
|
capabilities: discoverResult2?.capabilities ?? {},
|
|
8106
8211
|
instructions: discoverResult2?.instructions
|
|
@@ -8183,17 +8288,17 @@ async function createStatelessConnection(options) {
|
|
|
8183
8288
|
redact: redact2 = (text) => text
|
|
8184
8289
|
} = options;
|
|
8185
8290
|
let nextId2 = 1;
|
|
8186
|
-
|
|
8291
|
+
const protocolVersion = STATELESS_PROTOCOL_VERSION;
|
|
8187
8292
|
function buildHeaders(method, params, token) {
|
|
8188
8293
|
const h = {
|
|
8189
8294
|
"Content-Type": "application/json",
|
|
8190
8295
|
Accept: "application/json, text/event-stream",
|
|
8296
|
+
"MCP-Protocol-Version": protocolVersion,
|
|
8191
8297
|
"Mcp-Method": method,
|
|
8192
8298
|
...extraHeaders
|
|
8193
8299
|
};
|
|
8194
8300
|
const n = mcpNameForMethod(method, params);
|
|
8195
|
-
if (n) h["Mcp-Name"] = n;
|
|
8196
|
-
if (negotiatedVersion) h["Mcp-Protocol-Version"] = negotiatedVersion;
|
|
8301
|
+
if (n) h["Mcp-Name"] = encodeHeaderValue(n);
|
|
8197
8302
|
if (token) h["Authorization"] = `Bearer ${token}`;
|
|
8198
8303
|
return h;
|
|
8199
8304
|
}
|
|
@@ -8213,7 +8318,7 @@ async function createStatelessConnection(options) {
|
|
|
8213
8318
|
if (p.error && typeof p.error.code === "number") rpc = p.error;
|
|
8214
8319
|
} catch {
|
|
8215
8320
|
}
|
|
8216
|
-
if (rpc) throw new StatelessRpcError(rpc.code, rpc.message, rpc.data);
|
|
8321
|
+
if (rpc) throw new StatelessRpcError(rpc.code, rpc.message, rpc.data, res.status);
|
|
8217
8322
|
throw new StatelessHttpError(res.status, res.statusText, method, redact2(text).slice(0, 512));
|
|
8218
8323
|
}
|
|
8219
8324
|
async function doFetch(method, params, body) {
|
|
@@ -8256,7 +8361,12 @@ async function createStatelessConnection(options) {
|
|
|
8256
8361
|
}
|
|
8257
8362
|
if (verbose?.enabled) verbose.response(JSON.stringify(frame));
|
|
8258
8363
|
if (frame.error) {
|
|
8259
|
-
throw new StatelessRpcError(
|
|
8364
|
+
throw new StatelessRpcError(
|
|
8365
|
+
frame.error.code,
|
|
8366
|
+
frame.error.message,
|
|
8367
|
+
frame.error.data,
|
|
8368
|
+
res.status
|
|
8369
|
+
);
|
|
8260
8370
|
}
|
|
8261
8371
|
return frame.result;
|
|
8262
8372
|
}
|
|
@@ -8275,23 +8385,10 @@ async function createStatelessConnection(options) {
|
|
|
8275
8385
|
}
|
|
8276
8386
|
}
|
|
8277
8387
|
async function request(method, params) {
|
|
8278
|
-
const
|
|
8279
|
-
const meta = {
|
|
8280
|
-
protocolVersion: negotiatedVersion ?? STATELESS_PROTOCOL_VERSION,
|
|
8281
|
-
clientInfo
|
|
8282
|
-
};
|
|
8283
|
-
const cleanParams = { ...params };
|
|
8284
|
-
if (cleanParams._inputResponses) {
|
|
8285
|
-
meta.inputResponses = cleanParams._inputResponses;
|
|
8286
|
-
delete cleanParams._inputResponses;
|
|
8287
|
-
}
|
|
8288
|
-
const body = JSON.stringify({
|
|
8289
|
-
jsonrpc: "2.0",
|
|
8290
|
-
id,
|
|
8291
|
-
method,
|
|
8292
|
-
params: { ...cleanParams, _meta: meta }
|
|
8293
|
-
});
|
|
8388
|
+
const wireParams = modernRequestParams(params, protocolVersion, clientInfo);
|
|
8294
8389
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
8390
|
+
const id = nextId2++;
|
|
8391
|
+
const body = JSON.stringify({ jsonrpc: "2.0", id, method, params: wireParams });
|
|
8295
8392
|
const { res, token, detach } = await doFetch(method, params, body);
|
|
8296
8393
|
let retry;
|
|
8297
8394
|
try {
|
|
@@ -8311,16 +8408,11 @@ async function createStatelessConnection(options) {
|
|
|
8311
8408
|
}
|
|
8312
8409
|
throw new McpAuthError(401, url);
|
|
8313
8410
|
}
|
|
8314
|
-
const discoverResult2 = await request("server/discover", {
|
|
8315
|
-
protocolVersion: STATELESS_PROTOCOL_VERSION
|
|
8316
|
-
});
|
|
8411
|
+
const discoverResult2 = await request("server/discover", {});
|
|
8317
8412
|
const supported = discoverResult2?.supportedVersions?.filter((v) => typeof v === "string") ?? [];
|
|
8318
8413
|
if (!supported.includes(STATELESS_PROTOCOL_VERSION)) {
|
|
8319
|
-
throw new
|
|
8320
|
-
`Server does not support ${STATELESS_PROTOCOL_VERSION} (advertised: ${supported.join(", ") || "none"})`
|
|
8321
|
-
);
|
|
8414
|
+
throw new UnsupportedModernVersionError(STATELESS_PROTOCOL_VERSION, supported);
|
|
8322
8415
|
}
|
|
8323
|
-
negotiatedVersion = STATELESS_PROTOCOL_VERSION;
|
|
8324
8416
|
const extra = buildStatelessMethods(request, discoverResult2);
|
|
8325
8417
|
return {
|
|
8326
8418
|
...extra,
|
|
@@ -8467,14 +8559,13 @@ async function createPiConnection(options) {
|
|
|
8467
8559
|
}
|
|
8468
8560
|
|
|
8469
8561
|
// src/client/stdio-stateless.ts
|
|
8470
|
-
var PROTOCOL_VERSION =
|
|
8562
|
+
var PROTOCOL_VERSION = MODERN_PROTOCOL_VERSION;
|
|
8471
8563
|
function createStdioJsonRpc(proc, platform2, options) {
|
|
8472
8564
|
const encoder2 = new TextEncoder();
|
|
8473
8565
|
const decoder3 = new TextDecoder();
|
|
8474
8566
|
let nextId2 = 1;
|
|
8475
8567
|
let readBuffer = "";
|
|
8476
8568
|
const reader = proc.stdout.getReader();
|
|
8477
|
-
let negotiatedVersion;
|
|
8478
8569
|
const { version = "0.0.0", timeoutMs = 6e4, signal: externalSignal, verbose } = options;
|
|
8479
8570
|
async function readLine2() {
|
|
8480
8571
|
while (true) {
|
|
@@ -8514,20 +8605,11 @@ function createStdioJsonRpc(proc, platform2, options) {
|
|
|
8514
8605
|
}
|
|
8515
8606
|
async function request(method, params) {
|
|
8516
8607
|
const id = nextId2++;
|
|
8517
|
-
const meta = {
|
|
8518
|
-
protocolVersion: negotiatedVersion ?? PROTOCOL_VERSION,
|
|
8519
|
-
clientInfo: { name: "mcpcat", version }
|
|
8520
|
-
};
|
|
8521
|
-
const cleanParams = { ...params };
|
|
8522
|
-
if (cleanParams._inputResponses) {
|
|
8523
|
-
meta.inputResponses = cleanParams._inputResponses;
|
|
8524
|
-
delete cleanParams._inputResponses;
|
|
8525
|
-
}
|
|
8526
8608
|
const body = JSON.stringify({
|
|
8527
8609
|
jsonrpc: "2.0",
|
|
8528
8610
|
id,
|
|
8529
8611
|
method,
|
|
8530
|
-
params:
|
|
8612
|
+
params: modernRequestParams(params, PROTOCOL_VERSION, { name: "mcpcat", version })
|
|
8531
8613
|
});
|
|
8532
8614
|
if (verbose?.enabled) verbose.request(method, body);
|
|
8533
8615
|
await send(body);
|
|
@@ -8561,10 +8643,11 @@ function createStdioJsonRpc(proc, platform2, options) {
|
|
|
8561
8643
|
};
|
|
8562
8644
|
}
|
|
8563
8645
|
function buildServerInfo2(discoverResult2) {
|
|
8646
|
+
const serverInfo = discoverServerInfo(discoverResult2);
|
|
8564
8647
|
return {
|
|
8565
|
-
name:
|
|
8566
|
-
version:
|
|
8567
|
-
title:
|
|
8648
|
+
name: serverInfo?.name,
|
|
8649
|
+
version: serverInfo?.version,
|
|
8650
|
+
title: serverInfo?.title,
|
|
8568
8651
|
protocolVersion: PROTOCOL_VERSION,
|
|
8569
8652
|
capabilities: discoverResult2?.capabilities ?? {},
|
|
8570
8653
|
instructions: discoverResult2?.instructions
|
|
@@ -8638,25 +8721,27 @@ async function probeStdioStateless(options) {
|
|
|
8638
8721
|
});
|
|
8639
8722
|
let discoverRaw;
|
|
8640
8723
|
try {
|
|
8641
|
-
discoverRaw = await rpc.request("server/discover", {
|
|
8642
|
-
protocolVersion: PROTOCOL_VERSION
|
|
8643
|
-
});
|
|
8724
|
+
discoverRaw = await rpc.request("server/discover", {});
|
|
8644
8725
|
} catch (err) {
|
|
8645
8726
|
const pending = rpc.pendingBuffer();
|
|
8646
8727
|
rpc.close();
|
|
8647
8728
|
return { proc, pendingStdout: pending, error: err };
|
|
8648
8729
|
}
|
|
8649
|
-
void readStderr(proc, options.verbose);
|
|
8650
8730
|
const discoverResult2 = discoverRaw;
|
|
8651
|
-
const
|
|
8731
|
+
const advertised = discoverResult2?.supportedVersions;
|
|
8732
|
+
const supported = (Array.isArray(advertised) ? advertised : []).filter(
|
|
8652
8733
|
(v) => typeof v === "string"
|
|
8653
8734
|
);
|
|
8654
8735
|
if (!supported.includes(PROTOCOL_VERSION)) {
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8736
|
+
const pending = rpc.pendingBuffer();
|
|
8737
|
+
rpc.close();
|
|
8738
|
+
return {
|
|
8739
|
+
proc,
|
|
8740
|
+
pendingStdout: pending,
|
|
8741
|
+
error: new UnsupportedModernVersionError(PROTOCOL_VERSION, supported)
|
|
8742
|
+
};
|
|
8659
8743
|
}
|
|
8744
|
+
void readStderr(proc, options.verbose);
|
|
8660
8745
|
return buildConnectionMethods(rpc, discoverResult2, proc);
|
|
8661
8746
|
}
|
|
8662
8747
|
async function readStderr(proc, verbose) {
|
|
@@ -8700,16 +8785,7 @@ async function connect(platform2, options) {
|
|
|
8700
8785
|
verbose: options.verbose
|
|
8701
8786
|
});
|
|
8702
8787
|
if (!("proc" in result)) return result;
|
|
8703
|
-
|
|
8704
|
-
const isUnsupported = result.error.message.includes("does not support");
|
|
8705
|
-
if (options.protocolVersion?.startsWith("2026")) {
|
|
8706
|
-
try {
|
|
8707
|
-
await result.proc.kill("SIGTERM");
|
|
8708
|
-
} catch {
|
|
8709
|
-
}
|
|
8710
|
-
throw result.error;
|
|
8711
|
-
}
|
|
8712
|
-
if (!isMethodNotFound && !isUnsupported) {
|
|
8788
|
+
if (options.protocolVersion?.startsWith("2026") || !indicatesLegacyServer(result.error, false)) {
|
|
8713
8789
|
try {
|
|
8714
8790
|
await result.proc.kill("SIGTERM");
|
|
8715
8791
|
} catch {
|
|
@@ -8752,12 +8828,11 @@ async function connect(platform2, options) {
|
|
|
8752
8828
|
redact: options.redact
|
|
8753
8829
|
});
|
|
8754
8830
|
} catch (err) {
|
|
8755
|
-
const isMethodNotFound = err instanceof StatelessRpcError && err.code === -32601 || err instanceof StatelessHttpError && err.status >= 400 && err.status < 500;
|
|
8756
8831
|
if (options.protocolVersion?.startsWith("2026")) throw err;
|
|
8757
8832
|
if (err instanceof McpAuthError || err instanceof AuthStepUpError) throw err;
|
|
8758
8833
|
if (err instanceof TransportRefusalError) throw err;
|
|
8759
8834
|
if (err.name === "McpOAuthAuthorizationRequiredError") throw err;
|
|
8760
|
-
if (
|
|
8835
|
+
if (indicatesLegacyServer(err, true)) {
|
|
8761
8836
|
return createPiConnection({
|
|
8762
8837
|
url: options.url,
|
|
8763
8838
|
headers: options.headers,
|
|
@@ -10508,11 +10583,21 @@ async function probeLinkHeaders(fetcher, targetUrl, origin, page, userUrlIsPriva
|
|
|
10508
10583
|
}
|
|
10509
10584
|
return events;
|
|
10510
10585
|
}
|
|
10586
|
+
function sseResponse(text, id) {
|
|
10587
|
+
for (const block of text.replace(/\r\n?/g, "\n").split("\n\n")) {
|
|
10588
|
+
const data = block.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).replace(/^ /, "")).join("\n");
|
|
10589
|
+
const parsed = tryParseJson(data);
|
|
10590
|
+
if (isRecord4(parsed) && parsed.id === id) return parsed;
|
|
10591
|
+
}
|
|
10592
|
+
return void 0;
|
|
10593
|
+
}
|
|
10511
10594
|
function mcpJsonRpc(method, params, id = 1) {
|
|
10512
10595
|
return JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
10513
10596
|
}
|
|
10514
10597
|
function parseServerInfo(result) {
|
|
10515
|
-
const
|
|
10598
|
+
const meta = isRecord4(result._meta) ? result._meta : void 0;
|
|
10599
|
+
const fromMeta = meta && isRecord4(meta[META_SERVER_INFO]) ? meta[META_SERVER_INFO] : void 0;
|
|
10600
|
+
const si = fromMeta ?? (isRecord4(result.serverInfo) ? result.serverInfo : void 0);
|
|
10516
10601
|
if (!si) return void 0;
|
|
10517
10602
|
return {
|
|
10518
10603
|
name: typeof si.name === "string" ? si.name : void 0,
|
|
@@ -10528,7 +10613,7 @@ function checkAuthResponse(resp) {
|
|
|
10528
10613
|
async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
10529
10614
|
const headers = {
|
|
10530
10615
|
"Content-Type": "application/json",
|
|
10531
|
-
Accept: "application/json",
|
|
10616
|
+
Accept: "application/json, text/event-stream",
|
|
10532
10617
|
...extraHeaders
|
|
10533
10618
|
};
|
|
10534
10619
|
try {
|
|
@@ -10543,7 +10628,8 @@ async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
|
10543
10628
|
if (authSignal) return { url, trust: [authSignal] };
|
|
10544
10629
|
if (resp.status === 200) {
|
|
10545
10630
|
const text = await resp.text();
|
|
10546
|
-
const
|
|
10631
|
+
const sse = (resp.headers.get("content-type") ?? "").includes("text/event-stream");
|
|
10632
|
+
const parsed = sse ? sseResponse(text, tryParseJson(body)?.id) : tryParseJson(text);
|
|
10547
10633
|
if (isRecord4(parsed) && isRecord4(parsed.result)) {
|
|
10548
10634
|
return { url, serverInfo: parseServerInfo(parsed.result), trust: [] };
|
|
10549
10635
|
}
|
|
@@ -10554,18 +10640,22 @@ async function tryMcpPost(fetcher, url, body, extraHeaders) {
|
|
|
10554
10640
|
}
|
|
10555
10641
|
async function probeMcpEndpoint(fetcher, url) {
|
|
10556
10642
|
const discoverBody = mcpJsonRpc("server/discover", {
|
|
10557
|
-
|
|
10558
|
-
clientInfo: { name: "mcpcat", version: "0.0.0" }
|
|
10643
|
+
_meta: modernRequestMeta(MODERN_PROTOCOL_VERSION, { name: "mcpcat", version: "0.0.0" })
|
|
10559
10644
|
});
|
|
10560
10645
|
const hit = await tryMcpPost(fetcher, url, discoverBody, {
|
|
10646
|
+
"MCP-Protocol-Version": MODERN_PROTOCOL_VERSION,
|
|
10561
10647
|
"Mcp-Method": "server/discover"
|
|
10562
10648
|
});
|
|
10563
10649
|
if (hit) return hit;
|
|
10564
|
-
const initBody = mcpJsonRpc(
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10568
|
-
|
|
10650
|
+
const initBody = mcpJsonRpc(
|
|
10651
|
+
"initialize",
|
|
10652
|
+
{
|
|
10653
|
+
protocolVersion: "2025-11-25",
|
|
10654
|
+
clientInfo: { name: "mcpcat", version: "0.0.0" },
|
|
10655
|
+
capabilities: {}
|
|
10656
|
+
},
|
|
10657
|
+
2
|
|
10658
|
+
);
|
|
10569
10659
|
return tryMcpPost(fetcher, url, initBody);
|
|
10570
10660
|
}
|
|
10571
10661
|
async function probeMcp(fetcher, origin, page, targetUrl) {
|
|
@@ -11694,6 +11784,12 @@ async function handleJsonRpc(raw, source, call, serverName, serverVersion) {
|
|
|
11694
11784
|
if (!hasOwn(parsed, "id")) return { status: 202, contentType: "text/plain", body: "" };
|
|
11695
11785
|
const id = readId(parsed);
|
|
11696
11786
|
const params = Object.getOwnPropertyDescriptor(parsed, "params")?.value;
|
|
11787
|
+
return completeModernOutcome(
|
|
11788
|
+
await dispatch(id, method, params, source, call, serverName, serverVersion),
|
|
11789
|
+
params
|
|
11790
|
+
);
|
|
11791
|
+
}
|
|
11792
|
+
async function dispatch(id, method, params, source, call, serverName, serverVersion) {
|
|
11697
11793
|
if (method === "initialize")
|
|
11698
11794
|
return rpcOk(id, initializeResult(params, serverName, serverVersion));
|
|
11699
11795
|
if (method === "server/discover") return rpcOk(id, discoverResult(serverName, serverVersion));
|
|
@@ -11748,12 +11844,11 @@ function initializeResult(params, serverName, serverVersion) {
|
|
|
11748
11844
|
};
|
|
11749
11845
|
}
|
|
11750
11846
|
function discoverResult(serverName, serverVersion) {
|
|
11751
|
-
return
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
};
|
|
11847
|
+
return modernDiscoverResult(
|
|
11848
|
+
PROTOCOL_VERSIONS,
|
|
11849
|
+
{ tools: { listChanged: false } },
|
|
11850
|
+
{ name: serverName, version: serverVersion }
|
|
11851
|
+
);
|
|
11757
11852
|
}
|
|
11758
11853
|
function cap(value) {
|
|
11759
11854
|
if (value.length <= OUTPUT_CAP) return value;
|
|
@@ -11889,15 +11984,18 @@ function translateCapabilities(info) {
|
|
|
11889
11984
|
if (info.capabilities.prompts) caps.prompts = { listChanged: false };
|
|
11890
11985
|
return caps;
|
|
11891
11986
|
}
|
|
11987
|
+
function proxyServerInfo(info) {
|
|
11988
|
+
return {
|
|
11989
|
+
name: info.name ?? "mcpcat-proxy",
|
|
11990
|
+
version: info.version ?? "0.0.0",
|
|
11991
|
+
...info.title ? { title: info.title } : {}
|
|
11992
|
+
};
|
|
11993
|
+
}
|
|
11892
11994
|
function buildServerResult(info, protocolVersion) {
|
|
11893
11995
|
return {
|
|
11894
11996
|
protocolVersion,
|
|
11895
11997
|
capabilities: translateCapabilities(info),
|
|
11896
|
-
serverInfo:
|
|
11897
|
-
name: info.name ?? "mcpcat-proxy",
|
|
11898
|
-
version: info.version ?? "0.0.0",
|
|
11899
|
-
...info.title ? { title: info.title } : {}
|
|
11900
|
-
},
|
|
11998
|
+
serverInfo: proxyServerInfo(info),
|
|
11901
11999
|
...info.instructions ? { instructions: info.instructions } : {}
|
|
11902
12000
|
};
|
|
11903
12001
|
}
|
|
@@ -11945,10 +12043,16 @@ function createProxyHandler(options) {
|
|
|
11945
12043
|
return scrubOk(id, buildServerResult(cachedInfo, pv));
|
|
11946
12044
|
}
|
|
11947
12045
|
function handleDiscover(id) {
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
12046
|
+
const info = cachedInfo;
|
|
12047
|
+
return scrubOk(
|
|
12048
|
+
id,
|
|
12049
|
+
modernDiscoverResult(
|
|
12050
|
+
PROTOCOL_VERSIONS2,
|
|
12051
|
+
translateCapabilities(info),
|
|
12052
|
+
proxyServerInfo(info),
|
|
12053
|
+
info.instructions
|
|
12054
|
+
)
|
|
12055
|
+
);
|
|
11952
12056
|
}
|
|
11953
12057
|
async function forwardWithRetry(method, doForward, id) {
|
|
11954
12058
|
try {
|
|
@@ -11975,7 +12079,7 @@ function createProxyHandler(options) {
|
|
|
11975
12079
|
return scrubErr(id, -32e3, err.message);
|
|
11976
12080
|
}
|
|
11977
12081
|
}
|
|
11978
|
-
async function
|
|
12082
|
+
async function dispatch2(method, id, params) {
|
|
11979
12083
|
try {
|
|
11980
12084
|
await getConnection();
|
|
11981
12085
|
} catch (err) {
|
|
@@ -12012,7 +12116,7 @@ function createProxyHandler(options) {
|
|
|
12012
12116
|
if (!hasOwn2(parsed, "id")) return { status: 202, contentType: "text/plain", body: "" };
|
|
12013
12117
|
const id = readId2(parsed);
|
|
12014
12118
|
const params = Object.getOwnPropertyDescriptor(parsed, "params")?.value;
|
|
12015
|
-
return
|
|
12119
|
+
return completeModernOutcome(await dispatch2(method, id, params), params);
|
|
12016
12120
|
}
|
|
12017
12121
|
async function shutdown() {
|
|
12018
12122
|
if (conn) {
|
|
@@ -17273,7 +17377,7 @@ async function main(ctx) {
|
|
|
17273
17377
|
packageDir: "/node_modules/@ai-ecoverse/mcpcat"
|
|
17274
17378
|
});
|
|
17275
17379
|
const args = ctx.argv.slice(1);
|
|
17276
|
-
return run(platform2, "0.20.
|
|
17380
|
+
return run(platform2, "0.20.4", args);
|
|
17277
17381
|
}
|
|
17278
17382
|
export {
|
|
17279
17383
|
main as default
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/mcpcat",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.4",
|
|
4
4
|
"description": "A curl for the Model Context Protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"trust:dry": "npx fledgling sync --dry-run -y --skip-publish"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@ai-ecoverse/slicc-kernel": "1.146.
|
|
62
|
-
"@ai-ecoverse/slicc-shared-web": "2.10.
|
|
61
|
+
"@ai-ecoverse/slicc-kernel": "1.146.5",
|
|
62
|
+
"@ai-ecoverse/slicc-shared-web": "2.10.4",
|
|
63
63
|
"@biomejs/biome": "2.5.15",
|
|
64
64
|
"@earendil-works/pi-codemode": "1.2.0",
|
|
65
65
|
"@earendil-works/pi-mcp": "1.2.0",
|