@chrischall/gemini-mcp 2.1.1 → 2.1.3

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
10
- "version": "2.1.1"
10
+ "version": "2.1.3"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Gemini Images",
16
16
  "source": "./",
17
17
  "description": "Generate and edit images with Google Gemini image models (Nano Banana / Nano Banana Pro) via natural language prompts",
18
- "version": "2.1.1",
18
+ "version": "2.1.3",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gemini-mcp",
3
3
  "displayName": "Gemini Images",
4
- "version": "2.1.1",
4
+ "version": "2.1.3",
5
5
  "description": "MCP server for Google Gemini image generation and editing — generate and edit images via the Gemini API",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/dist/bundle.js CHANGED
@@ -41,6 +41,41 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
41
41
  mod
42
42
  ));
43
43
 
44
+ // node_modules/@chrischall/mcp-utils/dist/cancel/index.js
45
+ import { AsyncLocalStorage } from "node:async_hooks";
46
+ function withCallSignal(signal, fn, request) {
47
+ return signal ? storage.run({ signal, ...request ? { request } : {} }, fn) : fn();
48
+ }
49
+ function currentCallSignal() {
50
+ return storage.getStore()?.signal;
51
+ }
52
+ function withAmbientCancellation(own2) {
53
+ const ambient = currentCallSignal();
54
+ if (!ambient)
55
+ return own2;
56
+ if (!own2)
57
+ return ambient;
58
+ return AbortSignal.any([own2, ambient]);
59
+ }
60
+ var storage;
61
+ var init_cancel = __esm({
62
+ "node_modules/@chrischall/mcp-utils/dist/cancel/index.js"() {
63
+ storage = new AsyncLocalStorage();
64
+ }
65
+ });
66
+
67
+ // node_modules/@chrischall/mcp-utils/dist/caller/index.js
68
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
69
+ function withCallerCapabilities(capabilities, fn) {
70
+ return capabilities ? storage2.run(capabilities, fn) : fn();
71
+ }
72
+ var storage2;
73
+ var init_caller = __esm({
74
+ "node_modules/@chrischall/mcp-utils/dist/caller/index.js"() {
75
+ storage2 = new AsyncLocalStorage2();
76
+ }
77
+ });
78
+
44
79
  // node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
45
80
  var __create2, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __getProtoOf2, __hasOwnProp2, __commonJSMin, __exportAll, __copyProps2, __toESM2;
46
81
  var init_chunk_Br0eD_fh = __esm({
@@ -4926,7 +4961,7 @@ var require_memoizer = __commonJS({
4926
4961
  var NONE2 = 0;
4927
4962
  var ASSUMED2 = 1;
4928
4963
  var PROVEN2 = 2;
4929
- function isRecursive2(inst, stack, resolve2) {
4964
+ function isRecursive2(inst, stack, resolve4) {
4930
4965
  const cached2 = recursive2.get(inst);
4931
4966
  if (cached2 !== void 0)
4932
4967
  return cached2 ? PROVEN2 : NONE2;
@@ -4936,7 +4971,7 @@ var require_memoizer = __commonJS({
4936
4971
  let result = NONE2;
4937
4972
  const check2 = (child) => {
4938
4973
  if (result !== PROVEN2 && child?._zod) {
4939
- const answer = isRecursive2(child, stack, resolve2);
4974
+ const answer = isRecursive2(child, stack, resolve4);
4940
4975
  if (answer > result)
4941
4976
  result = answer;
4942
4977
  }
@@ -4947,7 +4982,7 @@ var require_memoizer = __commonJS({
4947
4982
  const desc = Object.getOwnPropertyDescriptor(sh, key);
4948
4983
  if (spread && !desc.enumerable)
4949
4984
  continue;
4950
- const child = desc.get ? ASSUMED2 : desc.value?._zod ? isRecursive2(desc.value, stack, resolve2) : NONE2;
4985
+ const child = desc.get ? ASSUMED2 : desc.value?._zod ? isRecursive2(desc.value, stack, resolve4) : NONE2;
4951
4986
  if (child > answer)
4952
4987
  answer = child;
4953
4988
  }
@@ -5011,7 +5046,7 @@ var require_memoizer = __commonJS({
5011
5046
  break;
5012
5047
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
5013
5048
  case "lazy": {
5014
- const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
5049
+ const inner = def._cachedInner ?? (resolve4 ? inst._zod.innerType : void 0);
5015
5050
  merge2(inner ? isRecursive2(inner, stack, false) : ASSUMED2);
5016
5051
  break;
5017
5052
  }
@@ -26845,14 +26880,14 @@ function inputRequiredRoundsExceededMessage(method, maxRounds) {
26845
26880
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
26846
26881
  }
26847
26882
  function sleep(ms, signal) {
26848
- return new Promise((resolve2, reject) => {
26883
+ return new Promise((resolve4, reject) => {
26849
26884
  if (signal?.aborted) {
26850
26885
  reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
26851
26886
  return;
26852
26887
  }
26853
26888
  const timer = setTimeout(() => {
26854
26889
  signal?.removeEventListener("abort", onAbort);
26855
- resolve2();
26890
+ resolve4();
26856
26891
  }, ms);
26857
26892
  const onAbort = () => {
26858
26893
  clearTimeout(timer);
@@ -28648,7 +28683,7 @@ var init_src_CX2iR2pK = __esm({
28648
28683
  const flowStartedAt = Date.now();
28649
28684
  let onAbort;
28650
28685
  let cleanupMessageId;
28651
- return new Promise((resolve2, reject) => {
28686
+ return new Promise((resolve4, reject) => {
28652
28687
  const earlyReject = (error62) => {
28653
28688
  reject(error62);
28654
28689
  };
@@ -28716,7 +28751,7 @@ var init_src_CX2iR2pK = __esm({
28716
28751
  }
28717
28752
  if (decoded.kind === "invalid") return reject(decoded.error);
28718
28753
  if (decoded.kind === "input_required") {
28719
- if (options?.allowInputRequired === true) return resolve2(manualInputRequiredValue(decoded));
28754
+ if (options?.allowInputRequired === true) return resolve4(manualInputRequiredValue(decoded));
28720
28755
  const flow = {
28721
28756
  codec: codec2,
28722
28757
  request,
@@ -28728,11 +28763,11 @@ var init_src_CX2iR2pK = __esm({
28728
28763
  params
28729
28764
  }, resultSchema, legOptions)
28730
28765
  };
28731
- return resolve2(this._resolveNonCompleteResult(decoded, flow));
28766
+ return resolve4(this._resolveNonCompleteResult(decoded, flow));
28732
28767
  }
28733
28768
  const result = decoded.result;
28734
28769
  validateStandardSchema(resultSchema, result).then((parseResult) => {
28735
- if (parseResult.success) resolve2(parseResult.data);
28770
+ if (parseResult.success) resolve4(parseResult.data);
28736
28771
  else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
28737
28772
  }, reject);
28738
28773
  });
@@ -31548,7 +31583,7 @@ var init_ajvProvider_CEoC_sr = __esm({
31548
31583
  ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
31549
31584
  const schOrFunc = root.refs[ref];
31550
31585
  if (schOrFunc) return schOrFunc;
31551
- let _sch = resolve2.call(this, root, ref);
31586
+ let _sch = resolve4.call(this, root, ref);
31552
31587
  if (_sch === void 0) {
31553
31588
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
31554
31589
  const { schemaId } = this.opts;
@@ -31574,7 +31609,7 @@ var init_ajvProvider_CEoC_sr = __esm({
31574
31609
  function sameSchemaEnv(s1, s2) {
31575
31610
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
31576
31611
  }
31577
- function resolve2(root, ref) {
31612
+ function resolve4(root, ref) {
31578
31613
  let sch;
31579
31614
  while (typeof (sch = this.refs[ref]) == "string") ref = sch;
31580
31615
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
@@ -32024,47 +32059,47 @@ var init_ajvProvider_CEoC_sr = __esm({
32024
32059
  else if (typeof uri === "object") uri = parse3(serialize(uri, options), options);
32025
32060
  return uri;
32026
32061
  }
32027
- function resolve2(baseURI, relativeURI, options) {
32062
+ function resolve4(baseURI, relativeURI, options) {
32028
32063
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
32029
32064
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
32030
32065
  schemelessOptions.skipEscape = true;
32031
32066
  return serialize(resolved, schemelessOptions);
32032
32067
  }
32033
- function resolveComponent(base, relative, options, skipNormalization) {
32068
+ function resolveComponent(base, relative2, options, skipNormalization) {
32034
32069
  const target = {};
32035
32070
  if (!skipNormalization) {
32036
32071
  base = parse3(serialize(base, options), options);
32037
- relative = parse3(serialize(relative, options), options);
32072
+ relative2 = parse3(serialize(relative2, options), options);
32038
32073
  }
32039
32074
  options = options || {};
32040
- if (!options.tolerant && relative.scheme) {
32041
- target.scheme = relative.scheme;
32042
- target.userinfo = relative.userinfo;
32043
- target.host = relative.host;
32044
- target.port = relative.port;
32045
- target.path = removeDotSegments(relative.path || "");
32046
- target.query = relative.query;
32075
+ if (!options.tolerant && relative2.scheme) {
32076
+ target.scheme = relative2.scheme;
32077
+ target.userinfo = relative2.userinfo;
32078
+ target.host = relative2.host;
32079
+ target.port = relative2.port;
32080
+ target.path = removeDotSegments(relative2.path || "");
32081
+ target.query = relative2.query;
32047
32082
  } else {
32048
- if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
32049
- target.userinfo = relative.userinfo;
32050
- target.host = relative.host;
32051
- target.port = relative.port;
32052
- target.path = removeDotSegments(relative.path || "");
32053
- target.query = relative.query;
32083
+ if (relative2.userinfo !== void 0 || relative2.host !== void 0 || relative2.port !== void 0) {
32084
+ target.userinfo = relative2.userinfo;
32085
+ target.host = relative2.host;
32086
+ target.port = relative2.port;
32087
+ target.path = removeDotSegments(relative2.path || "");
32088
+ target.query = relative2.query;
32054
32089
  } else {
32055
- if (!relative.path) {
32090
+ if (!relative2.path) {
32056
32091
  target.path = base.path;
32057
- if (relative.query !== void 0) target.query = relative.query;
32092
+ if (relative2.query !== void 0) target.query = relative2.query;
32058
32093
  else target.query = base.query;
32059
32094
  } else {
32060
- if (relative.path[0] === "/") target.path = removeDotSegments(relative.path);
32095
+ if (relative2.path[0] === "/") target.path = removeDotSegments(relative2.path);
32061
32096
  else {
32062
- if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" + relative.path;
32063
- else if (!base.path) target.path = relative.path;
32064
- else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
32097
+ if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" + relative2.path;
32098
+ else if (!base.path) target.path = relative2.path;
32099
+ else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative2.path;
32065
32100
  target.path = removeDotSegments(target.path);
32066
32101
  }
32067
- target.query = relative.query;
32102
+ target.query = relative2.query;
32068
32103
  }
32069
32104
  target.userinfo = base.userinfo;
32070
32105
  target.host = base.host;
@@ -32072,7 +32107,7 @@ var init_ajvProvider_CEoC_sr = __esm({
32072
32107
  }
32073
32108
  target.scheme = base.scheme;
32074
32109
  }
32075
- target.fragment = relative.fragment;
32110
+ target.fragment = relative2.fragment;
32076
32111
  return target;
32077
32112
  }
32078
32113
  function equal(uriA, uriB, options) {
@@ -32198,7 +32233,7 @@ var init_ajvProvider_CEoC_sr = __esm({
32198
32233
  const fastUri = {
32199
32234
  SCHEMES,
32200
32235
  normalize,
32201
- resolve: resolve2,
32236
+ resolve: resolve4,
32202
32237
  resolveComponent,
32203
32238
  equal,
32204
32239
  serialize,
@@ -37890,7 +37925,7 @@ var init_stdio = __esm({
37890
37925
  }
37891
37926
  send(message) {
37892
37927
  if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
37893
- return new Promise((resolve2, reject) => {
37928
+ return new Promise((resolve4, reject) => {
37894
37929
  const json2 = serializeMessage(message);
37895
37930
  let settled = false;
37896
37931
  const onError = (error62) => {
@@ -37905,14 +37940,14 @@ var init_stdio = __esm({
37905
37940
  settled = true;
37906
37941
  this._stdout.off("error", onError);
37907
37942
  this._stdout.off("drain", onDrain);
37908
- resolve2();
37943
+ resolve4();
37909
37944
  };
37910
37945
  this._stdout.once("error", onError);
37911
37946
  if (this._stdout.write(json2)) {
37912
37947
  if (settled) return;
37913
37948
  settled = true;
37914
37949
  this._stdout.off("error", onError);
37915
- resolve2();
37950
+ resolve4();
37916
37951
  } else if (!settled) this._stdout.once("drain", onDrain);
37917
37952
  });
37918
37953
  }
@@ -37966,14 +38001,14 @@ var init_stdio = __esm({
37966
38001
  */
37967
38002
  async whenRequestsAnswered(timeoutMs) {
37968
38003
  if (this._closed || this._pendingRequests.size === 0) return true;
37969
- return await new Promise((resolve2) => {
38004
+ return await new Promise((resolve4) => {
37970
38005
  const waiter = () => {
37971
38006
  clearTimeout(timer);
37972
- resolve2(true);
38007
+ resolve4(true);
37973
38008
  };
37974
38009
  const timer = setTimeout(() => {
37975
38010
  this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
37976
- resolve2(false);
38011
+ resolve4(false);
37977
38012
  }, timeoutMs);
37978
38013
  this._drainWaiters.push(waiter);
37979
38014
  });
@@ -38013,7 +38048,7 @@ var init_dist = __esm({
38013
38048
 
38014
38049
  // node_modules/@chrischall/mcp-utils/dist/errors/index.js
38015
38050
  function redactSecrets(text) {
38016
- 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]");
38051
+ 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]");
38017
38052
  }
38018
38053
  function truncateErrorMessage(text, max = DEFAULT_ERROR_MESSAGE_MAX) {
38019
38054
  const str = text === null || text === void 0 ? "" : String(text);
@@ -38027,7 +38062,7 @@ function messageOf(err) {
38027
38062
  return err.message;
38028
38063
  return String(err);
38029
38064
  }
38030
- var DEFAULT_ERROR_MESSAGE_MAX, McpToolError, BEARER_RE, JWT_RE, BASIC_AUTH_RE, SET_COOKIE_RE, COOKIE_HEADER_RE, API_KEY_RE, QUERY_SECRET_RE, AWS_SIGV4_RE, JSON_SECRET_KEYS, JSON_SECRET_DQ_RE, JSON_SECRET_SQ_RE;
38065
+ var DEFAULT_ERROR_MESSAGE_MAX, McpToolError, BEARER_RE, JWT_RE, BASIC_AUTH_RE, SET_COOKIE_RE, COOKIE_HEADER_RE, API_KEY_RE, QUERY_SECRET_RE, OAUTH_CODE_RE, FORM_PASSWORD_RE, HEADER_SECRET_RE, AWS_SIGV4_RE, JSON_SECRET_KEYS, JSON_SECRET_DQ_RE, JSON_SECRET_SQ_RE;
38031
38066
  var init_errors = __esm({
38032
38067
  "node_modules/@chrischall/mcp-utils/dist/errors/index.js"() {
38033
38068
  DEFAULT_ERROR_MESSAGE_MAX = 500;
@@ -38061,11 +38096,26 @@ var init_errors = __esm({
38061
38096
  "whsec_[A-Za-z0-9]{16,}\\b"
38062
38097
  // webhook signing secret (Stripe-style)
38063
38098
  ].map((p) => `\\b${p}`).join("|"), "g");
38064
- QUERY_SECRET_RE = /([?&](?:access_token|refresh_token|client_secret|api_?key|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
38099
+ 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;
38100
+ OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
38101
+ FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
38102
+ HEADER_SECRET_RE = /(\b(?:x[-_][a-z0-9_-]*?(?:api[-_]?key|token|secret|auth)[a-z0-9_-]*|api[-_]?key)\s*:\s*)[^\s,;"'<>`]+/gi;
38065
38103
  AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
38066
- JSON_SECRET_KEYS = "access_token|refresh_token|client_secret|api_?key|password|passwd|secret|token";
38067
- JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")[^"]*(")`, "gi");
38068
- JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')[^']*(')`, "gi");
38104
+ JSON_SECRET_KEYS = [
38105
+ "(?:access|refresh|id|auth|session|bearer|csrf|xsrf)[_-]?token",
38106
+ "client[_-]?secret",
38107
+ "api[_-]?secret",
38108
+ "(?:x[_-])?api[_-]?key",
38109
+ "private[_-]?key",
38110
+ "x[_-][a-z0-9_-]*?(?:api[_-]?key|token|secret|auth)[a-z0-9_-]*",
38111
+ "(?:proxy-)?authorization",
38112
+ "password",
38113
+ "passwd",
38114
+ "secret",
38115
+ "token"
38116
+ ].join("|");
38117
+ JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")(?:[^"\\\\]|\\\\.)*(")`, "gi");
38118
+ JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')(?:[^'\\\\]|\\\\.)*(')`, "gi");
38069
38119
  }
38070
38120
  });
38071
38121
 
@@ -42565,7 +42615,7 @@ function isRef(value) {
42565
42615
  function cloneIssues(issues) {
42566
42616
  return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
42567
42617
  }
42568
- function isRecursive(inst, stack, resolve2) {
42618
+ function isRecursive(inst, stack, resolve4) {
42569
42619
  const cached2 = recursive.get(inst);
42570
42620
  if (cached2 !== void 0)
42571
42621
  return cached2 ? PROVEN : NONE;
@@ -42575,7 +42625,7 @@ function isRecursive(inst, stack, resolve2) {
42575
42625
  let result = NONE;
42576
42626
  const check2 = (child) => {
42577
42627
  if (result !== PROVEN && child?._zod) {
42578
- const answer = isRecursive(child, stack, resolve2);
42628
+ const answer = isRecursive(child, stack, resolve4);
42579
42629
  if (answer > result)
42580
42630
  result = answer;
42581
42631
  }
@@ -42586,7 +42636,7 @@ function isRecursive(inst, stack, resolve2) {
42586
42636
  const desc = Object.getOwnPropertyDescriptor(sh, key);
42587
42637
  if (spread && !desc.enumerable)
42588
42638
  continue;
42589
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
42639
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve4) : NONE;
42590
42640
  if (child > answer)
42591
42641
  answer = child;
42592
42642
  }
@@ -42650,7 +42700,7 @@ function isRecursive(inst, stack, resolve2) {
42650
42700
  break;
42651
42701
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
42652
42702
  case "lazy": {
42653
- const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
42703
+ const inner = def._cachedInner ?? (resolve4 ? inst._zod.innerType : void 0);
42654
42704
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
42655
42705
  break;
42656
42706
  }
@@ -58466,6 +58516,7 @@ var init_response = __esm({
58466
58516
  var init_confirmation = __esm({
58467
58517
  "node_modules/@chrischall/mcp-utils/dist/server/confirmation.js"() {
58468
58518
  init_dist();
58519
+ init_caller();
58469
58520
  init_response();
58470
58521
  }
58471
58522
  });
@@ -58479,17 +58530,73 @@ Hint: ${err.hint}`);
58479
58530
  }
58480
58531
  throw err;
58481
58532
  }
58533
+ function mcpRequestFrom(args) {
58534
+ const ctx = args.at(-1);
58535
+ if (typeof ctx !== "object" || ctx === null)
58536
+ return void 0;
58537
+ const req = ctx.mcpReq;
58538
+ if (typeof req !== "object" || req === null)
58539
+ return void 0;
58540
+ return typeof req.notify === "function" ? req : void 0;
58541
+ }
58542
+ function callSignalFrom(args) {
58543
+ const ctx = args.at(-1);
58544
+ if (typeof ctx !== "object" || ctx === null)
58545
+ return void 0;
58546
+ const req = ctx.mcpReq;
58547
+ if (typeof req !== "object" || req === null)
58548
+ return void 0;
58549
+ const signal = req.signal;
58550
+ return signal instanceof AbortSignal ? signal : void 0;
58551
+ }
58552
+ function declaredCapabilitiesFrom(server) {
58553
+ const inner = server.server;
58554
+ if (typeof inner !== "object" || inner === null)
58555
+ return void 0;
58556
+ const read = inner.getClientCapabilities;
58557
+ if (typeof read !== "function")
58558
+ return void 0;
58559
+ try {
58560
+ const declared = read.call(inner);
58561
+ return typeof declared === "object" && declared !== null ? declared : void 0;
58562
+ } catch {
58563
+ return void 0;
58564
+ }
58565
+ }
58482
58566
  function surfaceToolHints(server) {
58483
58567
  const register2 = server.registerTool.bind(server);
58484
- server.registerTool = (name, config2, cb) => register2(name, config2, (...args) => {
58485
- let result;
58486
- try {
58487
- result = cb(...args);
58488
- } catch (err) {
58489
- return hintResultOrRethrow(err);
58490
- }
58491
- return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
58492
- });
58568
+ server.registerTool = (name, config2, cb) => register2(name, config2, (...args) => (
58569
+ // THE CALLER'S CANCELLATION, made ambient for the whole handler
58570
+ // (`cancel/index.ts`). The SDK delivers it and the fleet ignored it:
58571
+ // measured against @modelcontextprotocol/server 2.0.0, a cancelled
58572
+ // call aborts `ctx.mcpReq.signal` with the caller's reason and the
58573
+ // handler runs to completion regardless — so the HTTP request stays
58574
+ // in flight, the child keeps burning metered CPU, and the upstream
58575
+ // keeps being hit for somebody who has gone. claude.ai sent 101
58576
+ // cancellations in the week to 2026-09-20.
58577
+ //
58578
+ // Here because this is the one wrapper every tool already passes
58579
+ // through: threading the signal by hand would mean editing several
58580
+ // hundred handlers and missing exactly the ones nobody edits.
58581
+ withCallSignal(callSignalFrom(args), () => (
58582
+ // WHAT THE CALLER CAN DO, made ambient for the same reason and in
58583
+ // the same place (`caller/index.ts`). Only the 2025-era half needs
58584
+ // the wrapper — a 2026-07-28 request answers for itself off its own
58585
+ // envelope — but a guarded tool that cannot tell whether the caller
58586
+ // can be shown a prompt returns one the SDK then refuses to deliver,
58587
+ // and that refusal reaches the caller as an unexplained protocol
58588
+ // error it had no chance to catch.
58589
+ withCallerCapabilities(declaredCapabilitiesFrom(server), () => {
58590
+ let result;
58591
+ try {
58592
+ result = cb(...args);
58593
+ } catch (err) {
58594
+ return hintResultOrRethrow(err);
58595
+ }
58596
+ return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
58597
+ })
58598
+ ), mcpRequestFrom(args))
58599
+ ));
58493
58600
  }
58494
58601
  async function createMcpServer(opts) {
58495
58602
  const server = new McpServer({ name: opts.name, version: opts.version }, { supportedProtocolVersions: [...SERVER_PROTOCOL_VERSIONS] });
@@ -58506,11 +58613,43 @@ async function createMcpServer(opts) {
58506
58613
  }
58507
58614
  function withGracefulShutdown(target, opts = {}) {
58508
58615
  const shouldExit = opts.exit ?? true;
58616
+ if (opts.timeoutMs !== void 0 && !(Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0)) {
58617
+ throw new RangeError("withGracefulShutdown: timeoutMs must be a finite number greater than 0.");
58618
+ }
58619
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
58620
+ if (opts.repeatSignalGraceMs !== void 0 && !(Number.isFinite(opts.repeatSignalGraceMs) && opts.repeatSignalGraceMs >= 0)) {
58621
+ throw new RangeError("withGracefulShutdown: repeatSignalGraceMs must be a finite number >= 0.");
58622
+ }
58623
+ const repeatGraceMs = opts.repeatSignalGraceMs ?? DEFAULT_REPEAT_SIGNAL_GRACE_MS;
58509
58624
  let shuttingDown = false;
58625
+ let firstSignalAt = 0;
58626
+ let exited = false;
58627
+ const exitOnce = () => {
58628
+ if (exited)
58629
+ return;
58630
+ exited = true;
58631
+ process.exit(0);
58632
+ };
58510
58633
  const handler = (signal) => {
58511
- if (shuttingDown)
58634
+ if (shuttingDown) {
58635
+ if (Date.now() - firstSignalAt < repeatGraceMs)
58636
+ return;
58637
+ if (shouldExit) {
58638
+ console.error(`[mcp-utils] second ${signal} during shutdown \u2014 exiting now`);
58639
+ exitOnce();
58640
+ }
58512
58641
  return;
58642
+ }
58513
58643
  shuttingDown = true;
58644
+ firstSignalAt = Date.now();
58645
+ let timer;
58646
+ if (shouldExit) {
58647
+ timer = setTimeout(() => {
58648
+ console.error(`[mcp-utils] graceful shutdown on ${signal} did not finish in ${timeoutMs}ms \u2014 exiting`);
58649
+ exitOnce();
58650
+ }, timeoutMs);
58651
+ timer.unref?.();
58652
+ }
58514
58653
  void (async () => {
58515
58654
  try {
58516
58655
  if (opts.onSignal)
@@ -58519,8 +58658,10 @@ function withGracefulShutdown(target, opts = {}) {
58519
58658
  } catch (err) {
58520
58659
  console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
58521
58660
  } finally {
58661
+ if (timer !== void 0)
58662
+ clearTimeout(timer);
58522
58663
  if (shouldExit)
58523
- process.exit(0);
58664
+ exitOnce();
58524
58665
  }
58525
58666
  })();
58526
58667
  };
@@ -58548,7 +58689,7 @@ function runMcp(opts) {
58548
58689
  }
58549
58690
  return handle;
58550
58691
  }
58551
- var SERVER_PROTOCOL_VERSIONS;
58692
+ var SERVER_PROTOCOL_VERSIONS, DEFAULT_SHUTDOWN_TIMEOUT_MS, DEFAULT_REPEAT_SIGNAL_GRACE_MS;
58552
58693
  var init_server = __esm({
58553
58694
  "node_modules/@chrischall/mcp-utils/dist/server/index.js"() {
58554
58695
  init_stdio();
@@ -58556,14 +58697,20 @@ var init_server = __esm({
58556
58697
  init_errors();
58557
58698
  init_response();
58558
58699
  init_confirmation();
58700
+ init_cancel();
58701
+ init_caller();
58559
58702
  SERVER_PROTOCOL_VERSIONS = Object.freeze([
58560
58703
  "2026-07-28",
58561
58704
  ...SUPPORTED_PROTOCOL_VERSIONS
58562
58705
  ]);
58706
+ DEFAULT_SHUTDOWN_TIMEOUT_MS = 5e3;
58707
+ DEFAULT_REPEAT_SIGNAL_GRACE_MS = 500;
58563
58708
  }
58564
58709
  });
58565
58710
 
58566
58711
  // node_modules/@chrischall/mcp-utils/dist/config/index.js
58712
+ import { homedir } from "node:os";
58713
+ import { isAbsolute, join, resolve } from "node:path";
58567
58714
  function readEnvVar(key, opts = {}) {
58568
58715
  const env = opts.env ?? process.env;
58569
58716
  const raw = env[key];
@@ -58575,6 +58722,15 @@ function readEnvVar(key, opts = {}) {
58575
58722
  }
58576
58723
  return opts.default;
58577
58724
  }
58725
+ function expandPath(p) {
58726
+ let expanded = p;
58727
+ if (p === "~") {
58728
+ expanded = homedir();
58729
+ } else if (p.startsWith("~/")) {
58730
+ expanded = join(homedir(), p.slice(2));
58731
+ }
58732
+ return isAbsolute(expanded) ? expanded : resolve(expanded);
58733
+ }
58578
58734
  async function loadDotenvSafely(opts = {}) {
58579
58735
  try {
58580
58736
  const mod = await import(
@@ -58598,19 +58754,61 @@ var init_config = __esm({
58598
58754
  }
58599
58755
  });
58600
58756
 
58757
+ // node_modules/@chrischall/mcp-utils/dist/fs/confine.js
58758
+ import { existsSync, realpathSync } from "node:fs";
58759
+ import { dirname, isAbsolute as isAbsolute2, relative, resolve as resolve2, sep } from "node:path";
58760
+ function isInside(root, target) {
58761
+ const rel = relative(root, target);
58762
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute2(rel);
58763
+ }
58764
+ function realPathAllowingMissing(p) {
58765
+ const abs = resolve2(p);
58766
+ let existing = abs;
58767
+ const tail = [];
58768
+ while (!existsSync(existing)) {
58769
+ const parent = dirname(existing);
58770
+ if (parent === existing)
58771
+ break;
58772
+ tail.unshift(existing.slice(parent.length).replace(/^[/\\]+/, ""));
58773
+ existing = parent;
58774
+ }
58775
+ let real;
58776
+ try {
58777
+ real = realpathSync(existing);
58778
+ } catch {
58779
+ real = existing;
58780
+ }
58781
+ return tail.length > 0 ? resolve2(real, ...tail) : real;
58782
+ }
58783
+ function assertPathWithinRoots(path, roots) {
58784
+ const target = realPathAllowingMissing(expandPath(path));
58785
+ for (const root of roots) {
58786
+ if (isInside(realPathAllowingMissing(expandPath(root)), target))
58787
+ return target;
58788
+ }
58789
+ throw new Error(`Path is outside the allowed directories: ${path}`);
58790
+ }
58791
+ var init_confine = __esm({
58792
+ "node_modules/@chrischall/mcp-utils/dist/fs/confine.js"() {
58793
+ init_config();
58794
+ }
58795
+ });
58796
+
58601
58797
  // node_modules/@chrischall/mcp-utils/dist/fs/output.js
58602
58798
  var init_output = __esm({
58603
58799
  "node_modules/@chrischall/mcp-utils/dist/fs/output.js"() {
58604
58800
  init_config();
58801
+ init_confine();
58605
58802
  }
58606
58803
  });
58607
58804
 
58608
58805
  // node_modules/@chrischall/mcp-utils/dist/fs/index.js
58609
58806
  import { openAsBlob } from "node:fs";
58610
58807
  async function fileBlob(path, opts = {}) {
58808
+ const target = opts.allowedRoots ? assertPathWithinRoots(path, opts.allowedRoots) : path;
58611
58809
  let blob;
58612
58810
  try {
58613
- blob = await openAsBlob(path, opts.type !== void 0 ? { type: opts.type } : void 0);
58811
+ blob = await openAsBlob(target, opts.type !== void 0 ? { type: opts.type } : void 0);
58614
58812
  } catch {
58615
58813
  throw new Error(`Cannot read file for upload: ${path}`);
58616
58814
  }
@@ -58621,7 +58819,9 @@ async function fileBlob(path, opts = {}) {
58621
58819
  }
58622
58820
  var init_fs = __esm({
58623
58821
  "node_modules/@chrischall/mcp-utils/dist/fs/index.js"() {
58822
+ init_confine();
58624
58823
  init_output();
58824
+ init_confine();
58625
58825
  }
58626
58826
  });
58627
58827
 
@@ -58672,23 +58872,78 @@ function createApiClient(opts) {
58672
58872
  const retryStatuses = retry.statuses ?? [429];
58673
58873
  const timeoutMs = opts.timeout;
58674
58874
  const authHeader = (token) => !token ? {} : opts.tokenHeader ? { [opts.tokenHeader]: token } : { Authorization: `Bearer ${token}` };
58675
- function withTimeout(run) {
58676
- if (timeoutMs == null || timeoutMs <= 0)
58677
- return run(void 0);
58875
+ async function withTimeout(run) {
58876
+ if (timeoutMs == null || timeoutMs <= 0) {
58877
+ const res2 = await run(withAmbientCancellation(void 0));
58878
+ return { res: res2, done: () => {
58879
+ }, expired: void 0 };
58880
+ }
58678
58881
  const controller = new AbortController();
58679
58882
  const timer = setTimeout(() => controller.abort(), timeoutMs);
58680
- return run(controller.signal).catch((err) => {
58681
- if (err instanceof Error && err.name === "AbortError")
58883
+ let res;
58884
+ try {
58885
+ res = await run(withAmbientCancellation(controller.signal));
58886
+ } catch (err) {
58887
+ clearTimeout(timer);
58888
+ if (err instanceof Error && err.name === "AbortError" && controller.signal.aborted) {
58682
58889
  throw new RequestTimeoutError(service, timeoutMs);
58890
+ }
58683
58891
  throw err;
58684
- }).finally(() => clearTimeout(timer));
58892
+ }
58893
+ const expired = new Promise((_resolve, reject) => {
58894
+ controller.signal.addEventListener("abort", () => reject(new RequestTimeoutError(service, timeoutMs)), {
58895
+ once: true
58896
+ });
58897
+ });
58898
+ expired.catch(() => {
58899
+ });
58900
+ return { res, done: () => clearTimeout(timer), expired };
58901
+ }
58902
+ async function readBody(attempt, read) {
58903
+ try {
58904
+ if (!attempt.expired)
58905
+ return await read(attempt.res);
58906
+ return await Promise.race([read(attempt.res), attempt.expired]);
58907
+ } catch (err) {
58908
+ if (err instanceof RequestTimeoutError) {
58909
+ attempt.res.body?.cancel().catch(() => {
58910
+ });
58911
+ }
58912
+ throw err;
58913
+ } finally {
58914
+ attempt.done();
58915
+ }
58916
+ }
58917
+ const baseParts = (() => {
58918
+ try {
58919
+ const u = new URL(base);
58920
+ return { origin: u.origin, username: u.username, password: u.password };
58921
+ } catch {
58922
+ return void 0;
58923
+ }
58924
+ })();
58925
+ const baseOrigin = baseParts?.origin;
58926
+ function resolveUrl2(path, query) {
58927
+ const url4 = `${base}${path}${query}`;
58928
+ if (baseOrigin === void 0)
58929
+ return url4;
58930
+ let parsed;
58931
+ try {
58932
+ parsed = new URL(url4);
58933
+ } catch {
58934
+ throw new Error(`Refusing request to ${service}: path ${JSON.stringify(path)} does not form a valid URL.`);
58935
+ }
58936
+ if (parsed.origin !== baseOrigin || parsed.username !== baseParts?.username || parsed.password !== baseParts?.password) {
58937
+ 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 "/").`);
58938
+ }
58939
+ return url4;
58685
58940
  }
58686
58941
  async function send(method, path, opt) {
58687
58942
  const isMultipart = opt.formData !== void 0;
58688
58943
  const hasJsonBody = !isMultipart && opt.body !== void 0;
58689
58944
  const reqBody = isMultipart ? opt.formData : hasJsonBody ? JSON.stringify(opt.body) : void 0;
58690
58945
  const query = opt.query ? buildQueryString(opt.query) : "";
58691
- const url4 = `${base}${path}${query}`;
58946
+ const url4 = resolveUrl2(path, query);
58692
58947
  const bodyInit = reqBody !== void 0 ? { body: reqBody } : {};
58693
58948
  const fetchWith = (token, signal) => doFetch(url4, {
58694
58949
  method,
@@ -58705,8 +58960,10 @@ function createApiClient(opts) {
58705
58960
  const once = () => withTimeout((signal) => opts.tokenManager ? opts.tokenManager.withAuth((token) => fetchWith(token, signal)) : (async () => fetchWith(await opts.getToken?.() || void 0, signal))());
58706
58961
  let attempt = 0;
58707
58962
  for (; ; ) {
58708
- const res = await once();
58963
+ const current = await once();
58964
+ const res = current.res;
58709
58965
  if (retryStatuses.includes(res.status) && attempt < retry.count) {
58966
+ current.done();
58710
58967
  attempt += 1;
58711
58968
  const delay = retry.honorRetryAfter ? parseRetryAfterMs(res.headers.get("retry-after"), {
58712
58969
  defaultMs: retry.delayMs,
@@ -58715,18 +58972,21 @@ function createApiClient(opts) {
58715
58972
  await sleep2(delay);
58716
58973
  continue;
58717
58974
  }
58718
- return res;
58975
+ return current;
58719
58976
  }
58720
58977
  }
58721
58978
  async function fetchJson(method, path, opt = {}) {
58722
- const res = await send(method, path, opt);
58979
+ const attempt = await send(method, path, opt);
58980
+ const res = attempt.res;
58981
+ if (res.status === 401 || res.status === 429 || res.status === 204)
58982
+ attempt.done();
58723
58983
  if (res.status === 401)
58724
58984
  throw unauthorized();
58725
58985
  if (res.status === 429)
58726
58986
  throw rateLimited();
58727
58987
  if (res.status === 204)
58728
58988
  return void 0;
58729
- const text = await res.text();
58989
+ const text = await readBody(attempt, (r) => r.text());
58730
58990
  if (!res.ok) {
58731
58991
  throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
58732
58992
  }
@@ -58736,12 +58996,15 @@ function createApiClient(opts) {
58736
58996
  }
58737
58997
  async function fetchHtml(method, path, opt = {}) {
58738
58998
  const headers = { Accept: "text/html,*/*", ...opt.headers };
58739
- const res = await send(method, path, { ...opt, headers });
58999
+ const attempt = await send(method, path, { ...opt, headers });
59000
+ const res = attempt.res;
59001
+ if (res.status === 401 || res.status === 429)
59002
+ attempt.done();
58740
59003
  if (res.status === 401)
58741
59004
  throw unauthorized();
58742
59005
  if (res.status === 429)
58743
59006
  throw rateLimited();
58744
- const text = await res.text();
59007
+ const text = await readBody(attempt, (r) => r.text());
58745
59008
  if (!res.ok) {
58746
59009
  throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
58747
59010
  }
@@ -58749,16 +59012,23 @@ function createApiClient(opts) {
58749
59012
  }
58750
59013
  async function fetchRaw(method, path, opt = {}) {
58751
59014
  const headers = { Accept: "*/*", ...opt.headers };
58752
- const res = await send(method, path, { ...opt, headers });
59015
+ const attempt = await send(method, path, { ...opt, headers });
59016
+ const res = attempt.res;
59017
+ if (res.status === 401 || res.status === 429)
59018
+ attempt.done();
58753
59019
  if (res.status === 401)
58754
59020
  throw unauthorized();
58755
59021
  if (res.status === 429)
58756
59022
  throw rateLimited();
58757
59023
  if (!res.ok) {
58758
- const text = await res.text().catch(() => "");
59024
+ const text = await readBody(attempt, (r) => r.text()).catch((err) => {
59025
+ if (err instanceof RequestTimeoutError)
59026
+ throw err;
59027
+ return "";
59028
+ });
58759
59029
  throw new ApiError(res.status, formatApiError(res.status, method, path, text, { service }));
58760
59030
  }
58761
- const bytes = new Uint8Array(await res.arrayBuffer());
59031
+ const bytes = new Uint8Array(await readBody(attempt, (r) => r.arrayBuffer()));
58762
59032
  return {
58763
59033
  status: res.status,
58764
59034
  contentType: res.headers.get("content-type"),
@@ -58794,6 +59064,7 @@ function formatApiError(status, method, path, errorText, opts = {}) {
58794
59064
  var DEFAULT_RETRY, defaultSleep, UnauthorizedError, RateLimitedError, RequestTimeoutError, ApiError;
58795
59065
  var init_http = __esm({
58796
59066
  "node_modules/@chrischall/mcp-utils/dist/http/index.js"() {
59067
+ init_cancel();
58797
59068
  init_errors();
58798
59069
  init_throttle();
58799
59070
  init_response_cache();
@@ -58866,10 +59137,14 @@ var init_parse_lenient = __esm({
58866
59137
 
58867
59138
  // node_modules/@chrischall/mcp-utils/dist/zod/index.js
58868
59139
  function toolAnnotations(opts = {}) {
59140
+ if (opts.readOnly === true && opts.destructive === true) {
59141
+ throw new Error("toolAnnotations: readOnly: true contradicts destructive: true \u2014 a destructive tool is not read-only.");
59142
+ }
58869
59143
  return {
58870
59144
  ...opts.title !== void 0 ? { title: opts.title } : {},
58871
- readOnlyHint: opts.readOnly ?? true,
59145
+ readOnlyHint: opts.readOnly ?? opts.destructive === void 0,
58872
59146
  ...opts.idempotent !== void 0 ? { idempotentHint: opts.idempotent } : {},
59147
+ ...opts.destructive !== void 0 ? { destructiveHint: opts.destructive } : {},
58873
59148
  ...opts.openWorld !== void 0 ? { openWorldHint: opts.openWorld } : {}
58874
59149
  };
58875
59150
  }
@@ -58921,15 +59196,24 @@ var init_auth = __esm({
58921
59196
  }
58922
59197
  });
58923
59198
 
59199
+ // node_modules/@chrischall/mcp-utils/dist/internal/ascii.js
59200
+ var init_ascii = __esm({
59201
+ "node_modules/@chrischall/mcp-utils/dist/internal/ascii.js"() {
59202
+ }
59203
+ });
59204
+
58924
59205
  // node_modules/@chrischall/mcp-utils/dist/scrape/index.js
58925
59206
  var init_scrape = __esm({
58926
59207
  "node_modules/@chrischall/mcp-utils/dist/scrape/index.js"() {
59208
+ init_ascii();
58927
59209
  }
58928
59210
  });
58929
59211
 
58930
59212
  // node_modules/@chrischall/mcp-utils/dist/index.js
58931
59213
  var init_dist2 = __esm({
58932
59214
  "node_modules/@chrischall/mcp-utils/dist/index.js"() {
59215
+ init_cancel();
59216
+ init_caller();
58933
59217
  init_server();
58934
59218
  init_response();
58935
59219
  init_errors();
@@ -58964,8 +59248,8 @@ __export(images_exports, {
58964
59248
  writeSidecar: () => writeSidecar
58965
59249
  });
58966
59250
  import { mkdir, readFile, writeFile, access, stat, open as open2 } from "node:fs/promises";
58967
- import { existsSync } from "node:fs";
58968
- import { join as join2, resolve, isAbsolute } from "node:path";
59251
+ import { existsSync as existsSync2 } from "node:fs";
59252
+ import { join as join3, resolve as resolve3, isAbsolute as isAbsolute3 } from "node:path";
58969
59253
  function slugify2(text, max = 40) {
58970
59254
  const s = text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max).replace(/-+$/g, "");
58971
59255
  return s || "image";
@@ -58979,10 +59263,10 @@ async function exists(p) {
58979
59263
  }
58980
59264
  }
58981
59265
  async function uniquePath(dir, base, ext) {
58982
- let candidate = join2(dir, `${base}.${ext}`);
59266
+ let candidate = join3(dir, `${base}.${ext}`);
58983
59267
  let n = 2;
58984
59268
  while (await exists(candidate)) {
58985
- candidate = join2(dir, `${base}-${n}.${ext}`);
59269
+ candidate = join3(dir, `${base}-${n}.${ext}`);
58986
59270
  n++;
58987
59271
  }
58988
59272
  return candidate;
@@ -59016,7 +59300,7 @@ async function writeMedia(dir, base, base643, mimeType) {
59016
59300
  await mkdir(dir, { recursive: true });
59017
59301
  const path = await uniquePath(dir, base, mediaExt(mimeType));
59018
59302
  await writeFile(path, Buffer.from(base643, "base64"));
59019
- return resolve(path);
59303
+ return resolve3(path);
59020
59304
  }
59021
59305
  async function writeImage(dir, base, base643, mimeType) {
59022
59306
  return writeMedia(dir, base, base643, mimeType);
@@ -59025,14 +59309,14 @@ async function writeSidecar(imagePath, data) {
59025
59309
  await writeFile(`${imagePath}.json`, JSON.stringify(data, null, 2));
59026
59310
  }
59027
59311
  function resolveInputPath(p, kind) {
59028
- if (isAbsolute(p) && existsSync(p)) return p;
59312
+ if (isAbsolute3(p) && existsSync2(p)) return p;
59029
59313
  const inputDir = readEnvVar("GEMINI_INPUT_DIR");
59030
59314
  if (inputDir) {
59031
- const candidate = join2(inputDir, p);
59032
- if (existsSync(candidate)) return resolve(candidate);
59315
+ const candidate = join3(inputDir, p);
59316
+ if (existsSync2(candidate)) return resolve3(candidate);
59033
59317
  }
59034
- const cwd = resolve(p);
59035
- if (existsSync(cwd)) return cwd;
59318
+ const cwd = resolve3(p);
59319
+ if (existsSync2(cwd)) return cwd;
59036
59320
  const hint = `Set GEMINI_INPUT_DIR to a directory containing your ${kind.toLowerCase()}s, or pass an absolute path.`;
59037
59321
  throw new McpToolError(
59038
59322
  `${kind} not found: ${p}` + (inputDir ? ` (also searched GEMINI_INPUT_DIR=${inputDir})` : ""),
@@ -59128,7 +59412,7 @@ import { execFile } from "node:child_process";
59128
59412
  import { promisify } from "node:util";
59129
59413
  import { readFile as readFile2, unlink } from "node:fs/promises";
59130
59414
  import { tmpdir } from "node:os";
59131
- import { join as join3 } from "node:path";
59415
+ import { join as join4 } from "node:path";
59132
59416
  async function readClipboardImage(run = defaultRun) {
59133
59417
  if (process.platform !== "darwin") {
59134
59418
  throw new McpToolError("from_clipboard is only supported on macOS", {
@@ -59136,8 +59420,8 @@ async function readClipboardImage(run = defaultRun) {
59136
59420
  });
59137
59421
  }
59138
59422
  const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
59139
- const png = join3(tmpdir(), `gemini-clip-${id}.png`);
59140
- const jpg = join3(tmpdir(), `gemini-clip-${id}.jpg`);
59423
+ const png = join4(tmpdir(), `gemini-clip-${id}.png`);
59424
+ const jpg = join4(tmpdir(), `gemini-clip-${id}.jpg`);
59141
59425
  try {
59142
59426
  try {
59143
59427
  await run("osascript", [
@@ -59184,15 +59468,15 @@ init_dist2();
59184
59468
 
59185
59469
  // src/dotenv.ts
59186
59470
  init_dist2();
59187
- import { dirname, join } from "node:path";
59471
+ import { dirname as dirname2, join as join2 } from "node:path";
59188
59472
  import { fileURLToPath } from "node:url";
59189
59473
  async function loadStdioDotenv() {
59190
- const here = dirname(fileURLToPath(import.meta.url));
59191
- await loadDotenvSafely({ path: join(here, "..", ".env"), override: false });
59474
+ const here = dirname2(fileURLToPath(import.meta.url));
59475
+ await loadDotenvSafely({ path: join2(here, "..", ".env"), override: false });
59192
59476
  }
59193
59477
 
59194
59478
  // src/version.ts
59195
- var VERSION = "2.1.1";
59479
+ var VERSION = "2.1.3";
59196
59480
 
59197
59481
  // src/errors.ts
59198
59482
  init_dist2();
@@ -60510,8 +60794,8 @@ async function emitMedia(named, kind, opts, meta3, onWritten) {
60510
60794
  ...p.key ? { curl_hint: `curl -sS -o ${downloadFilename(p.key)} "${p.ref}"` } : {}
60511
60795
  }))
60512
60796
  } : {};
60513
- const storage = sink.persistsFiles ? {} : { storage: sink.kind, storage_note: storageNote };
60514
- return minifiedResult({ [`${kind}s`]: refs, ...media, ...unavailable, ...note, ...storage, ...meta3 });
60797
+ const storage3 = sink.persistsFiles ? {} : { storage: sink.kind, storage_note: storageNote };
60798
+ return minifiedResult({ [`${kind}s`]: refs, ...media, ...unavailable, ...note, ...storage3, ...meta3 });
60515
60799
  }
60516
60800
  async function emit(named, opts, meta3, onWritten) {
60517
60801
  return emitMedia(named.map((n) => ({ media: n.image, base: n.base })), "image", opts, meta3, onWritten);
@@ -60827,13 +61111,13 @@ function persistableResult(result) {
60827
61111
  return { result };
60828
61112
  }
60829
61113
  function awaitWithBudget(promise2, waitMs) {
60830
- return new Promise((resolve2, reject) => {
60831
- const timer = setTimeout(() => resolve2(void 0), waitMs);
61114
+ return new Promise((resolve4, reject) => {
61115
+ const timer = setTimeout(() => resolve4(void 0), waitMs);
60832
61116
  timer.unref?.();
60833
61117
  promise2.then(
60834
61118
  (result) => {
60835
61119
  clearTimeout(timer);
60836
- resolve2(result);
61120
+ resolve4(result);
60837
61121
  },
60838
61122
  (err) => {
60839
61123
  clearTimeout(timer);
@@ -60901,7 +61185,7 @@ var JobRegistry = class {
60901
61185
  /** Await outstanding durable writes. Tests only — handlers never need it. */
60902
61186
  async drain() {
60903
61187
  for (let round = 0; round < 50; round++) {
60904
- await new Promise((resolve2) => setTimeout(resolve2, 0));
61188
+ await new Promise((resolve4) => setTimeout(resolve4, 0));
60905
61189
  if (!this.pending.size) return;
60906
61190
  await Promise.allSettled([...this.pending]);
60907
61191
  }
@@ -62967,8 +63251,8 @@ init_images();
62967
63251
 
62968
63252
  // src/sidecar.ts
62969
63253
  import { readdir, readFile as readFile3, stat as stat2 } from "node:fs/promises";
62970
- import { existsSync as existsSync2 } from "node:fs";
62971
- import { join as join4 } from "node:path";
63254
+ import { existsSync as existsSync3 } from "node:fs";
63255
+ import { join as join5 } from "node:path";
62972
63256
  var SIDECAR_SUFFIX2 = ".json";
62973
63257
  async function readSidecars(dir) {
62974
63258
  let entries;
@@ -62980,7 +63264,7 @@ async function readSidecars(dir) {
62980
63264
  const records = [];
62981
63265
  for (const entry of entries) {
62982
63266
  if (!entry.endsWith(SIDECAR_SUFFIX2)) continue;
62983
- const sidecarPath = join4(dir, entry);
63267
+ const sidecarPath = join5(dir, entry);
62984
63268
  try {
62985
63269
  const parsed = JSON.parse(await readFile3(sidecarPath, "utf8"));
62986
63270
  if (typeof parsed !== "object" || parsed === null) continue;
@@ -62990,7 +63274,7 @@ async function readSidecars(dir) {
62990
63274
  records.push({
62991
63275
  sidecarPath,
62992
63276
  interactionId,
62993
- images: paths.filter((p) => existsSync2(p)),
63277
+ images: paths.filter((p) => existsSync3(p)),
62994
63278
  mtimeMs: (await stat2(sidecarPath)).mtimeMs
62995
63279
  });
62996
63280
  } catch {
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Single source of the server version. release-please bumps the literal below. */
2
- export const VERSION = '2.1.1'; // x-release-please-version
2
+ export const VERSION = '2.1.3'; // x-release-please-version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/gemini-mcp",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "mcpName": "io.github.chrischall/gemini-mcp",
5
5
  "description": "Gemini image-generation MCP server for Claude — developed and maintained by AI (Claude Code)",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -46,10 +46,10 @@
46
46
  "typecheck": "tsc -p tsconfig.test.json"
47
47
  },
48
48
  "dependencies": {
49
- "@chrischall/mcp-utils": "^1.0.0",
49
+ "@chrischall/mcp-utils": "^2.4.0",
50
50
  "@modelcontextprotocol/server": "^2.0.0",
51
51
  "dotenv": "^17.4.0",
52
- "zod": "^4.6.2"
52
+ "zod": "^4.6.5"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@modelcontextprotocol/client": "^2.0.0",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/chrischall/gemini-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "2.1.1",
9
+ "version": "2.1.3",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/gemini-mcp",
14
- "version": "2.1.1",
14
+ "version": "2.1.3",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },