gogcli-mcp-calendar 4.2.5 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -37,6 +37,33 @@ var storage2 = new AsyncLocalStorage2();
37
37
  function withCallerCapabilities(capabilities, fn) {
38
38
  return capabilities ? storage2.run(capabilities, fn) : fn();
39
39
  }
40
+ function currentCallerCapabilities() {
41
+ return storage2.getStore();
42
+ }
43
+ var ENVELOPE_CAPABILITIES_KEY = "io.modelcontextprotocol/clientCapabilities";
44
+ var ELICITATION_MODES = ["form", "url"];
45
+ function isRecord(value) {
46
+ return typeof value === "object" && value !== null && !Array.isArray(value);
47
+ }
48
+ function callerCapabilities(ctx) {
49
+ const envelope = isRecord(ctx) && isRecord(ctx.mcpReq) ? ctx.mcpReq.envelope : void 0;
50
+ if (isRecord(envelope)) {
51
+ const declared = envelope[ENVELOPE_CAPABILITIES_KEY];
52
+ if (isRecord(declared))
53
+ return declared;
54
+ }
55
+ return currentCallerCapabilities();
56
+ }
57
+ function callerAcceptsFormElicitation(ctx) {
58
+ const capabilities = callerCapabilities(ctx);
59
+ if (!capabilities)
60
+ return void 0;
61
+ const elicitation = capabilities.elicitation;
62
+ if (!isRecord(elicitation))
63
+ return false;
64
+ const namedModes = ELICITATION_MODES.filter((mode) => mode in elicitation);
65
+ return namedModes.length === 0 || namedModes.includes("form");
66
+ }
40
67
 
41
68
  // ../../node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
42
69
  var __create = Object.create;
@@ -2092,8 +2119,8 @@ function emoji() {
2092
2119
  }
2093
2120
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
2094
2121
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
2095
- var mac = (delimiter2) => {
2096
- const escapedDelim = escapeRegex(delimiter2 ?? ":");
2122
+ var mac = (delimiter3) => {
2123
+ const escapedDelim = escapeRegex(delimiter3 ?? ":");
2097
2124
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
2098
2125
  };
2099
2126
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -5121,7 +5148,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
5121
5148
  var NONE = 0;
5122
5149
  var ASSUMED = 1;
5123
5150
  var PROVEN = 2;
5124
- function isRecursive(inst, stack, resolve) {
5151
+ function isRecursive(inst, stack, resolve4) {
5125
5152
  const cached2 = recursive.get(inst);
5126
5153
  if (cached2 !== void 0)
5127
5154
  return cached2 ? PROVEN : NONE;
@@ -5131,7 +5158,7 @@ function isRecursive(inst, stack, resolve) {
5131
5158
  let result = NONE;
5132
5159
  const check2 = (child) => {
5133
5160
  if (result !== PROVEN && child?._zod) {
5134
- const answer = isRecursive(child, stack, resolve);
5161
+ const answer = isRecursive(child, stack, resolve4);
5135
5162
  if (answer > result)
5136
5163
  result = answer;
5137
5164
  }
@@ -5142,7 +5169,7 @@ function isRecursive(inst, stack, resolve) {
5142
5169
  const desc = Object.getOwnPropertyDescriptor(sh, key);
5143
5170
  if (spread && !desc.enumerable)
5144
5171
  continue;
5145
- const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
5172
+ const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve4) : NONE;
5146
5173
  if (child > answer)
5147
5174
  answer = child;
5148
5175
  }
@@ -5206,7 +5233,7 @@ function isRecursive(inst, stack, resolve) {
5206
5233
  break;
5207
5234
  // `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
5208
5235
  case "lazy": {
5209
- const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : void 0);
5236
+ const inner = def._cachedInner ?? (resolve4 ? inst._zod.innerType : void 0);
5210
5237
  merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
5211
5238
  break;
5212
5239
  }
@@ -24101,19 +24128,50 @@ var inputRequired = Object.assign(buildInputRequired, {
24101
24128
  return { method: "roots/list" };
24102
24129
  }
24103
24130
  });
24131
+ function acceptedContent(responses, key, schema) {
24132
+ const view = inputResponse(responses, key);
24133
+ if (view.kind !== "elicit" || view.action !== "accept" || view.content === void 0) return void 0;
24134
+ if (schema === void 0) return view.content;
24135
+ const outcome = schema["~standard"].validate(view.content);
24136
+ if (outcome instanceof Promise) throw new TypeError("acceptedContent(responses, key, schema) requires a synchronously-validating schema");
24137
+ return outcome.issues === void 0 ? outcome.value : void 0;
24138
+ }
24139
+ function inputResponse(responses, key) {
24140
+ if (responses === void 0 || typeof responses !== "object" || responses === null) return { kind: "missing" };
24141
+ const entry = responses[key];
24142
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return { kind: "missing" };
24143
+ const candidate = entry;
24144
+ if (candidate["action"] === "accept" || candidate["action"] === "decline" || candidate["action"] === "cancel") {
24145
+ const content = candidate["content"];
24146
+ return {
24147
+ kind: "elicit",
24148
+ action: candidate["action"],
24149
+ ...content !== null && typeof content === "object" && !Array.isArray(content) && { content }
24150
+ };
24151
+ }
24152
+ if (Array.isArray(candidate["roots"])) return {
24153
+ kind: "roots",
24154
+ roots: candidate["roots"]
24155
+ };
24156
+ if (typeof candidate["role"] === "string" && candidate["content"] !== void 0) return {
24157
+ kind: "sampling",
24158
+ result: candidate
24159
+ };
24160
+ return { kind: "missing" };
24161
+ }
24104
24162
  var REQUEST_STATE_ONLY_LEG_PACING_MS = 250;
24105
24163
  function inputRequiredRoundsExceededMessage(method, maxRounds) {
24106
24164
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
24107
24165
  }
24108
24166
  function sleep(ms, signal) {
24109
- return new Promise((resolve, reject) => {
24167
+ return new Promise((resolve4, reject) => {
24110
24168
  if (signal?.aborted) {
24111
24169
  reject(signal.reason instanceof SdkError ? signal.reason : new SdkError(SdkErrorCode.RequestTimeout, String(signal.reason)));
24112
24170
  return;
24113
24171
  }
24114
24172
  const timer = setTimeout(() => {
24115
24173
  signal?.removeEventListener("abort", onAbort);
24116
- resolve();
24174
+ resolve4();
24117
24175
  }, ms);
24118
24176
  const onAbort = () => {
24119
24177
  clearTimeout(timer);
@@ -24907,7 +24965,7 @@ var Protocol = class {
24907
24965
  const flowStartedAt = Date.now();
24908
24966
  let onAbort;
24909
24967
  let cleanupMessageId;
24910
- return new Promise((resolve, reject) => {
24968
+ return new Promise((resolve4, reject) => {
24911
24969
  const earlyReject = (error62) => {
24912
24970
  reject(error62);
24913
24971
  };
@@ -24975,7 +25033,7 @@ var Protocol = class {
24975
25033
  }
24976
25034
  if (decoded.kind === "invalid") return reject(decoded.error);
24977
25035
  if (decoded.kind === "input_required") {
24978
- if (options?.allowInputRequired === true) return resolve(manualInputRequiredValue(decoded));
25036
+ if (options?.allowInputRequired === true) return resolve4(manualInputRequiredValue(decoded));
24979
25037
  const flow = {
24980
25038
  codec: codec2,
24981
25039
  request,
@@ -24987,11 +25045,11 @@ var Protocol = class {
24987
25045
  params
24988
25046
  }, resultSchema, legOptions)
24989
25047
  };
24990
- return resolve(this._resolveNonCompleteResult(decoded, flow));
25048
+ return resolve4(this._resolveNonCompleteResult(decoded, flow));
24991
25049
  }
24992
25050
  const result = decoded.result;
24993
25051
  validateStandardSchema(resultSchema, result).then((parseResult) => {
24994
- if (parseResult.success) resolve(parseResult.data);
25052
+ if (parseResult.success) resolve4(parseResult.data);
24995
25053
  else reject(new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${request.method}: ${parseResult.error}`));
24996
25054
  }, reject);
24997
25055
  });
@@ -27903,7 +27961,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin(((exports) => {
27903
27961
  ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
27904
27962
  const schOrFunc = root.refs[ref];
27905
27963
  if (schOrFunc) return schOrFunc;
27906
- let _sch = resolve.call(this, root, ref);
27964
+ let _sch = resolve4.call(this, root, ref);
27907
27965
  if (_sch === void 0) {
27908
27966
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
27909
27967
  const { schemaId } = this.opts;
@@ -27929,7 +27987,7 @@ var require_compile = /* @__PURE__ */ __commonJSMin(((exports) => {
27929
27987
  function sameSchemaEnv(s1, s2) {
27930
27988
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
27931
27989
  }
27932
- function resolve(root, ref) {
27990
+ function resolve4(root, ref) {
27933
27991
  let sch;
27934
27992
  while (typeof (sch = this.refs[ref]) == "string") ref = sch;
27935
27993
  return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
@@ -28379,47 +28437,47 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
28379
28437
  else if (typeof uri === "object") uri = parse3(serialize(uri, options), options);
28380
28438
  return uri;
28381
28439
  }
28382
- function resolve(baseURI, relativeURI, options) {
28440
+ function resolve4(baseURI, relativeURI, options) {
28383
28441
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
28384
28442
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
28385
28443
  schemelessOptions.skipEscape = true;
28386
28444
  return serialize(resolved, schemelessOptions);
28387
28445
  }
28388
- function resolveComponent(base, relative, options, skipNormalization) {
28446
+ function resolveComponent(base, relative3, options, skipNormalization) {
28389
28447
  const target = {};
28390
28448
  if (!skipNormalization) {
28391
28449
  base = parse3(serialize(base, options), options);
28392
- relative = parse3(serialize(relative, options), options);
28450
+ relative3 = parse3(serialize(relative3, options), options);
28393
28451
  }
28394
28452
  options = options || {};
28395
- if (!options.tolerant && relative.scheme) {
28396
- target.scheme = relative.scheme;
28397
- target.userinfo = relative.userinfo;
28398
- target.host = relative.host;
28399
- target.port = relative.port;
28400
- target.path = removeDotSegments(relative.path || "");
28401
- target.query = relative.query;
28453
+ if (!options.tolerant && relative3.scheme) {
28454
+ target.scheme = relative3.scheme;
28455
+ target.userinfo = relative3.userinfo;
28456
+ target.host = relative3.host;
28457
+ target.port = relative3.port;
28458
+ target.path = removeDotSegments(relative3.path || "");
28459
+ target.query = relative3.query;
28402
28460
  } else {
28403
- if (relative.userinfo !== void 0 || relative.host !== void 0 || relative.port !== void 0) {
28404
- target.userinfo = relative.userinfo;
28405
- target.host = relative.host;
28406
- target.port = relative.port;
28407
- target.path = removeDotSegments(relative.path || "");
28408
- target.query = relative.query;
28461
+ if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
28462
+ target.userinfo = relative3.userinfo;
28463
+ target.host = relative3.host;
28464
+ target.port = relative3.port;
28465
+ target.path = removeDotSegments(relative3.path || "");
28466
+ target.query = relative3.query;
28409
28467
  } else {
28410
- if (!relative.path) {
28468
+ if (!relative3.path) {
28411
28469
  target.path = base.path;
28412
- if (relative.query !== void 0) target.query = relative.query;
28470
+ if (relative3.query !== void 0) target.query = relative3.query;
28413
28471
  else target.query = base.query;
28414
28472
  } else {
28415
- if (relative.path[0] === "/") target.path = removeDotSegments(relative.path);
28473
+ if (relative3.path[0] === "/") target.path = removeDotSegments(relative3.path);
28416
28474
  else {
28417
- if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" + relative.path;
28418
- else if (!base.path) target.path = relative.path;
28419
- else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
28475
+ if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) target.path = "/" + relative3.path;
28476
+ else if (!base.path) target.path = relative3.path;
28477
+ else target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
28420
28478
  target.path = removeDotSegments(target.path);
28421
28479
  }
28422
- target.query = relative.query;
28480
+ target.query = relative3.query;
28423
28481
  }
28424
28482
  target.userinfo = base.userinfo;
28425
28483
  target.host = base.host;
@@ -28427,7 +28485,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
28427
28485
  }
28428
28486
  target.scheme = base.scheme;
28429
28487
  }
28430
- target.fragment = relative.fragment;
28488
+ target.fragment = relative3.fragment;
28431
28489
  return target;
28432
28490
  }
28433
28491
  function equal(uriA, uriB, options) {
@@ -28553,7 +28611,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
28553
28611
  const fastUri = {
28554
28612
  SCHEMES,
28555
28613
  normalize,
28556
- resolve,
28614
+ resolve: resolve4,
28557
28615
  resolveComponent,
28558
28616
  equal,
28559
28617
  serialize,
@@ -29335,14 +29393,14 @@ var require_ucs2length = /* @__PURE__ */ __commonJSMin(((exports) => {
29335
29393
  function ucs2length(str) {
29336
29394
  const len = str.length;
29337
29395
  let length = 0;
29338
- let pos = 0;
29396
+ let pos2 = 0;
29339
29397
  let value;
29340
- while (pos < len) {
29398
+ while (pos2 < len) {
29341
29399
  length++;
29342
- value = str.charCodeAt(pos++);
29343
- if (value >= 55296 && value <= 56319 && pos < len) {
29344
- value = str.charCodeAt(pos);
29345
- if ((value & 64512) === 56320) pos++;
29400
+ value = str.charCodeAt(pos2++);
29401
+ if (value >= 55296 && value <= 56319 && pos2 < len) {
29402
+ value = str.charCodeAt(pos2);
29403
+ if ((value & 64512) === 56320) pos2++;
29346
29404
  }
29347
29405
  }
29348
29406
  return length;
@@ -33926,7 +33984,7 @@ var StdioServerTransport = class {
33926
33984
  }
33927
33985
  send(message) {
33928
33986
  if (this._closed) return Promise.reject(/* @__PURE__ */ new Error("StdioServerTransport is closed"));
33929
- return new Promise((resolve, reject) => {
33987
+ return new Promise((resolve4, reject) => {
33930
33988
  const json2 = serializeMessage(message);
33931
33989
  let settled = false;
33932
33990
  const onError = (error62) => {
@@ -33941,14 +33999,14 @@ var StdioServerTransport = class {
33941
33999
  settled = true;
33942
34000
  this._stdout.off("error", onError);
33943
34001
  this._stdout.off("drain", onDrain);
33944
- resolve();
34002
+ resolve4();
33945
34003
  };
33946
34004
  this._stdout.once("error", onError);
33947
34005
  if (this._stdout.write(json2)) {
33948
34006
  if (settled) return;
33949
34007
  settled = true;
33950
34008
  this._stdout.off("error", onError);
33951
- resolve();
34009
+ resolve4();
33952
34010
  } else if (!settled) this._stdout.once("drain", onDrain);
33953
34011
  });
33954
34012
  }
@@ -34002,14 +34060,14 @@ var StdioConnectionChannel = class {
34002
34060
  */
34003
34061
  async whenRequestsAnswered(timeoutMs) {
34004
34062
  if (this._closed || this._pendingRequests.size === 0) return true;
34005
- return await new Promise((resolve) => {
34063
+ return await new Promise((resolve4) => {
34006
34064
  const waiter = () => {
34007
34065
  clearTimeout(timer);
34008
- resolve(true);
34066
+ resolve4(true);
34009
34067
  };
34010
34068
  const timer = setTimeout(() => {
34011
34069
  this._drainWaiters = this._drainWaiters.filter((pending) => pending !== waiter);
34012
- resolve(false);
34070
+ resolve4(false);
34013
34071
  }, timeoutMs);
34014
34072
  this._drainWaiters.push(waiter);
34015
34073
  });
@@ -34148,14 +34206,14 @@ function serveStdio(factory, options = {}) {
34148
34206
  return false;
34149
34207
  };
34150
34208
  const answerLegacyRejection = (request, reason, requestedVersion) => {
34151
- const rejection2 = modernOnlyStrictRejection({
34209
+ const rejection3 = modernOnlyStrictRejection({
34152
34210
  kind: "legacy",
34153
34211
  reason,
34154
34212
  ...requestedVersion !== void 0 && { requestedVersion }
34155
34213
  }, SUPPORTED_MODERN_PROTOCOL_VERSIONS);
34156
- if (rejection2 === void 0) return Promise.resolve();
34157
- reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection2.cell}): ${rejection2.message}`));
34158
- return writeErrorResponse(request.id, rejection2.code, rejection2.message, rejection2.data);
34214
+ if (rejection3 === void 0) return Promise.resolve();
34215
+ reportError(/* @__PURE__ */ new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection3.cell}): ${rejection3.message}`));
34216
+ return writeErrorResponse(request.id, rejection3.code, rejection3.message, rejection3.data);
34159
34217
  };
34160
34218
  const onInstanceClosed = (channel) => {
34161
34219
  if (closing || channel === discarding) return;
@@ -34379,13 +34437,28 @@ var API_KEY_RE = new RegExp([
34379
34437
  "whsec_[A-Za-z0-9]{16,}\\b"
34380
34438
  // webhook signing secret (Stripe-style)
34381
34439
  ].map((p) => `\\b${p}`).join("|"), "g");
34382
- var QUERY_SECRET_RE = /([?&](?:access_token|refresh_token|client_secret|api_?key|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
34440
+ 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;
34441
+ var OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
34442
+ var FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
34443
+ var HEADER_SECRET_RE = /(\b(?:x[-_][a-z0-9_-]*?(?:api[-_]?key|token|secret|auth)[a-z0-9_-]*|api[-_]?key)\s*:\s*)[^\s,;"'<>`]+/gi;
34383
34444
  var AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
34384
- var JSON_SECRET_KEYS = "access_token|refresh_token|client_secret|api_?key|password|passwd|secret|token";
34385
- var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")[^"]*(")`, "gi");
34386
- var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')[^']*(')`, "gi");
34445
+ var JSON_SECRET_KEYS = [
34446
+ "(?:access|refresh|id|auth|session|bearer|csrf|xsrf)[_-]?token",
34447
+ "client[_-]?secret",
34448
+ "api[_-]?secret",
34449
+ "(?:x[_-])?api[_-]?key",
34450
+ "private[_-]?key",
34451
+ "x[_-][a-z0-9_-]*?(?:api[_-]?key|token|secret|auth)[a-z0-9_-]*",
34452
+ "(?:proxy-)?authorization",
34453
+ "password",
34454
+ "passwd",
34455
+ "secret",
34456
+ "token"
34457
+ ].join("|");
34458
+ var JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")(?:[^"\\\\]|\\\\.)*(")`, "gi");
34459
+ var JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')(?:[^'\\\\]|\\\\.)*(')`, "gi");
34387
34460
  function redactSecrets(text) {
34388
- 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]");
34461
+ 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]");
34389
34462
  }
34390
34463
 
34391
34464
  // ../../node_modules/@chrischall/mcp-utils/dist/response/view.js
@@ -34464,6 +34537,11 @@ function walk(value, keep, drop) {
34464
34537
  }
34465
34538
 
34466
34539
  // ../../node_modules/@chrischall/mcp-utils/dist/response/index.js
34540
+ function textResult(data) {
34541
+ return {
34542
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
34543
+ };
34544
+ }
34467
34545
  function rawTextResult(text) {
34468
34546
  return { content: [{ type: "text", text }] };
34469
34547
  }
@@ -34474,6 +34552,154 @@ function errorResult(message) {
34474
34552
  };
34475
34553
  }
34476
34554
 
34555
+ // ../../node_modules/@chrischall/mcp-utils/dist/server/confirmation.js
34556
+ import { createHash, createHmac, timingSafeEqual } from "node:crypto";
34557
+ var DEFAULT_REQUEST_KEY = "confirmation";
34558
+ var DEFAULT_CONFIRMATION_LABEL = "Confirm this action should proceed.";
34559
+ var UNSUPPORTED_NOTE = "Nothing was done because this client cannot show a confirmation prompt (it declares no MCP elicitation capability), and this action is never taken without one";
34560
+ var STATE_PREFIX = "mcpu.confirm.v1.";
34561
+ function canonicalJson(value) {
34562
+ if (value === null || typeof value === "string" || typeof value === "boolean")
34563
+ return JSON.stringify(value);
34564
+ if (value === void 0)
34565
+ return "null";
34566
+ if (typeof value === "number")
34567
+ return Number.isFinite(value) ? JSON.stringify(value) : `{"$num":"${String(value)}"}`;
34568
+ if (typeof value === "bigint")
34569
+ return `{"$bigint":"${value.toString()}"}`;
34570
+ if (typeof value === "function" || typeof value === "symbol") {
34571
+ throw new TypeError(`requireConfirmation: cannot bind a ${typeof value} argument value.`);
34572
+ }
34573
+ if (Array.isArray(value))
34574
+ return `[${value.map(canonicalJson).join(",")}]`;
34575
+ if (value instanceof Date) {
34576
+ return `{"$date":${JSON.stringify(Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString())}}`;
34577
+ }
34578
+ if (ArrayBuffer.isView(value)) {
34579
+ const bytes = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
34580
+ return `{"$bytes":${JSON.stringify(bytes.toString("base64"))}}`;
34581
+ }
34582
+ if (value instanceof ArrayBuffer)
34583
+ return `{"$bytes":${JSON.stringify(Buffer.from(value).toString("base64"))}}`;
34584
+ if (value instanceof Map) {
34585
+ const entries2 = [...value.entries()].map(([k, v]) => `[${canonicalJson(k)},${canonicalJson(v)}]`).sort();
34586
+ return `{"$map":[${entries2.join(",")}]}`;
34587
+ }
34588
+ if (value instanceof Set) {
34589
+ return `{"$set":[${[...value].map(canonicalJson).sort().join(",")}]}`;
34590
+ }
34591
+ const proto = Object.getPrototypeOf(value);
34592
+ if (proto !== Object.prototype && proto !== null) {
34593
+ throw new TypeError("requireConfirmation: cannot bind a non-plain object argument value (class instance).");
34594
+ }
34595
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
34596
+ return `{${entries.map(([k, v]) => `${JSON.stringify(escapeKey(k))}:${canonicalJson(v)}`).join(",")}}`;
34597
+ }
34598
+ function escapeKey(key) {
34599
+ return key.startsWith("$") ? `$${key}` : key;
34600
+ }
34601
+ function bindingKey(binding) {
34602
+ if (binding.ttlSeconds !== void 0 && !(Number.isFinite(binding.ttlSeconds) && binding.ttlSeconds > 0)) {
34603
+ throw new RangeError("requireConfirmation: binding.ttlSeconds must be a finite number greater than 0.");
34604
+ }
34605
+ const key = typeof binding.key === "string" ? Buffer.from(binding.key, "utf8") : Buffer.from(binding.key);
34606
+ if (key.length < 32) {
34607
+ throw new RangeError("requireConfirmation: binding.key must be at least 32 bytes.");
34608
+ }
34609
+ return key;
34610
+ }
34611
+ function commitment(action, args) {
34612
+ return createHash("sha256").update(`${action}\0${canonicalJson(args)}`).digest("base64url");
34613
+ }
34614
+ function mintState(key, action, binding) {
34615
+ const exp = Math.floor(Date.now() / 1e3) + (binding.ttlSeconds ?? 600);
34616
+ const body = Buffer.from(JSON.stringify({ c: commitment(action, binding.args), exp })).toString("base64url");
34617
+ const mac3 = createHmac("sha256", key).update(`${STATE_PREFIX}${body}`).digest("base64url");
34618
+ return `${STATE_PREFIX}${body}.${mac3}`;
34619
+ }
34620
+ function verifyState(key, action, binding, state) {
34621
+ if (typeof state !== "string" || !state.startsWith(STATE_PREFIX))
34622
+ return false;
34623
+ const rest = state.slice(STATE_PREFIX.length);
34624
+ const dot = rest.indexOf(".");
34625
+ if (dot < 0)
34626
+ return false;
34627
+ const body = rest.slice(0, dot);
34628
+ const mac3 = Buffer.from(rest.slice(dot + 1), "base64url");
34629
+ const expected = createHmac("sha256", key).update(`${STATE_PREFIX}${body}`).digest();
34630
+ if (mac3.length !== expected.length || !timingSafeEqual(mac3, expected))
34631
+ return false;
34632
+ let payload;
34633
+ try {
34634
+ payload = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
34635
+ } catch {
34636
+ return false;
34637
+ }
34638
+ if (typeof payload.exp !== "number" || payload.exp * 1e3 <= Date.now())
34639
+ return false;
34640
+ const want = Buffer.from(commitment(action, binding.args));
34641
+ const got = Buffer.from(typeof payload.c === "string" ? payload.c : "");
34642
+ return got.length === want.length && timingSafeEqual(got, want);
34643
+ }
34644
+ function echoedState(ctx) {
34645
+ const accessor = ctx.mcpReq.requestState;
34646
+ return typeof accessor === "function" ? accessor() : void 0;
34647
+ }
34648
+ function requireConfirmation(ctx, options) {
34649
+ const requestKey = options.requestKey ?? DEFAULT_REQUEST_KEY;
34650
+ const key = options.binding ? bindingKey(options.binding) : void 0;
34651
+ const confirmationSchema = external_exports.object({
34652
+ confirmed: external_exports.boolean().describe(options.confirmationLabel ?? DEFAULT_CONFIRMATION_LABEL)
34653
+ });
34654
+ const ask = () => {
34655
+ const preview = {
34656
+ action: options.action,
34657
+ ...options.details === void 0 ? {} : { details: options.details }
34658
+ };
34659
+ return inputRequired({
34660
+ inputRequests: {
34661
+ [requestKey]: inputRequired.elicit({
34662
+ message: `${options.message}
34663
+ ${JSON.stringify(preview, null, 2)}`,
34664
+ requestedSchema: confirmationSchema
34665
+ })
34666
+ },
34667
+ ...key && options.binding ? { requestState: mintState(key, options.action, options.binding) } : {}
34668
+ });
34669
+ };
34670
+ const response = inputResponse(ctx.mcpReq.inputResponses, requestKey);
34671
+ const accepted = acceptedContent(ctx.mcpReq.inputResponses, requestKey, confirmationSchema);
34672
+ if (response.kind === "missing") {
34673
+ if (callerAcceptsFormElicitation(ctx) === false) {
34674
+ return textResult({
34675
+ confirmed: false,
34676
+ dispatched: false,
34677
+ action: options.action,
34678
+ reason: "confirmation-unsupported",
34679
+ note: options.unsupportedNote ? `${UNSUPPORTED_NOTE}. ${options.unsupportedNote}` : `${UNSUPPORTED_NOTE}.`
34680
+ });
34681
+ }
34682
+ return ask();
34683
+ }
34684
+ if (response.kind === "elicit" && response.action === "accept" && accepted?.confirmed === true) {
34685
+ if (key && options.binding) {
34686
+ const state = echoedState(ctx);
34687
+ if (state === void 0 || state === null) {
34688
+ return errorResult(`Confirmation for ${options.action} was accepted, but the retry carried no requestState, so it cannot be checked against the prompt that was shown. Nothing was done. The likely cause is that the MCP client or host does not round-trip requestState (it must echo the requestState from the input_required result back on the retry); asking again would loop.`);
34689
+ }
34690
+ if (!verifyState(key, options.action, options.binding, state))
34691
+ return ask();
34692
+ }
34693
+ return void 0;
34694
+ }
34695
+ return textResult({
34696
+ confirmed: false,
34697
+ cancelled: true,
34698
+ action: options.action,
34699
+ note: "Nothing was changed because the confirmation was declined, cancelled, or left unchecked."
34700
+ });
34701
+ }
34702
+
34477
34703
  // ../../node_modules/@chrischall/mcp-utils/dist/server/index.js
34478
34704
  var SERVER_PROTOCOL_VERSIONS = Object.freeze([
34479
34705
  "2026-07-28",
@@ -34568,13 +34794,47 @@ async function createMcpServer(opts) {
34568
34794
  }
34569
34795
  return server;
34570
34796
  }
34797
+ var DEFAULT_SHUTDOWN_TIMEOUT_MS = 5e3;
34798
+ var DEFAULT_REPEAT_SIGNAL_GRACE_MS = 500;
34571
34799
  function withGracefulShutdown(target, opts = {}) {
34572
34800
  const shouldExit = opts.exit ?? true;
34801
+ if (opts.timeoutMs !== void 0 && !(Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0)) {
34802
+ throw new RangeError("withGracefulShutdown: timeoutMs must be a finite number greater than 0.");
34803
+ }
34804
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS;
34805
+ if (opts.repeatSignalGraceMs !== void 0 && !(Number.isFinite(opts.repeatSignalGraceMs) && opts.repeatSignalGraceMs >= 0)) {
34806
+ throw new RangeError("withGracefulShutdown: repeatSignalGraceMs must be a finite number >= 0.");
34807
+ }
34808
+ const repeatGraceMs = opts.repeatSignalGraceMs ?? DEFAULT_REPEAT_SIGNAL_GRACE_MS;
34573
34809
  let shuttingDown = false;
34810
+ let firstSignalAt = 0;
34811
+ let exited = false;
34812
+ const exitOnce = () => {
34813
+ if (exited)
34814
+ return;
34815
+ exited = true;
34816
+ process.exit(0);
34817
+ };
34574
34818
  const handler = (signal) => {
34575
- if (shuttingDown)
34819
+ if (shuttingDown) {
34820
+ if (Date.now() - firstSignalAt < repeatGraceMs)
34821
+ return;
34822
+ if (shouldExit) {
34823
+ console.error(`[mcp-utils] second ${signal} during shutdown \u2014 exiting now`);
34824
+ exitOnce();
34825
+ }
34576
34826
  return;
34827
+ }
34577
34828
  shuttingDown = true;
34829
+ firstSignalAt = Date.now();
34830
+ let timer;
34831
+ if (shouldExit) {
34832
+ timer = setTimeout(() => {
34833
+ console.error(`[mcp-utils] graceful shutdown on ${signal} did not finish in ${timeoutMs}ms \u2014 exiting`);
34834
+ exitOnce();
34835
+ }, timeoutMs);
34836
+ timer.unref?.();
34837
+ }
34578
34838
  void (async () => {
34579
34839
  try {
34580
34840
  if (opts.onSignal)
@@ -34583,8 +34843,10 @@ function withGracefulShutdown(target, opts = {}) {
34583
34843
  } catch (err) {
34584
34844
  console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
34585
34845
  } finally {
34846
+ if (timer !== void 0)
34847
+ clearTimeout(timer);
34586
34848
  if (shouldExit)
34587
- process.exit(0);
34849
+ exitOnce();
34588
34850
  }
34589
34851
  })();
34590
34852
  };
@@ -34614,6 +34876,8 @@ function runMcp(opts) {
34614
34876
  }
34615
34877
 
34616
34878
  // ../../node_modules/@chrischall/mcp-utils/dist/config/index.js
34879
+ import { homedir } from "node:os";
34880
+ import { isAbsolute, join, resolve } from "node:path";
34617
34881
  var PLACEHOLDER_RE = /^\$\{[^}]*\}$/;
34618
34882
  function readEnvVar(key, opts = {}) {
34619
34883
  const env = opts.env ?? process.env;
@@ -34640,6 +34904,50 @@ function parseBoolEnv(key, opts = {}) {
34640
34904
  return false;
34641
34905
  return fallback;
34642
34906
  }
34907
+ function expandPath(p) {
34908
+ let expanded = p;
34909
+ if (p === "~") {
34910
+ expanded = homedir();
34911
+ } else if (p.startsWith("~/")) {
34912
+ expanded = join(homedir(), p.slice(2));
34913
+ }
34914
+ return isAbsolute(expanded) ? expanded : resolve(expanded);
34915
+ }
34916
+
34917
+ // ../../node_modules/@chrischall/mcp-utils/dist/fs/confine.js
34918
+ import { existsSync, realpathSync } from "node:fs";
34919
+ import { dirname, isAbsolute as isAbsolute2, relative, resolve as resolve2, sep } from "node:path";
34920
+ function isInside(root, target) {
34921
+ const rel = relative(root, target);
34922
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute2(rel);
34923
+ }
34924
+ function realPathAllowingMissing(p) {
34925
+ const abs = resolve2(p);
34926
+ let existing = abs;
34927
+ const tail = [];
34928
+ while (!existsSync(existing)) {
34929
+ const parent = dirname(existing);
34930
+ if (parent === existing)
34931
+ break;
34932
+ tail.unshift(existing.slice(parent.length).replace(/^[/\\]+/, ""));
34933
+ existing = parent;
34934
+ }
34935
+ let real;
34936
+ try {
34937
+ real = realpathSync(existing);
34938
+ } catch {
34939
+ real = existing;
34940
+ }
34941
+ return tail.length > 0 ? resolve2(real, ...tail) : real;
34942
+ }
34943
+ function assertPathWithinRoots(path, roots) {
34944
+ const target = realPathAllowingMissing(expandPath(path));
34945
+ for (const root of roots) {
34946
+ if (isInside(realPathAllowingMissing(expandPath(root)), target))
34947
+ return target;
34948
+ }
34949
+ throw new Error(`Path is outside the allowed directories: ${path}`);
34950
+ }
34643
34951
 
34644
34952
  // ../../node_modules/@chrischall/mcp-utils/dist/zod/index.js
34645
34953
  var PositiveInt = external_exports.number().int().positive();
@@ -34661,7 +34969,7 @@ var pageSchema = {
34661
34969
  };
34662
34970
 
34663
34971
  // ../gogcli-mcp/src/runner.ts
34664
- import { delimiter, join } from "node:path";
34972
+ import { delimiter, join as join2 } from "node:path";
34665
34973
 
34666
34974
  // ../gogcli-mcp/src/timestamps.ts
34667
34975
  var DEFAULT_DISPLAY_TZ = "America/New_York";
@@ -34687,9 +34995,9 @@ function offsetAt(instant, tz) {
34687
34995
  const w = wallPartsIn(instant, tz);
34688
34996
  const asUTC = Date.UTC(w.year, w.month - 1, w.day, w.hour, w.minute, w.second, instant.getUTCMilliseconds());
34689
34997
  const minutes = Math.round((asUTC - instant.getTime()) / 6e4);
34690
- const sign = minutes < 0 ? "-" : "+";
34998
+ const sign2 = minutes < 0 ? "-" : "+";
34691
34999
  const abs = Math.abs(minutes);
34692
- return `${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`;
35000
+ return `${sign2}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`;
34693
35001
  }
34694
35002
  function wallPartsIn(instant, tz) {
34695
35003
  const parts = new Intl.DateTimeFormat("en-US", {
@@ -34862,9 +35170,48 @@ function normalizeTimestamps(text, tz = displayTimeZone(), naiveTz = naiveSource
34862
35170
  return JSON.stringify(parsed, null, detectIndent(text));
34863
35171
  }
34864
35172
 
35173
+ // ../gogcli-mcp/src/arg-guard.ts
35174
+ var FORBIDDEN_LONG_FLAG = /^--(readonly|enable-commands|enable-commands-exact|disable-commands|access-token|home|account|acct|client|gmail-no-send|no-input|non-interactive|noninteractive)(=|$)/i;
35175
+ var SHORT_ACCOUNT_CLUSTER = /^-(?!-)[A-Za-z]*a/;
35176
+ function forbiddenArgReason(arg) {
35177
+ if (arg === "--") {
35178
+ return 'The argument "--" is not allowed: it ends flag parsing and would disable safety flags appended after it.';
35179
+ }
35180
+ const match = FORBIDDEN_LONG_FLAG.exec(arg);
35181
+ if (match) {
35182
+ return `The flag ${arg} is not allowed here: --${match[1].toLowerCase()} is a safety/credential control set by the server operator, not a per-call option.`;
35183
+ }
35184
+ if (SHORT_ACCOUNT_CLUSTER.test(arg)) {
35185
+ return `The flag ${arg} is not allowed here: -a selects the account. Use the tool's account parameter instead.`;
35186
+ }
35187
+ return void 0;
35188
+ }
35189
+ function assertSafeForwardedArgs(args) {
35190
+ for (const arg of args) {
35191
+ const reason = forbiddenArgReason(arg);
35192
+ if (reason) throw new Error(reason);
35193
+ }
35194
+ }
35195
+ var SUBCOMMAND_SHAPE = /^[a-z][a-z0-9-]*$/;
35196
+ function assertSafeSubcommand(subcommand) {
35197
+ if (!SUBCOMMAND_SHAPE.test(subcommand)) {
35198
+ throw new Error(
35199
+ `Invalid subcommand ${JSON.stringify(subcommand)}: pass a single gog subcommand name such as "list" or "mark-read", and put its arguments in args.`
35200
+ );
35201
+ }
35202
+ }
35203
+
35204
+ // ../gogcli-mcp/src/argv.ts
35205
+ function pos(value) {
35206
+ return { kind: "positional", value };
35207
+ }
35208
+ function isGogPositional(arg) {
35209
+ return typeof arg === "object" && arg !== null && arg.kind === "positional";
35210
+ }
35211
+
34865
35212
  // ../gogcli-mcp/src/runner.ts
34866
35213
  function isGogFileArg(arg) {
34867
- return typeof arg !== "string";
35214
+ return typeof arg !== "string" && arg.kind === "file";
34868
35215
  }
34869
35216
  var TIMEOUT_MS = 3e4;
34870
35217
  function readonlyEnvEnabled() {
@@ -34948,8 +35295,8 @@ function formatTimeout(ms) {
34948
35295
  }
34949
35296
  async function spawnWithTempFiles(args, opts) {
34950
35297
  const { mkdtemp, mkdir, writeFile, rm } = await import("node:fs/promises");
34951
- const { tmpdir } = await import("node:os");
34952
- const dir = await mkdtemp(join(tmpdir(), "gogcli-mcp-"));
35298
+ const { tmpdir: tmpdir2 } = await import("node:os");
35299
+ const dir = await mkdtemp(join2(tmpdir2(), "gogcli-mcp-"));
34953
35300
  try {
34954
35301
  const argv = [];
34955
35302
  let seq = 0;
@@ -34958,10 +35305,10 @@ async function spawnWithTempFiles(args, opts) {
34958
35305
  argv.push(arg);
34959
35306
  continue;
34960
35307
  }
34961
- const sub = join(dir, String(seq));
35308
+ const sub = join2(dir, String(seq));
34962
35309
  seq += 1;
34963
35310
  await mkdir(sub, { recursive: true, mode: 448 });
34964
- const path = join(sub, arg.filename ?? `${arg.flag}.${arg.ext ?? "txt"}`);
35311
+ const path = join2(sub, arg.filename ?? `${arg.flag}.${arg.ext ?? "txt"}`);
34965
35312
  const data = arg.encoding === "base64" ? Buffer.from(arg.contents, "base64") : Buffer.from(arg.contents, "utf8");
34966
35313
  await writeFile(path, data, { mode: 384 });
34967
35314
  argv.push(arg.positional ? path : `--${arg.flag}=${path}`);
@@ -34979,10 +35326,10 @@ function spawnExecutor(args, opts) {
34979
35326
  return spawnGog(args, opts);
34980
35327
  }
34981
35328
  async function spawnGog(fullArgs, opts) {
34982
- const { timeout, interactive = false, spawner, binary = false } = opts;
35329
+ const { timeout, interactive = false, spawner, binary = false, maxOutputBytes } = opts;
34983
35330
  const spawn = spawner ?? (await import("node:child_process")).spawn;
34984
35331
  const effectiveTimeout = timeout ?? TIMEOUT_MS;
34985
- return new Promise((resolve, reject) => {
35332
+ return new Promise((resolve4, reject) => {
34986
35333
  const childEnv = { ...sanitizedEnv(), GOG_TIMEZONE: naiveSourceTimeZone(), PATH: augmentedPath() };
34987
35334
  const child = spawn(readEnvVar("GOG_PATH") ?? "gog", fullArgs, { env: childEnv });
34988
35335
  const stdoutChunks = [];
@@ -35000,7 +35347,17 @@ async function spawnGog(fullArgs, opts) {
35000
35347
  child.kill();
35001
35348
  reject(new Error(`gog timed out after ${formatTimeout(effectiveTimeout)}`));
35002
35349
  }, effectiveTimeout);
35350
+ let stdoutBytes = 0;
35003
35351
  child.stdout.on("data", (chunk) => {
35352
+ if (settled) return;
35353
+ stdoutBytes += chunk.length;
35354
+ if (maxOutputBytes !== void 0 && stdoutBytes > maxOutputBytes) {
35355
+ settled = true;
35356
+ stopWatching();
35357
+ child.kill();
35358
+ reject(new Error(`gog output exceeded the limit: more than ${maxOutputBytes} bytes`));
35359
+ return;
35360
+ }
35004
35361
  stdoutChunks.push(chunk);
35005
35362
  });
35006
35363
  child.stderr.on("data", (chunk) => {
@@ -35017,14 +35374,14 @@ async function spawnGog(fullArgs, opts) {
35017
35374
  const stderr = Buffer.concat(stderrChunks).toString().trim();
35018
35375
  if (code === 0) {
35019
35376
  if (binary) {
35020
- resolve(Buffer.concat(stdoutChunks).toString("base64"));
35377
+ resolve4(Buffer.concat(stdoutChunks).toString("base64"));
35021
35378
  return;
35022
35379
  }
35023
35380
  const stdout = Buffer.concat(stdoutChunks).toString();
35024
35381
  if (interactive && stderr) {
35025
- resolve(stdout + "\n" + stderr);
35382
+ resolve4(stdout + "\n" + stderr);
35026
35383
  } else {
35027
- resolve(stdout);
35384
+ resolve4(stdout);
35028
35385
  }
35029
35386
  } else {
35030
35387
  reject(new Error(stderr || `gog exited with code ${code}`));
@@ -35044,7 +35401,33 @@ async function spawnGog(fullArgs, opts) {
35044
35401
  });
35045
35402
  });
35046
35403
  }
35404
+ function placePositionals(args) {
35405
+ const flags = [];
35406
+ const positionals = [];
35407
+ let afterSeparator = false;
35408
+ for (const arg of args) {
35409
+ if (arg === "--") {
35410
+ afterSeparator = true;
35411
+ } else if (isGogPositional(arg)) {
35412
+ positionals.push(arg.value);
35413
+ } else if (afterSeparator || isGogFileArg(arg) && arg.positional) {
35414
+ positionals.push(arg);
35415
+ } else {
35416
+ flags.push(arg);
35417
+ }
35418
+ }
35419
+ return { flags, positionals };
35420
+ }
35421
+ function assertNoSafetyOverrides(flags) {
35422
+ for (const arg of flags) {
35423
+ if (typeof arg !== "string") continue;
35424
+ const reason = forbiddenArgReason(arg);
35425
+ if (reason) throw new Error(reason);
35426
+ }
35427
+ }
35047
35428
  function assembleArgs(args, opts) {
35429
+ const { flags, positionals } = placePositionals(args);
35430
+ assertNoSafetyOverrides(flags);
35048
35431
  const effectiveAccount = opts.account ?? readEnvVar("GOG_ACCOUNT");
35049
35432
  const fullArgs = ["--json", "--color=never"];
35050
35433
  if (!opts.interactive) {
@@ -35053,17 +35436,21 @@ function assembleArgs(args, opts) {
35053
35436
  if (opts.readonly || readonlyEnvEnabled()) {
35054
35437
  fullArgs.push("--readonly");
35055
35438
  }
35439
+ if (opts.gmailNoSend) {
35440
+ fullArgs.push("--gmail-no-send");
35441
+ }
35056
35442
  if (effectiveAccount) {
35057
35443
  fullArgs.push("--account", effectiveAccount);
35058
35444
  }
35059
- fullArgs.push(...args);
35445
+ fullArgs.push(...flags);
35446
+ if (positionals.length > 0) fullArgs.push("--", ...positionals);
35060
35447
  return fullArgs;
35061
35448
  }
35062
35449
  async function run(args, options = {}) {
35063
- const { account, spawner, interactive = false, timeout, readonly: readonly2 = false, redactMode = "full", opaqueFields } = options;
35450
+ const { account, spawner, interactive = false, timeout, readonly: readonly2 = false, redactMode = "full", opaqueFields, gmailNoSend = false } = options;
35064
35451
  const base = redactMode === "tokens" ? redactGoogleTokens : redactSecrets2;
35065
35452
  const redact = opaqueFields?.length ? (text) => redactPreservingOpaqueFields(text, opaqueFields, base) : base;
35066
- const fullArgs = assembleArgs(args, { account, interactive, readonly: readonly2 });
35453
+ const fullArgs = assembleArgs(args, { account, interactive, readonly: readonly2, gmailNoSend });
35067
35454
  try {
35068
35455
  return redact(await spawnExecutor(fullArgs, { timeout, interactive, spawner }));
35069
35456
  } catch (err) {
@@ -35120,6 +35507,107 @@ function annotateTruncatedList(result, itemsKey) {
35120
35507
  return rawTextResult(JSON.stringify(out));
35121
35508
  }
35122
35509
 
35510
+ // ../gogcli-mcp/src/file-roots.ts
35511
+ import { homedir as homedir2 } from "node:os";
35512
+ import { delimiter as delimiter2, join as join4 } from "node:path";
35513
+
35514
+ // ../gogcli-mcp/src/attachment-root.ts
35515
+ import { tmpdir, userInfo } from "node:os";
35516
+ import { dirname as dirname2, join as join3, relative as relative2, resolve as resolve3, isAbsolute as isAbsolute3, sep as sep2 } from "node:path";
35517
+ var ATTACHMENT_DOWNLOAD_ROOT = join3(tmpdir(), `gogcli-mcp-attachments-${userInfo().uid}`);
35518
+ var ATTACHMENT_TTL_MS = 24 * 60 * 60 * 1e3;
35519
+
35520
+ // ../gogcli-mcp/src/file-roots.ts
35521
+ var FILE_ROOTS_ENV = "GOG_FILE_ROOTS";
35522
+ function defaultFileRoot() {
35523
+ return join4(homedir2(), "gogcli-mcp-files");
35524
+ }
35525
+ function fileRoots() {
35526
+ const raw = readEnvVar(FILE_ROOTS_ENV);
35527
+ const roots = (raw ?? "").split(delimiter2).map((r) => r.trim()).filter(Boolean);
35528
+ return roots.length > 0 ? roots : [defaultFileRoot()];
35529
+ }
35530
+ function confinePath(path, param, opts = {}) {
35531
+ if (opts.allowDash && path === "-") return path;
35532
+ const roots = [...fileRoots(), ATTACHMENT_DOWNLOAD_ROOT];
35533
+ try {
35534
+ assertPathWithinRoots(path, roots);
35535
+ } catch {
35536
+ throw new Error(
35537
+ `${param} ${JSON.stringify(path)} is outside the directories this server may read or write (${roots.join(", ")}). Put the file in one of them, or ask the server operator to widen ${FILE_ROOTS_ENV}.`
35538
+ );
35539
+ }
35540
+ return path;
35541
+ }
35542
+
35543
+ // ../gogcli-mcp/src/run-path-guard.ts
35544
+ var POSITIONAL_PATH_SUBCOMMANDS = {
35545
+ appscript: { pull: "gog_appscript_pull" },
35546
+ drive: { upload: "gog_drive_upload", sync: "gog_drive_sync_push" },
35547
+ gmail: { import: "gog_gmail_import" },
35548
+ slides: {
35549
+ "add-slide": "gog_slides_add_slide",
35550
+ "insert-image": "gog_slides_insert_image",
35551
+ "replace-slide": "gog_slides_replace_slide"
35552
+ }
35553
+ };
35554
+ var PATH_FLAGS = /* @__PURE__ */ new Set(["out", "output", "out-dir", "output-dir", "dir", "worker-dir", "attach", "file", "key", "cert", "replacements"]);
35555
+ var ID_FLAGS = {
35556
+ drive: /* @__PURE__ */ new Set(["file", "filter-file"])
35557
+ };
35558
+ var EXEC_FLAGS = /* @__PURE__ */ new Set(["on-change", "on-new", "mmdc"]);
35559
+ var SHORT_PATH_CLUSTER = /^-(?!-)[A-Za-z]*[of]/;
35560
+ var LONG_FLAG = /^--([A-Za-z0-9][A-Za-z0-9-]*)(?:=([\s\S]*))?$/;
35561
+ function isPathFlag(service, name) {
35562
+ if (ID_FLAGS[service]?.has(name)) return false;
35563
+ return PATH_FLAGS.has(name) || name.endsWith("-file");
35564
+ }
35565
+ function confineFlagValue(flag, value) {
35566
+ if (value === "-") return;
35567
+ confinePath(value, flag);
35568
+ for (const part of value.split(",")) {
35569
+ if (part !== "" && part !== "-") confinePath(part, flag);
35570
+ }
35571
+ }
35572
+ function positionalPathTool(service, subcommand) {
35573
+ return POSITIONAL_PATH_SUBCOMMANDS[service]?.[subcommand];
35574
+ }
35575
+ function assertRunPathsConfined(service, subcommand, args) {
35576
+ const dedicated = positionalPathTool(service, subcommand);
35577
+ if (dedicated) {
35578
+ throw new Error(
35579
+ `gog ${service} ${subcommand} reads or writes a local path given as a positional argument, so it is not available through gog_${service}_run. Use ${dedicated}, which confines the path to GOG_FILE_ROOTS.`
35580
+ );
35581
+ }
35582
+ for (let i = 0; i < args.length; i++) {
35583
+ const arg = args[i];
35584
+ if (SHORT_PATH_CLUSTER.test(arg)) {
35585
+ throw new Error(
35586
+ `The flag ${arg} is not allowed here: spell a path flag out as --out or --file (e.g. --out=<path>) so its path can be checked against GOG_FILE_ROOTS.`
35587
+ );
35588
+ }
35589
+ const match = LONG_FLAG.exec(arg);
35590
+ if (!match) continue;
35591
+ const name = match[1].toLowerCase();
35592
+ if (EXEC_FLAGS.has(name)) {
35593
+ throw new Error(`The flag --${name} is not allowed here: it runs a local program chosen by the caller.`);
35594
+ }
35595
+ const isJson = name.endsWith("-json");
35596
+ if (!isJson && !isPathFlag(service, name)) continue;
35597
+ let value = match[2];
35598
+ if (value === void 0) {
35599
+ value = args[i + 1];
35600
+ if (value === void 0) continue;
35601
+ i++;
35602
+ }
35603
+ if (isJson) {
35604
+ if (value.startsWith("@")) confineFlagValue(`--${name}`, value.slice(1));
35605
+ continue;
35606
+ }
35607
+ confineFlagValue(`--${name}`, value);
35608
+ }
35609
+ }
35610
+
35123
35611
  // ../gogcli-mcp/src/tools/utils.ts
35124
35612
  var accountParam = external_exports.string().optional().describe(
35125
35613
  "Google account email to use, e.g. you@gmail.com \u2014 must be the full address, not a bare username. Overrides the GOG_ACCOUNT env var. Omit to use the single configured account."
@@ -35164,9 +35652,17 @@ var paginationParams = {
35164
35652
  all: external_exports.boolean().optional().describe("Fetch all pages")
35165
35653
  };
35166
35654
  function registerRunTool(server, options) {
35167
- const { service, examples, omitAccount = false, note } = options;
35655
+ const { service, examples, omitAccount = false, note, allowedSubcommands, vet, gmailNoSend = false } = options;
35656
+ for (const [, example] of examples.matchAll(/"([^"]+)"/g)) {
35657
+ const refused = allowedSubcommands && !allowedSubcommands.includes(example) || vet?.(example, []) || positionalPathTool(service, example);
35658
+ if (refused) {
35659
+ throw new Error(`gog_${service}_run example "${example}" is refused by the tool itself; list a subcommand it runs.`);
35660
+ }
35661
+ }
35168
35662
  const baseDescription = `Run any gog ${service} subcommand not covered by the other tools. Run \`gog ${service} --help\` for the full list of subcommands, or \`gog ${service} <subcommand> --help\` for flags on a specific subcommand.`;
35169
- const description = note ? `${baseDescription} ${note}` : baseDescription;
35663
+ const restriction = allowedSubcommands ? ` Only these subcommands are available: ${allowedSubcommands.join(", ")}.` : "";
35664
+ const safety = ' Flags that override server safety controls (--readonly, --enable-commands, --disable-commands, --account, --access-token, --home, --client, --gmail-no-send, --no-input) and a bare "--" are refused. Local file paths (--out, --out-dir, --attach, --file, --*-file, @file JSON) must be inside GOG_FILE_ROOTS; subcommands that take a local path positionally (e.g. drive upload) are refused in favour of their dedicated tools.';
35665
+ const description = `${baseDescription}${restriction}${safety}${note ? ` ${note}` : ""}`;
35170
35666
  const inputSchema = {
35171
35667
  subcommand: external_exports.string().describe(`The gog ${service} subcommand to run, e.g. ${examples}`),
35172
35668
  args: external_exports.array(external_exports.string()).describe("Additional positional args and flags")
@@ -35180,7 +35676,21 @@ function registerRunTool(server, options) {
35180
35676
  inputSchema: external_exports.object(inputSchema)
35181
35677
  }, async (rawArgs) => {
35182
35678
  const { subcommand, args, account } = rawArgs;
35183
- return runOrDiagnose([service, subcommand, ...args], { account });
35679
+ try {
35680
+ assertSafeSubcommand(subcommand);
35681
+ assertSafeForwardedArgs(args);
35682
+ if (allowedSubcommands && !allowedSubcommands.includes(subcommand)) {
35683
+ throw new Error(
35684
+ `gog ${service} ${subcommand} is not available through gog_${service}_run. Allowed: ${allowedSubcommands.join(", ")}.`
35685
+ );
35686
+ }
35687
+ const refusal = vet?.(subcommand, args);
35688
+ if (refusal) throw new Error(refusal);
35689
+ assertRunPathsConfined(service, subcommand, args);
35690
+ } catch (err) {
35691
+ return errorResult(errorText(err));
35692
+ }
35693
+ return runOrDiagnose([service, subcommand, ...args], gmailNoSend ? { account, gmailNoSend } : { account });
35184
35694
  });
35185
35695
  }
35186
35696
  function errorText(err) {
@@ -35301,7 +35811,176 @@ function formatAuthHealth(raw, now) {
35301
35811
  return accounts.map((a) => formatOneAccountHealth(a, now)).join("\n\n");
35302
35812
  }
35303
35813
 
35814
+ // ../gogcli-mcp/src/send-confirm-token.ts
35815
+ import { createHash as createHash2, createHmac as createHmac2, randomBytes, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
35816
+ var CONFIRM_TOKEN_TTL_DEFAULT_SECONDS = 600;
35817
+ var PREFIX = "gct1";
35818
+ var secret;
35819
+ var spent = /* @__PURE__ */ new Map();
35820
+ function sendConfirmFallbackEnabled() {
35821
+ return readEnvVar("GOG_SEND_CONFIRM_FALLBACK")?.trim().toLowerCase() === "token";
35822
+ }
35823
+ function confirmTokenTtlSeconds() {
35824
+ const raw = readEnvVar("GOG_CONFIRM_TTL_SECONDS")?.trim();
35825
+ if (raw && /^\d+$/.test(raw)) {
35826
+ const n = Number(raw);
35827
+ if (n > 0) return n;
35828
+ }
35829
+ return CONFIRM_TOKEN_TTL_DEFAULT_SECONDS;
35830
+ }
35831
+ function hmacKey() {
35832
+ if (!secret) {
35833
+ const configured = readEnvVar("GOG_CONFIRM_SECRET");
35834
+ secret = configured ? Buffer.from(configured, "utf8") : randomBytes(32);
35835
+ }
35836
+ return secret;
35837
+ }
35838
+ function canonicalize(value) {
35839
+ if (Array.isArray(value)) return value.map(canonicalize);
35840
+ if (value && typeof value === "object") {
35841
+ const out = {};
35842
+ for (const key of Object.keys(value).sort()) {
35843
+ const v = value[key];
35844
+ if (v !== void 0) out[key] = canonicalize(v);
35845
+ }
35846
+ return out;
35847
+ }
35848
+ return value;
35849
+ }
35850
+ function hashSendPayload(payload) {
35851
+ return createHash2("sha256").update(JSON.stringify(canonicalize(payload))).digest("hex");
35852
+ }
35853
+ function sign(body) {
35854
+ return createHmac2("sha256", hmacKey()).update(`${PREFIX}.${body}`).digest("base64url");
35855
+ }
35856
+ function issueConfirmToken(binding, now = Date.now()) {
35857
+ const exp = now + confirmTokenTtlSeconds() * 1e3;
35858
+ const claims = {
35859
+ t: binding.tool,
35860
+ a: binding.account,
35861
+ g: binding.target,
35862
+ ...binding.revision === void 0 ? {} : { r: binding.revision },
35863
+ h: binding.payloadHash,
35864
+ iat: now,
35865
+ exp,
35866
+ n: randomBytes(16).toString("base64url")
35867
+ };
35868
+ const body = Buffer.from(JSON.stringify(claims), "utf8").toString("base64url");
35869
+ return { token: `${PREFIX}.${body}.${sign(body)}`, expiresAt: new Date(exp).toISOString() };
35870
+ }
35871
+ function signatureMatches(body, sig) {
35872
+ const expected = Buffer.from(sign(body), "utf8");
35873
+ const actual = Buffer.from(sig, "utf8");
35874
+ return expected.length === actual.length && timingSafeEqual2(expected, actual);
35875
+ }
35876
+ function parseClaims(body) {
35877
+ try {
35878
+ return JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
35879
+ } catch {
35880
+ return void 0;
35881
+ }
35882
+ }
35883
+ function verifyConfirmToken(token, binding, now = Date.now()) {
35884
+ for (const [nonce, exp] of spent) if (exp < now) spent.delete(nonce);
35885
+ const parts = token.split(".");
35886
+ if (parts.length !== 3 || parts[0] !== PREFIX || !parts[1] || !parts[2]) return { ok: false, error: "TOKEN_INVALID" };
35887
+ const [, body, sig] = parts;
35888
+ if (!signatureMatches(body, sig)) return { ok: false, error: "TOKEN_INVALID" };
35889
+ const claims = parseClaims(body);
35890
+ if (!claims) return { ok: false, error: "TOKEN_INVALID" };
35891
+ if (claims.t !== binding.tool || claims.a !== binding.account || claims.g !== binding.target) {
35892
+ return { ok: false, error: "TOKEN_INVALID" };
35893
+ }
35894
+ if (spent.has(claims.n)) return { ok: false, error: "TOKEN_REUSED" };
35895
+ if (now > claims.exp) return { ok: false, error: "TOKEN_EXPIRED" };
35896
+ if (claims.r !== binding.revision) return { ok: false, error: "DRAFT_CHANGED", reason: "message-id-rotated" };
35897
+ if (claims.h !== binding.payloadHash) return { ok: false, error: "DRAFT_CHANGED", reason: "payload-changed" };
35898
+ spent.set(claims.n, claims.exp);
35899
+ return { ok: true };
35900
+ }
35901
+
35902
+ // ../gogcli-mcp/src/dispatch-confirmation.ts
35903
+ var CONFIRM_ACTION_INSTRUCTION = "Show this preview to the user verbatim and proceed only after they explicitly approve in chat. Then call again with confirmToken.";
35904
+ var FALLBACK_HINT = "Or set GOG_SEND_CONFIRM_FALLBACK=token to enable two-step confirmation.";
35905
+ var CONFIRM_FALLBACK_DESCRIPTION = ' If the client cannot show that prompt (no MCP elicitation, e.g. claude.ai) and the server sets GOG_SEND_CONFIRM_FALLBACK=token, a two-step flow applies instead: call WITHOUT confirmToken and nothing is sent or changed \u2014 the result has status "confirmation-required", the full preview and a confirmToken. Show that preview to the user verbatim; only after they explicitly approve it in chat, call again with the SAME arguments plus confirmToken. The tool re-reads what it would act on and refuses (DRAFT_CHANGED, with a fresh preview and token) if it changed; TOKEN_EXPIRED / TOKEN_REUSED / TOKEN_INVALID also do nothing.';
35906
+ var confirmTokenParam = external_exports.string().optional().describe(
35907
+ `ONLY for the two-step fallback (client without MCP elicitation, server with GOG_SEND_CONFIRM_FALLBACK=token). The confirmToken from this same tool's phase-1 "confirmation-required" response, passed back ONLY after the user has seen that preview and explicitly approved it in chat \u2014 never on the first call, never invented, never reused. Call again with the same arguments. Ignored when the client supports elicitation.`
35908
+ );
35909
+ var TOKEN_ERROR_NOTE = {
35910
+ TOKEN_EXPIRED: "Nothing was sent or changed: the confirmToken expired. Call again WITHOUT confirmToken for a fresh preview, and ask the user to approve it again.",
35911
+ TOKEN_REUSED: "Nothing was sent or changed by this call: this confirmToken was already used, and one approval acts once. If doing it again is really intended, call again WITHOUT confirmToken and get a new approval.",
35912
+ TOKEN_INVALID: "Nothing was sent or changed: this confirmToken was not issued by this server for this tool, account and target (or the server has restarted since). Call again WITHOUT confirmToken for a fresh preview and approval."
35913
+ };
35914
+ var DRAFT_CHANGED_NOTE = {
35915
+ "message-id-rotated": "Nothing was sent or changed: the target was edited since the user approved it (a draft's messageId or an event's version rotated), so what would happen is not what they saw.",
35916
+ "payload-changed": "Nothing was sent or changed: what would happen no longer matches what the user approved."
35917
+ };
35918
+ function isToolResult(value) {
35919
+ return Array.isArray(value.content);
35920
+ }
35921
+ function rejection2(data) {
35922
+ return { ...textResult({ status: "confirmation-rejected", confirmed: false, dispatched: false, ...data }), isError: true };
35923
+ }
35924
+ async function tokenConfirmation(op, fallback) {
35925
+ const subject = await fallback.subject();
35926
+ if (isToolResult(subject)) return subject;
35927
+ const binding = {
35928
+ tool: fallback.tool,
35929
+ account: fallback.account ?? readEnvVar("GOG_ACCOUNT") ?? "",
35930
+ target: subject.target,
35931
+ ...subject.revision === void 0 ? {} : { revision: subject.revision },
35932
+ payloadHash: hashSendPayload(subject.payload)
35933
+ };
35934
+ const phaseOne = () => {
35935
+ const { token, expiresAt } = issueConfirmToken(binding);
35936
+ return {
35937
+ action: op,
35938
+ preview: subject.preview,
35939
+ confirmToken: token,
35940
+ expiresAt,
35941
+ ttlSeconds: confirmTokenTtlSeconds(),
35942
+ instruction: fallback.instruction ?? CONFIRM_ACTION_INSTRUCTION
35943
+ };
35944
+ };
35945
+ if (!fallback.confirmToken) {
35946
+ return textResult({ status: "confirmation-required", confirmed: false, dispatched: false, ...phaseOne() });
35947
+ }
35948
+ const verdict = verifyConfirmToken(fallback.confirmToken, binding);
35949
+ if (verdict.ok) return void 0;
35950
+ if (verdict.error === "DRAFT_CHANGED") {
35951
+ return rejection2({
35952
+ error: "DRAFT_CHANGED",
35953
+ reason: verdict.reason,
35954
+ note: `${DRAFT_CHANGED_NOTE[verdict.reason]} The current preview and a fresh confirmToken are below.`,
35955
+ ...phaseOne()
35956
+ });
35957
+ }
35958
+ return rejection2({ error: verdict.error, action: op, note: TOKEN_ERROR_NOTE[verdict.error] });
35959
+ }
35960
+ function gatedElsewhere(what, via, does, tool) {
35961
+ return `${what} ${does} and is not available through ${via}. Use ${tool}, which asks the user to confirm.`;
35962
+ }
35963
+ async function requireDispatchConfirmation(ctx, options) {
35964
+ const { action, fallback } = options;
35965
+ if (fallback && callerAcceptsFormElicitation(ctx) === false && sendConfirmFallbackEnabled()) {
35966
+ return tokenConfirmation(action, fallback);
35967
+ }
35968
+ const note = fallback ? [options.unsupportedNote, FALLBACK_HINT].filter(Boolean).join(" ") : options.unsupportedNote;
35969
+ return requireConfirmation(ctx, {
35970
+ action,
35971
+ message: options.message,
35972
+ details: options.details,
35973
+ confirmationLabel: options.confirmationLabel,
35974
+ ...note ? { unsupportedNote: note } : {}
35975
+ });
35976
+ }
35977
+ function resultText(result) {
35978
+ const first = result.content[0];
35979
+ return first && first.type === "text" && typeof first.text === "string" ? first.text : "{}";
35980
+ }
35981
+
35304
35982
  // ../gogcli-mcp/src/tools/auth.ts
35983
+ var AUTH_RUN_SUBCOMMANDS = ["list", "status", "services", "remove", "alias"];
35305
35984
  function registerAuthToolsWith(server, defaultServices) {
35306
35985
  const servicesDescribe = `Services to authorize: "all" or comma-separated list (e.g. "sheets,gmail,calendar"). Default: "${defaultServices}". Prefer the narrowest set you need \u2014 requesting a service whose Google API is not enabled on the OAuth client's project makes Google reject the WHOLE request with invalid_scope.`;
35307
35986
  const extraScopesDescribe = "Additional raw OAuth scope URIs to request, comma-separated, on top of the ones `services` implies. Use for scopes no service covers \u2014 e.g. https://www.googleapis.com/auth/bigquery.readonly, required before gog_sheets_datasource_* can read BigQuery-backed Connected Sheets. Leave unset otherwise: an extra scope whose API is not enabled on the OAuth client project makes Google reject the WHOLE authorization with invalid_scope.";
@@ -35359,7 +36038,7 @@ function registerAuthToolsWith(server, defaultServices) {
35359
36038
  })
35360
36039
  }, async ({ email: email3, services = defaultServices, extraScopes }) => {
35361
36040
  try {
35362
- const args = ["auth", "add", email3, "--services", services];
36041
+ const args = ["auth", "add", pos(email3), "--services", services];
35363
36042
  if (extraScopes) args.push(`--extra-scopes=${extraScopes}`, "--force-consent");
35364
36043
  return rawTextResult(await run(args, {
35365
36044
  interactive: true,
@@ -35379,7 +36058,7 @@ function registerAuthToolsWith(server, defaultServices) {
35379
36058
  })
35380
36059
  }, async ({ email: email3, services = defaultServices, extraScopes }) => {
35381
36060
  try {
35382
- const args = ["auth", "add", email3, "--remote", "--step", "1", "--services", services, "--force-consent"];
36061
+ const args = ["auth", "add", pos(email3), "--remote", "--step", "1", "--services", services, "--force-consent"];
35383
36062
  if (extraScopes) args.push(`--extra-scopes=${extraScopes}`);
35384
36063
  return rawTextResult(await run(args, { redactMode: "tokens" }));
35385
36064
  } catch (err) {
@@ -35406,7 +36085,7 @@ function registerAuthToolsWith(server, defaultServices) {
35406
36085
  const args = [
35407
36086
  "auth",
35408
36087
  "add",
35409
- email3,
36088
+ pos(email3),
35410
36089
  "--remote",
35411
36090
  "--step",
35412
36091
  "2",
@@ -35426,6 +36105,7 @@ function registerAuthToolsWith(server, defaultServices) {
35426
36105
  service: "auth",
35427
36106
  examples: '"remove", "alias", "list"',
35428
36107
  omitAccount: true,
36108
+ allowedSubcommands: AUTH_RUN_SUBCOMMANDS,
35429
36109
  note: "For browser-based authorization, use gog_auth_add instead."
35430
36110
  });
35431
36111
  }
@@ -35434,6 +36114,54 @@ function authToolsFor(defaultServices) {
35434
36114
  }
35435
36115
 
35436
36116
  // ../gogcli-mcp/src/tools/calendar.ts
36117
+ var CALENDAR_GATED = {
36118
+ create: "gog_calendar_create",
36119
+ add: "gog_calendar_create",
36120
+ new: "gog_calendar_create",
36121
+ update: "gog_calendar_update",
36122
+ edit: "gog_calendar_update",
36123
+ set: "gog_calendar_update",
36124
+ respond: "gog_calendar_respond",
36125
+ rsvp: "gog_calendar_respond",
36126
+ reply: "gog_calendar_respond"
36127
+ };
36128
+ function vetCalendarRun(subcommand, _args) {
36129
+ const sub = subcommand.toLowerCase();
36130
+ const tool = Object.hasOwn(CALENDAR_GATED, sub) ? CALENDAR_GATED[sub] : void 0;
36131
+ return tool ? gatedElsewhere(`gog calendar ${sub}`, "gog_calendar_run", "can change what guests see", tool) : void 0;
36132
+ }
36133
+ function parseAttendees(value) {
36134
+ if (!value) return [];
36135
+ return value.split(",").map((entry) => entry.split(";")).filter((parts) => !parts.slice(1).some((m) => m.trim().toLowerCase() === "resource")).map((parts) => parts[0].trim()).filter(Boolean);
36136
+ }
36137
+ function timeOf(t) {
36138
+ const v = t?.dateTime ?? t?.date;
36139
+ return typeof v === "string" ? v : void 0;
36140
+ }
36141
+ function eventSnapshot(raw) {
36142
+ let event;
36143
+ try {
36144
+ event = JSON.parse(raw)?.event;
36145
+ } catch {
36146
+ event = void 0;
36147
+ }
36148
+ const str = (v) => typeof v === "string" ? v : void 0;
36149
+ return {
36150
+ summary: str(event?.summary),
36151
+ start: timeOf(event?.start),
36152
+ end: timeOf(event?.end),
36153
+ organizer: str(event?.organizer?.email),
36154
+ // Guests are the OTHER people: not this account's own attendee row, not rooms.
36155
+ guests: (Array.isArray(event?.attendees) ? event.attendees : []).filter((a) => a.self !== true && a.resource !== true && typeof a.email === "string").map((a) => a.email),
36156
+ etag: str(event?.etag)
36157
+ };
36158
+ }
36159
+ async function readEvent(calendarId, eventId, account) {
36160
+ const got = await runOrDiagnose(["calendar", "event", pos(calendarId), pos(eventId)], { account });
36161
+ if (got.isError) return { error: got };
36162
+ return { event: eventSnapshot(resultText(got)) };
36163
+ }
36164
+ var CALENDAR_CONFIRM_LABEL = "Confirm that this change, which other people will see, should be made now.";
35437
36165
  var reminderParams = {
35438
36166
  reminders: external_exports.array(external_exports.string()).max(5).optional().describe(
35439
36167
  `Reminders as method:duration, e.g. ["popup:30m", "email:1d"]. Method is popup or email; duration accepts m/h/d (max 40320 minutes = 4 weeks). Google allows at most 5. These REPLACE the event's reminders \u2014 on update, pass an EMPTY array to drop custom reminders and go back to the calendar's defaults. Cannot be combined with noReminders.`
@@ -35487,7 +36215,7 @@ function registerCalendarTools(server) {
35487
36215
  })
35488
36216
  }, async ({ calendarId, from, to, days, today, query, max, pageToken, page, all, eventTypes, timezone, view, account }) => {
35489
36217
  const args = ["calendar", "events"];
35490
- if (calendarId) args.push(calendarId);
36218
+ if (calendarId) args.push(pos(calendarId));
35491
36219
  if (from) args.push(`--from=${from}`);
35492
36220
  if (to) args.push(`--to=${to}`);
35493
36221
  if (days !== void 0) args.push(`--days=${days}`);
@@ -35516,12 +36244,12 @@ function registerCalendarTools(server) {
35516
36244
  account: accountParam
35517
36245
  })
35518
36246
  }, async ({ calendarId, eventId, timezone, account }) => {
35519
- const args = ["calendar", "event", calendarId, eventId];
36247
+ const args = ["calendar", "event", pos(calendarId), pos(eventId)];
35520
36248
  if (timezone) args.push(`--timezone=${timezone}`);
35521
36249
  return runOrDiagnose(args, { account });
35522
36250
  });
35523
36251
  server.registerTool("gog_calendar_create", {
35524
- description: "Create a calendar event. Set withZoom=true to attach a Zoom meeting (requires Zoom S2S OAuth setup via gog_zoom_auth_setup; the join URL + meeting ID + passcode are appended to the event description \u2014 Google rejects native conference card writes from non-Workspace-Marketplace OAuth clients).",
36252
+ description: "Create a calendar event. Set withZoom=true to attach a Zoom meeting (requires Zoom S2S OAuth setup via gog_zoom_auth_setup; the join URL + meeting ID + passcode are appended to the event description \u2014 Google rejects native conference card writes from non-Workspace-Marketplace OAuth clients). With attendees, the event lands on other people's calendars (no invitation email is sent), so the MCP host is asked to show the user a confirmation prompt with the guests, time and details first; a guest-free event is created without asking." + CONFIRM_FALLBACK_DESCRIPTION,
35525
36253
  annotations: { destructiveHint: false },
35526
36254
  inputSchema: external_exports.object({
35527
36255
  calendarId: external_exports.string().describe('Calendar ID (use "primary" for the default calendar)'),
@@ -35535,10 +36263,11 @@ function registerCalendarTools(server) {
35535
36263
  timezone: external_exports.string().optional().describe("IANA timezone metadata applied to from/to (e.g. America/New_York). Sets both start and end timezone unless start/end timezone are overridden."),
35536
36264
  withZoom: external_exports.boolean().optional().describe("Create a Zoom video conference for this event (requires Zoom S2S OAuth setup)"),
35537
36265
  ...reminderParams,
35538
- account: accountParam
36266
+ account: accountParam,
36267
+ confirmToken: confirmTokenParam
35539
36268
  })
35540
- }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, timezone, withZoom, reminders, noReminders, account }) => {
35541
- const args = ["calendar", "create", calendarId, `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
36269
+ }, async ({ calendarId, summary, from, to, description, location, attendees, allDay, timezone, withZoom, reminders, noReminders, account, confirmToken }, ctx) => {
36270
+ const args = ["calendar", "create", pos(calendarId), `--summary=${summary}`, `--from=${from}`, `--to=${to}`];
35542
36271
  if (description) args.push(`--description=${description}`);
35543
36272
  if (location) args.push(`--location=${location}`);
35544
36273
  if (attendees) args.push(`--attendees=${attendees}`);
@@ -35546,10 +36275,28 @@ function registerCalendarTools(server) {
35546
36275
  if (timezone) args.push(`--timezone=${timezone}`);
35547
36276
  if (withZoom) args.push("--with-zoom");
35548
36277
  pushReminderFlags(args, { reminders, noReminders });
36278
+ const guests = parseAttendees(attendees);
36279
+ if (guests.length > 0) {
36280
+ const event = { calendarId, summary, from, to, allDay: Boolean(allDay), timezone, location, description, guests, attendees, withZoom: Boolean(withZoom) };
36281
+ const confirmation = await requireDispatchConfirmation(ctx, {
36282
+ action: "calendar.create",
36283
+ message: "Review and confirm this event, which will appear on the guests' calendars:",
36284
+ confirmationLabel: CALENDAR_CONFIRM_LABEL,
36285
+ details: event,
36286
+ unsupportedNote: "Create it without attendees instead; the user can add the guests in Google Calendar.",
36287
+ fallback: {
36288
+ tool: "gog_calendar_create",
36289
+ account,
36290
+ confirmToken,
36291
+ subject: () => ({ target: calendarId, payload: event, preview: event })
36292
+ }
36293
+ });
36294
+ if (confirmation) return confirmation;
36295
+ }
35549
36296
  return runOrDiagnose(args, { account });
35550
36297
  });
35551
36298
  server.registerTool("gog_calendar_update", {
35552
- description: "Update an existing calendar event. Zoom: withZoom adds a Zoom meeting, regenerateZoom replaces the existing one, removeZoom strips it. removeMeet clears the event's Google Meet conference data (e.g. before attaching another provider). Conference flags are independent \u2014 use one per call.",
36299
+ description: "Update an existing calendar event. Zoom: withZoom adds a Zoom meeting, regenerateZoom replaces the existing one, removeZoom strips it. removeMeet clears the event's Google Meet conference data (e.g. before attaching another provider). Conference flags are independent \u2014 use one per call. A change guests can see (time, title, place, description, attendees, attachments, conferencing) on an event that has guests \u2014 or gains them \u2014 reads the event and asks the MCP host to show the user a confirmation prompt with the event as it stands and the change; no invitation email is sent. Reminder-only changes and guest-free events are updated without asking." + CONFIRM_FALLBACK_DESCRIPTION,
35553
36300
  annotations: { destructiveHint: false },
35554
36301
  inputSchema: external_exports.object({
35555
36302
  calendarId: external_exports.string().describe("Calendar ID"),
@@ -35567,10 +36314,11 @@ function registerCalendarTools(server) {
35567
36314
  removeZoom: external_exports.boolean().optional().describe("Remove the event's Zoom video conference"),
35568
36315
  removeMeet: external_exports.boolean().optional().describe("Remove the event's Google Meet video conference (clears conference data only)"),
35569
36316
  ...reminderParams,
35570
- account: accountParam
36317
+ account: accountParam,
36318
+ confirmToken: confirmTokenParam
35571
36319
  })
35572
- }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, addAttendees, attachments, withZoom, regenerateZoom, removeZoom, removeMeet, reminders, noReminders, account }) => {
35573
- const args = ["calendar", "update", calendarId, eventId];
36320
+ }, async ({ calendarId, eventId, summary, from, to, description, location, attendees, addAttendees, attachments, withZoom, regenerateZoom, removeZoom, removeMeet, reminders, noReminders, account, confirmToken }, ctx) => {
36321
+ const args = ["calendar", "update", pos(calendarId), pos(eventId)];
35574
36322
  if (summary !== void 0) args.push(`--summary=${summary}`);
35575
36323
  if (from !== void 0) args.push(`--from=${from}`);
35576
36324
  if (to !== void 0) args.push(`--to=${to}`);
@@ -35584,6 +36332,45 @@ function registerCalendarTools(server) {
35584
36332
  if (removeZoom) args.push("--remove-zoom");
35585
36333
  if (removeMeet) args.push("--remove-meet");
35586
36334
  pushReminderFlags(args, { reminders, noReminders });
36335
+ const changes = Object.fromEntries(Object.entries({
36336
+ summary,
36337
+ from,
36338
+ to,
36339
+ description,
36340
+ location,
36341
+ attendees,
36342
+ addAttendees,
36343
+ attachments,
36344
+ withZoom,
36345
+ regenerateZoom,
36346
+ removeZoom,
36347
+ removeMeet
36348
+ }).filter(([, v]) => v !== void 0 && v !== false));
36349
+ if (Object.keys(changes).length > 0) {
36350
+ const read = await readEvent(calendarId, eventId, account);
36351
+ if (read.error) return read.error;
36352
+ const { etag, ...current } = read.event;
36353
+ const added = [...parseAttendees(attendees), ...parseAttendees(addAttendees)];
36354
+ if (current.guests.length > 0 || added.length > 0) {
36355
+ const view = { calendarId, eventId, current, changes };
36356
+ const confirmation = await requireDispatchConfirmation(ctx, {
36357
+ action: "calendar.update",
36358
+ message: "Review and confirm this change to an event other people are on:",
36359
+ confirmationLabel: CALENDAR_CONFIRM_LABEL,
36360
+ details: view,
36361
+ unsupportedNote: "Ask the user to make this change in Google Calendar.",
36362
+ fallback: {
36363
+ tool: "gog_calendar_update",
36364
+ account,
36365
+ confirmToken,
36366
+ // The etag rotates on any edit, so an event changed elsewhere between
36367
+ // the two phases is DRAFT_CHANGED rather than edited over.
36368
+ subject: () => ({ target: `${calendarId}/${eventId}`, revision: etag, payload: view, preview: view })
36369
+ }
36370
+ });
36371
+ if (confirmation) return confirmation;
36372
+ }
36373
+ }
35587
36374
  return runOrDiagnose(args, { account });
35588
36375
  });
35589
36376
  server.registerTool("gog_calendar_delete", {
@@ -35595,24 +36382,43 @@ function registerCalendarTools(server) {
35595
36382
  account: accountParam
35596
36383
  })
35597
36384
  }, async ({ calendarId, eventId, account }) => {
35598
- return runOrDiagnose(["calendar", "delete", calendarId, eventId, "--force"], { account });
36385
+ return runOrDiagnose(["calendar", "delete", pos(calendarId), pos(eventId), "--force"], { account });
35599
36386
  });
35600
36387
  server.registerTool("gog_calendar_respond", {
35601
- description: "Respond to a calendar event invitation.",
36388
+ description: "Respond to a calendar event invitation. The organizer sees the response, so this reads the event and asks the MCP host to show the user a confirmation prompt with the event, organizer, response and comment; nothing is recorded unless they accept." + CONFIRM_FALLBACK_DESCRIPTION,
35602
36389
  annotations: { destructiveHint: true },
35603
36390
  inputSchema: external_exports.object({
35604
36391
  calendarId: external_exports.string().describe("Calendar ID"),
35605
36392
  eventId: external_exports.string().describe("Event ID"),
35606
36393
  status: external_exports.enum(["accepted", "declined", "tentative"]).describe("Response status"),
35607
36394
  comment: external_exports.string().optional().describe("Optional comment to include with response"),
35608
- account: accountParam
36395
+ account: accountParam,
36396
+ confirmToken: confirmTokenParam
35609
36397
  })
35610
- }, async ({ calendarId, eventId, status, comment, account }) => {
35611
- const args = ["calendar", "respond", calendarId, eventId, `--status=${status}`];
36398
+ }, async ({ calendarId, eventId, status, comment, account, confirmToken }, ctx) => {
36399
+ const args = ["calendar", "respond", pos(calendarId), pos(eventId), `--status=${status}`];
35612
36400
  if (comment) args.push(`--comment=${comment}`);
36401
+ const read = await readEvent(calendarId, eventId, account);
36402
+ if (read.error) return read.error;
36403
+ const { etag, ...event } = read.event;
36404
+ const view = { calendarId, eventId, event, response: status, ...comment ? { comment } : {} };
36405
+ const confirmation = await requireDispatchConfirmation(ctx, {
36406
+ action: "calendar.respond",
36407
+ message: "Review and confirm this response, which the organizer will see:",
36408
+ confirmationLabel: "Confirm that this response should be recorded now.",
36409
+ details: view,
36410
+ unsupportedNote: "Ask the user to respond from Google Calendar.",
36411
+ fallback: {
36412
+ tool: "gog_calendar_respond",
36413
+ account,
36414
+ confirmToken,
36415
+ subject: () => ({ target: `${calendarId}/${eventId}`, revision: etag, payload: view, preview: view })
36416
+ }
36417
+ });
36418
+ if (confirmation) return confirmation;
35613
36419
  return runOrDiagnose(args, { account });
35614
36420
  });
35615
- registerRunTool(server, { service: "calendar", examples: '"calendars", "freebusy"' });
36421
+ registerRunTool(server, { service: "calendar", examples: '"calendars", "freebusy"', vet: vetCalendarRun });
35616
36422
  }
35617
36423
 
35618
36424
  // ../gogcli-mcp/src/attachments.ts
@@ -35647,7 +36453,7 @@ var replySchema = {
35647
36453
  remove: external_exports.array(external_exports.string()).optional().describe("Remove these recipients from all fields (repeatable) \u2014 e.g. to drop someone from a reply-all."),
35648
36454
  subject: external_exports.string().optional().describe('Override reply subject (default: "Re: <original>"). A changed subject starts a NEW Gmail thread.'),
35649
36455
  noQuote: external_exports.boolean().optional().describe("Do not include the original message quoted below the reply (default: the original is quoted)"),
35650
- attach: external_exports.array(external_exports.string()).optional().describe(`File paths to attach (repeatable), resolved ON THE GOG SERVER's filesystem \u2014 NOT this client's. Only usable when gog runs on the same machine you do (local stdio); on a hosted deployment (e.g. mcp-host) these paths do not exist and the call fails with "no such file or directory" \u2014 use attachInline there. Read on the server, base64-encoded with a MIME type inferred from the extension.`),
36456
+ attach: external_exports.array(external_exports.string()).optional().describe(`File paths to attach (repeatable), resolved ON THE GOG SERVER's filesystem \u2014 NOT this client's. Only usable when gog runs on the same machine you do (local stdio); on a hosted deployment (e.g. mcp-host) these paths do not exist and the call fails with "no such file or directory" \u2014 use attachInline there. Read on the server, base64-encoded with a MIME type inferred from the extension. Must be inside the server's GOG_FILE_ROOTS directories (default ~/gogcli-mcp-files).`),
35651
36457
  attachInline: attachInlineParam,
35652
36458
  from: external_exports.string().optional().describe("Send from this email address (must be a verified send-as alias)"),
35653
36459
  autoFromAddressedAlias: external_exports.boolean().optional().describe("When from is omitted, send from the verified send-as alias the original message was addressed TO, instead of the account's primary address \u2014 so a reply to mail sent to an alias goes back out from that alias. Ignored when from is set."),
@@ -35656,7 +36462,7 @@ var replySchema = {
35656
36462
  signatureFile: external_exports.string().optional().describe("Append a local signature file (plain text or HTML), read on the gog server"),
35657
36463
  account: accountParam
35658
36464
  };
35659
- var sendReplySchema = external_exports.object(replySchema);
36465
+ var sendReplySchema = external_exports.object({ ...replySchema, confirmToken: confirmTokenParam });
35660
36466
 
35661
36467
  // ../gogcli-mcp/src/tools/sheets.ts
35662
36468
  var cellValueParam = external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null()]);
@@ -35668,10 +36474,10 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
35668
36474
  );
35669
36475
 
35670
36476
  // ../gogcli-mcp/src/server.ts
35671
- var VERSION = true ? "4.2.5" : "0.0.0";
36477
+ var VERSION = true ? "4.4.0" : "0.0.0";
35672
36478
 
35673
36479
  // ../gogcli-mcp/src/bootstrap-auth.ts
35674
- import { join as join2 } from "node:path";
36480
+ import { join as join5 } from "node:path";
35675
36481
  var AUTH_BOOTSTRAP_MARKER = "auth-bootstrap.sha256";
35676
36482
  var VARS = ["GOG_CLIENT_ID", "GOG_CLIENT_SECRET", "GOG_REFRESH_TOKEN", "GOG_ACCOUNT"];
35677
36483
  var log = (line) => {
@@ -35705,12 +36511,12 @@ async function bootstrapGogAuth(env = process.env, options = {}) {
35705
36511
  const [clientId, clientSecret, refreshToken, account] = values;
35706
36512
  const { spawner } = options;
35707
36513
  try {
35708
- const { createHash } = await import("node:crypto");
36514
+ const { createHash: createHash3 } = await import("node:crypto");
35709
36515
  const { mkdir, readFile, writeFile, chmod } = await import("node:fs/promises");
35710
36516
  const home = options.home ?? (await import("node:os")).homedir();
35711
- const dir = join2(home, ".gogcli-mcp");
35712
- const marker = join2(dir, AUTH_BOOTSTRAP_MARKER);
35713
- const fingerprint = createHash("sha256").update(values.join("\0")).digest("hex");
36517
+ const dir = join5(home, ".gogcli-mcp");
36518
+ const marker = join5(dir, AUTH_BOOTSTRAP_MARKER);
36519
+ const fingerprint = createHash3("sha256").update(values.join("\0")).digest("hex");
35714
36520
  const previous = await readFile(marker, "utf8").catch(() => void 0);
35715
36521
  if (previous === fingerprint && await accountListed(account, spawner)) return "present";
35716
36522
  await run(
@@ -35767,7 +36573,7 @@ function registerExtraCalendarTools(server) {
35767
36573
  account: accountParam
35768
36574
  })
35769
36575
  }, async ({ meetingCode, account }) => {
35770
- return runOrDiagnose(["meet", "get", meetingCode], { account });
36576
+ return runOrDiagnose(["meet", "get", pos(meetingCode)], { account });
35771
36577
  });
35772
36578
  server.registerTool("gog_meet_update", {
35773
36579
  description: "Update a Google Meet space configuration.",
@@ -35778,7 +36584,7 @@ function registerExtraCalendarTools(server) {
35778
36584
  account: accountParam
35779
36585
  })
35780
36586
  }, async ({ meetingCode, access, account }) => {
35781
- const args = ["meet", "update", meetingCode];
36587
+ const args = ["meet", "update", pos(meetingCode)];
35782
36588
  if (access) args.push(`--access=${access}`);
35783
36589
  return runOrDiagnose(args, { account });
35784
36590
  });
@@ -35790,7 +36596,7 @@ function registerExtraCalendarTools(server) {
35790
36596
  account: accountParam
35791
36597
  })
35792
36598
  }, async ({ meetingCode, account }) => {
35793
- return runOrDiagnose(["meet", "end", meetingCode, "--force"], { account });
36599
+ return runOrDiagnose(["meet", "end", pos(meetingCode), "--force"], { account });
35794
36600
  });
35795
36601
  server.registerTool("gog_meet_history", {
35796
36602
  description: "List past calls (conferences) in a Google Meet space.",
@@ -35804,7 +36610,7 @@ function registerExtraCalendarTools(server) {
35804
36610
  account: accountParam
35805
36611
  })
35806
36612
  }, async ({ meetingCode, max, pageToken, page, all, account }) => {
35807
- const args = ["meet", "history", meetingCode];
36613
+ const args = ["meet", "history", pos(meetingCode)];
35808
36614
  if (max !== void 0) args.push(`--max=${max}`);
35809
36615
  const token = resolvePageToken({ pageToken, page });
35810
36616
  if (token) args.push(`--page=${token}`);
@@ -35879,7 +36685,7 @@ function registerExtraCalendarTools(server) {
35879
36685
  account: accountParam
35880
36686
  })
35881
36687
  }, async ({ query, from, to, today, tomorrow, week, days, weekStart, calendar, max, account }) => {
35882
- const args = ["calendar", "search", query];
36688
+ const args = ["calendar", "search", pos(query)];
35883
36689
  if (from) args.push(`--from=${from}`);
35884
36690
  if (to) args.push(`--to=${to}`);
35885
36691
  if (today) args.push("--today");
@@ -35904,7 +36710,7 @@ function registerExtraCalendarTools(server) {
35904
36710
  })
35905
36711
  }, async ({ calendarId, calendarIds, since, max, all, account }) => {
35906
36712
  const args = ["calendar", "changed"];
35907
- if (calendarId) args.push(calendarId);
36713
+ if (calendarId) args.push(pos(calendarId));
35908
36714
  if (calendarIds) args.push(`--calendars=${calendarIds}`);
35909
36715
  if (since) args.push(`--since=${since}`);
35910
36716
  if (max !== void 0) args.push(`--max=${max}`);
@@ -35923,7 +36729,7 @@ function registerExtraCalendarTools(server) {
35923
36729
  })
35924
36730
  }, async ({ from, to, calendarIds, all, account }) => {
35925
36731
  const args = ["calendar", "freebusy"];
35926
- if (calendarIds) args.push(calendarIds);
36732
+ if (calendarIds) args.push(pos(calendarIds));
35927
36733
  args.push(`--from=${from}`);
35928
36734
  args.push(`--to=${to}`);
35929
36735
  if (all) args.push("--all");
@@ -35950,7 +36756,7 @@ function registerExtraCalendarTools(server) {
35950
36756
  account: accountParam
35951
36757
  })
35952
36758
  }, async ({ calendarId, max, pageToken, page, all, account }) => {
35953
- const args = ["calendar", "acl", calendarId];
36759
+ const args = ["calendar", "acl", pos(calendarId)];
35954
36760
  if (max !== void 0) args.push(`--max=${max}`);
35955
36761
  const token = resolvePageToken({ pageToken, page });
35956
36762
  if (token) args.push(`--page=${token}`);
@@ -35968,7 +36774,7 @@ function registerExtraCalendarTools(server) {
35968
36774
  account: accountParam
35969
36775
  })
35970
36776
  }, async ({ calendarId, eventId, destinationCalendarId, sendUpdates, account }) => {
35971
- const args = ["calendar", "move", calendarId, eventId, destinationCalendarId];
36777
+ const args = ["calendar", "move", pos(calendarId), pos(eventId), pos(destinationCalendarId)];
35972
36778
  if (sendUpdates) args.push(`--send-updates=${sendUpdates}`);
35973
36779
  return runOrDiagnose(args, { account });
35974
36780
  });
@@ -35987,7 +36793,7 @@ function registerExtraCalendarTools(server) {
35987
36793
  })
35988
36794
  }, async ({ from, to, calendarId, summary, autoDecline, declineMessage, allDay, account }) => {
35989
36795
  const args = ["calendar", "out-of-office"];
35990
- if (calendarId) args.push(calendarId);
36796
+ if (calendarId) args.push(pos(calendarId));
35991
36797
  args.push(`--from=${from}`);
35992
36798
  args.push(`--to=${to}`);
35993
36799
  if (summary) args.push(`--summary=${summary}`);
@@ -36004,7 +36810,7 @@ function registerExtraCalendarTools(server) {
36004
36810
  account: accountParam
36005
36811
  })
36006
36812
  }, async ({ calendarId, account }) => {
36007
- return runOrDiagnose(["calendar", "unsubscribe", calendarId], { account });
36813
+ return runOrDiagnose(["calendar", "unsubscribe", pos(calendarId)], { account });
36008
36814
  });
36009
36815
  server.registerTool("gog_calendar_delete_calendar", {
36010
36816
  description: "Permanently delete an owned secondary calendar and all its events. Cannot delete your primary calendar. To merely remove a calendar you do not own from your list, use gog_calendar_unsubscribe.",
@@ -36014,7 +36820,7 @@ function registerExtraCalendarTools(server) {
36014
36820
  account: accountParam
36015
36821
  })
36016
36822
  }, async ({ calendarId, account }) => {
36017
- return runOrDiagnose(["calendar", "delete-calendar", calendarId, "--force"], { account });
36823
+ return runOrDiagnose(["calendar", "delete-calendar", pos(calendarId), "--force"], { account });
36018
36824
  });
36019
36825
  server.registerTool("gog_meet_participants", {
36020
36826
  description: "List participants from the latest (or a specific) Meet call.",
@@ -36029,7 +36835,7 @@ function registerExtraCalendarTools(server) {
36029
36835
  account: accountParam
36030
36836
  })
36031
36837
  }, async ({ meetingCode, conference, max, pageToken, page, all, account }) => {
36032
- const args = ["meet", "participants", meetingCode];
36838
+ const args = ["meet", "participants", pos(meetingCode)];
36033
36839
  if (conference) args.push(`--conference=${conference}`);
36034
36840
  if (max !== void 0) args.push(`--max=${max}`);
36035
36841
  const token = resolvePageToken({ pageToken, page });