gogcli-mcp-docs 4.7.0 → 4.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -34537,11 +34537,19 @@ var DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
34537
34537
  var McpToolError = class extends Error {
34538
34538
  /** Actionable remediation text, when one applies. */
34539
34539
  hint;
34540
+ /** The upstream HTTP status this failure came from, when known. */
34541
+ status;
34542
+ /** What kind of failure this is, when the thrower knows. */
34543
+ kind;
34540
34544
  constructor(message, opts) {
34541
34545
  super(message, opts?.cause !== void 0 ? { cause: opts.cause } : void 0);
34542
34546
  this.name = "McpToolError";
34543
34547
  if (opts?.hint !== void 0)
34544
34548
  this.hint = opts.hint;
34549
+ if (opts?.status !== void 0)
34550
+ this.status = opts.status;
34551
+ if (opts?.kind !== void 0)
34552
+ this.kind = opts.kind;
34545
34553
  Object.setPrototypeOf(this, new.target.prototype);
34546
34554
  }
34547
34555
  };
@@ -34566,7 +34574,7 @@ var API_KEY_RE = new RegExp([
34566
34574
  // webhook signing secret (Stripe-style)
34567
34575
  ].map((p) => `\\b${p}`).join("|"), "g");
34568
34576
  var GOOGLE_OAUTH_TOKEN_RE = /(?<![A-Za-z0-9+/])(?:ya29\.|1\/\/)[A-Za-z0-9._-]{8,}/g;
34569
- var QUERY_SECRET_RE = new RegExp(`([?&](?:(?:access|refresh|id|auth|session|csrf|xsrf)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|token|key|sig|(?:php|j)?sess(?:ion)?[_-]?id|sid|x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN})=)[^&#\\s"'<>\`]+`, "gi");
34577
+ var QUERY_SECRET_RE = new RegExp(`([?&](?:(?:access|refresh|id|auth|session|csrf|xsrf)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|token|key|sig|(?:code[_-]?)?verifier|(?:php|j)?sess(?:ion)?[_-]?id|sid|x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN})=)[^&#\\s"'<>\`]+`, "gi");
34570
34578
  var OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
34571
34579
  var FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
34572
34580
  var HEADER_SECRET_RE = new RegExp(`(\\b(?:x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN}|api[-_]?key)\\s*:\\s*)[^\\s,;"'<>\`]+`, "gi");
@@ -34577,6 +34585,8 @@ var JSON_SECRET_KEYS = [
34577
34585
  "api[_-]?secret",
34578
34586
  "(?:x[_-])?api[_-]?key",
34579
34587
  "private[_-]?key",
34588
+ "code[_-]?verifier",
34589
+ // PKCE; a bare `verifier` key is too generic for JSON
34580
34590
  `x[_-]${HEADER_NAME_RUN}?(?:api[_-]?key|token|secret|auth)${HEADER_NAME_RUN}`,
34581
34591
  // bounded like HEADER_SECRET_RE
34582
34592
  "(?:proxy-)?authorization",
@@ -34607,6 +34617,11 @@ function redactSecrets(text) {
34607
34617
  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(GOOGLE_OAUTH_TOKEN_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_COOKIE_DQ_RE, redactJsonCookie('"')).replace(JSON_COOKIE_SQ_RE, redactJsonCookie("'")).replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_NUM_RE, "$1[REDACTED]").replace(JWT_RE, "[REDACTED]");
34608
34618
  }
34609
34619
  var ERROR_REDACTION_INPUT_MAX = 64 * 1024;
34620
+ function messageOf(err) {
34621
+ if (err instanceof Error)
34622
+ return err.message;
34623
+ return String(err);
34624
+ }
34610
34625
 
34611
34626
  // ../../node_modules/@chrischall/mcp-utils/dist/response/view.js
34612
34627
  function minifiedResult(data) {
@@ -35027,7 +35042,7 @@ function readEnvVar(key, opts = {}) {
35027
35042
  if (typeof raw === "string") {
35028
35043
  const trimmed = raw.trim();
35029
35044
  if (trimmed.length > 0 && trimmed !== "undefined" && trimmed !== "null" && !PLACEHOLDER_RE.test(trimmed)) {
35030
- return trimmed;
35045
+ return opts.trim === false ? raw : trimmed;
35031
35046
  }
35032
35047
  }
35033
35048
  return opts.default;
@@ -35222,12 +35237,19 @@ function boundArgs(args) {
35222
35237
  }
35223
35238
  function confirmationFromEnv(options) {
35224
35239
  const { tool, account, confirmToken, subject, instruction, args, env = process.env, spent: callerSpent, ...rest } = options;
35240
+ if (args === void 0 || args === null) {
35241
+ throw new TypeError(`confirmationFromEnv: ${tool} passed no args; pass the tool's validated arguments ({} for a tool with none).`);
35242
+ }
35225
35243
  const spent2 = callerSpent ?? spentTokenStoreFromEnv(env);
35226
35244
  const mode = readConfirmMode(env);
35227
35245
  const ttlSeconds = readConfirmTtl(env);
35228
35246
  const elicitationOff = readConfirmElicitation(env) === "off";
35229
- const bound = args === void 0 ? void 0 : boundArgs(args);
35230
- const bindingAdded = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
35247
+ const bound = boundArgs(args);
35248
+ const elicitationBound = account === void 0 ? { args: bound } : { account, args: bound };
35249
+ const bindingAdded = rest.binding ? rest : {
35250
+ ...rest,
35251
+ binding: { key: confirmKeyFromEnv(env), args: elicitationBound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 }
35252
+ };
35231
35253
  const confirmation = elicitationOff ? { ...bindingAdded, elicitation: false } : bindingAdded;
35232
35254
  if (mode === "refuse" || ttlSeconds === void 0) {
35233
35255
  const reason = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
@@ -35237,7 +35259,7 @@ function confirmationFromEnv(options) {
35237
35259
  unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
35238
35260
  };
35239
35261
  }
35240
- const boundSubject = bound === void 0 ? subject : async () => {
35262
+ const boundSubject = async () => {
35241
35263
  const read = await subject();
35242
35264
  if ("content" in read)
35243
35265
  return read;
@@ -35264,12 +35286,14 @@ var SERVER_PROTOCOL_VERSIONS = Object.freeze([
35264
35286
  ...SUPPORTED_PROTOCOL_VERSIONS
35265
35287
  ]);
35266
35288
  function hintResultOrRethrow(err) {
35289
+ if (err instanceof ProtocolError && err.code === ProtocolErrorCode.UrlElicitationRequired)
35290
+ throw err;
35267
35291
  if (err instanceof McpToolError && err.hint) {
35268
35292
  return errorResult(`${err.message}
35269
35293
 
35270
35294
  Hint: ${err.hint}`);
35271
35295
  }
35272
- throw err;
35296
+ return errorResult(messageOf(err));
35273
35297
  }
35274
35298
  function mcpRequestFrom(args) {
35275
35299
  const ctx = args.at(-1);
@@ -35503,7 +35527,7 @@ var PositiveInt = external_exports.number().int().positive();
35503
35527
  var NonNegInt = external_exports.number().int().nonnegative();
35504
35528
  var NonEmptyString = external_exports.string().min(1);
35505
35529
  var IsoDate = external_exports.iso.date();
35506
- var IsoTime = external_exports.string().regex(/^([01]?\d|2[0-3]):[0-5]\d$/, "must be HH:MM (24h), e.g. 19:30");
35530
+ var IsoTime = external_exports.string().regex(/^([01]?\d|2[0-3]):[0-5]\d$/, "must be HH:MM (24h), e.g. 19:30").overwrite((v) => v.padStart(5, "0"));
35507
35531
  var NumericIdString = external_exports.string().regex(/^\d+$/, "must be a numeric id (digits only)").describe("A numeric id string (digits only), safe to interpolate into a URL path.");
35508
35532
  var SafePathSegment = external_exports.string().min(1).regex(/^[^/?#\s]+$/, 'must not contain "/", "?", "#", or whitespace').refine((v) => !v.includes(".."), 'must not contain ".."').describe('A single URL path segment, safe to interpolate: no "/", "..", "?", "#", or whitespace.');
35509
35533
  var schemaOrigin = external_exports.string().optional().describe("Portal origin (e.g. https://<vendor>.example.co) selecting which active session to use. Optional when only one session is active.");
@@ -36203,7 +36227,7 @@ function registerRunTool(server, options) {
36203
36227
  }
36204
36228
  server.registerTool(`gog_${service}_run`, {
36205
36229
  description,
36206
- annotations: { destructiveHint: true },
36230
+ annotations: { destructiveHint: true, openWorldHint: true },
36207
36231
  inputSchema: external_exports.object(inputSchema)
36208
36232
  }, async (rawArgs) => {
36209
36233
  const { subcommand, args, account } = rawArgs;
@@ -36412,6 +36436,7 @@ async function requireDispatchConfirmation(ctx, options) {
36412
36436
  ...confirmation,
36413
36437
  tool: fallback.tool,
36414
36438
  account: fallback.account ?? readEnvVar("GOG_ACCOUNT") ?? "",
36439
+ args: fallback.args,
36415
36440
  confirmToken: fallback.confirmToken,
36416
36441
  subject: fallback.subject,
36417
36442
  instruction: fallback.instruction ?? CONFIRM_ACTION_INSTRUCTION,
@@ -36424,13 +36449,13 @@ function resultText(result) {
36424
36449
  }
36425
36450
 
36426
36451
  // ../gogcli-mcp/src/tools/auth.ts
36427
- var AUTH_RUN_SUBCOMMANDS = ["list", "status", "services", "remove", "alias"];
36452
+ var AUTH_RUN_SUBCOMMANDS = ["list", "status", "services", "alias"];
36428
36453
  function registerAuthToolsWith(server, defaultServices) {
36429
36454
  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.`;
36430
36455
  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.";
36431
36456
  server.registerTool("gog_auth_list", {
36432
36457
  description: "List the Google accounts stored in gogcli, with their scopes. This reads local configuration only \u2014 it does not contact Google and does NOT tell you whether an account still works: a signed-out account whose refresh token expired or was revoked is listed here exactly like a healthy one, scopes and all. Use gog_auth_health to check whether an account can actually authenticate.",
36433
- annotations: { readOnlyHint: true },
36458
+ annotations: { readOnlyHint: true, openWorldHint: false },
36434
36459
  inputSchema: external_exports.object({})
36435
36460
  }, async () => {
36436
36461
  try {
@@ -36441,7 +36466,7 @@ function registerAuthToolsWith(server, defaultServices) {
36441
36466
  });
36442
36467
  server.registerTool("gog_auth_status", {
36443
36468
  description: "Show gogcli auth CONFIGURATION: keyring backend, credential files, and auth setup. Despite the name this is not a health check \u2014 it reads local setup and does not contact Google, so it says nothing about whether an account can still authenticate. Use gog_auth_health for that.",
36444
- annotations: { readOnlyHint: true },
36469
+ annotations: { readOnlyHint: true, openWorldHint: false },
36445
36470
  inputSchema: external_exports.object({})
36446
36471
  }, async () => {
36447
36472
  try {
@@ -36452,7 +36477,7 @@ function registerAuthToolsWith(server, defaultServices) {
36452
36477
  });
36453
36478
  server.registerTool("gog_auth_health", {
36454
36479
  description: `Check the LIVE health of each stored Google account. Unlike gog_auth_status (which only reports keyring/config setup), this performs a real token refresh against Google, so it detects expired or revoked (invalid_grant) refresh tokens \u2014 the account-wide sign-out that blocks every service. Reports per account: whether the token is currently valid, the mapped cause when it is not, how long ago it was authorized, and a warning as it approaches the 7-day refresh-token limit that applies to OAuth apps whose consent screen is still in "Testing" mode. Run it proactively to re-authorize on your own schedule instead of mid-task. On a hosted deployment this is the ONLY check that measures Google: a connector showing "connected" or "refreshed" has verified the client's connection to the MCP host, and nothing else \u2014 the Google credential lives in gog's keyring on that host and can be dead while the connection looks perfectly healthy.`,
36455
- annotations: { readOnlyHint: true },
36480
+ annotations: { readOnlyHint: true, openWorldHint: true },
36456
36481
  inputSchema: external_exports.object({})
36457
36482
  }, async () => {
36458
36483
  try {
@@ -36463,7 +36488,7 @@ function registerAuthToolsWith(server, defaultServices) {
36463
36488
  });
36464
36489
  server.registerTool("gog_auth_services", {
36465
36490
  description: "List all Google services supported by gogcli and the OAuth scopes each requires.",
36466
- annotations: { readOnlyHint: true },
36491
+ annotations: { readOnlyHint: true, openWorldHint: false },
36467
36492
  inputSchema: external_exports.object({})
36468
36493
  }, async () => {
36469
36494
  try {
@@ -36474,7 +36499,7 @@ function registerAuthToolsWith(server, defaultServices) {
36474
36499
  });
36475
36500
  server.registerTool("gog_auth_add", {
36476
36501
  description: "Authorize a Google account via browser-based OAuth. Opens a browser window where the user must sign in and grant access. Blocks for up to 5 minutes waiting for the user to complete authorization. If the browser does not open automatically, a fallback URL is included in the response. Use gog_auth_list to check which accounts are already configured.",
36477
- annotations: { destructiveHint: true },
36502
+ annotations: { destructiveHint: true, openWorldHint: true },
36478
36503
  inputSchema: external_exports.object({
36479
36504
  email: external_exports.string().describe("Google account email to authorize"),
36480
36505
  services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe),
@@ -36494,7 +36519,7 @@ function registerAuthToolsWith(server, defaultServices) {
36494
36519
  });
36495
36520
  server.registerTool("gog_auth_add_url", {
36496
36521
  description: "Begin REMOTE/headless Google authorization (step 1 of 2). Returns a sign-in URL to open in any browser \u2014 no local server or terminal on the gogcli host is needed, so this works on a hosted deployment where the interactive gog_auth_add cannot. Hand the URL to the user; after they sign in, the browser is redirected to a localhost URL that fails to load \u2014 that is expected. They copy that full redirected URL (from the address bar) and you pass it to gog_auth_add_complete. The link is valid for 10 minutes. If you pass a custom `services` here, pass the SAME value to gog_auth_add_complete or the second step will not match this one.",
36497
- annotations: { readOnlyHint: true },
36522
+ annotations: { readOnlyHint: true, openWorldHint: false },
36498
36523
  inputSchema: external_exports.object({
36499
36524
  email: external_exports.string().describe("Google account email to authorize"),
36500
36525
  services: external_exports.string().optional().default(defaultServices).describe(servicesDescribe),
@@ -36511,7 +36536,7 @@ function registerAuthToolsWith(server, defaultServices) {
36511
36536
  });
36512
36537
  server.registerTool("gog_auth_add_complete", {
36513
36538
  description: "Complete REMOTE/headless Google authorization (step 2 of 2). Takes the full redirected localhost URL the user copied after finishing gog_auth_add_url, exchanges it for a refresh token, and stores it. Use the SAME `services` value you passed to gog_auth_add_url. Must run within 10 minutes of step 1 and against the same gogcli host.",
36514
- annotations: { destructiveHint: true },
36539
+ annotations: { destructiveHint: true, openWorldHint: true },
36515
36540
  inputSchema: external_exports.object({
36516
36541
  email: external_exports.string().describe("Google account email being authorized (same as step 1)"),
36517
36542
  redirectUrl: external_exports.string().describe(
@@ -36547,7 +36572,7 @@ function registerAuthToolsWith(server, defaultServices) {
36547
36572
  });
36548
36573
  registerRunTool(server, {
36549
36574
  service: "auth",
36550
- examples: '"remove", "alias", "list"',
36575
+ examples: '"alias", "list", "status"',
36551
36576
  omitAccount: true,
36552
36577
  allowedSubcommands: AUTH_RUN_SUBCOMMANDS,
36553
36578
  note: "For browser-based authorization, use gog_auth_add instead."
@@ -36615,7 +36640,7 @@ function vetDocsRun(subcommand, args) {
36615
36640
  function registerDocsTools(server) {
36616
36641
  server.registerTool("gog_docs_info", {
36617
36642
  description: "Get Google Doc metadata: title, ID, and other properties.",
36618
- annotations: { readOnlyHint: true },
36643
+ annotations: { readOnlyHint: true, openWorldHint: true },
36619
36644
  inputSchema: external_exports.object({
36620
36645
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36621
36646
  account: accountParam
@@ -36625,7 +36650,7 @@ function registerDocsTools(server) {
36625
36650
  });
36626
36651
  server.registerTool("gog_docs_cat", {
36627
36652
  description: "Read a Google Doc as plain text.",
36628
- annotations: { readOnlyHint: true },
36653
+ annotations: { readOnlyHint: true, openWorldHint: true },
36629
36654
  inputSchema: external_exports.object({
36630
36655
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36631
36656
  chips: external_exports.boolean().optional().describe("Render Google Docs smart chips (people, dates, rich links) inline in the text output"),
@@ -36638,7 +36663,7 @@ function registerDocsTools(server) {
36638
36663
  });
36639
36664
  server.registerTool("gog_docs_create", {
36640
36665
  description: "Create a new Google Doc. Returns JSON with the new docId and URL.",
36641
- annotations: { destructiveHint: true },
36666
+ annotations: { destructiveHint: true, openWorldHint: true },
36642
36667
  inputSchema: external_exports.object({
36643
36668
  title: external_exports.string().describe("Title for the new document"),
36644
36669
  account: accountParam
@@ -36648,7 +36673,7 @@ function registerDocsTools(server) {
36648
36673
  });
36649
36674
  server.registerTool("gog_docs_write", {
36650
36675
  description: "Write text content to a Google Doc, replacing existing body content by default. Set append=true to add after existing content.",
36651
- annotations: { destructiveHint: true },
36676
+ annotations: { destructiveHint: true, openWorldHint: true },
36652
36677
  inputSchema: external_exports.object({
36653
36678
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36654
36679
  text: external_exports.string().describe("Text content to write"),
@@ -36688,7 +36713,7 @@ function registerDocsTools(server) {
36688
36713
  });
36689
36714
  server.registerTool("gog_docs_find_replace", {
36690
36715
  description: "Find and replace text in a Google Doc.",
36691
- annotations: { destructiveHint: true },
36716
+ annotations: { destructiveHint: true, openWorldHint: true },
36692
36717
  inputSchema: external_exports.object({
36693
36718
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36694
36719
  find: external_exports.string().describe("Text to find"),
@@ -36700,7 +36725,7 @@ function registerDocsTools(server) {
36700
36725
  });
36701
36726
  server.registerTool("gog_docs_structure", {
36702
36727
  description: "Show a Google Doc's structure with numbered paragraphs. Useful for understanding the document layout before making index-based edits.",
36703
- annotations: { readOnlyHint: true },
36728
+ annotations: { readOnlyHint: true, openWorldHint: true },
36704
36729
  inputSchema: external_exports.object({
36705
36730
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36706
36731
  account: accountParam
@@ -36766,7 +36791,7 @@ var failIfNotEmptyParam = external_exports.boolean().optional().describe(
36766
36791
  );
36767
36792
 
36768
36793
  // ../gogcli-mcp/src/server.ts
36769
- var VERSION = true ? "4.7.0" : "0.0.0";
36794
+ var VERSION = true ? "4.7.1" : "0.0.0";
36770
36795
 
36771
36796
  // ../gogcli-mcp/src/bootstrap-auth.ts
36772
36797
  import { join as join7 } from "node:path";
@@ -36853,7 +36878,7 @@ function docTitle(raw) {
36853
36878
  function registerExtraDocsTools(server) {
36854
36879
  server.registerTool("gog_docs_copy", {
36855
36880
  description: "Copy a Google Doc to a new document with the given title.",
36856
- annotations: { destructiveHint: true },
36881
+ annotations: { destructiveHint: true, openWorldHint: true },
36857
36882
  inputSchema: external_exports.object({
36858
36883
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36859
36884
  title: external_exports.string().describe("Title for the new copy"),
@@ -36867,7 +36892,7 @@ function registerExtraDocsTools(server) {
36867
36892
  });
36868
36893
  server.registerTool("gog_docs_delete", {
36869
36894
  description: "Delete content within a Google Doc by character index range. To remove the entire document (move to Drive trash), use gog_docs_trash.",
36870
- annotations: { destructiveHint: true },
36895
+ annotations: { destructiveHint: true, openWorldHint: true },
36871
36896
  inputSchema: external_exports.object({
36872
36897
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36873
36898
  start: external_exports.number().optional().describe("Start index (character position, 1-based). Required unless `at` is set."),
@@ -36895,7 +36920,7 @@ function registerExtraDocsTools(server) {
36895
36920
  });
36896
36921
  server.registerTool("gog_docs_trash", {
36897
36922
  description: "Move an entire Google Doc to Drive trash. Convenience wrapper around `gog drive delete` so docs-only users can clean up without installing gogcli-mcp-drive. The doc remains recoverable from Drive trash for ~30 days.",
36898
- annotations: { destructiveHint: true },
36923
+ annotations: { destructiveHint: true, openWorldHint: true },
36899
36924
  inputSchema: external_exports.object({
36900
36925
  docId: external_exports.string().describe("Doc ID to move to trash"),
36901
36926
  account: accountParam
@@ -36905,7 +36930,7 @@ function registerExtraDocsTools(server) {
36905
36930
  });
36906
36931
  server.registerTool("gog_docs_edit", {
36907
36932
  description: "Edit a Google Doc by finding and replacing text (stream-edit style).",
36908
- annotations: { destructiveHint: true },
36933
+ annotations: { destructiveHint: true, openWorldHint: true },
36909
36934
  inputSchema: external_exports.object({
36910
36935
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36911
36936
  find: external_exports.string().describe("Text to find"),
@@ -36920,7 +36945,7 @@ function registerExtraDocsTools(server) {
36920
36945
  });
36921
36946
  server.registerTool("gog_docs_read", {
36922
36947
  description: 'Read the content of a Google Doc. Default: plain text body. Use format="json" for the raw Google Docs API response (lossless, includes character indices needed for index-based gog_docs_insert / gog_docs_delete calls). For markdown output, use gog_docs_export with format="md" \u2014 it writes to a file. Use gog_docs_structure to see paragraph-by-paragraph layout with indices.',
36923
- annotations: { readOnlyHint: true },
36948
+ annotations: { readOnlyHint: true, openWorldHint: true },
36924
36949
  inputSchema: external_exports.object({
36925
36950
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36926
36951
  format: external_exports.enum(["text", "json"]).optional().describe("Output format (default: text)"),
@@ -36946,7 +36971,7 @@ function registerExtraDocsTools(server) {
36946
36971
  });
36947
36972
  server.registerTool("gog_docs_format", {
36948
36973
  description: "Apply text or paragraph formatting to a Google Doc. Use `match` to format a specific text occurrence, `matchAll` to format every occurrence, or omit both to format the whole doc. Boolean flags (bold/italic/etc.) set the attribute; negated flags (noBold/noItalic/etc.) clear it.",
36949
- annotations: { destructiveHint: true },
36974
+ annotations: { destructiveHint: true, openWorldHint: true },
36950
36975
  inputSchema: external_exports.object({
36951
36976
  docId: external_exports.string().describe("Doc ID (from the URL)"),
36952
36977
  match: external_exports.string().optional().describe("Format only the first text match"),
@@ -37032,7 +37057,7 @@ function registerExtraDocsTools(server) {
37032
37057
  });
37033
37058
  server.registerTool("gog_docs_suggestions_list", {
37034
37059
  description: "List pending suggestions (suggested text insertions and deletions) in a Google Doc, with exact UTF-16 ranges and segment context. Read-only; does not accept or reject suggestions.",
37035
- annotations: { readOnlyHint: true },
37060
+ annotations: { readOnlyHint: true, openWorldHint: true },
37036
37061
  inputSchema: external_exports.object({
37037
37062
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37038
37063
  tab: external_exports.string().optional().describe("Tab title or ID (omit for the first tab)"),
@@ -37046,7 +37071,7 @@ function registerExtraDocsTools(server) {
37046
37071
  server.registerTool("gog_docs_export", {
37047
37072
  description: "Export a Google Doc as PDF, plain text, HTML, DOCX, or other format.",
37048
37073
  // Writes a file on the gog host and can overwrite one: not read-only (audit SEC-4).
37049
- annotations: { readOnlyHint: false, destructiveHint: true },
37074
+ annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
37050
37075
  inputSchema: external_exports.object({
37051
37076
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37052
37077
  format: external_exports.string().optional().describe("Export format: pdf, txt, html, docx, rtf, odt, epub (default: pdf)"),
@@ -37064,7 +37089,7 @@ function registerExtraDocsTools(server) {
37064
37089
  });
37065
37090
  server.registerTool("gog_docs_insert", {
37066
37091
  description: "Insert text at a specific character index in a Google Doc. When `index` is omitted, gog defaults to 1 (the very beginning), NOT the end \u2014 sequential inserts without an explicit index produce reversed output. To append at the end of the doc, use gog_docs_append (which uses `gog docs write --append` and is the right tool for iterative document construction). To find a valid index for mid-document inserts, call gog_docs_structure or gog_docs_read first.",
37067
- annotations: { destructiveHint: true },
37092
+ annotations: { destructiveHint: true, openWorldHint: true },
37068
37093
  inputSchema: external_exports.object({
37069
37094
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37070
37095
  content: external_exports.string().optional().describe("Text content to insert"),
@@ -37094,7 +37119,7 @@ function registerExtraDocsTools(server) {
37094
37119
  });
37095
37120
  server.registerTool("gog_docs_append", {
37096
37121
  description: "Append text to the end of a Google Doc. This is the right tool for iterative document construction \u2014 multiple sequential calls produce content in the order they were called. Use gog_docs_insert only when you need to insert at a specific character position. Known markdown=true limitations (tracked upstream): (a) 3+ tables in one call reorders the trailing punctuation of the paragraph before the 3rd table \u2014 split into multiple calls with \u22642 tables each (openclaw/gogcli#607); (b) inline **bold** / *italic* / `code` inside table cells renders as literal characters \u2014 pre-format cell text separately or apply formatting after the append via gog_docs_format (openclaw/gogcli#608); (c) tables with an empty header row leak the last data row as literal pipe text \u2014 always supply a non-empty header (openclaw/gogcli#609).",
37097
- annotations: { destructiveHint: true },
37122
+ annotations: { destructiveHint: true, openWorldHint: true },
37098
37123
  inputSchema: external_exports.object({
37099
37124
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37100
37125
  text: external_exports.string().optional().describe("Text content to append"),
@@ -37114,7 +37139,7 @@ function registerExtraDocsTools(server) {
37114
37139
  });
37115
37140
  server.registerTool("gog_docs_list_tabs", {
37116
37141
  description: "List all tabs in a Google Doc.",
37117
- annotations: { readOnlyHint: true },
37142
+ annotations: { readOnlyHint: true, openWorldHint: true },
37118
37143
  inputSchema: external_exports.object({
37119
37144
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37120
37145
  account: accountParam
@@ -37124,7 +37149,7 @@ function registerExtraDocsTools(server) {
37124
37149
  });
37125
37150
  server.registerTool("gog_docs_sed", {
37126
37151
  description: "Stream-edit a Google Doc with sed-like regex expressions (s/find/replace/ syntax).",
37127
- annotations: { destructiveHint: true },
37152
+ annotations: { destructiveHint: true, openWorldHint: true },
37128
37153
  inputSchema: external_exports.object({
37129
37154
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37130
37155
  expression: external_exports.string().optional().describe('Single sed expression (e.g. "s/old/new/g")'),
@@ -37148,7 +37173,7 @@ function registerExtraDocsTools(server) {
37148
37173
  });
37149
37174
  server.registerTool("gog_docs_update", {
37150
37175
  description: "Update a Google Doc \u2014 insert or replace text at a specific position.",
37151
- annotations: { destructiveHint: true },
37176
+ annotations: { destructiveHint: true, openWorldHint: true },
37152
37177
  inputSchema: external_exports.object({
37153
37178
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37154
37179
  text: external_exports.string().optional().describe("Text content to write"),
@@ -37184,7 +37209,7 @@ function registerExtraDocsTools(server) {
37184
37209
  });
37185
37210
  server.registerTool("gog_docs_comments_list", {
37186
37211
  description: "List comments on a Google Doc. Returns open comments by default; set includeResolved=true to include resolved comments. Set locate=true (or pass tab) to attach each comment's tab and Docs index ranges as location.matches[] plus location.orphaned \u2014 that costs one extra document fetch, but only one for the whole listing, where gog_docs_comments_locate costs one per comment. Either flag additionally requires the Docs scope; the plain listing needs only Drive. matches[] always spans every tab, so a quote appearing in two tabs is visible as an ambiguity rather than silently resolved. tab keeps only comments with a match in that tab, which drops orphaned comments and comments that quote nothing.",
37187
- annotations: { readOnlyHint: true },
37212
+ annotations: { readOnlyHint: true, openWorldHint: true },
37188
37213
  inputSchema: external_exports.object({
37189
37214
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37190
37215
  includeResolved: external_exports.boolean().optional().describe("Include resolved comments (default: false, open only)"),
@@ -37205,7 +37230,7 @@ function registerExtraDocsTools(server) {
37205
37230
  });
37206
37231
  server.registerTool("gog_docs_comments_get", {
37207
37232
  description: "Get a single comment by ID, including its replies.",
37208
- annotations: { readOnlyHint: true },
37233
+ annotations: { readOnlyHint: true, openWorldHint: true },
37209
37234
  inputSchema: external_exports.object({
37210
37235
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37211
37236
  commentId: external_exports.string().describe("Comment ID"),
@@ -37216,7 +37241,7 @@ function registerExtraDocsTools(server) {
37216
37241
  });
37217
37242
  server.registerTool("gog_docs_comments_add", {
37218
37243
  description: "Add a comment to a Google Doc. Optionally attach quoted text that appears as the highlighted passage in the Google Docs UI. The Doc's owner and everyone the text +mentions are notified, so this reads the Doc and asks the MCP host to show the user a confirmation prompt with the Doc, the text and who is mentioned first; nothing is posted unless they accept." + CONFIRM_FALLBACK_DESCRIPTION,
37219
- annotations: { destructiveHint: false },
37244
+ annotations: { destructiveHint: false, openWorldHint: true },
37220
37245
  inputSchema: external_exports.object({
37221
37246
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37222
37247
  content: external_exports.string().describe("Comment text"),
@@ -37239,6 +37264,7 @@ function registerExtraDocsTools(server) {
37239
37264
  details: { doc, textPreview: bodyPreview(content), quoted, mentions },
37240
37265
  unsupportedNote: "Ask the user to comment from Google Docs.",
37241
37266
  fallback: {
37267
+ args: { docId, content, quoted, account },
37242
37268
  tool: "gog_docs_comments_add",
37243
37269
  account,
37244
37270
  confirmToken,
@@ -37253,7 +37279,7 @@ function registerExtraDocsTools(server) {
37253
37279
  });
37254
37280
  server.registerTool("gog_docs_comments_reply", {
37255
37281
  description: "Reply to an existing comment on a Google Doc. Everyone on the thread and anyone the reply +mentions is notified, so this reads the Doc and the comment and asks the MCP host to show the user a confirmation prompt with both and the reply first; nothing is posted unless they accept." + CONFIRM_FALLBACK_DESCRIPTION,
37256
- annotations: { destructiveHint: false },
37282
+ annotations: { destructiveHint: false, openWorldHint: true },
37257
37283
  inputSchema: external_exports.object({
37258
37284
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37259
37285
  commentId: external_exports.string().describe("Comment ID to reply to"),
@@ -37277,6 +37303,7 @@ function registerExtraDocsTools(server) {
37277
37303
  details: { doc, replyingTo, textPreview: bodyPreview(content), mentions },
37278
37304
  unsupportedNote: "Ask the user to reply from Google Docs.",
37279
37305
  fallback: {
37306
+ args: { docId, commentId, content, account },
37280
37307
  tool: "gog_docs_comments_reply",
37281
37308
  account,
37282
37309
  confirmToken,
@@ -37291,7 +37318,7 @@ function registerExtraDocsTools(server) {
37291
37318
  });
37292
37319
  server.registerTool("gog_docs_comments_resolve", {
37293
37320
  description: "Resolve a comment (mark as done). Optionally include a closing message.",
37294
- annotations: { destructiveHint: true },
37321
+ annotations: { destructiveHint: true, openWorldHint: true },
37295
37322
  inputSchema: external_exports.object({
37296
37323
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37297
37324
  commentId: external_exports.string().describe("Comment ID to resolve"),
@@ -37305,7 +37332,7 @@ function registerExtraDocsTools(server) {
37305
37332
  });
37306
37333
  server.registerTool("gog_docs_comments_delete", {
37307
37334
  description: "Delete a comment from a Google Doc. This action is permanent.",
37308
- annotations: { destructiveHint: true },
37335
+ annotations: { destructiveHint: true, openWorldHint: true },
37309
37336
  inputSchema: external_exports.object({
37310
37337
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37311
37338
  commentId: external_exports.string().describe("Comment ID to delete"),
@@ -37316,7 +37343,7 @@ function registerExtraDocsTools(server) {
37316
37343
  });
37317
37344
  server.registerTool("gog_docs_comments_reopen", {
37318
37345
  description: "Reopen a previously resolved comment (flip resolved \u2192 open).",
37319
- annotations: { destructiveHint: true },
37346
+ annotations: { destructiveHint: true, openWorldHint: true },
37320
37347
  inputSchema: external_exports.object({
37321
37348
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37322
37349
  commentId: external_exports.string().describe("Comment ID to reopen"),
@@ -37327,7 +37354,7 @@ function registerExtraDocsTools(server) {
37327
37354
  });
37328
37355
  server.registerTool("gog_docs_comments_locate", {
37329
37356
  description: "Locate a comment's anchor in a Google Doc \u2014 resolves the comment's quoted text to its current Docs API index range, or reports the comment as orphaned if the quote can no longer be found (e.g. the anchored text was edited away). Read-only; useful before an index-based edit near a comment.",
37330
- annotations: { readOnlyHint: true },
37357
+ annotations: { readOnlyHint: true, openWorldHint: true },
37331
37358
  inputSchema: external_exports.object({
37332
37359
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37333
37360
  commentId: external_exports.string().describe("Comment ID to locate"),
@@ -37345,7 +37372,7 @@ function registerExtraDocsTools(server) {
37345
37372
  });
37346
37373
  server.registerTool("gog_docs_find_range", {
37347
37374
  description: "Map literal text in a Google Doc to its Docs API UTF-16 index range(s). Read-only helper for computing the start/end indices that index-based tools (gog_docs_delete, gog_docs_update --replace-range) need. Returns the first match by default; use occurrence to pick a specific one or all to return every match.",
37348
- annotations: { readOnlyHint: true },
37375
+ annotations: { readOnlyHint: true, openWorldHint: true },
37349
37376
  inputSchema: external_exports.object({
37350
37377
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37351
37378
  text: external_exports.string().describe("Literal text to locate"),
@@ -37371,7 +37398,7 @@ function registerExtraDocsTools(server) {
37371
37398
  });
37372
37399
  server.registerTool("gog_batch_begin", {
37373
37400
  description: "Open a persisted, revision-locked request batch for a Google Doc. Subsequent docs mutation tools called with batch=<batchId> append their requests locally instead of applying them; gog_batch_end submits everything atomically. Returns the batchId.",
37374
- annotations: { destructiveHint: false },
37401
+ annotations: { destructiveHint: false, openWorldHint: false },
37375
37402
  inputSchema: external_exports.object({
37376
37403
  docId: external_exports.string().describe("Google Doc ID the batch is locked to"),
37377
37404
  name: external_exports.string().optional().describe("Optional batch label"),
@@ -37384,7 +37411,7 @@ function registerExtraDocsTools(server) {
37384
37411
  });
37385
37412
  server.registerTool("gog_batch_end", {
37386
37413
  description: "Submit a persisted batch: applies every composed request to the doc in one atomic batchUpdate against the locked revision. Atomic by default \u2014 set autoSplit to submit >500-request batches as ordered chunks (non-atomic), or continueOnError to retry individually after an atomic validation failure, retaining failures in the batch.",
37387
- annotations: { destructiveHint: true },
37414
+ annotations: { destructiveHint: true, openWorldHint: true },
37388
37415
  inputSchema: external_exports.object({
37389
37416
  batchId: external_exports.string().describe("Batch ID (from gog_batch_begin)"),
37390
37417
  autoSplit: external_exports.boolean().optional().describe("Submit batches over 500 requests as ordered chunks (non-atomic)"),
@@ -37399,7 +37426,7 @@ function registerExtraDocsTools(server) {
37399
37426
  });
37400
37427
  server.registerTool("gog_batch_abort", {
37401
37428
  description: "Discard a persisted batch and its composed requests without applying anything to the doc.",
37402
- annotations: { destructiveHint: true },
37429
+ annotations: { destructiveHint: true, openWorldHint: false },
37403
37430
  inputSchema: external_exports.object({
37404
37431
  batchId: external_exports.string().describe("Batch ID to discard"),
37405
37432
  account: accountParam
@@ -37409,7 +37436,7 @@ function registerExtraDocsTools(server) {
37409
37436
  });
37410
37437
  server.registerTool("gog_batch_list", {
37411
37438
  description: "List persisted Docs request batches (id, doc, label, request count, status).",
37412
- annotations: { readOnlyHint: true },
37439
+ annotations: { readOnlyHint: true, openWorldHint: false },
37413
37440
  inputSchema: external_exports.object({
37414
37441
  account: accountParam
37415
37442
  })
@@ -37418,7 +37445,7 @@ function registerExtraDocsTools(server) {
37418
37445
  });
37419
37446
  server.registerTool("gog_batch_show", {
37420
37447
  description: "Show one persisted batch: its doc, locked revision, and the composed requests awaiting submission.",
37421
- annotations: { readOnlyHint: true },
37448
+ annotations: { readOnlyHint: true, openWorldHint: false },
37422
37449
  inputSchema: external_exports.object({
37423
37450
  batchId: external_exports.string().describe("Batch ID"),
37424
37451
  account: accountParam
@@ -37428,7 +37455,7 @@ function registerExtraDocsTools(server) {
37428
37455
  });
37429
37456
  server.registerTool("gog_batch_prune", {
37430
37457
  description: "Delete stale persisted batches (not updated within olderThan).",
37431
- annotations: { destructiveHint: true },
37458
+ annotations: { destructiveHint: true, openWorldHint: false },
37432
37459
  inputSchema: external_exports.object({
37433
37460
  olderThan: external_exports.string().optional().describe("Delete batches not updated within this duration (e.g. 72h, 7d)"),
37434
37461
  account: accountParam
@@ -37440,7 +37467,7 @@ function registerExtraDocsTools(server) {
37440
37467
  });
37441
37468
  server.registerTool("gog_docs_table_column_width", {
37442
37469
  description: "Set a fixed width (in points) for a table column, or reset columns to Docs-managed even distribution. Target the table by 1-based index in document order (negative counts from the end) and the column by 1-based number. Pass evenlyDistributed without col to reset every column in the table.",
37443
- annotations: { destructiveHint: true },
37470
+ annotations: { destructiveHint: true, openWorldHint: true },
37444
37471
  inputSchema: external_exports.object({
37445
37472
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37446
37473
  col: external_exports.number().int().optional().describe("1-based column number. Omit with evenlyDistributed to reset all columns."),
@@ -37464,7 +37491,7 @@ function registerExtraDocsTools(server) {
37464
37491
  const tableSelectorParam = external_exports.string().optional().describe("Table selector: 1-based index (negative from the end), exact first-cell text, * for the only table, or text:VALUE for numeric/syntax-looking first-cell text (default: 1)");
37465
37492
  server.registerTool("gog_docs_table_row_insert", {
37466
37493
  description: 'Insert a row into a native Google Docs table, optionally populated from a JSON string array. Inserts before the 1-based position given by `at` (negative counts from the end; "end" appends \u2014 the default).',
37467
- annotations: { destructiveHint: true },
37494
+ annotations: { destructiveHint: true, openWorldHint: true },
37468
37495
  inputSchema: external_exports.object({
37469
37496
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37470
37497
  table: tableSelectorParam,
@@ -37483,7 +37510,7 @@ function registerExtraDocsTools(server) {
37483
37510
  });
37484
37511
  server.registerTool("gog_docs_table_row_delete", {
37485
37512
  description: "Delete a row from a native Google Docs table by 1-based row number (negative counts from the end). The row's cell content is lost.",
37486
- annotations: { destructiveHint: true },
37513
+ annotations: { destructiveHint: true, openWorldHint: true },
37487
37514
  inputSchema: external_exports.object({
37488
37515
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37489
37516
  row: external_exports.number().int().describe("1-based row number; negative indexes count from the end"),
@@ -37499,7 +37526,7 @@ function registerExtraDocsTools(server) {
37499
37526
  });
37500
37527
  server.registerTool("gog_docs_table_column_insert", {
37501
37528
  description: 'Insert a column into a native Google Docs table. Inserts before the 1-based position given by `at` (negative counts from the end; "end" appends \u2014 the default).',
37502
- annotations: { destructiveHint: true },
37529
+ annotations: { destructiveHint: true, openWorldHint: true },
37503
37530
  inputSchema: external_exports.object({
37504
37531
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37505
37532
  table: tableSelectorParam,
@@ -37516,7 +37543,7 @@ function registerExtraDocsTools(server) {
37516
37543
  });
37517
37544
  server.registerTool("gog_docs_table_column_delete", {
37518
37545
  description: "Delete a column from a native Google Docs table by 1-based column number (negative counts from the end). The column's cell content is lost.",
37519
- annotations: { destructiveHint: true },
37546
+ annotations: { destructiveHint: true, openWorldHint: true },
37520
37547
  inputSchema: external_exports.object({
37521
37548
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37522
37549
  col: external_exports.number().int().describe("1-based column number; negative indexes count from the end"),
@@ -37532,7 +37559,7 @@ function registerExtraDocsTools(server) {
37532
37559
  });
37533
37560
  server.registerTool("gog_docs_table_merge", {
37534
37561
  description: "Merge a rectangular cell range in a native Google Docs table. Content of non-first cells in the range is absorbed/discarded by the merge \u2014 use gog_docs_table_unmerge to split back.",
37535
- annotations: { destructiveHint: true },
37562
+ annotations: { destructiveHint: true, openWorldHint: true },
37536
37563
  inputSchema: external_exports.object({
37537
37564
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37538
37565
  range: external_exports.string().describe('1-based cell range r1,c1:r2,c2 (e.g. "1,1:2,3")'),
@@ -37548,7 +37575,7 @@ function registerExtraDocsTools(server) {
37548
37575
  });
37549
37576
  server.registerTool("gog_docs_table_unmerge", {
37550
37577
  description: "Unmerge (split) the merged region containing a given cell in a native Google Docs table.",
37551
- annotations: { destructiveHint: true },
37578
+ annotations: { destructiveHint: true, openWorldHint: true },
37552
37579
  inputSchema: external_exports.object({
37553
37580
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37554
37581
  cell: external_exports.string().describe('1-based cell r,c inside the merged region (e.g. "1,1")'),
@@ -37564,7 +37591,7 @@ function registerExtraDocsTools(server) {
37564
37591
  });
37565
37592
  server.registerTool("gog_docs_named_range_create", {
37566
37593
  description: "Create a named range \u2014 a durable, tab-aware anchor over a span of document text that survives subsequent edits (unlike raw indices). Anchor by literal text (`at`) or explicit UTF-16 start/end indices. Pair with gog_docs_named_range_replace for repeatable templated updates.",
37567
- annotations: { destructiveHint: true },
37594
+ annotations: { destructiveHint: true, openWorldHint: true },
37568
37595
  inputSchema: external_exports.object({
37569
37596
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37570
37597
  name: external_exports.string().describe("Unique named range name"),
@@ -37588,7 +37615,7 @@ function registerExtraDocsTools(server) {
37588
37615
  });
37589
37616
  server.registerTool("gog_docs_named_range_list", {
37590
37617
  description: "List named ranges in a Google Doc, optionally filtered by name.",
37591
- annotations: { readOnlyHint: true },
37618
+ annotations: { readOnlyHint: true, openWorldHint: true },
37592
37619
  inputSchema: external_exports.object({
37593
37620
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37594
37621
  name: external_exports.string().optional().describe("Only return ranges with this name"),
@@ -37603,7 +37630,7 @@ function registerExtraDocsTools(server) {
37603
37630
  });
37604
37631
  server.registerTool("gog_docs_named_range_delete", {
37605
37632
  description: "Delete a named range (the anchor only \u2014 the underlying document text is untouched).",
37606
- annotations: { destructiveHint: true },
37633
+ annotations: { destructiveHint: true, openWorldHint: true },
37607
37634
  inputSchema: external_exports.object({
37608
37635
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37609
37636
  nameOrId: external_exports.string().describe("Named range name or ID"),
@@ -37617,7 +37644,7 @@ function registerExtraDocsTools(server) {
37617
37644
  });
37618
37645
  server.registerTool("gog_docs_named_range_replace", {
37619
37646
  description: "Replace the text inside a named range with new content (inline or from a file), keeping the anchor for future updates \u2014 the templated-update workhorse.",
37620
- annotations: { destructiveHint: true },
37647
+ annotations: { destructiveHint: true, openWorldHint: true },
37621
37648
  inputSchema: external_exports.object({
37622
37649
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37623
37650
  nameOrId: external_exports.string().describe("Named range name or ID"),
@@ -37636,7 +37663,7 @@ function registerExtraDocsTools(server) {
37636
37663
  });
37637
37664
  server.registerTool("gog_docs_tables_list", {
37638
37665
  description: "Enumerate the native tables in a Google Doc (dimensions, position) \u2014 the index/first-cell-text it reports feeds the `table` selector on the table-row/column/merge tools.",
37639
- annotations: { readOnlyHint: true },
37666
+ annotations: { readOnlyHint: true, openWorldHint: true },
37640
37667
  inputSchema: external_exports.object({
37641
37668
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37642
37669
  tab: external_exports.string().optional().describe("Tab title or ID (omit for default)"),
@@ -37649,7 +37676,7 @@ function registerExtraDocsTools(server) {
37649
37676
  });
37650
37677
  server.registerTool("gog_docs_images_list", {
37651
37678
  description: "Enumerate inline/positioned images in a Google Doc.",
37652
- annotations: { readOnlyHint: true },
37679
+ annotations: { readOnlyHint: true, openWorldHint: true },
37653
37680
  inputSchema: external_exports.object({
37654
37681
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37655
37682
  tab: external_exports.string().optional().describe("Tab title or ID (omit for default)"),
@@ -37662,7 +37689,7 @@ function registerExtraDocsTools(server) {
37662
37689
  });
37663
37690
  server.registerTool("gog_docs_headings_list", {
37664
37691
  description: "Enumerate headings in a Google Doc (a lightweight outline view), optionally filtered to one heading level.",
37665
- annotations: { readOnlyHint: true },
37692
+ annotations: { readOnlyHint: true, openWorldHint: true },
37666
37693
  inputSchema: external_exports.object({
37667
37694
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37668
37695
  level: external_exports.number().int().optional().describe("Only return this heading level (1-6)"),
@@ -37677,7 +37704,7 @@ function registerExtraDocsTools(server) {
37677
37704
  });
37678
37705
  server.registerTool("gog_docs_paragraphs_list", {
37679
37706
  description: "Enumerate paragraphs in a Google Doc with emptiness, text-run ranges, styles, and links \u2014 richer than gog_docs_structure when you need per-run detail. Optionally filter to one named style.",
37680
- annotations: { readOnlyHint: true },
37707
+ annotations: { readOnlyHint: true, openWorldHint: true },
37681
37708
  inputSchema: external_exports.object({
37682
37709
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37683
37710
  style: external_exports.string().optional().describe("Only return this named style (e.g. NORMAL_TEXT or HEADING_2)"),
@@ -37692,7 +37719,7 @@ function registerExtraDocsTools(server) {
37692
37719
  });
37693
37720
  server.registerTool("gog_docs_insert_page_break", {
37694
37721
  description: "Insert a Google Docs page break via InsertPageBreakRequest \u2014 the only path for multi-page deliverables (markdown has no page-break construct). Specify `index` for a precise character position, or `atEnd` for end-of-doc.",
37695
- annotations: { destructiveHint: true },
37722
+ annotations: { destructiveHint: true, openWorldHint: true },
37696
37723
  inputSchema: external_exports.object({
37697
37724
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37698
37725
  index: external_exports.number().int().optional().describe("Character index to insert at (1 = beginning). Omit or use atEnd for end-of-doc."),
@@ -37717,7 +37744,7 @@ function registerExtraDocsTools(server) {
37717
37744
  });
37718
37745
  server.registerTool("gog_docs_page_layout", {
37719
37746
  description: "Toggle the page layout (pageless | pages) of an existing Google Doc. Sibling to the --pageless flag on docs create/write/update for docs that were already created (e.g. by Drive markdown conversion) without the desired layout.",
37720
- annotations: { destructiveHint: true },
37747
+ annotations: { destructiveHint: true, openWorldHint: true },
37721
37748
  inputSchema: external_exports.object({
37722
37749
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37723
37750
  layout: external_exports.enum(["pageless", "pages"]).optional().describe("Page layout (default: pageless)"),
@@ -37744,7 +37771,7 @@ function registerExtraDocsTools(server) {
37744
37771
  });
37745
37772
  server.registerTool("gog_docs_insert_table", {
37746
37773
  description: "Insert a native Google Docs table via InsertTableRequest, bypassing the markdown writer. Use this instead of writing a markdown table when you need precise dimensions or to avoid the markdown writer's table limitations. `valuesJson` is a JSON 2D string array whose dimensions must match rows x cols.",
37747
- annotations: { destructiveHint: true },
37774
+ annotations: { destructiveHint: true, openWorldHint: true },
37748
37775
  inputSchema: external_exports.object({
37749
37776
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37750
37777
  rows: external_exports.number().int().min(1).describe("Number of rows (>=1)"),
@@ -37765,7 +37792,7 @@ function registerExtraDocsTools(server) {
37765
37792
  });
37766
37793
  server.registerTool("gog_docs_cell_update", {
37767
37794
  description: "Replace (or append to) the content of a single table cell, addressed by table / row / column \u2014 non-destructive to the rest of the table, unlike index-based edits that shift on every change. Provide content inline or read it from contentFile. Note: row/col/tableIndex are 1-based here; the sibling gog_docs_cell_style uses 0-based addressing.",
37768
- annotations: { destructiveHint: true },
37795
+ annotations: { destructiveHint: true, openWorldHint: true },
37769
37796
  inputSchema: external_exports.object({
37770
37797
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37771
37798
  row: external_exports.number().int().describe("1-based row number"),
@@ -37796,7 +37823,7 @@ function registerExtraDocsTools(server) {
37796
37823
  });
37797
37824
  server.registerTool("gog_docs_cell_style", {
37798
37825
  description: "Apply background color and/or inline text styling (bold, italic, underline, colors) to one or more table cells, addressed by 0-based row/column with optional spans. Sibling to gog_docs_cell_update, which changes cell content rather than styling. Note: row/col/tableIndex are 0-based here; gog_docs_cell_update uses 1-based addressing.",
37799
- annotations: { destructiveHint: true },
37826
+ annotations: { destructiveHint: true, openWorldHint: true },
37800
37827
  inputSchema: external_exports.object({
37801
37828
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37802
37829
  row: external_exports.number().int().describe("0-based row number"),
@@ -37851,7 +37878,7 @@ function registerExtraDocsTools(server) {
37851
37878
  });
37852
37879
  server.registerTool("gog_docs_insert_image", {
37853
37880
  description: "Insert an image into a Google Doc from a local file or a public HTTPS URL. file: uploaded to Drive, temporarily shared so Docs can fetch it, inserted, then the public permission is revoked. url: inserted directly with no Drive upload or temporary sharing. Replaces placeholder text (at) or appends at end-of-doc.",
37854
- annotations: { destructiveHint: true },
37881
+ annotations: { destructiveHint: true, openWorldHint: true },
37855
37882
  inputSchema: external_exports.object({
37856
37883
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37857
37884
  file: external_exports.string().optional().describe("Local PNG, JPEG, or GIF image to upload and insert (exactly one of file or url)"),
@@ -37886,7 +37913,7 @@ function registerExtraDocsTools(server) {
37886
37913
  });
37887
37914
  server.registerTool("gog_docs_insert_person", {
37888
37915
  description: "Insert a native Google Docs person smart chip (the interactive @-mention chip) for an email address, at a character index or end-of-doc.",
37889
- annotations: { destructiveHint: true },
37916
+ annotations: { destructiveHint: true, openWorldHint: true },
37890
37917
  inputSchema: external_exports.object({
37891
37918
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37892
37919
  email: external_exports.string().describe("Email address for the person chip"),
@@ -37912,7 +37939,7 @@ function registerExtraDocsTools(server) {
37912
37939
  });
37913
37940
  server.registerTool("gog_docs_insert_date_chip", {
37914
37941
  description: "Insert a native Google Docs date smart chip, at a character index or end-of-doc.",
37915
- annotations: { destructiveHint: true },
37942
+ annotations: { destructiveHint: true, openWorldHint: true },
37916
37943
  inputSchema: external_exports.object({
37917
37944
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37918
37945
  date: external_exports.string().optional().describe("Date to insert as YYYY-MM-DD (default: today)"),
@@ -37935,7 +37962,7 @@ function registerExtraDocsTools(server) {
37935
37962
  });
37936
37963
  server.registerTool("gog_docs_add_tab", {
37937
37964
  description: "Add a tab to a Google Doc. Tabs partition a doc into independently-addressable sections (multi-tab docs). Optionally set the title, zero-based position, parent tab (for nesting), and an emoji icon.",
37938
- annotations: { destructiveHint: false },
37965
+ annotations: { destructiveHint: false, openWorldHint: true },
37939
37966
  inputSchema: external_exports.object({
37940
37967
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37941
37968
  title: external_exports.string().optional().describe("User-visible tab title"),
@@ -37954,7 +37981,7 @@ function registerExtraDocsTools(server) {
37954
37981
  });
37955
37982
  server.registerTool("gog_docs_rename_tab", {
37956
37983
  description: "Rename a tab in a Google Doc. Identify the existing tab by title or ID and give it a new title.",
37957
- annotations: { destructiveHint: false },
37984
+ annotations: { destructiveHint: false, openWorldHint: true },
37958
37985
  inputSchema: external_exports.object({
37959
37986
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37960
37987
  tab: external_exports.string().describe("Existing tab title or ID to rename"),
@@ -37967,7 +37994,7 @@ function registerExtraDocsTools(server) {
37967
37994
  });
37968
37995
  server.registerTool("gog_docs_delete_tab", {
37969
37996
  description: "Delete a tab (and its content) from a Google Doc. Identify the tab by title or ID. This permanently removes the tab and everything in it.",
37970
- annotations: { destructiveHint: true },
37997
+ annotations: { destructiveHint: true, openWorldHint: true },
37971
37998
  inputSchema: external_exports.object({
37972
37999
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37973
38000
  tab: external_exports.string().describe("Existing tab title or ID to delete"),
@@ -37979,7 +38006,7 @@ function registerExtraDocsTools(server) {
37979
38006
  });
37980
38007
  server.registerTool("gog_docs_clear", {
37981
38008
  description: "Clear all content from a Google Doc, leaving an empty document. The doc itself is preserved (same ID/URL); only its body content is removed. To delete the whole doc instead, use gog_docs_trash.",
37982
- annotations: { destructiveHint: true },
38009
+ annotations: { destructiveHint: true, openWorldHint: true },
37983
38010
  inputSchema: external_exports.object({
37984
38011
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37985
38012
  account: accountParam
@@ -37989,7 +38016,7 @@ function registerExtraDocsTools(server) {
37989
38016
  });
37990
38017
  server.registerTool("gog_docs_insert_footnote", {
37991
38018
  description: "Insert a footnote at a character index (or end-of-doc) and populate its text. The footnote reference mark is placed in the body; the footnote content goes in the new footnote segment.",
37992
- annotations: { destructiveHint: true },
38019
+ annotations: { destructiveHint: true, openWorldHint: true },
37993
38020
  inputSchema: external_exports.object({
37994
38021
  docId: external_exports.string().describe("Doc ID (from the URL)"),
37995
38022
  text: external_exports.string().optional().describe("Footnote text"),
@@ -38017,7 +38044,7 @@ function registerExtraDocsTools(server) {
38017
38044
  });
38018
38045
  server.registerTool("gog_docs_insert_section_break", {
38019
38046
  description: "Insert a continuous or next-page section break at a character index (or end-of-doc). Section breaks enable per-section layout such as column counts (see gog_docs_section_columns).",
38020
- annotations: { destructiveHint: true },
38047
+ annotations: { destructiveHint: true, openWorldHint: true },
38021
38048
  inputSchema: external_exports.object({
38022
38049
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38023
38050
  type: external_exports.enum(["next-page", "continuous"]).optional().describe("Section break type (default: next-page)"),
@@ -38044,7 +38071,7 @@ function registerExtraDocsTools(server) {
38044
38071
  });
38045
38072
  server.registerTool("gog_docs_insert_horizontal_rule", {
38046
38073
  description: "Insert a horizontal rule (paragraph border) at a character index (or end-of-doc).",
38047
- annotations: { destructiveHint: true },
38074
+ annotations: { destructiveHint: true, openWorldHint: true },
38048
38075
  inputSchema: external_exports.object({
38049
38076
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38050
38077
  index: external_exports.number().int().optional().describe("Character index to insert at (1 = beginning). Omit or use atEnd for end-of-doc."),
@@ -38069,7 +38096,7 @@ function registerExtraDocsTools(server) {
38069
38096
  });
38070
38097
  server.registerTool("gog_docs_section_columns", {
38071
38098
  description: "Set the column count (1-3) for the document section containing the target position. Use count=1 to reset to a single column. Anchor by index, end-of-doc, or literal text.",
38072
- annotations: { destructiveHint: true },
38099
+ annotations: { destructiveHint: true, openWorldHint: true },
38073
38100
  inputSchema: external_exports.object({
38074
38101
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38075
38102
  count: external_exports.number().int().min(1).max(3).describe("Number of columns (1-3; 1 resets to one column)"),
@@ -38097,7 +38124,7 @@ function registerExtraDocsTools(server) {
38097
38124
  });
38098
38125
  server.registerTool("gog_docs_header_list", {
38099
38126
  description: "List a Google Doc's headers and their segment IDs. Use a segment ID with the segment param on gog_docs_insert / gog_docs_update / gog_docs_delete / gog_docs_format / gog_docs_find_range to edit inside a header.",
38100
- annotations: { readOnlyHint: true },
38127
+ annotations: { readOnlyHint: true, openWorldHint: true },
38101
38128
  inputSchema: external_exports.object({
38102
38129
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38103
38130
  tab: external_exports.string().optional().describe("Limit results to a tab title or ID"),
@@ -38110,7 +38137,7 @@ function registerExtraDocsTools(server) {
38110
38137
  });
38111
38138
  server.registerTool("gog_docs_header_create", {
38112
38139
  description: "Create a header in a Google Doc and optionally populate its initial text. Returns the new header segment ID.",
38113
- annotations: { destructiveHint: false },
38140
+ annotations: { destructiveHint: false, openWorldHint: true },
38114
38141
  inputSchema: external_exports.object({
38115
38142
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38116
38143
  text: external_exports.string().optional().describe("Initial header text"),
@@ -38138,7 +38165,7 @@ function registerExtraDocsTools(server) {
38138
38165
  });
38139
38166
  server.registerTool("gog_docs_header_delete", {
38140
38167
  description: "Delete a header from a Google Doc by its segment ID (from gog_docs_header_list).",
38141
- annotations: { destructiveHint: true },
38168
+ annotations: { destructiveHint: true, openWorldHint: true },
38142
38169
  inputSchema: external_exports.object({
38143
38170
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38144
38171
  headerId: external_exports.string().describe("Header segment ID (from gog_docs_header_list)"),
@@ -38153,7 +38180,7 @@ function registerExtraDocsTools(server) {
38153
38180
  });
38154
38181
  server.registerTool("gog_docs_footer_list", {
38155
38182
  description: "List a Google Doc's footers and their segment IDs. Use a segment ID with the segment param on gog_docs_insert / gog_docs_update / gog_docs_delete / gog_docs_format / gog_docs_find_range to edit inside a footer.",
38156
- annotations: { readOnlyHint: true },
38183
+ annotations: { readOnlyHint: true, openWorldHint: true },
38157
38184
  inputSchema: external_exports.object({
38158
38185
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38159
38186
  tab: external_exports.string().optional().describe("Limit results to a tab title or ID"),
@@ -38166,7 +38193,7 @@ function registerExtraDocsTools(server) {
38166
38193
  });
38167
38194
  server.registerTool("gog_docs_footer_create", {
38168
38195
  description: "Create a footer in a Google Doc and optionally populate its initial text. Returns the new footer segment ID.",
38169
- annotations: { destructiveHint: false },
38196
+ annotations: { destructiveHint: false, openWorldHint: true },
38170
38197
  inputSchema: external_exports.object({
38171
38198
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38172
38199
  text: external_exports.string().optional().describe("Initial footer text"),
@@ -38194,7 +38221,7 @@ function registerExtraDocsTools(server) {
38194
38221
  });
38195
38222
  server.registerTool("gog_docs_footer_delete", {
38196
38223
  description: "Delete a footer from a Google Doc by its segment ID (from gog_docs_footer_list).",
38197
- annotations: { destructiveHint: true },
38224
+ annotations: { destructiveHint: true, openWorldHint: true },
38198
38225
  inputSchema: external_exports.object({
38199
38226
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38200
38227
  footerId: external_exports.string().describe("Footer segment ID (from gog_docs_footer_list)"),
@@ -38209,7 +38236,7 @@ function registerExtraDocsTools(server) {
38209
38236
  });
38210
38237
  server.registerTool("gog_docs_replace_image", {
38211
38238
  description: "Replace an existing image in a Google Doc in place \u2014 keeping its position and bounds \u2014 with a new image from a local file or public HTTPS URL. Target the image by exact object ID (from gog_docs_images_list), by alt-text substring, or leave both off to replace the only image in the doc/tab.",
38212
- annotations: { destructiveHint: true },
38239
+ annotations: { destructiveHint: true, openWorldHint: true },
38213
38240
  inputSchema: external_exports.object({
38214
38241
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38215
38242
  file: external_exports.string().optional().describe("Local PNG, JPEG, or GIF image to upload and use (exactly one of file or url)"),
@@ -38236,7 +38263,7 @@ function registerExtraDocsTools(server) {
38236
38263
  });
38237
38264
  server.registerTool("gog_docs_table_row_pin_header", {
38238
38265
  description: "Pin (or unpin) leading rows of a native Google Docs table as repeating header rows. rows=N pins the first N rows; rows=0 unpins all header rows.",
38239
- annotations: { destructiveHint: true },
38266
+ annotations: { destructiveHint: true, openWorldHint: true },
38240
38267
  inputSchema: external_exports.object({
38241
38268
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38242
38269
  rows: external_exports.number().int().min(0).describe("Number of leading rows to pin as headers; 0 unpins all header rows"),
@@ -38252,7 +38279,7 @@ function registerExtraDocsTools(server) {
38252
38279
  });
38253
38280
  server.registerTool("gog_docs_table_row_style", {
38254
38281
  description: "Set native table row height and page-overflow behaviour. Target a 1-based row (negative counts from the end) or omit row to style every row in the table.",
38255
- annotations: { destructiveHint: true },
38282
+ annotations: { destructiveHint: true, openWorldHint: true },
38256
38283
  inputSchema: external_exports.object({
38257
38284
  docId: external_exports.string().describe("Doc ID (from the URL)"),
38258
38285
  row: external_exports.number().int().optional().describe("1-based row number; negative indexes count from the end; omit to style all rows"),