gogcli-mcp-drive 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) {
@@ -35071,9 +35458,9 @@ async function run(args, options = {}) {
35071
35458
  }
35072
35459
  }
35073
35460
  async function runBinary(args, options = {}) {
35074
- const { account, spawner, timeout, readonly: readonly2 = false } = options;
35075
- const fullArgs = assembleArgs(args, { account, interactive: false, readonly: readonly2 });
35076
- return spawnExecutor(fullArgs, { timeout, interactive: false, spawner, binary: true });
35461
+ const { account, spawner, timeout, readonly: readonly2 = false, gmailNoSend = false, maxOutputBytes } = options;
35462
+ const fullArgs = assembleArgs(args, { account, interactive: false, readonly: readonly2, gmailNoSend });
35463
+ return spawnExecutor(fullArgs, { timeout, interactive: false, spawner, binary: true, maxOutputBytes });
35077
35464
  }
35078
35465
 
35079
35466
  // ../gogcli-mcp/src/pagination.ts
@@ -35096,6 +35483,107 @@ function stripConsumedPageToken(text) {
35096
35483
  return JSON.stringify(obj, null, detectIndent2(text));
35097
35484
  }
35098
35485
 
35486
+ // ../gogcli-mcp/src/file-roots.ts
35487
+ import { homedir as homedir2 } from "node:os";
35488
+ import { delimiter as delimiter2, join as join4 } from "node:path";
35489
+
35490
+ // ../gogcli-mcp/src/attachment-root.ts
35491
+ import { tmpdir, userInfo } from "node:os";
35492
+ import { dirname as dirname2, join as join3, relative as relative2, resolve as resolve3, isAbsolute as isAbsolute3, sep as sep2 } from "node:path";
35493
+ var ATTACHMENT_DOWNLOAD_ROOT = join3(tmpdir(), `gogcli-mcp-attachments-${userInfo().uid}`);
35494
+ var ATTACHMENT_TTL_MS = 24 * 60 * 60 * 1e3;
35495
+
35496
+ // ../gogcli-mcp/src/file-roots.ts
35497
+ var FILE_ROOTS_ENV = "GOG_FILE_ROOTS";
35498
+ function defaultFileRoot() {
35499
+ return join4(homedir2(), "gogcli-mcp-files");
35500
+ }
35501
+ function fileRoots() {
35502
+ const raw = readEnvVar(FILE_ROOTS_ENV);
35503
+ const roots = (raw ?? "").split(delimiter2).map((r) => r.trim()).filter(Boolean);
35504
+ return roots.length > 0 ? roots : [defaultFileRoot()];
35505
+ }
35506
+ function confinePath(path, param, opts = {}) {
35507
+ if (opts.allowDash && path === "-") return path;
35508
+ const roots = [...fileRoots(), ATTACHMENT_DOWNLOAD_ROOT];
35509
+ try {
35510
+ assertPathWithinRoots(path, roots);
35511
+ } catch {
35512
+ throw new Error(
35513
+ `${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}.`
35514
+ );
35515
+ }
35516
+ return path;
35517
+ }
35518
+
35519
+ // ../gogcli-mcp/src/run-path-guard.ts
35520
+ var POSITIONAL_PATH_SUBCOMMANDS = {
35521
+ appscript: { pull: "gog_appscript_pull" },
35522
+ drive: { upload: "gog_drive_upload", sync: "gog_drive_sync_push" },
35523
+ gmail: { import: "gog_gmail_import" },
35524
+ slides: {
35525
+ "add-slide": "gog_slides_add_slide",
35526
+ "insert-image": "gog_slides_insert_image",
35527
+ "replace-slide": "gog_slides_replace_slide"
35528
+ }
35529
+ };
35530
+ var PATH_FLAGS = /* @__PURE__ */ new Set(["out", "output", "out-dir", "output-dir", "dir", "worker-dir", "attach", "file", "key", "cert", "replacements"]);
35531
+ var ID_FLAGS = {
35532
+ drive: /* @__PURE__ */ new Set(["file", "filter-file"])
35533
+ };
35534
+ var EXEC_FLAGS = /* @__PURE__ */ new Set(["on-change", "on-new", "mmdc"]);
35535
+ var SHORT_PATH_CLUSTER = /^-(?!-)[A-Za-z]*[of]/;
35536
+ var LONG_FLAG = /^--([A-Za-z0-9][A-Za-z0-9-]*)(?:=([\s\S]*))?$/;
35537
+ function isPathFlag(service, name) {
35538
+ if (ID_FLAGS[service]?.has(name)) return false;
35539
+ return PATH_FLAGS.has(name) || name.endsWith("-file");
35540
+ }
35541
+ function confineFlagValue(flag, value) {
35542
+ if (value === "-") return;
35543
+ confinePath(value, flag);
35544
+ for (const part of value.split(",")) {
35545
+ if (part !== "" && part !== "-") confinePath(part, flag);
35546
+ }
35547
+ }
35548
+ function positionalPathTool(service, subcommand) {
35549
+ return POSITIONAL_PATH_SUBCOMMANDS[service]?.[subcommand];
35550
+ }
35551
+ function assertRunPathsConfined(service, subcommand, args) {
35552
+ const dedicated = positionalPathTool(service, subcommand);
35553
+ if (dedicated) {
35554
+ throw new Error(
35555
+ `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.`
35556
+ );
35557
+ }
35558
+ for (let i = 0; i < args.length; i++) {
35559
+ const arg = args[i];
35560
+ if (SHORT_PATH_CLUSTER.test(arg)) {
35561
+ throw new Error(
35562
+ `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.`
35563
+ );
35564
+ }
35565
+ const match = LONG_FLAG.exec(arg);
35566
+ if (!match) continue;
35567
+ const name = match[1].toLowerCase();
35568
+ if (EXEC_FLAGS.has(name)) {
35569
+ throw new Error(`The flag --${name} is not allowed here: it runs a local program chosen by the caller.`);
35570
+ }
35571
+ const isJson = name.endsWith("-json");
35572
+ if (!isJson && !isPathFlag(service, name)) continue;
35573
+ let value = match[2];
35574
+ if (value === void 0) {
35575
+ value = args[i + 1];
35576
+ if (value === void 0) continue;
35577
+ i++;
35578
+ }
35579
+ if (isJson) {
35580
+ if (value.startsWith("@")) confineFlagValue(`--${name}`, value.slice(1));
35581
+ continue;
35582
+ }
35583
+ confineFlagValue(`--${name}`, value);
35584
+ }
35585
+ }
35586
+
35099
35587
  // ../gogcli-mcp/src/tools/utils.ts
35100
35588
  var accountParam = external_exports.string().optional().describe(
35101
35589
  "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."
@@ -35146,9 +35634,17 @@ function pushPaginationFlags(args, p) {
35146
35634
  if (p.all) args.push("--all");
35147
35635
  }
35148
35636
  function registerRunTool(server, options) {
35149
- const { service, examples, omitAccount = false, note } = options;
35637
+ const { service, examples, omitAccount = false, note, allowedSubcommands, vet, gmailNoSend = false } = options;
35638
+ for (const [, example] of examples.matchAll(/"([^"]+)"/g)) {
35639
+ const refused = allowedSubcommands && !allowedSubcommands.includes(example) || vet?.(example, []) || positionalPathTool(service, example);
35640
+ if (refused) {
35641
+ throw new Error(`gog_${service}_run example "${example}" is refused by the tool itself; list a subcommand it runs.`);
35642
+ }
35643
+ }
35150
35644
  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.`;
35151
- const description = note ? `${baseDescription} ${note}` : baseDescription;
35645
+ const restriction = allowedSubcommands ? ` Only these subcommands are available: ${allowedSubcommands.join(", ")}.` : "";
35646
+ 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.';
35647
+ const description = `${baseDescription}${restriction}${safety}${note ? ` ${note}` : ""}`;
35152
35648
  const inputSchema = {
35153
35649
  subcommand: external_exports.string().describe(`The gog ${service} subcommand to run, e.g. ${examples}`),
35154
35650
  args: external_exports.array(external_exports.string()).describe("Additional positional args and flags")
@@ -35162,7 +35658,21 @@ function registerRunTool(server, options) {
35162
35658
  inputSchema: external_exports.object(inputSchema)
35163
35659
  }, async (rawArgs) => {
35164
35660
  const { subcommand, args, account } = rawArgs;
35165
- return runOrDiagnose([service, subcommand, ...args], { account });
35661
+ try {
35662
+ assertSafeSubcommand(subcommand);
35663
+ assertSafeForwardedArgs(args);
35664
+ if (allowedSubcommands && !allowedSubcommands.includes(subcommand)) {
35665
+ throw new Error(
35666
+ `gog ${service} ${subcommand} is not available through gog_${service}_run. Allowed: ${allowedSubcommands.join(", ")}.`
35667
+ );
35668
+ }
35669
+ const refusal = vet?.(subcommand, args);
35670
+ if (refusal) throw new Error(refusal);
35671
+ assertRunPathsConfined(service, subcommand, args);
35672
+ } catch (err) {
35673
+ return errorResult(errorText(err));
35674
+ }
35675
+ return runOrDiagnose([service, subcommand, ...args], gmailNoSend ? { account, gmailNoSend } : { account });
35166
35676
  });
35167
35677
  }
35168
35678
  function errorText(err) {
@@ -35283,7 +35793,176 @@ function formatAuthHealth(raw, now) {
35283
35793
  return accounts.map((a) => formatOneAccountHealth(a, now)).join("\n\n");
35284
35794
  }
35285
35795
 
35796
+ // ../gogcli-mcp/src/send-confirm-token.ts
35797
+ import { createHash as createHash2, createHmac as createHmac2, randomBytes, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
35798
+ var CONFIRM_TOKEN_TTL_DEFAULT_SECONDS = 600;
35799
+ var PREFIX = "gct1";
35800
+ var secret;
35801
+ var spent = /* @__PURE__ */ new Map();
35802
+ function sendConfirmFallbackEnabled() {
35803
+ return readEnvVar("GOG_SEND_CONFIRM_FALLBACK")?.trim().toLowerCase() === "token";
35804
+ }
35805
+ function confirmTokenTtlSeconds() {
35806
+ const raw = readEnvVar("GOG_CONFIRM_TTL_SECONDS")?.trim();
35807
+ if (raw && /^\d+$/.test(raw)) {
35808
+ const n = Number(raw);
35809
+ if (n > 0) return n;
35810
+ }
35811
+ return CONFIRM_TOKEN_TTL_DEFAULT_SECONDS;
35812
+ }
35813
+ function hmacKey() {
35814
+ if (!secret) {
35815
+ const configured = readEnvVar("GOG_CONFIRM_SECRET");
35816
+ secret = configured ? Buffer.from(configured, "utf8") : randomBytes(32);
35817
+ }
35818
+ return secret;
35819
+ }
35820
+ function canonicalize(value) {
35821
+ if (Array.isArray(value)) return value.map(canonicalize);
35822
+ if (value && typeof value === "object") {
35823
+ const out = {};
35824
+ for (const key of Object.keys(value).sort()) {
35825
+ const v = value[key];
35826
+ if (v !== void 0) out[key] = canonicalize(v);
35827
+ }
35828
+ return out;
35829
+ }
35830
+ return value;
35831
+ }
35832
+ function hashSendPayload(payload) {
35833
+ return createHash2("sha256").update(JSON.stringify(canonicalize(payload))).digest("hex");
35834
+ }
35835
+ function sign(body) {
35836
+ return createHmac2("sha256", hmacKey()).update(`${PREFIX}.${body}`).digest("base64url");
35837
+ }
35838
+ function issueConfirmToken(binding, now = Date.now()) {
35839
+ const exp = now + confirmTokenTtlSeconds() * 1e3;
35840
+ const claims = {
35841
+ t: binding.tool,
35842
+ a: binding.account,
35843
+ g: binding.target,
35844
+ ...binding.revision === void 0 ? {} : { r: binding.revision },
35845
+ h: binding.payloadHash,
35846
+ iat: now,
35847
+ exp,
35848
+ n: randomBytes(16).toString("base64url")
35849
+ };
35850
+ const body = Buffer.from(JSON.stringify(claims), "utf8").toString("base64url");
35851
+ return { token: `${PREFIX}.${body}.${sign(body)}`, expiresAt: new Date(exp).toISOString() };
35852
+ }
35853
+ function signatureMatches(body, sig) {
35854
+ const expected = Buffer.from(sign(body), "utf8");
35855
+ const actual = Buffer.from(sig, "utf8");
35856
+ return expected.length === actual.length && timingSafeEqual2(expected, actual);
35857
+ }
35858
+ function parseClaims(body) {
35859
+ try {
35860
+ return JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
35861
+ } catch {
35862
+ return void 0;
35863
+ }
35864
+ }
35865
+ function verifyConfirmToken(token, binding, now = Date.now()) {
35866
+ for (const [nonce, exp] of spent) if (exp < now) spent.delete(nonce);
35867
+ const parts = token.split(".");
35868
+ if (parts.length !== 3 || parts[0] !== PREFIX || !parts[1] || !parts[2]) return { ok: false, error: "TOKEN_INVALID" };
35869
+ const [, body, sig] = parts;
35870
+ if (!signatureMatches(body, sig)) return { ok: false, error: "TOKEN_INVALID" };
35871
+ const claims = parseClaims(body);
35872
+ if (!claims) return { ok: false, error: "TOKEN_INVALID" };
35873
+ if (claims.t !== binding.tool || claims.a !== binding.account || claims.g !== binding.target) {
35874
+ return { ok: false, error: "TOKEN_INVALID" };
35875
+ }
35876
+ if (spent.has(claims.n)) return { ok: false, error: "TOKEN_REUSED" };
35877
+ if (now > claims.exp) return { ok: false, error: "TOKEN_EXPIRED" };
35878
+ if (claims.r !== binding.revision) return { ok: false, error: "DRAFT_CHANGED", reason: "message-id-rotated" };
35879
+ if (claims.h !== binding.payloadHash) return { ok: false, error: "DRAFT_CHANGED", reason: "payload-changed" };
35880
+ spent.set(claims.n, claims.exp);
35881
+ return { ok: true };
35882
+ }
35883
+
35884
+ // ../gogcli-mcp/src/dispatch-confirmation.ts
35885
+ 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.";
35886
+ var FALLBACK_HINT = "Or set GOG_SEND_CONFIRM_FALLBACK=token to enable two-step confirmation.";
35887
+ 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.';
35888
+ var confirmTokenParam = external_exports.string().optional().describe(
35889
+ `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.`
35890
+ );
35891
+ var TOKEN_ERROR_NOTE = {
35892
+ 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.",
35893
+ 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.",
35894
+ 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."
35895
+ };
35896
+ var DRAFT_CHANGED_NOTE = {
35897
+ "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.",
35898
+ "payload-changed": "Nothing was sent or changed: what would happen no longer matches what the user approved."
35899
+ };
35900
+ function isToolResult(value) {
35901
+ return Array.isArray(value.content);
35902
+ }
35903
+ function rejection2(data) {
35904
+ return { ...textResult({ status: "confirmation-rejected", confirmed: false, dispatched: false, ...data }), isError: true };
35905
+ }
35906
+ async function tokenConfirmation(op, fallback) {
35907
+ const subject = await fallback.subject();
35908
+ if (isToolResult(subject)) return subject;
35909
+ const binding = {
35910
+ tool: fallback.tool,
35911
+ account: fallback.account ?? readEnvVar("GOG_ACCOUNT") ?? "",
35912
+ target: subject.target,
35913
+ ...subject.revision === void 0 ? {} : { revision: subject.revision },
35914
+ payloadHash: hashSendPayload(subject.payload)
35915
+ };
35916
+ const phaseOne = () => {
35917
+ const { token, expiresAt } = issueConfirmToken(binding);
35918
+ return {
35919
+ action: op,
35920
+ preview: subject.preview,
35921
+ confirmToken: token,
35922
+ expiresAt,
35923
+ ttlSeconds: confirmTokenTtlSeconds(),
35924
+ instruction: fallback.instruction ?? CONFIRM_ACTION_INSTRUCTION
35925
+ };
35926
+ };
35927
+ if (!fallback.confirmToken) {
35928
+ return textResult({ status: "confirmation-required", confirmed: false, dispatched: false, ...phaseOne() });
35929
+ }
35930
+ const verdict = verifyConfirmToken(fallback.confirmToken, binding);
35931
+ if (verdict.ok) return void 0;
35932
+ if (verdict.error === "DRAFT_CHANGED") {
35933
+ return rejection2({
35934
+ error: "DRAFT_CHANGED",
35935
+ reason: verdict.reason,
35936
+ note: `${DRAFT_CHANGED_NOTE[verdict.reason]} The current preview and a fresh confirmToken are below.`,
35937
+ ...phaseOne()
35938
+ });
35939
+ }
35940
+ return rejection2({ error: verdict.error, action: op, note: TOKEN_ERROR_NOTE[verdict.error] });
35941
+ }
35942
+ function gatedElsewhere(what, via, does, tool) {
35943
+ return `${what} ${does} and is not available through ${via}. Use ${tool}, which asks the user to confirm.`;
35944
+ }
35945
+ async function requireDispatchConfirmation(ctx, options) {
35946
+ const { action, fallback } = options;
35947
+ if (fallback && callerAcceptsFormElicitation(ctx) === false && sendConfirmFallbackEnabled()) {
35948
+ return tokenConfirmation(action, fallback);
35949
+ }
35950
+ const note = fallback ? [options.unsupportedNote, FALLBACK_HINT].filter(Boolean).join(" ") : options.unsupportedNote;
35951
+ return requireConfirmation(ctx, {
35952
+ action,
35953
+ message: options.message,
35954
+ details: options.details,
35955
+ confirmationLabel: options.confirmationLabel,
35956
+ ...note ? { unsupportedNote: note } : {}
35957
+ });
35958
+ }
35959
+ function resultText(result) {
35960
+ const first = result.content[0];
35961
+ return first && first.type === "text" && typeof first.text === "string" ? first.text : "{}";
35962
+ }
35963
+
35286
35964
  // ../gogcli-mcp/src/tools/auth.ts
35965
+ var AUTH_RUN_SUBCOMMANDS = ["list", "status", "services", "remove", "alias"];
35287
35966
  function registerAuthToolsWith(server, defaultServices) {
35288
35967
  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.`;
35289
35968
  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.";
@@ -35341,7 +36020,7 @@ function registerAuthToolsWith(server, defaultServices) {
35341
36020
  })
35342
36021
  }, async ({ email: email3, services = defaultServices, extraScopes }) => {
35343
36022
  try {
35344
- const args = ["auth", "add", email3, "--services", services];
36023
+ const args = ["auth", "add", pos(email3), "--services", services];
35345
36024
  if (extraScopes) args.push(`--extra-scopes=${extraScopes}`, "--force-consent");
35346
36025
  return rawTextResult(await run(args, {
35347
36026
  interactive: true,
@@ -35361,7 +36040,7 @@ function registerAuthToolsWith(server, defaultServices) {
35361
36040
  })
35362
36041
  }, async ({ email: email3, services = defaultServices, extraScopes }) => {
35363
36042
  try {
35364
- const args = ["auth", "add", email3, "--remote", "--step", "1", "--services", services, "--force-consent"];
36043
+ const args = ["auth", "add", pos(email3), "--remote", "--step", "1", "--services", services, "--force-consent"];
35365
36044
  if (extraScopes) args.push(`--extra-scopes=${extraScopes}`);
35366
36045
  return rawTextResult(await run(args, { redactMode: "tokens" }));
35367
36046
  } catch (err) {
@@ -35388,7 +36067,7 @@ function registerAuthToolsWith(server, defaultServices) {
35388
36067
  const args = [
35389
36068
  "auth",
35390
36069
  "add",
35391
- email3,
36070
+ pos(email3),
35392
36071
  "--remote",
35393
36072
  "--step",
35394
36073
  "2",
@@ -35408,6 +36087,7 @@ function registerAuthToolsWith(server, defaultServices) {
35408
36087
  service: "auth",
35409
36088
  examples: '"remove", "alias", "list"',
35410
36089
  omitAccount: true,
36090
+ allowedSubcommands: AUTH_RUN_SUBCOMMANDS,
35411
36091
  note: "For browser-based authorization, use gog_auth_add instead."
35412
36092
  });
35413
36093
  }
@@ -35481,12 +36161,25 @@ function inlineFileArg(flag, attachment, opts = {}) {
35481
36161
  }
35482
36162
 
35483
36163
  // ../gogcli-mcp/src/tools/drive.ts
36164
+ function vetDriveRun(subcommand, _args) {
36165
+ return subcommand.toLowerCase() === "share" ? gatedElsewhere("gog drive share", "gog_drive_run", "grants access to a file", "gog_drive_share") : void 0;
36166
+ }
35484
36167
  var GOOGLE_DOC_MIME = "application/vnd.google-apps.document";
36168
+ function shareTargetMeta(raw) {
36169
+ try {
36170
+ const { name, mimeType } = fileMeta(raw);
36171
+ return { name, mimeType };
36172
+ } catch {
36173
+ return {};
36174
+ }
36175
+ }
35485
36176
  function fileMeta(raw) {
35486
36177
  const parsed = JSON.parse(raw);
35487
36178
  const f = parsed.file ?? parsed;
35488
- return { name: f.name, mimeType: f.mimeType };
36179
+ const size = f.size === void 0 ? void 0 : Number(f.size);
36180
+ return { name: f.name, mimeType: f.mimeType, size: Number.isFinite(size) ? size : void 0 };
35489
36181
  }
36182
+ var MAX_DRIVE_READ_BYTES = MAX_INLINE_ATTACHMENT_BYTES;
35490
36183
  var DRIVE_LS_COMPACT_FIELDS = "nextPageToken,files(id,name,mimeType,modifiedTime,size,webViewLink)";
35491
36184
  function registerDriveTools(server) {
35492
36185
  server.registerTool("gog_drive_ls", {
@@ -35530,7 +36223,7 @@ function registerDriveTools(server) {
35530
36223
  account: accountParam
35531
36224
  })
35532
36225
  }, async ({ query, view, account }) => {
35533
- return runOrDiagnose(["drive", "search", query], {
36226
+ return runOrDiagnose(["drive", "search", pos(query)], {
35534
36227
  account,
35535
36228
  stripMedia: resolveView(view, ["compact", "full"]) === "compact"
35536
36229
  });
@@ -35550,7 +36243,7 @@ function registerDriveTools(server) {
35550
36243
  account: accountParam
35551
36244
  })
35552
36245
  }, async ({ fileId, view, account }) => {
35553
- return runOrDiagnose(["drive", "get", fileId], {
36246
+ return runOrDiagnose(["drive", "get", pos(fileId)], {
35554
36247
  account,
35555
36248
  stripMedia: resolveView(view, ["compact", "full"]) === "compact"
35556
36249
  });
@@ -35563,7 +36256,7 @@ function registerDriveTools(server) {
35563
36256
  account: accountParam
35564
36257
  })
35565
36258
  }, async ({ name, account }) => {
35566
- return runOrDiagnose(["drive", "mkdir", name], { account });
36259
+ return runOrDiagnose(["drive", "mkdir", pos(name)], { account });
35567
36260
  });
35568
36261
  server.registerTool("gog_drive_rename", {
35569
36262
  description: "Rename a file or folder in Google Drive.",
@@ -35574,7 +36267,7 @@ function registerDriveTools(server) {
35574
36267
  account: accountParam
35575
36268
  })
35576
36269
  }, async ({ fileId, newName, account }) => {
35577
- return runOrDiagnose(["drive", "rename", fileId, newName], { account });
36270
+ return runOrDiagnose(["drive", "rename", pos(fileId), pos(newName)], { account });
35578
36271
  });
35579
36272
  server.registerTool("gog_drive_move", {
35580
36273
  description: "Move a file to a different folder in Google Drive.",
@@ -35585,7 +36278,7 @@ function registerDriveTools(server) {
35585
36278
  account: accountParam
35586
36279
  })
35587
36280
  }, async ({ fileId, parentId, account }) => {
35588
- return runOrDiagnose(["drive", "move", fileId, `--parent=${parentId}`], { account });
36281
+ return runOrDiagnose(["drive", "move", pos(fileId), `--parent=${parentId}`], { account });
35589
36282
  });
35590
36283
  server.registerTool("gog_drive_delete", {
35591
36284
  description: "Move a Google Drive file to trash, or permanently delete it with permanent=true (irreversible).",
@@ -35596,13 +36289,13 @@ function registerDriveTools(server) {
35596
36289
  account: accountParam
35597
36290
  })
35598
36291
  }, async ({ fileId, permanent, account }) => {
35599
- const args = ["drive", "delete", fileId];
36292
+ const args = ["drive", "delete", pos(fileId)];
35600
36293
  if (permanent) args.push("--permanent");
35601
36294
  args.push("--force");
35602
36295
  return runOrDiagnose(args, { account });
35603
36296
  });
35604
36297
  server.registerTool("gog_drive_share", {
35605
- description: "Share a Google Drive file or folder.",
36298
+ description: "Share a Google Drive file or folder. Granting access is the risk even though no email is sent (gog does not notify by default), so this reads the file and asks the MCP host to show the user a confirmation prompt naming it, who gets access and with what role; nothing is shared unless they accept." + CONFIRM_FALLBACK_DESCRIPTION,
35606
36299
  annotations: { destructiveHint: true },
35607
36300
  inputSchema: external_exports.object({
35608
36301
  fileId: external_exports.string().describe("File or folder ID"),
@@ -35610,10 +36303,36 @@ function registerDriveTools(server) {
35610
36303
  email: external_exports.string().optional().describe("User email (required when to=user)"),
35611
36304
  domain: external_exports.string().optional().describe("Domain (required when to=domain)"),
35612
36305
  role: external_exports.enum(["reader", "writer"]).optional().describe("Permission role (default: reader)"),
35613
- account: accountParam
36306
+ account: accountParam,
36307
+ confirmToken: confirmTokenParam
35614
36308
  })
35615
- }, async ({ fileId, to, email: email3, domain: domain2, role, account }) => {
35616
- const args = ["drive", "share", fileId, `--to=${to}`];
36309
+ }, async ({ fileId, to, email: email3, domain: domain2, role, account, confirmToken }, ctx) => {
36310
+ const got = await runOrDiagnose(["drive", "get", pos(fileId)], { account });
36311
+ if (got.isError) return got;
36312
+ const file2 = { id: fileId, ...shareTargetMeta(resultText(got)) };
36313
+ const grant = {
36314
+ file: file2,
36315
+ to,
36316
+ ...email3 ? { email: email3 } : {},
36317
+ ...domain2 ? { domain: domain2 } : {},
36318
+ role: role ?? "reader",
36319
+ publicLink: to === "anyone"
36320
+ };
36321
+ const confirmation = await requireDispatchConfirmation(ctx, {
36322
+ action: "drive.share",
36323
+ message: to === "anyone" ? "Review and confirm making this file available to ANYONE with the link:" : "Review and confirm this Drive share:",
36324
+ confirmationLabel: "Confirm that this access should be granted now.",
36325
+ details: grant,
36326
+ unsupportedNote: "Ask the user to share it themselves from Google Drive.",
36327
+ fallback: {
36328
+ tool: "gog_drive_share",
36329
+ account,
36330
+ confirmToken,
36331
+ subject: () => ({ target: fileId, payload: grant, preview: grant })
36332
+ }
36333
+ });
36334
+ if (confirmation) return confirmation;
36335
+ const args = ["drive", "share", pos(fileId), `--to=${to}`];
35617
36336
  if (email3) args.push(`--email=${email3}`);
35618
36337
  if (domain2) args.push(`--domain=${domain2}`);
35619
36338
  if (role) args.push(`--role=${role}`);
@@ -35636,7 +36355,7 @@ function registerDriveTools(server) {
35636
36355
  }, async ({ fileId, ocrLanguage, offset = 0, maxChars, account }) => {
35637
36356
  let tempDocId;
35638
36357
  try {
35639
- const { name, mimeType } = fileMeta(await run(["drive", "get", fileId], { account }));
36358
+ const { name, mimeType } = fileMeta(await run(["drive", "get", pos(fileId)], { account }));
35640
36359
  let sourceId = fileId;
35641
36360
  if (mimeType !== GOOGLE_DOC_MIME) {
35642
36361
  const params = JSON.stringify({ fileId, ...ocrLanguage ? { ocrLanguage } : {} });
@@ -35681,13 +36400,13 @@ function registerDriveTools(server) {
35681
36400
  return diagnose(err);
35682
36401
  } finally {
35683
36402
  if (tempDocId) {
35684
- await run(["drive", "delete", tempDocId, "--permanent", "--force"], { account }).catch(() => {
36403
+ await run(["drive", "delete", pos(tempDocId), "--permanent", "--force"], { account }).catch(() => {
35685
36404
  });
35686
36405
  }
35687
36406
  }
35688
36407
  });
35689
36408
  server.registerTool("gog_drive_read_bytes", {
35690
- description: "Fetch a Drive file's raw bytes and return them base64-encoded as an embedded resource \u2014 the generic fallback for callers that want the file itself (to parse locally) rather than extracted text. For readable text from a PDF, prefer gog_drive_extract_text.",
36409
+ description: "Fetch a Drive file's raw bytes and return them base64-encoded as an embedded resource \u2014 the generic fallback for callers that want the file itself (to parse locally) rather than extracted text. Files over 8 MiB are refused (checked before downloading). For readable text from a PDF, prefer gog_drive_extract_text.",
35691
36410
  annotations: { readOnlyHint: true },
35692
36411
  inputSchema: external_exports.object({
35693
36412
  fileId: external_exports.string().describe("Drive file ID"),
@@ -35695,9 +36414,17 @@ function registerDriveTools(server) {
35695
36414
  })
35696
36415
  }, async ({ fileId, account }) => {
35697
36416
  try {
35698
- const { name, mimeType } = fileMeta(await run(["drive", "get", fileId], { account }));
36417
+ const { name, mimeType, size } = fileMeta(await run(["drive", "get", pos(fileId)], { account }));
36418
+ if (size !== void 0 && size > MAX_DRIVE_READ_BYTES) {
36419
+ return errorResult(
36420
+ `${name ?? fileId} is ${size} bytes, over the 8 MiB this tool returns inline. Use gog_drive_extract_text for its text, or share its webViewLink (gog_drive_get) instead.`
36421
+ );
36422
+ }
35699
36423
  const params = JSON.stringify({ fileId, alt: "media" });
35700
- const blob = await runBinary(["api", "call", "drive", "v3", "files.get", `--params=${params}`], { account });
36424
+ const blob = await runBinary(
36425
+ ["api", "call", "drive", "v3", "files.get", `--params=${params}`],
36426
+ { account, maxOutputBytes: MAX_DRIVE_READ_BYTES }
36427
+ );
35701
36428
  const type = mimeType ?? "application/octet-stream";
35702
36429
  const unrenderableHint = type.startsWith("image/") ? "" : ` If your client does not render a ${type} resource, gog_drive_extract_text returns the same file as text (PDFs included, via OCR).`;
35703
36430
  return {
@@ -35717,7 +36444,7 @@ function registerDriveTools(server) {
35717
36444
  return diagnose(err);
35718
36445
  }
35719
36446
  });
35720
- registerRunTool(server, { service: "drive", examples: '"copy", "upload", "download", "permissions"' });
36447
+ registerRunTool(server, { service: "drive", examples: '"copy", "download", "permissions"', vet: vetDriveRun });
35721
36448
  }
35722
36449
 
35723
36450
  // ../gogcli-mcp/src/tools/gmail.ts
@@ -35732,7 +36459,7 @@ var replySchema = {
35732
36459
  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."),
35733
36460
  subject: external_exports.string().optional().describe('Override reply subject (default: "Re: <original>"). A changed subject starts a NEW Gmail thread.'),
35734
36461
  noQuote: external_exports.boolean().optional().describe("Do not include the original message quoted below the reply (default: the original is quoted)"),
35735
- 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.`),
36462
+ 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).`),
35736
36463
  attachInline: attachInlineParam,
35737
36464
  from: external_exports.string().optional().describe("Send from this email address (must be a verified send-as alias)"),
35738
36465
  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."),
@@ -35741,7 +36468,7 @@ var replySchema = {
35741
36468
  signatureFile: external_exports.string().optional().describe("Append a local signature file (plain text or HTML), read on the gog server"),
35742
36469
  account: accountParam
35743
36470
  };
35744
- var sendReplySchema = external_exports.object(replySchema);
36471
+ var sendReplySchema = external_exports.object({ ...replySchema, confirmToken: confirmTokenParam });
35745
36472
 
35746
36473
  // ../gogcli-mcp/src/tools/sheets.ts
35747
36474
  var cellValueParam = external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null()]);
@@ -35753,10 +36480,10 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
35753
36480
  );
35754
36481
 
35755
36482
  // ../gogcli-mcp/src/server.ts
35756
- var VERSION = true ? "4.2.5" : "0.0.0";
36483
+ var VERSION = true ? "4.4.0" : "0.0.0";
35757
36484
 
35758
36485
  // ../gogcli-mcp/src/bootstrap-auth.ts
35759
- import { join as join2 } from "node:path";
36486
+ import { join as join5 } from "node:path";
35760
36487
  var AUTH_BOOTSTRAP_MARKER = "auth-bootstrap.sha256";
35761
36488
  var VARS = ["GOG_CLIENT_ID", "GOG_CLIENT_SECRET", "GOG_REFRESH_TOKEN", "GOG_ACCOUNT"];
35762
36489
  var log = (line) => {
@@ -35790,12 +36517,12 @@ async function bootstrapGogAuth(env = process.env, options = {}) {
35790
36517
  const [clientId, clientSecret, refreshToken, account] = values;
35791
36518
  const { spawner } = options;
35792
36519
  try {
35793
- const { createHash } = await import("node:crypto");
36520
+ const { createHash: createHash3 } = await import("node:crypto");
35794
36521
  const { mkdir, readFile, writeFile, chmod } = await import("node:fs/promises");
35795
36522
  const home = options.home ?? (await import("node:os")).homedir();
35796
- const dir = join2(home, ".gogcli-mcp");
35797
- const marker = join2(dir, AUTH_BOOTSTRAP_MARKER);
35798
- const fingerprint = createHash("sha256").update(values.join("\0")).digest("hex");
36523
+ const dir = join5(home, ".gogcli-mcp");
36524
+ const marker = join5(dir, AUTH_BOOTSTRAP_MARKER);
36525
+ const fingerprint = createHash3("sha256").update(values.join("\0")).digest("hex");
35799
36526
  const previous = await readFile(marker, "utf8").catch(() => void 0);
35800
36527
  if (previous === fingerprint && await accountListed(account, spawner)) return "present";
35801
36528
  await run(
@@ -35831,7 +36558,8 @@ var MAX_BLOB_UPLOAD_BYTES = 100 * 1024 * 1024;
35831
36558
  function registerExtraDriveTools(server) {
35832
36559
  server.registerTool("gog_drive_download", {
35833
36560
  description: "Download a Drive file to the local filesystem. For Google Docs formats, specify an export format (pdf, csv, xlsx, pptx, txt, png, docx, md).",
35834
- annotations: { readOnlyHint: true },
36561
+ // Writes a file on the gog host and can overwrite one: not read-only (audit SEC-4).
36562
+ annotations: { readOnlyHint: false, destructiveHint: true },
35835
36563
  inputSchema: external_exports.object({
35836
36564
  fileId: external_exports.string().describe("File ID to download"),
35837
36565
  out: external_exports.string().optional().describe("Output file path (default: gogcli config dir)"),
@@ -35840,7 +36568,8 @@ function registerExtraDriveTools(server) {
35840
36568
  account: accountParam
35841
36569
  })
35842
36570
  }, async ({ fileId, out, format, overwrite, account }) => {
35843
- const args = ["drive", "download", fileId];
36571
+ if (out) confinePath(out, "out");
36572
+ const args = ["drive", "download", pos(fileId)];
35844
36573
  if (out) args.push(`--out=${out}`);
35845
36574
  if (format) args.push(`--format=${format}`);
35846
36575
  if (overwrite) args.push("--overwrite");
@@ -35850,7 +36579,7 @@ function registerExtraDriveTools(server) {
35850
36579
  description: `Upload a file to Drive. Supply it EITHER as localPath (a path on the gog server's own filesystem \u2014 local stdio deployments only) OR as content (the bytes, base64-encoded, carried with the request), which is what works when this server runs remotely from you and no path you can name exists on it. Use replace to replace the content of an existing file (preserves link/permissions), or convert to auto-convert to a Google format. Pair replace with ifVersion to make the overwrite conditional: gog sends an atomic If-Match precondition and reports a conflict \u2014 applying nothing \u2014 if the file changed since you read it, instead of silently clobbering a concurrent edit. No read tool surfaces the version number: fetch it immediately before uploading with gog_drive_run { subcommand: "raw", args: ["<fileId>", "--fields=version"] } \u2014 it comes back as a JSON string, so pass it on as a number. Conditional replacement refuses Google Workspace files (Docs/Sheets/Slides), which have no replaceable binary content.`,
35851
36580
  annotations: { destructiveHint: false },
35852
36581
  inputSchema: external_exports.object({
35853
- localPath: external_exports.string().optional().describe(`Path to the file to upload, 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) this path does not exist and the call fails with "no such file or directory" \u2014 use content there. Exactly one of localPath / content is required.`),
36582
+ localPath: external_exports.string().optional().describe(`Path to the file to upload, 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) this path does not exist and the call fails with "no such file or directory" \u2014 use content there. Exactly one of localPath / content is required. Must be inside the server's GOG_FILE_ROOTS directories (default ~/gogcli-mcp-files).`),
35854
36583
  content: external_exports.string().optional().describe("The file's bytes, base64-encoded (standard alphabet, with padding) \u2014 upload a file you hold without it existing anywhere on the gog server. This is the only route that works when the caller and gog share no filesystem. Requires name (there is no path to take a filename from). Max 8 MiB; for anything larger use localPath from a local deployment. Exactly one of localPath / content is required \u2014 supplying both is an error, not a precedence rule."),
35855
36584
  name: external_exports.string().optional().describe("Override filename (create) or rename target (replace)"),
35856
36585
  parent: external_exports.string().optional().describe("Destination folder ID (create only)"),
@@ -35875,7 +36604,7 @@ function registerExtraDriveTools(server) {
35875
36604
  }
35876
36605
  let pathArg;
35877
36606
  if (localPath !== void 0) {
35878
- pathArg = localPath;
36607
+ pathArg = confinePath(localPath, "localPath");
35879
36608
  } else {
35880
36609
  if (!name) {
35881
36610
  throw new Error("content requires name: there is no path to derive the Drive filename from.");
@@ -35886,7 +36615,7 @@ function registerExtraDriveTools(server) {
35886
36615
  { positional: true, where: "content" }
35887
36616
  ).arg;
35888
36617
  }
35889
- const args = ["drive", "upload", pathArg];
36618
+ const args = ["drive", "upload", typeof pathArg === "string" ? pos(pathArg) : pathArg];
35890
36619
  if (name) args.push(`--name=${name}`);
35891
36620
  if (parent) args.push(`--parent=${parent}`);
35892
36621
  if (replace) args.push(`--replace=${replace}`);
@@ -35901,14 +36630,15 @@ function registerExtraDriveTools(server) {
35901
36630
  description: "Recursively push a local directory's contents into an existing Drive folder \u2014 uploads new files, updates changed ones (matched by name + MD5), and creates missing subfolders. One-way and additive: it never deletes anything on Drive. Use dryRun to preview the planned actions first.",
35902
36631
  annotations: { destructiveHint: true },
35903
36632
  inputSchema: external_exports.object({
35904
- localPath: external_exports.string().describe("Local directory to push (its contents are mirrored into the parent folder)"),
36633
+ localPath: external_exports.string().describe("Local directory to push (its contents are mirrored into the parent folder). Must be inside the server's GOG_FILE_ROOTS directories (default ~/gogcli-mcp-files)."),
35905
36634
  parent: external_exports.string().describe("Existing destination Drive folder ID"),
35906
36635
  dryRun: external_exports.boolean().optional().describe("Preview the planned actions without making any changes"),
35907
36636
  allDrives: external_exports.boolean().optional().describe("Include shared drives (default: true; set false for My Drive only)"),
35908
36637
  account: accountParam
35909
36638
  })
35910
36639
  }, async ({ localPath, parent, dryRun, allDrives, account }) => {
35911
- const args = ["drive", "sync", "push", localPath, `--parent=${parent}`];
36640
+ confinePath(localPath, "localPath");
36641
+ const args = ["drive", "sync", "push", pos(localPath), `--parent=${parent}`];
35912
36642
  if (dryRun) args.push("--dry-run");
35913
36643
  if (allDrives === false) args.push("--no-all-drives");
35914
36644
  return runOrDiagnose(args, { account });
@@ -35923,7 +36653,7 @@ function registerExtraDriveTools(server) {
35923
36653
  account: accountParam
35924
36654
  })
35925
36655
  }, async ({ fileId, name, parent, account }) => {
35926
- const args = ["drive", "copy", fileId, name];
36656
+ const args = ["drive", "copy", pos(fileId), pos(name)];
35927
36657
  if (parent) args.push(`--parent=${parent}`);
35928
36658
  return runOrDiagnose(args, { account });
35929
36659
  });
@@ -35935,7 +36665,7 @@ function registerExtraDriveTools(server) {
35935
36665
  account: accountParam
35936
36666
  })
35937
36667
  }, async ({ fileIds, account }) => {
35938
- return runOrDiagnose(["drive", "url", ...fileIds], { account });
36668
+ return runOrDiagnose(["drive", "url", ...fileIds.map(pos)], { account });
35939
36669
  });
35940
36670
  server.registerTool("gog_drive_permissions", {
35941
36671
  description: "List permissions on a Drive file.",
@@ -35948,7 +36678,7 @@ function registerExtraDriveTools(server) {
35948
36678
  account: accountParam
35949
36679
  })
35950
36680
  }, async ({ fileId, max, pageToken, page, account }) => {
35951
- const args = ["drive", "permissions", fileId];
36681
+ const args = ["drive", "permissions", pos(fileId)];
35952
36682
  if (max !== void 0) args.push(`--max=${max}`);
35953
36683
  const token = resolvePageToken({ pageToken, page });
35954
36684
  if (token) args.push(`--page=${token}`);
@@ -35963,7 +36693,7 @@ function registerExtraDriveTools(server) {
35963
36693
  account: accountParam
35964
36694
  })
35965
36695
  }, async ({ fileId, permissionId, account }) => {
35966
- return runOrDiagnose(["drive", "unshare", fileId, permissionId, "--force"], { account });
36696
+ return runOrDiagnose(["drive", "unshare", pos(fileId), pos(permissionId), "--force"], { account });
35967
36697
  });
35968
36698
  server.registerTool("gog_drive_drives_list", {
35969
36699
  description: "List shared drives (Team Drives) accessible to the account.",
@@ -35996,7 +36726,7 @@ function registerExtraDriveTools(server) {
35996
36726
  account: accountParam
35997
36727
  })
35998
36728
  }, async ({ fileId, since, includeQuoted, max, page, all, account }) => {
35999
- const args = ["drive", "comments", "list", fileId];
36729
+ const args = ["drive", "comments", "list", pos(fileId)];
36000
36730
  if (since) args.push(`--since=${since}`);
36001
36731
  if (includeQuoted) args.push("--include-quoted");
36002
36732
  pushPaginationFlags(args, { max, page, all });
@@ -36011,7 +36741,7 @@ function registerExtraDriveTools(server) {
36011
36741
  account: accountParam
36012
36742
  })
36013
36743
  }, async ({ fileId, commentId, account }) => {
36014
- return runOrDiagnose(["drive", "comments", "get", fileId, commentId], { account });
36744
+ return runOrDiagnose(["drive", "comments", "get", pos(fileId), pos(commentId)], { account });
36015
36745
  });
36016
36746
  server.registerTool("gog_drive_comments_add", {
36017
36747
  description: "Add a new comment to a Drive file.",
@@ -36022,7 +36752,7 @@ function registerExtraDriveTools(server) {
36022
36752
  account: accountParam
36023
36753
  })
36024
36754
  }, async ({ fileId, content, account }) => {
36025
- return runOrDiagnose(["drive", "comments", "create", fileId, content], { account });
36755
+ return runOrDiagnose(["drive", "comments", "create", pos(fileId), pos(content)], { account });
36026
36756
  });
36027
36757
  server.registerTool("gog_drive_comments_update", {
36028
36758
  description: "Update the text of an existing comment.",
@@ -36034,7 +36764,7 @@ function registerExtraDriveTools(server) {
36034
36764
  account: accountParam
36035
36765
  })
36036
36766
  }, async ({ fileId, commentId, content, account }) => {
36037
- return runOrDiagnose(["drive", "comments", "update", fileId, commentId, content], { account });
36767
+ return runOrDiagnose(["drive", "comments", "update", pos(fileId), pos(commentId), pos(content)], { account });
36038
36768
  });
36039
36769
  server.registerTool("gog_drive_comments_delete", {
36040
36770
  description: "Delete a comment from a Drive file.",
@@ -36045,7 +36775,7 @@ function registerExtraDriveTools(server) {
36045
36775
  account: accountParam
36046
36776
  })
36047
36777
  }, async ({ fileId, commentId, account }) => {
36048
- return runOrDiagnose(["drive", "comments", "delete", fileId, commentId, "--force"], { account });
36778
+ return runOrDiagnose(["drive", "comments", "delete", pos(fileId), pos(commentId), "--force"], { account });
36049
36779
  });
36050
36780
  server.registerTool("gog_drive_comments_reply", {
36051
36781
  description: 'Reply to an existing comment on a Drive file. Pass `action: "resolve"` or `"reopen"` to atomically flip the parent comment\'s resolved state via the Drive API\'s Reply.action field \u2014 avoids the older workaround of deleting the comment (which destroys review-thread context).',
@@ -36058,7 +36788,7 @@ function registerExtraDriveTools(server) {
36058
36788
  account: accountParam
36059
36789
  })
36060
36790
  }, async ({ fileId, commentId, content, action, account }) => {
36061
- const args = ["drive", "comments", "reply", fileId, commentId, content];
36791
+ const args = ["drive", "comments", "reply", pos(fileId), pos(commentId), pos(content)];
36062
36792
  if (action) args.push(`--action=${action}`);
36063
36793
  return runOrDiagnose(args, { account });
36064
36794
  });
@@ -36071,7 +36801,7 @@ function registerExtraDriveTools(server) {
36071
36801
  account: accountParam
36072
36802
  })
36073
36803
  }, async ({ fileId, commentId, account }) => {
36074
- return runOrDiagnose(["drive", "comments", "resolve", fileId, commentId], { account });
36804
+ return runOrDiagnose(["drive", "comments", "resolve", pos(fileId), pos(commentId)], { account });
36075
36805
  });
36076
36806
  server.registerTool("gog_drive_comments_reopen", {
36077
36807
  description: 'Reopen a previously resolved comment on a Drive file. To reopen while replying, use gog_drive_comments_reply with action: "reopen".',
@@ -36082,7 +36812,7 @@ function registerExtraDriveTools(server) {
36082
36812
  account: accountParam
36083
36813
  })
36084
36814
  }, async ({ fileId, commentId, account }) => {
36085
- return runOrDiagnose(["drive", "comments", "reopen", fileId, commentId], { account });
36815
+ return runOrDiagnose(["drive", "comments", "reopen", pos(fileId), pos(commentId)], { account });
36086
36816
  });
36087
36817
  server.registerTool("gog_drive_du", {
36088
36818
  description: "Summarize Drive folder sizes (disk-usage style) starting from a folder.",
@@ -36168,7 +36898,7 @@ function registerExtraDriveTools(server) {
36168
36898
  account: accountParam
36169
36899
  })
36170
36900
  }, async ({ fileId, max, page, all, account }) => {
36171
- const args = ["drive", "revisions", "list", fileId];
36901
+ const args = ["drive", "revisions", "list", pos(fileId)];
36172
36902
  pushPaginationFlags(args, { max, page, all });
36173
36903
  return runOrDiagnose(args, { account });
36174
36904
  });
@@ -36181,7 +36911,7 @@ function registerExtraDriveTools(server) {
36181
36911
  account: accountParam
36182
36912
  })
36183
36913
  }, async ({ fileId, revisionId, account }) => {
36184
- return runOrDiagnose(["drive", "revisions", "get", fileId, revisionId], { account });
36914
+ return runOrDiagnose(["drive", "revisions", "get", pos(fileId), pos(revisionId)], { account });
36185
36915
  });
36186
36916
  server.registerTool("gog_drive_shortcut_create", {
36187
36917
  description: "Create a Drive shortcut to a file or folder inside a destination folder. Shortcuts are classified distinctly in listing/tree output and are never followed by tree scans.",
@@ -36193,7 +36923,7 @@ function registerExtraDriveTools(server) {
36193
36923
  account: accountParam
36194
36924
  })
36195
36925
  }, async ({ targetId, parent, name, account }) => {
36196
- const args = ["drive", "shortcut", "create", targetId, `--parent=${parent}`];
36926
+ const args = ["drive", "shortcut", "create", pos(targetId), `--parent=${parent}`];
36197
36927
  if (name) args.push(`--name=${name}`);
36198
36928
  return runOrDiagnose(args, { account });
36199
36929
  });
@@ -36234,7 +36964,7 @@ function registerExtraDriveTools(server) {
36234
36964
  account: accountParam
36235
36965
  })
36236
36966
  }, async ({ name, language, view, adminAccess, account }) => {
36237
- const args = ["drive", "labels", "get", name];
36967
+ const args = ["drive", "labels", "get", pos(name)];
36238
36968
  if (language) args.push(`--language=${language}`);
36239
36969
  if (view) args.push(`--view=${view}`);
36240
36970
  if (adminAccess) args.push("--admin-access");
@@ -36251,7 +36981,7 @@ function registerExtraDriveTools(server) {
36251
36981
  account: accountParam
36252
36982
  })
36253
36983
  }, async ({ fileId, max, pageToken, page, account }) => {
36254
- const args = ["drive", "labels", "file", "list", fileId];
36984
+ const args = ["drive", "labels", "file", "list", pos(fileId)];
36255
36985
  if (max !== void 0) args.push(`--max=${max}`);
36256
36986
  const token = resolvePageToken({ pageToken, page });
36257
36987
  if (token) args.push(`--page=${token}`);
@@ -36273,7 +37003,7 @@ function registerExtraDriveTools(server) {
36273
37003
  account: accountParam
36274
37004
  })
36275
37005
  }, async ({ fileId, labelId, text, selection, integer: integer2, date: date5, user, unset, fieldsJson, account }) => {
36276
- const args = ["drive", "labels", "file", "apply", fileId, labelId];
37006
+ const args = ["drive", "labels", "file", "apply", pos(fileId), pos(labelId)];
36277
37007
  if (text) for (const t of text) args.push(`--text=${t}`);
36278
37008
  if (selection) for (const s of selection) args.push(`--selection=${s}`);
36279
37009
  if (integer2) for (const i of integer2) args.push(`--integer=${i}`);
@@ -36292,7 +37022,7 @@ function registerExtraDriveTools(server) {
36292
37022
  account: accountParam
36293
37023
  })
36294
37024
  }, async ({ fileId, labelId, account }) => {
36295
- return runOrDiagnose(["drive", "labels", "file", "remove", fileId, labelId, "--force"], { account });
37025
+ return runOrDiagnose(["drive", "labels", "file", "remove", pos(fileId), pos(labelId), "--force"], { account });
36296
37026
  });
36297
37027
  server.registerTool("gog_drive_activity", {
36298
37028
  description: "Query the Drive Activity API for audit events (edits, creates, deletes, moves, shares, etc.) scoped to a file or folder and/or time range.",
@@ -36365,7 +37095,7 @@ function registerExtraDriveTools(server) {
36365
37095
  account: accountParam
36366
37096
  })
36367
37097
  }, async ({ user, file: file2, parent, depth, max, noAllDrives, account }) => {
36368
- const args = ["drive", "audit", "user", user];
37098
+ const args = ["drive", "audit", "user", pos(user)];
36369
37099
  if (file2) args.push(`--file=${file2}`);
36370
37100
  if (parent) args.push(`--parent=${parent}`);
36371
37101
  if (depth !== void 0) args.push(`--depth=${depth}`);