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/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, resolve2) {
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, resolve2);
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, resolve2) : NONE2;
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 ?? (resolve2 ? inst._zod.innerType : void 0);
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((resolve2) => (imageKey.startsWith("g_") ? page.commonObjs : page.objs).get(imageKey, resolve2));
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((resolve2) => {
63002
- canvas.toBlob(resolve2);
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((resolve2, reject) => {
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
- resolve2();
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((resolve2, reject) => {
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 resolve2(manualInputRequiredValue(decoded));
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 resolve2(this._resolveNonCompleteResult(decoded, flow));
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) resolve2(parseResult.data);
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 = resolve2.call(this, root, ref);
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 resolve2(root, ref) {
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 resolve2(baseURI, relativeURI, options) {
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, relative, options, skipNormalization) {
71908
+ function resolveComponent(base, relative2, options, skipNormalization) {
71822
71909
  const target = {};
71823
71910
  if (!skipNormalization) {
71824
71911
  base = parse3(serialize(base, options), options);
71825
- relative = parse3(serialize(relative, options), options);
71912
+ relative2 = parse3(serialize(relative2, options), options);
71826
71913
  }
71827
71914
  options = options || {};
71828
- if (!options.tolerant && relative.scheme) {
71829
- target.scheme = relative.scheme;
71830
- target.userinfo = relative.userinfo;
71831
- target.host = relative.host;
71832
- target.port = relative.port;
71833
- target.path = removeDotSegments(relative.path || "");
71834
- target.query = relative.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 (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
71837
- target.userinfo = relative.userinfo;
71838
- target.host = relative.host;
71839
- target.port = relative.port;
71840
- target.path = removeDotSegments(relative.path || "");
71841
- target.query = relative.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 (!relative.path) {
71930
+ if (!relative2.path) {
71844
71931
  target.path = base.path;
71845
- if (relative.query !== void 0) target.query = relative.query;
71932
+ if (relative2.query !== void 0) target.query = relative2.query;
71846
71933
  else target.query = base.query;
71847
71934
  } else {
71848
- if (relative.path[0] === "/") target.path = removeDotSegments(relative.path);
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 = "/" + relative.path;
71851
- else if (!base.path) target.path = relative.path;
71852
- else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
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 = relative.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 = relative.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: resolve2,
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((resolve2, reject) => {
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
- resolve2();
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
- resolve2();
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 = /([?&](?:access_token|refresh_token|client_secret|api_?key|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
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 = "access_token|refresh_token|client_secret|api_?key|password|passwd|secret|token";
77235
- var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")[^"]*(")`, "gi");
77236
- var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')[^']*(')`, "gi");
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, resolve2) {
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, resolve2);
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, resolve2) : NONE;
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 ?? (resolve2 ? inst._zod.innerType : void 0);
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
- let result;
97050
- try {
97051
- result = cb(...args);
97052
- } catch (err) {
97053
- return hintResultOrRethrow(err);
97054
- }
97055
- return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
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
- function withGracefulShutdown(server, opts = {}) {
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 server.close();
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
- process.exit(0);
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
- async function runMcp(opts) {
97095
- const server = await createMcpServer(opts);
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(server, shutdown === true ? {} : shutdown);
97889
+ withGracefulShutdown(handle, shutdown === true ? {} : shutdown);
97099
97890
  }
97100
- const spec = opts.transport ?? "stdio";
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 (!existsSync(first))
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 (!existsSync(candidate))
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
- return run(void 0);
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
- return run(controller.signal).catch((err) => {
97278
- if (err instanceof Error && err.name === "AbortError")
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
- }).finally(() => clearTimeout(timer));
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 = `${base}${path}${query}`;
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 res = await once();
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 res;
98201
+ return current;
97316
98202
  }
97317
98203
  }
97318
98204
  async function fetchJson(method, path, opt = {}) {
97319
- const res = await send(method, path, opt);
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 res.text();
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 res = await send(method, path, { ...opt, headers });
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 res.text();
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 res = await send(method, path, { ...opt, headers });
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 res.text().catch(() => "");
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 res.arrayBuffer());
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 = dirname(fileURLToPath(import.meta.url));
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.0.0",
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.",