splitwise-mcp 3.0.0 → 3.1.1
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bundle.js +993 -94
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/server.json +2 -2
package/dist/bundle.js
CHANGED
|
@@ -4859,7 +4859,7 @@ var require_memoizer = __commonJS({
|
|
|
4859
4859
|
var NONE2 = 0;
|
|
4860
4860
|
var ASSUMED2 = 1;
|
|
4861
4861
|
var PROVEN2 = 2;
|
|
4862
|
-
function isRecursive2(inst, stack,
|
|
4862
|
+
function isRecursive2(inst, stack, resolve3) {
|
|
4863
4863
|
const cached2 = recursive2.get(inst);
|
|
4864
4864
|
if (cached2 !== void 0)
|
|
4865
4865
|
return cached2 ? PROVEN2 : NONE2;
|
|
@@ -4869,7 +4869,7 @@ var require_memoizer = __commonJS({
|
|
|
4869
4869
|
let result = NONE2;
|
|
4870
4870
|
const check2 = (child) => {
|
|
4871
4871
|
if (result !== PROVEN2 && child?._zod) {
|
|
4872
|
-
const answer = isRecursive2(child, stack,
|
|
4872
|
+
const answer = isRecursive2(child, stack, resolve3);
|
|
4873
4873
|
if (answer > result)
|
|
4874
4874
|
result = answer;
|
|
4875
4875
|
}
|
|
@@ -4880,7 +4880,7 @@ var require_memoizer = __commonJS({
|
|
|
4880
4880
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
4881
4881
|
if (spread && !desc.enumerable)
|
|
4882
4882
|
continue;
|
|
4883
|
-
const child = desc.get ? ASSUMED2 : desc.value?._zod ? isRecursive2(desc.value, stack,
|
|
4883
|
+
const child = desc.get ? ASSUMED2 : desc.value?._zod ? isRecursive2(desc.value, stack, resolve3) : NONE2;
|
|
4884
4884
|
if (child > answer)
|
|
4885
4885
|
answer = child;
|
|
4886
4886
|
}
|
|
@@ -4944,7 +4944,7 @@ var require_memoizer = __commonJS({
|
|
|
4944
4944
|
break;
|
|
4945
4945
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
4946
4946
|
case "lazy": {
|
|
4947
|
-
const inner = def._cachedInner ?? (
|
|
4947
|
+
const inner = def._cachedInner ?? (resolve3 ? inst._zod.innerType : void 0);
|
|
4948
4948
|
merge2(inner ? isRecursive2(inner, stack, false) : ASSUMED2);
|
|
4949
4949
|
break;
|
|
4950
4950
|
}
|
|
@@ -62953,7 +62953,7 @@ async function extractImages$1(data, pageNumber) {
|
|
|
62953
62953
|
for (let i2 = 0; i2 < operatorList.fnArray.length; i2++) {
|
|
62954
62954
|
if (operatorList.fnArray[i2] !== OPS.paintImageXObject) continue;
|
|
62955
62955
|
const imageKey = operatorList.argsArray[i2][0];
|
|
62956
|
-
const image = await new Promise((
|
|
62956
|
+
const image = await new Promise((resolve3) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve3));
|
|
62957
62957
|
if (!image || !image.data || !image.width || !image.height) continue;
|
|
62958
62958
|
const { width, height, data: data2 } = image;
|
|
62959
62959
|
const calculatedChannels = data2.length / (width * height);
|
|
@@ -62998,8 +62998,8 @@ async function renderPageAsImage$1(data, pageNumber, options = {}) {
|
|
|
62998
62998
|
const buffer = await canvas.encode("png");
|
|
62999
62999
|
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
63000
63000
|
}
|
|
63001
|
-
const blob = await new Promise((
|
|
63002
|
-
canvas.toBlob(
|
|
63001
|
+
const blob = await new Promise((resolve3) => {
|
|
63002
|
+
canvas.toBlob(resolve3);
|
|
63003
63003
|
});
|
|
63004
63004
|
if (!blob) throw new Error("Failed to encode canvas to a PNG blob.");
|
|
63005
63005
|
return await blob.arrayBuffer();
|
|
@@ -63199,6 +63199,31 @@ var init_dist = __esm({
|
|
|
63199
63199
|
}
|
|
63200
63200
|
});
|
|
63201
63201
|
|
|
63202
|
+
// node_modules/@chrischall/mcp-utils/dist/cancel/index.js
|
|
63203
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
63204
|
+
var storage = new AsyncLocalStorage();
|
|
63205
|
+
function withCallSignal(signal, fn2, request) {
|
|
63206
|
+
return signal ? storage.run({ signal, ...request ? { request } : {} }, fn2) : fn2();
|
|
63207
|
+
}
|
|
63208
|
+
function currentCallSignal() {
|
|
63209
|
+
return storage.getStore()?.signal;
|
|
63210
|
+
}
|
|
63211
|
+
function withAmbientCancellation(own2) {
|
|
63212
|
+
const ambient = currentCallSignal();
|
|
63213
|
+
if (!ambient)
|
|
63214
|
+
return own2;
|
|
63215
|
+
if (!own2)
|
|
63216
|
+
return ambient;
|
|
63217
|
+
return AbortSignal.any([own2, ambient]);
|
|
63218
|
+
}
|
|
63219
|
+
|
|
63220
|
+
// node_modules/@chrischall/mcp-utils/dist/caller/index.js
|
|
63221
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
63222
|
+
var storage2 = new AsyncLocalStorage2();
|
|
63223
|
+
function withCallerCapabilities(capabilities, fn2) {
|
|
63224
|
+
return capabilities ? storage2.run(capabilities, fn2) : fn2();
|
|
63225
|
+
}
|
|
63226
|
+
|
|
63202
63227
|
// node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
|
|
63203
63228
|
var __create2 = Object.create;
|
|
63204
63229
|
var __defProp2 = Object.defineProperty;
|
|
@@ -64373,6 +64398,7 @@ function missingClientCapabilities(required2, declared) {
|
|
|
64373
64398
|
return Object.keys(missing).length > 0 ? missing : void 0;
|
|
64374
64399
|
}
|
|
64375
64400
|
var FIRST_MODERN_PROTOCOL_VERSION = "2026-07-28";
|
|
64401
|
+
var SUPPORTED_MODERN_PROTOCOL_VERSIONS = [FIRST_MODERN_PROTOCOL_VERSION];
|
|
64376
64402
|
function isModernProtocolVersion(version2) {
|
|
64377
64403
|
return version2 >= FIRST_MODERN_PROTOCOL_VERSION;
|
|
64378
64404
|
}
|
|
@@ -66931,6 +66957,25 @@ function isSpecNotificationMethod(method) {
|
|
|
66931
66957
|
return ALL_CODECS.some((codec2) => codec2.hasNotificationMethod(method));
|
|
66932
66958
|
}
|
|
66933
66959
|
var ALL_CODECS = [rev2025Codec, rev2026Codec];
|
|
66960
|
+
function isPlainObject$3(value) {
|
|
66961
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
66962
|
+
}
|
|
66963
|
+
function requestMetaOf(params) {
|
|
66964
|
+
if (!isPlainObject$3(params)) return void 0;
|
|
66965
|
+
const meta3 = params["_meta"];
|
|
66966
|
+
return isPlainObject$3(meta3) ? meta3 : void 0;
|
|
66967
|
+
}
|
|
66968
|
+
function hasEnvelopeClaim(params) {
|
|
66969
|
+
const meta3 = requestMetaOf(params);
|
|
66970
|
+
return meta3 !== void 0 && PROTOCOL_VERSION_META_KEY in meta3;
|
|
66971
|
+
}
|
|
66972
|
+
function envelopeClaimVersion(params) {
|
|
66973
|
+
const value = requestMetaOf(params)?.[PROTOCOL_VERSION_META_KEY];
|
|
66974
|
+
return typeof value === "string" ? value : void 0;
|
|
66975
|
+
}
|
|
66976
|
+
function validateEnvelopeMeta(meta3) {
|
|
66977
|
+
return codecForVersion(MODERN_WIRE_REVISION).validateEnvelopeMeta(meta3);
|
|
66978
|
+
}
|
|
66934
66979
|
var schemas_exports = /* @__PURE__ */ __exportAll({
|
|
66935
66980
|
AnnotationsSchema: () => AnnotationsSchema,
|
|
66936
66981
|
AudioContentSchema: () => AudioContentSchema,
|
|
@@ -67281,6 +67326,45 @@ var LADDER_ERROR_HTTP_STATUS = {
|
|
|
67281
67326
|
[ProtocolErrorCode.MissingRequiredClientCapability]: 400,
|
|
67282
67327
|
[HEADER_MISMATCH_ERROR_CODE]: 400
|
|
67283
67328
|
};
|
|
67329
|
+
function rejection(rung, cell, httpStatus, error62, settled) {
|
|
67330
|
+
return {
|
|
67331
|
+
kind: "reject",
|
|
67332
|
+
rung,
|
|
67333
|
+
cell,
|
|
67334
|
+
httpStatus,
|
|
67335
|
+
code: error62.code,
|
|
67336
|
+
message: error62.message,
|
|
67337
|
+
...error62.data !== void 0 && { data: error62.data },
|
|
67338
|
+
settled
|
|
67339
|
+
};
|
|
67340
|
+
}
|
|
67341
|
+
function carriesValidModernEnvelopeClaim(params) {
|
|
67342
|
+
if (!hasEnvelopeClaim(params)) return false;
|
|
67343
|
+
const claimedVersion = envelopeClaimVersion(params);
|
|
67344
|
+
if (claimedVersion === void 0 || !isModernProtocolVersion(claimedVersion)) return false;
|
|
67345
|
+
const meta3 = requestMetaOf(params);
|
|
67346
|
+
return meta3 !== void 0 && validateEnvelopeMeta(meta3).length === 0;
|
|
67347
|
+
}
|
|
67348
|
+
function modernOnlyStrictRejection(route, supportedVersions) {
|
|
67349
|
+
switch (route.reason) {
|
|
67350
|
+
case "http-method":
|
|
67351
|
+
return rejection("http-method", "modern-only-method-not-allowed", 405, new ProtocolError(-32e3, "Method not allowed."), true);
|
|
67352
|
+
case "batch":
|
|
67353
|
+
return rejection("jsonrpc-shape", "modern-only-batch-not-supported", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC batches are not supported by this endpoint"), true);
|
|
67354
|
+
case "response":
|
|
67355
|
+
return rejection("jsonrpc-shape", "modern-only-response-post", 400, new ProtocolError(ProtocolErrorCode.InvalidRequest, "Bad Request: JSON-RPC responses cannot be posted to this endpoint"), true);
|
|
67356
|
+
case "notification":
|
|
67357
|
+
return;
|
|
67358
|
+
case "initialize":
|
|
67359
|
+
case "no-claim": {
|
|
67360
|
+
const requested = route.requestedVersion;
|
|
67361
|
+
return rejection("era-classification", "modern-only-missing-envelope", 400, requested === void 0 ? new ProtocolError(ProtocolErrorCode.UnsupportedProtocolVersion, "Unsupported protocol version: the request did not name a protocol version", { supported: [...supportedVersions] }) : new UnsupportedProtocolVersionError({
|
|
67362
|
+
supported: [...supportedVersions],
|
|
67363
|
+
requested
|
|
67364
|
+
}), true);
|
|
67365
|
+
}
|
|
67366
|
+
}
|
|
67367
|
+
}
|
|
67284
67368
|
function parseSchema(schema, data) {
|
|
67285
67369
|
return z2.safeParse(schema, data);
|
|
67286
67370
|
}
|
|
@@ -67542,14 +67626,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
|
|
|
67542
67626
|
return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
|
|
67543
67627
|
}
|
|
67544
67628
|
function sleep(ms2, signal) {
|
|
67545
|
-
return new Promise((
|
|
67629
|
+
return new Promise((resolve3, reject) => {
|
|
67546
67630
|
if (signal?.aborted) {
|
|
67547
67631
|
reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
|
|
67548
67632
|
return;
|
|
67549
67633
|
}
|
|
67550
67634
|
const timer = setTimeout(() => {
|
|
67551
67635
|
signal?.removeEventListener("abort", onAbort);
|
|
67552
|
-
|
|
67636
|
+
resolve3();
|
|
67553
67637
|
}, ms2);
|
|
67554
67638
|
const onAbort = () => {
|
|
67555
67639
|
clearTimeout(timer);
|
|
@@ -67842,6 +67926,9 @@ function withRequestStateValue(ctx, value) {
|
|
|
67842
67926
|
};
|
|
67843
67927
|
}
|
|
67844
67928
|
var writeNegotiatedProtocolVersion;
|
|
67929
|
+
function setNegotiatedProtocolVersion(instance, version2) {
|
|
67930
|
+
writeNegotiatedProtocolVersion(instance, version2);
|
|
67931
|
+
}
|
|
67845
67932
|
var Protocol = class {
|
|
67846
67933
|
_transport;
|
|
67847
67934
|
_requestMessageId = 0;
|
|
@@ -68340,7 +68427,7 @@ var Protocol = class {
|
|
|
68340
68427
|
const flowStartedAt = Date.now();
|
|
68341
68428
|
let onAbort;
|
|
68342
68429
|
let cleanupMessageId;
|
|
68343
|
-
return new Promise((
|
|
68430
|
+
return new Promise((resolve3, reject) => {
|
|
68344
68431
|
const earlyReject = (error62) => {
|
|
68345
68432
|
reject(error62);
|
|
68346
68433
|
};
|
|
@@ -68408,7 +68495,7 @@ var Protocol = class {
|
|
|
68408
68495
|
}
|
|
68409
68496
|
if (decoded.kind === "invalid") return reject(decoded.error);
|
|
68410
68497
|
if (decoded.kind === "input_required") {
|
|
68411
|
-
if (options?.allowInputRequired === true) return
|
|
68498
|
+
if (options?.allowInputRequired === true) return resolve3(manualInputRequiredValue(decoded));
|
|
68412
68499
|
const flow = {
|
|
68413
68500
|
codec: codec2,
|
|
68414
68501
|
request,
|
|
@@ -68420,11 +68507,11 @@ var Protocol = class {
|
|
|
68420
68507
|
params
|
|
68421
68508
|
}, resultSchema, legOptions)
|
|
68422
68509
|
};
|
|
68423
|
-
return
|
|
68510
|
+
return resolve3(this._resolveNonCompleteResult(decoded, flow));
|
|
68424
68511
|
}
|
|
68425
68512
|
const result = decoded.result;
|
|
68426
68513
|
validateStandardSchema(resultSchema, result).then((parseResult) => {
|
|
68427
|
-
if (parseResult.success)
|
|
68514
|
+
if (parseResult.success) resolve3(parseResult.data);
|
|
68428
68515
|
else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
|
|
68429
68516
|
}, reject);
|
|
68430
68517
|
});
|
|
@@ -71336,7 +71423,7 @@ var require_compile2 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
71336
71423
|
ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
|
|
71337
71424
|
const schOrFunc = root.refs[ref];
|
|
71338
71425
|
if (schOrFunc) return schOrFunc;
|
|
71339
|
-
let _sch =
|
|
71426
|
+
let _sch = resolve3.call(this, root, ref);
|
|
71340
71427
|
if (_sch === void 0) {
|
|
71341
71428
|
const schema = (_a4 = root.localRefs) === null || _a4 === void 0 ? void 0 : _a4[ref];
|
|
71342
71429
|
const { schemaId } = this.opts;
|
|
@@ -71362,7 +71449,7 @@ var require_compile2 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
71362
71449
|
function sameSchemaEnv(s1, s2) {
|
|
71363
71450
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
71364
71451
|
}
|
|
71365
|
-
function
|
|
71452
|
+
function resolve3(root, ref) {
|
|
71366
71453
|
let sch;
|
|
71367
71454
|
while (typeof (sch = this.refs[ref]) == "string") ref = sch;
|
|
71368
71455
|
return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
|
|
@@ -71812,47 +71899,47 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
71812
71899
|
else if (typeof uri === "object") uri = parse3(serialize(uri, options), options);
|
|
71813
71900
|
return uri;
|
|
71814
71901
|
}
|
|
71815
|
-
function
|
|
71902
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
71816
71903
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
71817
71904
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
71818
71905
|
schemelessOptions.skipEscape = true;
|
|
71819
71906
|
return serialize(resolved, schemelessOptions);
|
|
71820
71907
|
}
|
|
71821
|
-
function resolveComponent(base,
|
|
71908
|
+
function resolveComponent(base, relative2, options, skipNormalization) {
|
|
71822
71909
|
const target = {};
|
|
71823
71910
|
if (!skipNormalization) {
|
|
71824
71911
|
base = parse3(serialize(base, options), options);
|
|
71825
|
-
|
|
71912
|
+
relative2 = parse3(serialize(relative2, options), options);
|
|
71826
71913
|
}
|
|
71827
71914
|
options = options || {};
|
|
71828
|
-
if (!options.tolerant &&
|
|
71829
|
-
target.scheme =
|
|
71830
|
-
target.userinfo =
|
|
71831
|
-
target.host =
|
|
71832
|
-
target.port =
|
|
71833
|
-
target.path = removeDotSegments(
|
|
71834
|
-
target.query =
|
|
71915
|
+
if (!options.tolerant && relative2.scheme) {
|
|
71916
|
+
target.scheme = relative2.scheme;
|
|
71917
|
+
target.userinfo = relative2.userinfo;
|
|
71918
|
+
target.host = relative2.host;
|
|
71919
|
+
target.port = relative2.port;
|
|
71920
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
71921
|
+
target.query = relative2.query;
|
|
71835
71922
|
} else {
|
|
71836
|
-
if (
|
|
71837
|
-
target.userinfo =
|
|
71838
|
-
target.host =
|
|
71839
|
-
target.port =
|
|
71840
|
-
target.path = removeDotSegments(
|
|
71841
|
-
target.query =
|
|
71923
|
+
if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
|
|
71924
|
+
target.userinfo = relative2.userinfo;
|
|
71925
|
+
target.host = relative2.host;
|
|
71926
|
+
target.port = relative2.port;
|
|
71927
|
+
target.path = removeDotSegments(relative2.path || "");
|
|
71928
|
+
target.query = relative2.query;
|
|
71842
71929
|
} else {
|
|
71843
|
-
if (!
|
|
71930
|
+
if (!relative2.path) {
|
|
71844
71931
|
target.path = base.path;
|
|
71845
|
-
if (
|
|
71932
|
+
if (relative2.query !== void 0) target.query = relative2.query;
|
|
71846
71933
|
else target.query = base.query;
|
|
71847
71934
|
} else {
|
|
71848
|
-
if (
|
|
71935
|
+
if (relative2.path[0] === "/") target.path = removeDotSegments(relative2.path);
|
|
71849
71936
|
else {
|
|
71850
|
-
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" +
|
|
71851
|
-
else if (!base.path) target.path =
|
|
71852
|
-
else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
71937
|
+
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" + relative2.path;
|
|
71938
|
+
else if (!base.path) target.path = relative2.path;
|
|
71939
|
+
else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
|
|
71853
71940
|
target.path = removeDotSegments(target.path);
|
|
71854
71941
|
}
|
|
71855
|
-
target.query =
|
|
71942
|
+
target.query = relative2.query;
|
|
71856
71943
|
}
|
|
71857
71944
|
target.userinfo = base.userinfo;
|
|
71858
71945
|
target.host = base.host;
|
|
@@ -71860,7 +71947,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
71860
71947
|
}
|
|
71861
71948
|
target.scheme = base.scheme;
|
|
71862
71949
|
}
|
|
71863
|
-
target.fragment =
|
|
71950
|
+
target.fragment = relative2.fragment;
|
|
71864
71951
|
return target;
|
|
71865
71952
|
}
|
|
71866
71953
|
function equal(uriA, uriB, options) {
|
|
@@ -71986,7 +72073,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
71986
72073
|
const fastUri = {
|
|
71987
72074
|
SCHEMES,
|
|
71988
72075
|
normalize,
|
|
71989
|
-
resolve:
|
|
72076
|
+
resolve: resolve3,
|
|
71990
72077
|
resolveComponent,
|
|
71991
72078
|
equal,
|
|
71992
72079
|
serialize,
|
|
@@ -75785,6 +75872,190 @@ function getCompleter(schema) {
|
|
|
75785
75872
|
return schema[COMPLETABLE_SYMBOL]?.complete;
|
|
75786
75873
|
}
|
|
75787
75874
|
var MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
75875
|
+
function listenFilterAccepts(filter, event) {
|
|
75876
|
+
switch (event.kind) {
|
|
75877
|
+
case "tools_list_changed":
|
|
75878
|
+
return filter.toolsListChanged === true;
|
|
75879
|
+
case "prompts_list_changed":
|
|
75880
|
+
return filter.promptsListChanged === true;
|
|
75881
|
+
case "resources_list_changed":
|
|
75882
|
+
return filter.resourcesListChanged === true;
|
|
75883
|
+
case "resource_updated":
|
|
75884
|
+
return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
75885
|
+
}
|
|
75886
|
+
}
|
|
75887
|
+
function honoredSubset(requested, capabilities) {
|
|
75888
|
+
const honored = {};
|
|
75889
|
+
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
75890
|
+
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
75891
|
+
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
75892
|
+
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
75893
|
+
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
75894
|
+
return honored;
|
|
75895
|
+
}
|
|
75896
|
+
var DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
75897
|
+
function stampSubscriptionId(notification, subscriptionId) {
|
|
75898
|
+
return {
|
|
75899
|
+
method: notification.method,
|
|
75900
|
+
params: {
|
|
75901
|
+
...notification.params,
|
|
75902
|
+
_meta: {
|
|
75903
|
+
...notification.params?._meta,
|
|
75904
|
+
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
75905
|
+
}
|
|
75906
|
+
}
|
|
75907
|
+
};
|
|
75908
|
+
}
|
|
75909
|
+
function parseListenFilter(message) {
|
|
75910
|
+
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
75911
|
+
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
75912
|
+
}
|
|
75913
|
+
var CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
75914
|
+
"notifications/tools/list_changed",
|
|
75915
|
+
"notifications/prompts/list_changed",
|
|
75916
|
+
"notifications/resources/list_changed",
|
|
75917
|
+
"notifications/resources/updated"
|
|
75918
|
+
]);
|
|
75919
|
+
var StdioListenRouter = class {
|
|
75920
|
+
/** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
|
|
75921
|
+
_subs = /* @__PURE__ */ new Map();
|
|
75922
|
+
/**
|
|
75923
|
+
* The serving instance's declared capabilities. Filled in by the entry
|
|
75924
|
+
* once the modern instance is constructed (the router is created before
|
|
75925
|
+
* the instance exists), so the acknowledged filter is narrowed against
|
|
75926
|
+
* what the server can actually deliver.
|
|
75927
|
+
*/
|
|
75928
|
+
_serverCapabilities;
|
|
75929
|
+
/**
|
|
75930
|
+
* The serving instance's identity, stamped onto the graceful-close
|
|
75931
|
+
* results' `_meta` (the spec's `SubscriptionsListenResultMeta` extends
|
|
75932
|
+
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
75933
|
+
*/
|
|
75934
|
+
_serverInfo;
|
|
75935
|
+
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
75936
|
+
this._maxSubscriptions = _maxSubscriptions;
|
|
75937
|
+
this._serverCapabilities = serverCapabilities;
|
|
75938
|
+
this._serverInfo = serverInfo;
|
|
75939
|
+
}
|
|
75940
|
+
/**
|
|
75941
|
+
* Record the serving instance's declared capabilities and identity once
|
|
75942
|
+
* it has been constructed. Called by `serveStdio`'s connect path;
|
|
75943
|
+
* subsequent `serve()` calls narrow the honored filter against the
|
|
75944
|
+
* capabilities, and `teardownAll()` stamps the identity.
|
|
75945
|
+
*/
|
|
75946
|
+
setServerCapabilities(capabilities, serverInfo) {
|
|
75947
|
+
this._serverCapabilities = capabilities;
|
|
75948
|
+
if (serverInfo !== void 0) this._serverInfo = serverInfo;
|
|
75949
|
+
}
|
|
75950
|
+
/** Whether `id` is an active listen subscription on this connection. */
|
|
75951
|
+
has(id) {
|
|
75952
|
+
return this._subs.has(id);
|
|
75953
|
+
}
|
|
75954
|
+
/**
|
|
75955
|
+
* Serve one inbound `subscriptions/listen` request: registers the
|
|
75956
|
+
* subscription and returns the stamped acknowledged notification (or, on
|
|
75957
|
+
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
75958
|
+
*
|
|
75959
|
+
* @throws when called before {@linkcode setServerCapabilities} (or the
|
|
75960
|
+
* constructor) has supplied the serving instance's capabilities. Honoring a
|
|
75961
|
+
* filter without knowing the server's advertised capabilities would fail
|
|
75962
|
+
* open (deliver unadvertised types); the entry guarantees capabilities are
|
|
75963
|
+
* set before any listen request is routed here.
|
|
75964
|
+
*/
|
|
75965
|
+
serve(message) {
|
|
75966
|
+
if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
|
|
75967
|
+
if (this._subs.size >= this._maxSubscriptions) return {
|
|
75968
|
+
jsonrpc: "2.0",
|
|
75969
|
+
id: message.id,
|
|
75970
|
+
error: {
|
|
75971
|
+
code: -32603,
|
|
75972
|
+
message: "Subscription limit reached"
|
|
75973
|
+
}
|
|
75974
|
+
};
|
|
75975
|
+
const filter = parseListenFilter(message);
|
|
75976
|
+
if (filter === void 0) return {
|
|
75977
|
+
jsonrpc: "2.0",
|
|
75978
|
+
id: message.id,
|
|
75979
|
+
error: {
|
|
75980
|
+
code: -32602,
|
|
75981
|
+
message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
|
|
75982
|
+
}
|
|
75983
|
+
};
|
|
75984
|
+
const honored = honoredSubset(filter, this._serverCapabilities);
|
|
75985
|
+
this._subs.set(message.id, honored);
|
|
75986
|
+
return stampSubscriptionId({
|
|
75987
|
+
method: "notifications/subscriptions/acknowledged",
|
|
75988
|
+
params: { notifications: honored }
|
|
75989
|
+
}, message.id);
|
|
75990
|
+
}
|
|
75991
|
+
/**
|
|
75992
|
+
* Tear down one subscription (inbound `notifications/cancelled`). Returns
|
|
75993
|
+
* `true` when a subscription was removed. After this call NOTHING further
|
|
75994
|
+
* is delivered for that subscription id (the post-cancel hardening).
|
|
75995
|
+
*/
|
|
75996
|
+
cancel(id) {
|
|
75997
|
+
return this._subs.delete(id);
|
|
75998
|
+
}
|
|
75999
|
+
/**
|
|
76000
|
+
* Route an outbound notification through the active subscriptions.
|
|
76001
|
+
*
|
|
76002
|
+
* - For a subscription-gated change notification, returns one stamped copy
|
|
76003
|
+
* per subscription that opted in to it (an empty array means it is
|
|
76004
|
+
* dropped — the modern era never delivers an un-requested change type).
|
|
76005
|
+
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
76006
|
+
* forwards it as-is).
|
|
76007
|
+
*/
|
|
76008
|
+
routeOutbound(message) {
|
|
76009
|
+
if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
|
|
76010
|
+
const uriParam = message.params?.["uri"];
|
|
76011
|
+
const uri = typeof uriParam === "string" ? uriParam : void 0;
|
|
76012
|
+
const event = notificationToServerEvent(message.method, uri);
|
|
76013
|
+
const out = [];
|
|
76014
|
+
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
76015
|
+
method: message.method,
|
|
76016
|
+
params: message.params ?? {}
|
|
76017
|
+
}, subscriptionId));
|
|
76018
|
+
return out;
|
|
76019
|
+
}
|
|
76020
|
+
/**
|
|
76021
|
+
* Server-side graceful teardown of every active subscription: returns the
|
|
76022
|
+
* empty `subscriptions/listen` JSON-RPC result for each subscription id —
|
|
76023
|
+
* the spec's graceful-close signal, `_meta` carrying the subscription id
|
|
76024
|
+
* and the serving instance's identity — for the entry to emit before
|
|
76025
|
+
* closing the wire. Clears the set so nothing further is delivered.
|
|
76026
|
+
*/
|
|
76027
|
+
teardownAll() {
|
|
76028
|
+
const out = [];
|
|
76029
|
+
for (const id of this._subs.keys()) out.push({
|
|
76030
|
+
jsonrpc: "2.0",
|
|
76031
|
+
id,
|
|
76032
|
+
result: {
|
|
76033
|
+
resultType: "complete",
|
|
76034
|
+
_meta: {
|
|
76035
|
+
[SUBSCRIPTION_ID_META_KEY]: id,
|
|
76036
|
+
...this._serverInfo !== void 0 && { [SERVER_INFO_META_KEY]: this._serverInfo }
|
|
76037
|
+
}
|
|
76038
|
+
}
|
|
76039
|
+
});
|
|
76040
|
+
this._subs.clear();
|
|
76041
|
+
return out;
|
|
76042
|
+
}
|
|
76043
|
+
};
|
|
76044
|
+
function notificationToServerEvent(method, uri) {
|
|
76045
|
+
switch (method) {
|
|
76046
|
+
case "notifications/tools/list_changed":
|
|
76047
|
+
return { kind: "tools_list_changed" };
|
|
76048
|
+
case "notifications/prompts/list_changed":
|
|
76049
|
+
return { kind: "prompts_list_changed" };
|
|
76050
|
+
case "notifications/resources/list_changed":
|
|
76051
|
+
return { kind: "resources_list_changed" };
|
|
76052
|
+
default:
|
|
76053
|
+
return {
|
|
76054
|
+
kind: "resource_updated",
|
|
76055
|
+
uri: uri ?? ""
|
|
76056
|
+
};
|
|
76057
|
+
}
|
|
76058
|
+
}
|
|
75788
76059
|
var DEFAULT_LEGACY_SHIM_MAX_ROUNDS = 8;
|
|
75789
76060
|
var DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS = 6e5;
|
|
75790
76061
|
function resolveLegacyShimOptions(options) {
|
|
@@ -75922,6 +76193,12 @@ var INPUT_REQUIRED_CAPABLE_METHODS = /* @__PURE__ */ new Set([
|
|
|
75922
76193
|
var writeClientIdentity;
|
|
75923
76194
|
var installDiscoverHandler;
|
|
75924
76195
|
var readServerIdentity;
|
|
76196
|
+
function installModernOnlyHandlers(server, servedModernVersions) {
|
|
76197
|
+
installDiscoverHandler(server, servedModernVersions);
|
|
76198
|
+
}
|
|
76199
|
+
function serverIdentityOf(server) {
|
|
76200
|
+
return readServerIdentity(server);
|
|
76201
|
+
}
|
|
75925
76202
|
var Server = class extends Protocol {
|
|
75926
76203
|
_clientCapabilities;
|
|
75927
76204
|
_clientVersion;
|
|
@@ -77169,7 +77446,7 @@ var StdioServerTransport = class {
|
|
|
77169
77446
|
}
|
|
77170
77447
|
send(message) {
|
|
77171
77448
|
if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
|
|
77172
|
-
return new Promise((
|
|
77449
|
+
return new Promise((resolve3, reject) => {
|
|
77173
77450
|
const json2 = serializeMessage(message);
|
|
77174
77451
|
let settled = false;
|
|
77175
77452
|
const onError = (error62) => {
|
|
@@ -77184,18 +77461,412 @@ var StdioServerTransport = class {
|
|
|
77184
77461
|
settled = true;
|
|
77185
77462
|
this._stdout.off("error", onError);
|
|
77186
77463
|
this._stdout.off("drain", onDrain);
|
|
77187
|
-
|
|
77464
|
+
resolve3();
|
|
77188
77465
|
};
|
|
77189
77466
|
this._stdout.once("error", onError);
|
|
77190
77467
|
if (this._stdout.write(json2)) {
|
|
77191
77468
|
if (settled) return;
|
|
77192
77469
|
settled = true;
|
|
77193
77470
|
this._stdout.off("error", onError);
|
|
77194
|
-
|
|
77471
|
+
resolve3();
|
|
77195
77472
|
} else if (!settled) this._stdout.once("drain", onDrain);
|
|
77196
77473
|
});
|
|
77197
77474
|
}
|
|
77198
77475
|
};
|
|
77476
|
+
var DISCARD_ANSWER_TIMEOUT_MS = 3e3;
|
|
77477
|
+
var StdioConnectionChannel = class {
|
|
77478
|
+
onclose;
|
|
77479
|
+
onerror;
|
|
77480
|
+
onmessage;
|
|
77481
|
+
_closed = false;
|
|
77482
|
+
/** Request ids the entry delivered to the instance that the instance has not yet answered. */
|
|
77483
|
+
_pendingRequests = /* @__PURE__ */ new Set();
|
|
77484
|
+
_drainWaiters = [];
|
|
77485
|
+
constructor(_wire, _onInstanceClose, _outboundIntercept) {
|
|
77486
|
+
this._wire = _wire;
|
|
77487
|
+
this._onInstanceClose = _onInstanceClose;
|
|
77488
|
+
this._outboundIntercept = _outboundIntercept;
|
|
77489
|
+
}
|
|
77490
|
+
async start() {
|
|
77491
|
+
}
|
|
77492
|
+
async send(message, options) {
|
|
77493
|
+
if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
|
|
77494
|
+
const { id } = message;
|
|
77495
|
+
if (id !== void 0) this._settle(id);
|
|
77496
|
+
}
|
|
77497
|
+
if (this._closed) return;
|
|
77498
|
+
if (this._outboundIntercept?.(message) === "handled") return;
|
|
77499
|
+
return this._wire.send(message, options);
|
|
77500
|
+
}
|
|
77501
|
+
setProtocolVersion = (version2) => {
|
|
77502
|
+
this._wire.setProtocolVersion?.(version2);
|
|
77503
|
+
};
|
|
77504
|
+
/** Forwards one inbound message to the connected instance. */
|
|
77505
|
+
deliver(message, extra) {
|
|
77506
|
+
if (this._closed) return;
|
|
77507
|
+
if (isJSONRPCRequest(message)) this._pendingRequests.add(message.id);
|
|
77508
|
+
else if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
|
|
77509
|
+
const cancelledId = message.params?.requestId;
|
|
77510
|
+
if (cancelledId !== void 0) this._settle(cancelledId);
|
|
77511
|
+
}
|
|
77512
|
+
this.onmessage?.(message, extra);
|
|
77513
|
+
}
|
|
77514
|
+
/**
|
|
77515
|
+
* Resolves once every request delivered to the instance has been answered
|
|
77516
|
+
* through {@linkcode send}, settled by a delivered cancellation, or the
|
|
77517
|
+
* channel has been closed and nothing further can be answered. The wait is
|
|
77518
|
+
* bounded by `timeoutMs` as a backstop so no edge can hold the caller
|
|
77519
|
+
* indefinitely; resolves `false` only when the bound elapsed with requests
|
|
77520
|
+
* still unanswered. Used by the probe-discard path so a probe request the
|
|
77521
|
+
* entry accepted is never silently dropped.
|
|
77522
|
+
*/
|
|
77523
|
+
async whenRequestsAnswered(timeoutMs) {
|
|
77524
|
+
if (this._closed || this._pendingRequests.size === 0) return true;
|
|
77525
|
+
return await new Promise((resolve3) => {
|
|
77526
|
+
const waiter = () => {
|
|
77527
|
+
clearTimeout(timer);
|
|
77528
|
+
resolve3(true);
|
|
77529
|
+
};
|
|
77530
|
+
const timer = setTimeout(() => {
|
|
77531
|
+
this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
|
|
77532
|
+
resolve3(false);
|
|
77533
|
+
}, timeoutMs);
|
|
77534
|
+
this._drainWaiters.push(waiter);
|
|
77535
|
+
});
|
|
77536
|
+
}
|
|
77537
|
+
async close() {
|
|
77538
|
+
if (this._closed) return;
|
|
77539
|
+
this._closed = true;
|
|
77540
|
+
this._pendingRequests.clear();
|
|
77541
|
+
this._releaseDrainWaiters();
|
|
77542
|
+
try {
|
|
77543
|
+
this._onInstanceClose();
|
|
77544
|
+
} finally {
|
|
77545
|
+
this.onclose?.();
|
|
77546
|
+
}
|
|
77547
|
+
}
|
|
77548
|
+
_settle(id) {
|
|
77549
|
+
this._pendingRequests.delete(id);
|
|
77550
|
+
if (this._pendingRequests.size === 0) this._releaseDrainWaiters();
|
|
77551
|
+
}
|
|
77552
|
+
_releaseDrainWaiters() {
|
|
77553
|
+
const waiters = this._drainWaiters;
|
|
77554
|
+
this._drainWaiters = [];
|
|
77555
|
+
for (const waiter of waiters) waiter();
|
|
77556
|
+
}
|
|
77557
|
+
};
|
|
77558
|
+
function classifyOpeningMessage(message) {
|
|
77559
|
+
const params = message.params;
|
|
77560
|
+
if (message.method === "initialize" && !carriesValidModernEnvelopeClaim(params)) {
|
|
77561
|
+
const requestedVersion = params !== null && typeof params === "object" && typeof params.protocolVersion === "string" ? params.protocolVersion : void 0;
|
|
77562
|
+
return {
|
|
77563
|
+
kind: "legacy",
|
|
77564
|
+
reason: "initialize",
|
|
77565
|
+
...requestedVersion !== void 0 && { requestedVersion }
|
|
77566
|
+
};
|
|
77567
|
+
}
|
|
77568
|
+
if (!hasEnvelopeClaim(params)) return {
|
|
77569
|
+
kind: "legacy",
|
|
77570
|
+
reason: "no-claim"
|
|
77571
|
+
};
|
|
77572
|
+
const meta3 = requestMetaOf(params);
|
|
77573
|
+
const firstIssue = (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0];
|
|
77574
|
+
if (firstIssue !== void 0) return {
|
|
77575
|
+
kind: "invalid-envelope",
|
|
77576
|
+
issue: firstIssue
|
|
77577
|
+
};
|
|
77578
|
+
const claimedVersion = envelopeClaimVersion(params);
|
|
77579
|
+
if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) return {
|
|
77580
|
+
kind: "unsupported-revision",
|
|
77581
|
+
requested: claimedVersion ?? "unknown"
|
|
77582
|
+
};
|
|
77583
|
+
return {
|
|
77584
|
+
kind: "modern",
|
|
77585
|
+
revision: claimedVersion,
|
|
77586
|
+
classification: {
|
|
77587
|
+
era: "modern",
|
|
77588
|
+
revision: claimedVersion
|
|
77589
|
+
}
|
|
77590
|
+
};
|
|
77591
|
+
}
|
|
77592
|
+
function serveStdio(factory, options = {}) {
|
|
77593
|
+
const legacyMode = options.legacy ?? "serve";
|
|
77594
|
+
const wire = options.transport ?? new StdioServerTransport();
|
|
77595
|
+
let state = { phase: "opening" };
|
|
77596
|
+
let discarding;
|
|
77597
|
+
let closing = false;
|
|
77598
|
+
const isTornDown = () => closing || state.phase === "closed";
|
|
77599
|
+
const reportError = (error62) => {
|
|
77600
|
+
try {
|
|
77601
|
+
options.onerror?.(error62);
|
|
77602
|
+
} catch {
|
|
77603
|
+
}
|
|
77604
|
+
};
|
|
77605
|
+
const writeErrorResponse = (id, code, message, data) => wire.send({
|
|
77606
|
+
jsonrpc: "2.0",
|
|
77607
|
+
id,
|
|
77608
|
+
error: {
|
|
77609
|
+
code,
|
|
77610
|
+
message,
|
|
77611
|
+
...data !== void 0 && { data }
|
|
77612
|
+
}
|
|
77613
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
77614
|
+
const listenRouter = new StdioListenRouter(options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS);
|
|
77615
|
+
const modernOutboundIntercept = (message) => {
|
|
77616
|
+
if (!isJSONRPCNotification(message)) return void 0;
|
|
77617
|
+
const routed = listenRouter.routeOutbound(message);
|
|
77618
|
+
if (routed === "passthrough") return void 0;
|
|
77619
|
+
for (const stamped of routed) wire.send({
|
|
77620
|
+
jsonrpc: "2.0",
|
|
77621
|
+
...stamped
|
|
77622
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
77623
|
+
return "handled";
|
|
77624
|
+
};
|
|
77625
|
+
const tryServeListen = async (message) => {
|
|
77626
|
+
if (isJSONRPCRequest(message) && message.method === "subscriptions/listen") {
|
|
77627
|
+
const meta3 = requestMetaOf(message.params);
|
|
77628
|
+
const issue2 = hasEnvelopeClaim(message.params) ? (meta3 === void 0 ? [] : validateEnvelopeMeta(meta3))[0] : {
|
|
77629
|
+
key: "_meta",
|
|
77630
|
+
problem: "the per-request envelope is required on protocol revision 2026-07-28"
|
|
77631
|
+
};
|
|
77632
|
+
const claimedVersion = envelopeClaimVersion(message.params);
|
|
77633
|
+
let reply;
|
|
77634
|
+
if (issue2 !== void 0) reply = {
|
|
77635
|
+
jsonrpc: "2.0",
|
|
77636
|
+
id: message.id,
|
|
77637
|
+
error: {
|
|
77638
|
+
code: -32602,
|
|
77639
|
+
message: `Invalid _meta envelope: ${issue2.key}: ${issue2.problem}`
|
|
77640
|
+
}
|
|
77641
|
+
};
|
|
77642
|
+
else if (claimedVersion === void 0 || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) {
|
|
77643
|
+
const error62 = new UnsupportedProtocolVersionError({
|
|
77644
|
+
supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
|
|
77645
|
+
requested: claimedVersion ?? "unknown"
|
|
77646
|
+
});
|
|
77647
|
+
reply = {
|
|
77648
|
+
jsonrpc: "2.0",
|
|
77649
|
+
id: message.id,
|
|
77650
|
+
error: {
|
|
77651
|
+
code: error62.code,
|
|
77652
|
+
message: error62.message,
|
|
77653
|
+
data: error62.data
|
|
77654
|
+
}
|
|
77655
|
+
};
|
|
77656
|
+
} else reply = listenRouter.serve(message);
|
|
77657
|
+
await wire.send("error" in reply ? reply : {
|
|
77658
|
+
jsonrpc: "2.0",
|
|
77659
|
+
method: reply.method,
|
|
77660
|
+
params: reply.params
|
|
77661
|
+
}).catch((error62) => reportError(toError(error62)));
|
|
77662
|
+
return true;
|
|
77663
|
+
}
|
|
77664
|
+
if (isJSONRPCNotification(message) && message.method === "notifications/cancelled") {
|
|
77665
|
+
const cancelledId = message.params?.requestId;
|
|
77666
|
+
if (cancelledId !== void 0 && listenRouter.cancel(cancelledId)) return true;
|
|
77667
|
+
}
|
|
77668
|
+
return false;
|
|
77669
|
+
};
|
|
77670
|
+
const answerLegacyRejection = (request, reason, requestedVersion) => {
|
|
77671
|
+
const rejection2 = modernOnlyStrictRejection({
|
|
77672
|
+
kind: "legacy",
|
|
77673
|
+
reason,
|
|
77674
|
+
...requestedVersion !== void 0 && { requestedVersion }
|
|
77675
|
+
}, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
77676
|
+
if (rejection2 === void 0) return Promise.resolve();
|
|
77677
|
+
reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection2.cell}): ${rejection2.message}`));
|
|
77678
|
+
return writeErrorResponse(request.id, rejection2.code, rejection2.message, rejection2.data);
|
|
77679
|
+
};
|
|
77680
|
+
const onInstanceClosed = (channel) => {
|
|
77681
|
+
if (closing || channel === discarding) return;
|
|
77682
|
+
closeAll();
|
|
77683
|
+
};
|
|
77684
|
+
const connectInstance = async (era, revision) => {
|
|
77685
|
+
const product = await factory({ era });
|
|
77686
|
+
const server = product instanceof McpServer ? product.server : product;
|
|
77687
|
+
if (era === "modern") {
|
|
77688
|
+
setNegotiatedProtocolVersion(server, revision);
|
|
77689
|
+
installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
|
|
77690
|
+
listenRouter.setServerCapabilities(server.getCapabilities(), serverIdentityOf(server));
|
|
77691
|
+
}
|
|
77692
|
+
const channel = new StdioConnectionChannel(wire, () => onInstanceClosed(channel), era === "modern" ? modernOutboundIntercept : void 0);
|
|
77693
|
+
await product.connect(channel);
|
|
77694
|
+
return {
|
|
77695
|
+
product,
|
|
77696
|
+
channel
|
|
77697
|
+
};
|
|
77698
|
+
};
|
|
77699
|
+
const disposeLateInstance = (instance) => instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
77700
|
+
const discardProbeInstance = async (instance) => {
|
|
77701
|
+
discarding = instance.channel;
|
|
77702
|
+
try {
|
|
77703
|
+
if (!await instance.channel.whenRequestsAnswered(DISCARD_ANSWER_TIMEOUT_MS)) reportError(/* @__PURE__ */ new Error(`Discarded the probe instance with requests still unanswered after ${DISCARD_ANSWER_TIMEOUT_MS}ms; continuing with the fallback`));
|
|
77704
|
+
await instance.product.close();
|
|
77705
|
+
} catch (error62) {
|
|
77706
|
+
reportError(toError(error62));
|
|
77707
|
+
} finally {
|
|
77708
|
+
discarding = void 0;
|
|
77709
|
+
}
|
|
77710
|
+
};
|
|
77711
|
+
const processMessage = async (message) => {
|
|
77712
|
+
if (state.phase === "closed") return;
|
|
77713
|
+
if (state.phase === "pinned") {
|
|
77714
|
+
if (state.era === "modern" && isJSONRPCRequest(message) && message.method === "initialize" && !carriesValidModernEnvelopeClaim(message.params)) {
|
|
77715
|
+
await answerLegacyRejection(message, "initialize", message.params !== null && typeof message.params === "object" && typeof message.params.protocolVersion === "string" ? message.params.protocolVersion : void 0);
|
|
77716
|
+
return;
|
|
77717
|
+
}
|
|
77718
|
+
if (state.era === "modern" && await tryServeListen(message)) return;
|
|
77719
|
+
state.instance.channel.deliver(message);
|
|
77720
|
+
return;
|
|
77721
|
+
}
|
|
77722
|
+
if (!isJSONRPCRequest(message) && !isJSONRPCNotification(message)) {
|
|
77723
|
+
reportError(/* @__PURE__ */ new Error("Discarded a JSON-RPC response received before the connection negotiated an era"));
|
|
77724
|
+
return;
|
|
77725
|
+
}
|
|
77726
|
+
const opening = classifyOpeningMessage(message);
|
|
77727
|
+
switch (opening.kind) {
|
|
77728
|
+
case "invalid-envelope": {
|
|
77729
|
+
const detail = `Invalid _meta envelope for protocol revision 2026-07-28: ${opening.issue.key}: ${opening.issue.problem}`;
|
|
77730
|
+
if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InvalidParams, detail, { envelope: opening.issue });
|
|
77731
|
+
else reportError(/* @__PURE__ */ new Error(`Discarded a notification with a malformed envelope: ${detail}`));
|
|
77732
|
+
return;
|
|
77733
|
+
}
|
|
77734
|
+
case "unsupported-revision":
|
|
77735
|
+
if (isJSONRPCRequest(message)) {
|
|
77736
|
+
const error62 = new UnsupportedProtocolVersionError({
|
|
77737
|
+
supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],
|
|
77738
|
+
requested: opening.requested
|
|
77739
|
+
});
|
|
77740
|
+
reportError(error62);
|
|
77741
|
+
await writeErrorResponse(message.id, error62.code, error62.message, error62.data);
|
|
77742
|
+
} else reportError(/* @__PURE__ */ new Error(`Discarded a notification claiming unsupported protocol revision ${opening.requested}`));
|
|
77743
|
+
return;
|
|
77744
|
+
case "modern":
|
|
77745
|
+
if (isJSONRPCRequest(message) && message.method === "server/discover") {
|
|
77746
|
+
if (state.phase === "probe") {
|
|
77747
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
77748
|
+
return;
|
|
77749
|
+
}
|
|
77750
|
+
const instance = await connectInstance("modern", opening.revision);
|
|
77751
|
+
if (isTornDown()) {
|
|
77752
|
+
await disposeLateInstance(instance);
|
|
77753
|
+
return;
|
|
77754
|
+
}
|
|
77755
|
+
state = {
|
|
77756
|
+
phase: "probe",
|
|
77757
|
+
instance
|
|
77758
|
+
};
|
|
77759
|
+
instance.channel.deliver(message, { classification: opening.classification });
|
|
77760
|
+
return;
|
|
77761
|
+
}
|
|
77762
|
+
if (state.phase === "probe") {
|
|
77763
|
+
if (isJSONRPCNotification(message)) {
|
|
77764
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
77765
|
+
return;
|
|
77766
|
+
}
|
|
77767
|
+
state = {
|
|
77768
|
+
phase: "pinned",
|
|
77769
|
+
era: "modern",
|
|
77770
|
+
instance: state.instance
|
|
77771
|
+
};
|
|
77772
|
+
} else {
|
|
77773
|
+
const instance = await connectInstance("modern", opening.revision);
|
|
77774
|
+
if (isTornDown()) {
|
|
77775
|
+
await disposeLateInstance(instance);
|
|
77776
|
+
return;
|
|
77777
|
+
}
|
|
77778
|
+
state = {
|
|
77779
|
+
phase: "pinned",
|
|
77780
|
+
era: "modern",
|
|
77781
|
+
instance
|
|
77782
|
+
};
|
|
77783
|
+
}
|
|
77784
|
+
if (await tryServeListen(message)) return;
|
|
77785
|
+
state.instance.channel.deliver(message, { classification: opening.classification });
|
|
77786
|
+
return;
|
|
77787
|
+
case "legacy": {
|
|
77788
|
+
if (legacyMode === "reject") {
|
|
77789
|
+
if (isJSONRPCRequest(message)) await answerLegacyRejection(message, opening.reason, opening.requestedVersion);
|
|
77790
|
+
return;
|
|
77791
|
+
}
|
|
77792
|
+
if (state.phase === "probe") {
|
|
77793
|
+
await discardProbeInstance(state.instance);
|
|
77794
|
+
if (isTornDown()) return;
|
|
77795
|
+
state = { phase: "opening" };
|
|
77796
|
+
}
|
|
77797
|
+
const instance = await connectInstance("legacy");
|
|
77798
|
+
if (isTornDown()) {
|
|
77799
|
+
await disposeLateInstance(instance);
|
|
77800
|
+
return;
|
|
77801
|
+
}
|
|
77802
|
+
state = {
|
|
77803
|
+
phase: "pinned",
|
|
77804
|
+
era: "legacy",
|
|
77805
|
+
instance
|
|
77806
|
+
};
|
|
77807
|
+
state.instance.channel.deliver(message);
|
|
77808
|
+
return;
|
|
77809
|
+
}
|
|
77810
|
+
}
|
|
77811
|
+
};
|
|
77812
|
+
const queue = [];
|
|
77813
|
+
let pumping = false;
|
|
77814
|
+
const pump = async () => {
|
|
77815
|
+
if (pumping) return;
|
|
77816
|
+
pumping = true;
|
|
77817
|
+
try {
|
|
77818
|
+
while (queue.length > 0) {
|
|
77819
|
+
const message = queue.shift();
|
|
77820
|
+
try {
|
|
77821
|
+
await processMessage(message);
|
|
77822
|
+
} catch (error62) {
|
|
77823
|
+
if (isJSONRPCRequest(message)) await writeErrorResponse(message.id, ProtocolErrorCode.InternalError, "Internal server error");
|
|
77824
|
+
reportError(toError(error62));
|
|
77825
|
+
}
|
|
77826
|
+
}
|
|
77827
|
+
} finally {
|
|
77828
|
+
pumping = false;
|
|
77829
|
+
}
|
|
77830
|
+
};
|
|
77831
|
+
const closeAll = async () => {
|
|
77832
|
+
if (closing || state.phase === "closed") return;
|
|
77833
|
+
closing = true;
|
|
77834
|
+
const current = state;
|
|
77835
|
+
state = { phase: "closed" };
|
|
77836
|
+
for (const result of listenRouter.teardownAll()) await wire.send(result).catch((error62) => reportError(toError(error62)));
|
|
77837
|
+
if (current.phase === "probe" || current.phase === "pinned") await current.instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
77838
|
+
await wire.close().catch((error62) => reportError(toError(error62)));
|
|
77839
|
+
};
|
|
77840
|
+
wire.onmessage = (message) => {
|
|
77841
|
+
queue.push(message);
|
|
77842
|
+
pump();
|
|
77843
|
+
};
|
|
77844
|
+
wire.onerror = (error62) => {
|
|
77845
|
+
reportError(error62);
|
|
77846
|
+
if (state.phase === "probe" || state.phase === "pinned") state.instance.channel.onerror?.(error62);
|
|
77847
|
+
};
|
|
77848
|
+
wire.onclose = () => {
|
|
77849
|
+
if (closing || state.phase === "closed") return;
|
|
77850
|
+
closing = true;
|
|
77851
|
+
const current = state;
|
|
77852
|
+
state = { phase: "closed" };
|
|
77853
|
+
if (current.phase === "probe" || current.phase === "pinned") current.instance.product.close().catch((error62) => reportError(toError(error62)));
|
|
77854
|
+
};
|
|
77855
|
+
const started = wire.start().catch((error62) => {
|
|
77856
|
+
reportError(toError(error62));
|
|
77857
|
+
throw error62;
|
|
77858
|
+
});
|
|
77859
|
+
started.catch(() => {
|
|
77860
|
+
});
|
|
77861
|
+
return { close: async () => {
|
|
77862
|
+
await started.catch(() => {
|
|
77863
|
+
});
|
|
77864
|
+
await closeAll();
|
|
77865
|
+
} };
|
|
77866
|
+
}
|
|
77867
|
+
function toError(value) {
|
|
77868
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
77869
|
+
}
|
|
77199
77870
|
|
|
77200
77871
|
// node_modules/@chrischall/mcp-utils/dist/errors/index.js
|
|
77201
77872
|
var DEFAULT_ERROR_MESSAGE_MAX = 500;
|
|
@@ -77229,13 +77900,28 @@ var API_KEY_RE = new RegExp([
|
|
|
77229
77900
|
"whsec_[A-Za-z0-9]{16,}\\b"
|
|
77230
77901
|
// webhook signing secret (Stripe-style)
|
|
77231
77902
|
].map((p2) => `\\b${p2}`).join("|"), "g");
|
|
77232
|
-
var QUERY_SECRET_RE = /([?&](?:
|
|
77903
|
+
var QUERY_SECRET_RE = /([?&](?:(?:access|refresh|id|auth|session|csrf|xsrf)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
|
|
77904
|
+
var OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
|
|
77905
|
+
var FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
|
|
77906
|
+
var HEADER_SECRET_RE = /(\b(?:x[-_][a-z0-9_-]*?(?:api[-_]?key|token|secret|auth)[a-z0-9_-]*|api[-_]?key)\s*:\s*)[^\s,;"'<>`]+/gi;
|
|
77233
77907
|
var AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
|
|
77234
|
-
var JSON_SECRET_KEYS =
|
|
77235
|
-
|
|
77236
|
-
|
|
77908
|
+
var JSON_SECRET_KEYS = [
|
|
77909
|
+
"(?:access|refresh|id|auth|session|bearer|csrf|xsrf)[_-]?token",
|
|
77910
|
+
"client[_-]?secret",
|
|
77911
|
+
"api[_-]?secret",
|
|
77912
|
+
"(?:x[_-])?api[_-]?key",
|
|
77913
|
+
"private[_-]?key",
|
|
77914
|
+
"x[_-][a-z0-9_-]*?(?:api[_-]?key|token|secret|auth)[a-z0-9_-]*",
|
|
77915
|
+
"(?:proxy-)?authorization",
|
|
77916
|
+
"password",
|
|
77917
|
+
"passwd",
|
|
77918
|
+
"secret",
|
|
77919
|
+
"token"
|
|
77920
|
+
].join("|");
|
|
77921
|
+
var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")(?:[^"\\\\]|\\\\.)*(")`, "gi");
|
|
77922
|
+
var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')(?:[^'\\\\]|\\\\.)*(')`, "gi");
|
|
77237
77923
|
function redactSecrets(text) {
|
|
77238
|
-
return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
|
|
77924
|
+
return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(HEADER_SECRET_RE, "$1[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(OAUTH_CODE_RE, "$1[REDACTED]").replace(FORM_PASSWORD_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
|
|
77239
77925
|
}
|
|
77240
77926
|
function truncateErrorMessage(text, max = DEFAULT_ERROR_MESSAGE_MAX) {
|
|
77241
77927
|
const str = text === null || text === void 0 ? "" : String(text);
|
|
@@ -82276,7 +82962,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
82276
82962
|
var NONE = 0;
|
|
82277
82963
|
var ASSUMED = 1;
|
|
82278
82964
|
var PROVEN = 2;
|
|
82279
|
-
function isRecursive(inst, stack,
|
|
82965
|
+
function isRecursive(inst, stack, resolve3) {
|
|
82280
82966
|
const cached2 = recursive.get(inst);
|
|
82281
82967
|
if (cached2 !== void 0)
|
|
82282
82968
|
return cached2 ? PROVEN : NONE;
|
|
@@ -82286,7 +82972,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
82286
82972
|
let result = NONE;
|
|
82287
82973
|
const check2 = (child) => {
|
|
82288
82974
|
if (result !== PROVEN && child?._zod) {
|
|
82289
|
-
const answer = isRecursive(child, stack,
|
|
82975
|
+
const answer = isRecursive(child, stack, resolve3);
|
|
82290
82976
|
if (answer > result)
|
|
82291
82977
|
result = answer;
|
|
82292
82978
|
}
|
|
@@ -82297,7 +82983,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
82297
82983
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
82298
82984
|
if (spread && !desc.enumerable)
|
|
82299
82985
|
continue;
|
|
82300
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
82986
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve3) : NONE;
|
|
82301
82987
|
if (child > answer)
|
|
82302
82988
|
answer = child;
|
|
82303
82989
|
}
|
|
@@ -82361,7 +83047,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
82361
83047
|
break;
|
|
82362
83048
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
82363
83049
|
case "lazy": {
|
|
82364
|
-
const inner = def._cachedInner ?? (
|
|
83050
|
+
const inner = def._cachedInner ?? (resolve3 ? inst._zod.innerType : void 0);
|
|
82365
83051
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
82366
83052
|
break;
|
|
82367
83053
|
}
|
|
@@ -97043,17 +97729,73 @@ Hint: ${err.hint}`);
|
|
|
97043
97729
|
}
|
|
97044
97730
|
throw err;
|
|
97045
97731
|
}
|
|
97732
|
+
function mcpRequestFrom(args) {
|
|
97733
|
+
const ctx = args.at(-1);
|
|
97734
|
+
if (typeof ctx !== "object" || ctx === null)
|
|
97735
|
+
return void 0;
|
|
97736
|
+
const req = ctx.mcpReq;
|
|
97737
|
+
if (typeof req !== "object" || req === null)
|
|
97738
|
+
return void 0;
|
|
97739
|
+
return typeof req.notify === "function" ? req : void 0;
|
|
97740
|
+
}
|
|
97741
|
+
function callSignalFrom(args) {
|
|
97742
|
+
const ctx = args.at(-1);
|
|
97743
|
+
if (typeof ctx !== "object" || ctx === null)
|
|
97744
|
+
return void 0;
|
|
97745
|
+
const req = ctx.mcpReq;
|
|
97746
|
+
if (typeof req !== "object" || req === null)
|
|
97747
|
+
return void 0;
|
|
97748
|
+
const signal = req.signal;
|
|
97749
|
+
return signal instanceof AbortSignal ? signal : void 0;
|
|
97750
|
+
}
|
|
97751
|
+
function declaredCapabilitiesFrom(server) {
|
|
97752
|
+
const inner = server.server;
|
|
97753
|
+
if (typeof inner !== "object" || inner === null)
|
|
97754
|
+
return void 0;
|
|
97755
|
+
const read = inner.getClientCapabilities;
|
|
97756
|
+
if (typeof read !== "function")
|
|
97757
|
+
return void 0;
|
|
97758
|
+
try {
|
|
97759
|
+
const declared = read.call(inner);
|
|
97760
|
+
return typeof declared === "object" && declared !== null ? declared : void 0;
|
|
97761
|
+
} catch {
|
|
97762
|
+
return void 0;
|
|
97763
|
+
}
|
|
97764
|
+
}
|
|
97046
97765
|
function surfaceToolHints(server) {
|
|
97047
97766
|
const register2 = server.registerTool.bind(server);
|
|
97048
|
-
server.registerTool = (name, config2, cb) => register2(name, config2, (...args) =>
|
|
97049
|
-
|
|
97050
|
-
|
|
97051
|
-
|
|
97052
|
-
|
|
97053
|
-
|
|
97054
|
-
|
|
97055
|
-
|
|
97056
|
-
|
|
97767
|
+
server.registerTool = (name, config2, cb) => register2(name, config2, (...args) => (
|
|
97768
|
+
// THE CALLER'S CANCELLATION, made ambient for the whole handler
|
|
97769
|
+
// (`cancel/index.ts`). The SDK delivers it and the fleet ignored it:
|
|
97770
|
+
// measured against @modelcontextprotocol/server 2.0.0, a cancelled
|
|
97771
|
+
// call aborts `ctx.mcpReq.signal` with the caller's reason and the
|
|
97772
|
+
// handler runs to completion regardless — so the HTTP request stays
|
|
97773
|
+
// in flight, the child keeps burning metered CPU, and the upstream
|
|
97774
|
+
// keeps being hit for somebody who has gone. claude.ai sent 101
|
|
97775
|
+
// cancellations in the week to 2026-09-20.
|
|
97776
|
+
//
|
|
97777
|
+
// Here because this is the one wrapper every tool already passes
|
|
97778
|
+
// through: threading the signal by hand would mean editing several
|
|
97779
|
+
// hundred handlers and missing exactly the ones nobody edits.
|
|
97780
|
+
withCallSignal(callSignalFrom(args), () => (
|
|
97781
|
+
// WHAT THE CALLER CAN DO, made ambient for the same reason and in
|
|
97782
|
+
// the same place (`caller/index.ts`). Only the 2025-era half needs
|
|
97783
|
+
// the wrapper — a 2026-07-28 request answers for itself off its own
|
|
97784
|
+
// envelope — but a guarded tool that cannot tell whether the caller
|
|
97785
|
+
// can be shown a prompt returns one the SDK then refuses to deliver,
|
|
97786
|
+
// and that refusal reaches the caller as an unexplained protocol
|
|
97787
|
+
// error it had no chance to catch.
|
|
97788
|
+
withCallerCapabilities(declaredCapabilitiesFrom(server), () => {
|
|
97789
|
+
let result;
|
|
97790
|
+
try {
|
|
97791
|
+
result = cb(...args);
|
|
97792
|
+
} catch (err) {
|
|
97793
|
+
return hintResultOrRethrow(err);
|
|
97794
|
+
}
|
|
97795
|
+
return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
|
|
97796
|
+
})
|
|
97797
|
+
), mcpRequestFrom(args))
|
|
97798
|
+
));
|
|
97057
97799
|
}
|
|
97058
97800
|
async function createMcpServer(opts) {
|
|
97059
97801
|
const server = new McpServer({ name: opts.name, version: opts.version }, { supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS] });
|
|
@@ -97068,39 +97810,85 @@ async function createMcpServer(opts) {
|
|
|
97068
97810
|
}
|
|
97069
97811
|
return server;
|
|
97070
97812
|
}
|
|
97071
|
-
|
|
97813
|
+
var DEFAULT_SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
97814
|
+
var DEFAULT_REPEAT_SIGNAL_GRACE_MS = 500;
|
|
97815
|
+
function withGracefulShutdown(target, opts = {}) {
|
|
97072
97816
|
const shouldExit = opts.exit ?? true;
|
|
97817
|
+
if (opts.timeoutMs !== void 0 && !(Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0)) {
|
|
97818
|
+
throw new RangeError("withGracefulShutdown: timeoutMs must be a finite number greater than 0.");
|
|
97819
|
+
}
|
|
97820
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
|
97821
|
+
if (opts.repeatSignalGraceMs !== void 0 && !(Number.isFinite(opts.repeatSignalGraceMs) && opts.repeatSignalGraceMs >= 0)) {
|
|
97822
|
+
throw new RangeError("withGracefulShutdown: repeatSignalGraceMs must be a finite number >= 0.");
|
|
97823
|
+
}
|
|
97824
|
+
const repeatGraceMs = opts.repeatSignalGraceMs ?? DEFAULT_REPEAT_SIGNAL_GRACE_MS;
|
|
97073
97825
|
let shuttingDown = false;
|
|
97826
|
+
let firstSignalAt = 0;
|
|
97827
|
+
let exited = false;
|
|
97828
|
+
const exitOnce = () => {
|
|
97829
|
+
if (exited)
|
|
97830
|
+
return;
|
|
97831
|
+
exited = true;
|
|
97832
|
+
process.exit(0);
|
|
97833
|
+
};
|
|
97074
97834
|
const handler = (signal) => {
|
|
97075
|
-
if (shuttingDown)
|
|
97835
|
+
if (shuttingDown) {
|
|
97836
|
+
if (Date.now() - firstSignalAt < repeatGraceMs)
|
|
97837
|
+
return;
|
|
97838
|
+
if (shouldExit) {
|
|
97839
|
+
console.error(`[mcp-utils] second ${signal} during shutdown \u2014 exiting now`);
|
|
97840
|
+
exitOnce();
|
|
97841
|
+
}
|
|
97076
97842
|
return;
|
|
97843
|
+
}
|
|
97077
97844
|
shuttingDown = true;
|
|
97845
|
+
firstSignalAt = Date.now();
|
|
97846
|
+
let timer;
|
|
97847
|
+
if (shouldExit) {
|
|
97848
|
+
timer = setTimeout(() => {
|
|
97849
|
+
console.error(`[mcp-utils] graceful shutdown on ${signal} did not finish in ${timeoutMs}ms \u2014 exiting`);
|
|
97850
|
+
exitOnce();
|
|
97851
|
+
}, timeoutMs);
|
|
97852
|
+
timer.unref?.();
|
|
97853
|
+
}
|
|
97078
97854
|
void (async () => {
|
|
97079
97855
|
try {
|
|
97080
97856
|
if (opts.onSignal)
|
|
97081
97857
|
await opts.onSignal(signal);
|
|
97082
|
-
await
|
|
97858
|
+
await target.close();
|
|
97083
97859
|
} catch (err) {
|
|
97084
97860
|
console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
|
|
97085
97861
|
} finally {
|
|
97862
|
+
if (timer !== void 0)
|
|
97863
|
+
clearTimeout(timer);
|
|
97086
97864
|
if (shouldExit)
|
|
97087
|
-
|
|
97865
|
+
exitOnce();
|
|
97088
97866
|
}
|
|
97089
97867
|
})();
|
|
97090
97868
|
};
|
|
97091
97869
|
process.on("SIGINT", () => handler("SIGINT"));
|
|
97092
97870
|
process.on("SIGTERM", () => handler("SIGTERM"));
|
|
97093
97871
|
}
|
|
97094
|
-
|
|
97095
|
-
|
|
97872
|
+
function runMcp(opts) {
|
|
97873
|
+
if (opts.banner !== void 0) {
|
|
97874
|
+
console.error(opts.banner);
|
|
97875
|
+
}
|
|
97876
|
+
const spec = opts.transport ?? "stdio";
|
|
97877
|
+
const handle = serveStdio(() => createMcpServer({ ...opts, banner: void 0 }), {
|
|
97878
|
+
legacy: opts.legacy ?? "serve",
|
|
97879
|
+
onerror: opts.onerror ?? ((error62) => {
|
|
97880
|
+
console.error(`[mcp-utils] stdio server error: ${redactSecrets(error62.message)}`);
|
|
97881
|
+
}),
|
|
97882
|
+
// `'stdio'` means "let the entry make its own StdioServerTransport over
|
|
97883
|
+
// this process"; anything else is the caller's transport, which the entry
|
|
97884
|
+
// then owns (it starts it, pumps it, and closes it with the handle).
|
|
97885
|
+
...spec === "stdio" ? {} : { transport: spec }
|
|
97886
|
+
});
|
|
97096
97887
|
const shutdown = opts.shutdown ?? true;
|
|
97097
97888
|
if (shutdown !== false) {
|
|
97098
|
-
withGracefulShutdown(
|
|
97889
|
+
withGracefulShutdown(handle, shutdown === true ? {} : shutdown);
|
|
97099
97890
|
}
|
|
97100
|
-
|
|
97101
|
-
const transport = spec === "stdio" ? new StdioServerTransport() : spec;
|
|
97102
|
-
await server.connect(transport);
|
|
97103
|
-
return server;
|
|
97891
|
+
return handle;
|
|
97104
97892
|
}
|
|
97105
97893
|
|
|
97106
97894
|
// node_modules/@chrischall/mcp-utils/dist/config/index.js
|
|
@@ -97144,14 +97932,55 @@ async function loadDotenvSafely(opts = {}) {
|
|
|
97144
97932
|
}
|
|
97145
97933
|
}
|
|
97146
97934
|
|
|
97935
|
+
// node_modules/@chrischall/mcp-utils/dist/fs/confine.js
|
|
97936
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
97937
|
+
import { dirname, isAbsolute as isAbsolute2, relative, resolve as resolve2, sep } from "node:path";
|
|
97938
|
+
function isInside(root, target) {
|
|
97939
|
+
const rel = relative(root, target);
|
|
97940
|
+
return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute2(rel);
|
|
97941
|
+
}
|
|
97942
|
+
function realPathAllowingMissing(p2) {
|
|
97943
|
+
const abs = resolve2(p2);
|
|
97944
|
+
let existing = abs;
|
|
97945
|
+
const tail = [];
|
|
97946
|
+
while (!existsSync(existing)) {
|
|
97947
|
+
const parent = dirname(existing);
|
|
97948
|
+
if (parent === existing)
|
|
97949
|
+
break;
|
|
97950
|
+
tail.unshift(existing.slice(parent.length).replace(/^[/\\]+/, ""));
|
|
97951
|
+
existing = parent;
|
|
97952
|
+
}
|
|
97953
|
+
let real;
|
|
97954
|
+
try {
|
|
97955
|
+
real = realpathSync(existing);
|
|
97956
|
+
} catch {
|
|
97957
|
+
real = existing;
|
|
97958
|
+
}
|
|
97959
|
+
return tail.length > 0 ? resolve2(real, ...tail) : real;
|
|
97960
|
+
}
|
|
97961
|
+
function assertPathWithinRoots(path, roots) {
|
|
97962
|
+
const target = realPathAllowingMissing(expandPath(path));
|
|
97963
|
+
for (const root of roots) {
|
|
97964
|
+
if (isInside(realPathAllowingMissing(expandPath(root)), target))
|
|
97965
|
+
return target;
|
|
97966
|
+
}
|
|
97967
|
+
throw new Error(`Path is outside the allowed directories: ${path}`);
|
|
97968
|
+
}
|
|
97969
|
+
|
|
97147
97970
|
// node_modules/@chrischall/mcp-utils/dist/fs/output.js
|
|
97148
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
97971
|
+
import { existsSync as existsSync2, mkdirSync, writeFileSync } from "node:fs";
|
|
97149
97972
|
import { join as join2 } from "node:path";
|
|
97150
97973
|
function resolveOutputDir(perCall, envVar, opts = {}) {
|
|
97151
97974
|
const raw = perCall ?? readEnvVar(envVar, opts.env ? { env: opts.env } : {});
|
|
97152
97975
|
if (!raw)
|
|
97153
97976
|
return process.cwd();
|
|
97154
97977
|
const dir = expandPath(raw);
|
|
97978
|
+
if (perCall !== void 0 && opts.allowedRoots) {
|
|
97979
|
+
assertPathWithinRoots(dir, opts.allowedRoots);
|
|
97980
|
+
mkdirSync(dir, { recursive: true });
|
|
97981
|
+
assertPathWithinRoots(dir, opts.allowedRoots);
|
|
97982
|
+
return dir;
|
|
97983
|
+
}
|
|
97155
97984
|
mkdirSync(dir, { recursive: true });
|
|
97156
97985
|
return dir;
|
|
97157
97986
|
}
|
|
@@ -97162,11 +97991,11 @@ function sanitizeBaseName(base) {
|
|
|
97162
97991
|
function uniquePath(dir, base, ext) {
|
|
97163
97992
|
const safe = sanitizeBaseName(base);
|
|
97164
97993
|
const first = join2(dir, `${safe}.${ext}`);
|
|
97165
|
-
if (!
|
|
97994
|
+
if (!existsSync2(first))
|
|
97166
97995
|
return first;
|
|
97167
97996
|
for (let n2 = 2; ; n2++) {
|
|
97168
97997
|
const candidate = join2(dir, `${safe}-${n2}.${ext}`);
|
|
97169
|
-
if (!
|
|
97998
|
+
if (!existsSync2(candidate))
|
|
97170
97999
|
return candidate;
|
|
97171
98000
|
}
|
|
97172
98001
|
}
|
|
@@ -97269,23 +98098,78 @@ function createApiClient(opts) {
|
|
|
97269
98098
|
const retryStatuses = retry.statuses ?? [429];
|
|
97270
98099
|
const timeoutMs = opts.timeout;
|
|
97271
98100
|
const authHeader = (token) => !token ? {} : opts.tokenHeader ? { [opts.tokenHeader]: token } : { Authorization: `Bearer ${token}` };
|
|
97272
|
-
function withTimeout(run) {
|
|
97273
|
-
if (timeoutMs == null || timeoutMs <= 0)
|
|
97274
|
-
|
|
98101
|
+
async function withTimeout(run) {
|
|
98102
|
+
if (timeoutMs == null || timeoutMs <= 0) {
|
|
98103
|
+
const res2 = await run(withAmbientCancellation(void 0));
|
|
98104
|
+
return { res: res2, done: () => {
|
|
98105
|
+
}, expired: void 0 };
|
|
98106
|
+
}
|
|
97275
98107
|
const controller = new AbortController();
|
|
97276
98108
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
97277
|
-
|
|
97278
|
-
|
|
98109
|
+
let res;
|
|
98110
|
+
try {
|
|
98111
|
+
res = await run(withAmbientCancellation(controller.signal));
|
|
98112
|
+
} catch (err) {
|
|
98113
|
+
clearTimeout(timer);
|
|
98114
|
+
if (err instanceof Error && err.name === "AbortError" && controller.signal.aborted) {
|
|
97279
98115
|
throw new RequestTimeoutError(service, timeoutMs);
|
|
98116
|
+
}
|
|
97280
98117
|
throw err;
|
|
97281
|
-
}
|
|
98118
|
+
}
|
|
98119
|
+
const expired = new Promise((_resolve, reject) => {
|
|
98120
|
+
controller.signal.addEventListener("abort", () => reject(new RequestTimeoutError(service, timeoutMs)), {
|
|
98121
|
+
once: true
|
|
98122
|
+
});
|
|
98123
|
+
});
|
|
98124
|
+
expired.catch(() => {
|
|
98125
|
+
});
|
|
98126
|
+
return { res, done: () => clearTimeout(timer), expired };
|
|
98127
|
+
}
|
|
98128
|
+
async function readBody(attempt, read) {
|
|
98129
|
+
try {
|
|
98130
|
+
if (!attempt.expired)
|
|
98131
|
+
return await read(attempt.res);
|
|
98132
|
+
return await Promise.race([read(attempt.res), attempt.expired]);
|
|
98133
|
+
} catch (err) {
|
|
98134
|
+
if (err instanceof RequestTimeoutError) {
|
|
98135
|
+
attempt.res.body?.cancel().catch(() => {
|
|
98136
|
+
});
|
|
98137
|
+
}
|
|
98138
|
+
throw err;
|
|
98139
|
+
} finally {
|
|
98140
|
+
attempt.done();
|
|
98141
|
+
}
|
|
98142
|
+
}
|
|
98143
|
+
const baseParts = (() => {
|
|
98144
|
+
try {
|
|
98145
|
+
const u2 = new URL(base);
|
|
98146
|
+
return { origin: u2.origin, username: u2.username, password: u2.password };
|
|
98147
|
+
} catch {
|
|
98148
|
+
return void 0;
|
|
98149
|
+
}
|
|
98150
|
+
})();
|
|
98151
|
+
const baseOrigin = baseParts?.origin;
|
|
98152
|
+
function resolveUrl(path, query) {
|
|
98153
|
+
const url4 = `${base}${path}${query}`;
|
|
98154
|
+
if (baseOrigin === void 0)
|
|
98155
|
+
return url4;
|
|
98156
|
+
let parsed;
|
|
98157
|
+
try {
|
|
98158
|
+
parsed = new URL(url4);
|
|
98159
|
+
} catch {
|
|
98160
|
+
throw new Error(`Refusing request to ${service}: path ${JSON.stringify(path)} does not form a valid URL.`);
|
|
98161
|
+
}
|
|
98162
|
+
if (parsed.origin !== baseOrigin || parsed.username !== baseParts?.username || parsed.password !== baseParts?.password) {
|
|
98163
|
+
throw new Error(`Refusing request to ${service}: path ${JSON.stringify(path)} resolves outside the base origin ${baseOrigin}. Paths must be relative to baseUrl (start them with "/").`);
|
|
98164
|
+
}
|
|
98165
|
+
return url4;
|
|
97282
98166
|
}
|
|
97283
98167
|
async function send(method, path, opt) {
|
|
97284
98168
|
const isMultipart = opt.formData !== void 0;
|
|
97285
98169
|
const hasJsonBody = !isMultipart && opt.body !== void 0;
|
|
97286
98170
|
const reqBody = isMultipart ? opt.formData : hasJsonBody ? JSON.stringify(opt.body) : void 0;
|
|
97287
98171
|
const query = opt.query ? buildQueryString(opt.query) : "";
|
|
97288
|
-
const url4 =
|
|
98172
|
+
const url4 = resolveUrl(path, query);
|
|
97289
98173
|
const bodyInit = reqBody !== void 0 ? { body: reqBody } : {};
|
|
97290
98174
|
const fetchWith = (token, signal) => doFetch(url4, {
|
|
97291
98175
|
method,
|
|
@@ -97302,8 +98186,10 @@ function createApiClient(opts) {
|
|
|
97302
98186
|
const once = () => withTimeout((signal) => opts.tokenManager ? opts.tokenManager.withAuth((token) => fetchWith(token, signal)) : (async () => fetchWith(await opts.getToken?.() || void 0, signal))());
|
|
97303
98187
|
let attempt = 0;
|
|
97304
98188
|
for (; ; ) {
|
|
97305
|
-
const
|
|
98189
|
+
const current = await once();
|
|
98190
|
+
const res = current.res;
|
|
97306
98191
|
if (retryStatuses.includes(res.status) && attempt < retry.count) {
|
|
98192
|
+
current.done();
|
|
97307
98193
|
attempt += 1;
|
|
97308
98194
|
const delay = retry.honorRetryAfter ? parseRetryAfterMs(res.headers.get("retry-after"), {
|
|
97309
98195
|
defaultMs: retry.delayMs,
|
|
@@ -97312,18 +98198,21 @@ function createApiClient(opts) {
|
|
|
97312
98198
|
await sleep2(delay);
|
|
97313
98199
|
continue;
|
|
97314
98200
|
}
|
|
97315
|
-
return
|
|
98201
|
+
return current;
|
|
97316
98202
|
}
|
|
97317
98203
|
}
|
|
97318
98204
|
async function fetchJson(method, path, opt = {}) {
|
|
97319
|
-
const
|
|
98205
|
+
const attempt = await send(method, path, opt);
|
|
98206
|
+
const res = attempt.res;
|
|
98207
|
+
if (res.status === 401 || res.status === 429 || res.status === 204)
|
|
98208
|
+
attempt.done();
|
|
97320
98209
|
if (res.status === 401)
|
|
97321
98210
|
throw unauthorized();
|
|
97322
98211
|
if (res.status === 429)
|
|
97323
98212
|
throw rateLimited();
|
|
97324
98213
|
if (res.status === 204)
|
|
97325
98214
|
return void 0;
|
|
97326
|
-
const text = await
|
|
98215
|
+
const text = await readBody(attempt, (r2) => r2.text());
|
|
97327
98216
|
if (!res.ok) {
|
|
97328
98217
|
throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
|
|
97329
98218
|
}
|
|
@@ -97333,12 +98222,15 @@ function createApiClient(opts) {
|
|
|
97333
98222
|
}
|
|
97334
98223
|
async function fetchHtml(method, path, opt = {}) {
|
|
97335
98224
|
const headers = { Accept: "text/html,*/*", ...opt.headers };
|
|
97336
|
-
const
|
|
98225
|
+
const attempt = await send(method, path, { ...opt, headers });
|
|
98226
|
+
const res = attempt.res;
|
|
98227
|
+
if (res.status === 401 || res.status === 429)
|
|
98228
|
+
attempt.done();
|
|
97337
98229
|
if (res.status === 401)
|
|
97338
98230
|
throw unauthorized();
|
|
97339
98231
|
if (res.status === 429)
|
|
97340
98232
|
throw rateLimited();
|
|
97341
|
-
const text = await
|
|
98233
|
+
const text = await readBody(attempt, (r2) => r2.text());
|
|
97342
98234
|
if (!res.ok) {
|
|
97343
98235
|
throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
|
|
97344
98236
|
}
|
|
@@ -97346,16 +98238,23 @@ function createApiClient(opts) {
|
|
|
97346
98238
|
}
|
|
97347
98239
|
async function fetchRaw(method, path, opt = {}) {
|
|
97348
98240
|
const headers = { Accept: "*/*", ...opt.headers };
|
|
97349
|
-
const
|
|
98241
|
+
const attempt = await send(method, path, { ...opt, headers });
|
|
98242
|
+
const res = attempt.res;
|
|
98243
|
+
if (res.status === 401 || res.status === 429)
|
|
98244
|
+
attempt.done();
|
|
97350
98245
|
if (res.status === 401)
|
|
97351
98246
|
throw unauthorized();
|
|
97352
98247
|
if (res.status === 429)
|
|
97353
98248
|
throw rateLimited();
|
|
97354
98249
|
if (!res.ok) {
|
|
97355
|
-
const text = await
|
|
98250
|
+
const text = await readBody(attempt, (r2) => r2.text()).catch((err) => {
|
|
98251
|
+
if (err instanceof RequestTimeoutError)
|
|
98252
|
+
throw err;
|
|
98253
|
+
return "";
|
|
98254
|
+
});
|
|
97356
98255
|
throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
|
|
97357
98256
|
}
|
|
97358
|
-
const bytes = new Uint8Array(await
|
|
98257
|
+
const bytes = new Uint8Array(await readBody(attempt, (r2) => r2.arrayBuffer()));
|
|
97359
98258
|
return {
|
|
97360
98259
|
status: res.status,
|
|
97361
98260
|
contentType: res.headers.get("content-type"),
|
|
@@ -97409,10 +98308,10 @@ var pageSchema = {
|
|
|
97409
98308
|
};
|
|
97410
98309
|
|
|
97411
98310
|
// src/client.ts
|
|
97412
|
-
import { dirname, join as join3 } from "path";
|
|
98311
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
97413
98312
|
import { fileURLToPath } from "url";
|
|
97414
98313
|
try {
|
|
97415
|
-
const dir =
|
|
98314
|
+
const dir = dirname2(fileURLToPath(import.meta.url));
|
|
97416
98315
|
await loadDotenvSafely({ path: join3(dir, "..", ".env"), override: false });
|
|
97417
98316
|
} catch {
|
|
97418
98317
|
}
|
|
@@ -98588,7 +99487,7 @@ function registerUtilityTools(server, client2) {
|
|
|
98588
99487
|
// src/index.ts
|
|
98589
99488
|
await runMcp({
|
|
98590
99489
|
name: "splitwise-mcp",
|
|
98591
|
-
version: "3.
|
|
99490
|
+
version: "3.1.1",
|
|
98592
99491
|
// x-release-please-version
|
|
98593
99492
|
deps: client,
|
|
98594
99493
|
banner: "[splitwise-mcp] This project was developed and is maintained by AI (Claude Sonnet 4.6). Use at your own discretion.",
|