gogcli-mcp-docs 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.
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from '@modelcontextprotocol/server';
2
2
  import { z } from 'zod';
3
- import { accountParam, runOrDiagnose, paginationParams, pushPaginationFlags, payloadArg } from '../../../gogcli-mcp/src/lib.js';
3
+ import { accountParam, runOrDiagnose, paginationParams, pushPaginationFlags, payloadArg, pos, confinePath } from '../../../gogcli-mcp/src/lib.js';
4
4
  import type { GogArg } from '../../../gogcli-mcp/src/lib.js';
5
5
 
6
6
  export function registerExtraDocsTools(server: McpServer): void {
@@ -14,7 +14,7 @@ export function registerExtraDocsTools(server: McpServer): void {
14
14
  account: accountParam,
15
15
  }),
16
16
  }, async ({ docId, title, parent, account }) => {
17
- const args = ['docs', 'copy', docId, title];
17
+ const args: GogArg[] = ['docs', 'copy', pos(docId), pos(title)];
18
18
  if (parent) args.push(`--parent=${parent}`);
19
19
  return runOrDiagnose(args, { account });
20
20
  });
@@ -35,10 +35,10 @@ export function registerExtraDocsTools(server: McpServer): void {
35
35
  account: accountParam,
36
36
  }),
37
37
  }, async ({ docId, start, end, at, occurrence, matchCase, tabId, segment, batch, account }) => {
38
- const args = ['docs', 'delete'];
38
+ const args: GogArg[] = ['docs', 'delete'];
39
39
  if (start !== undefined) args.push(`--start=${start}`);
40
40
  if (end !== undefined) args.push(`--end=${end}`);
41
- args.push(docId);
41
+ args.push(pos(docId));
42
42
  if (at) args.push(`--at=${at}`);
43
43
  if (occurrence !== undefined) args.push(`--occurrence=${occurrence}`);
44
44
  if (matchCase) args.push('--match-case');
@@ -56,7 +56,7 @@ export function registerExtraDocsTools(server: McpServer): void {
56
56
  account: accountParam,
57
57
  }),
58
58
  }, async ({ docId, account }) => {
59
- return runOrDiagnose(['drive', 'delete', docId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
59
+ return runOrDiagnose(['drive', 'delete', pos(docId), '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
60
60
  });
61
61
 
62
62
  server.registerTool('gog_docs_edit', {
@@ -70,7 +70,7 @@ export function registerExtraDocsTools(server: McpServer): void {
70
70
  account: accountParam,
71
71
  }),
72
72
  }, async ({ docId, find, replace, matchCase, account }) => {
73
- const args = ['docs', 'edit', docId, find, replace];
73
+ const args: GogArg[] = ['docs', 'edit', pos(docId), pos(find), pos(replace)];
74
74
  if (matchCase) args.push('--match-case');
75
75
  return runOrDiagnose(args, { account });
76
76
  });
@@ -89,13 +89,13 @@ export function registerExtraDocsTools(server: McpServer): void {
89
89
  }),
90
90
  }, async ({ docId, format, tab, allTabs, maxBytes, chips, account }) => {
91
91
  if (format === 'json') {
92
- const args = ['docs', 'raw', docId, '--pretty'];
92
+ const args: GogArg[] = ['docs', 'raw', pos(docId), '--pretty'];
93
93
  if (tab) args.push(`--tab=${tab}`);
94
94
  if (allTabs) args.push('--all-tabs');
95
95
  // Verbatim by contract: see the `lossless` note on runOrDiagnose.
96
96
  return runOrDiagnose(args, { account, lossless: true });
97
97
  }
98
- const args = ['docs', 'cat', docId];
98
+ const args: GogArg[] = ['docs', 'cat', pos(docId)];
99
99
  if (tab) args.push(`--tab=${tab}`);
100
100
  if (allTabs) args.push('--all-tabs');
101
101
  if (maxBytes !== undefined) args.push(`--max-bytes=${maxBytes}`);
@@ -176,7 +176,7 @@ export function registerExtraDocsTools(server: McpServer): void {
176
176
  segment?: string;
177
177
  account?: string;
178
178
  };
179
- const argv = ['docs', 'format', a.docId];
179
+ const argv: GogArg[] = ['docs', 'format', pos(a.docId)];
180
180
  if (a.match) argv.push(`--match=${a.match}`);
181
181
  if (a.matchAll) argv.push('--match-all');
182
182
  if (a.matchCase) argv.push('--match-case');
@@ -226,14 +226,15 @@ export function registerExtraDocsTools(server: McpServer): void {
226
226
  account: accountParam,
227
227
  }),
228
228
  }, async ({ docId, tab, account }) => {
229
- const args = ['docs', 'suggestions', 'list', docId];
229
+ const args: GogArg[] = ['docs', 'suggestions', 'list', pos(docId)];
230
230
  if (tab) args.push(`--tab=${tab}`);
231
231
  return runOrDiagnose(args, { account });
232
232
  });
233
233
 
234
234
  server.registerTool('gog_docs_export', {
235
235
  description: 'Export a Google Doc as PDF, plain text, HTML, DOCX, or other format.',
236
- annotations: { readOnlyHint: true },
236
+ // Writes a file on the gog host and can overwrite one: not read-only (audit SEC-4).
237
+ annotations: { readOnlyHint: false, destructiveHint: true },
237
238
  inputSchema: z.object({
238
239
  docId: z.string().describe('Doc ID (from the URL)'),
239
240
  format: z.string().optional().describe('Export format: pdf, txt, html, docx, rtf, odt, epub (default: pdf)'),
@@ -242,7 +243,8 @@ export function registerExtraDocsTools(server: McpServer): void {
242
243
  account: accountParam,
243
244
  }),
244
245
  }, async ({ docId, format, out, overwrite, account }) => {
245
- const args = ['docs', 'export', docId];
246
+ if (out) confinePath(out, 'out');
247
+ const args: GogArg[] = ['docs', 'export', pos(docId)];
246
248
  if (format) args.push(`--format=${format}`);
247
249
  if (out) args.push(`--out=${out}`);
248
250
  if (overwrite) args.push('--overwrite');
@@ -266,8 +268,9 @@ export function registerExtraDocsTools(server: McpServer): void {
266
268
  account: accountParam,
267
269
  }),
268
270
  }, async ({ docId, content, index, file, at, occurrence, matchCase, tabId, segment, batch, account }) => {
269
- const args = ['docs', 'insert', docId];
270
- if (content) args.push(content);
271
+ if (file) confinePath(file, 'file');
272
+ const args: GogArg[] = ['docs', 'insert', pos(docId)];
273
+ if (content) args.push(pos(content));
271
274
  if (index !== undefined) args.push(`--index=${index}`);
272
275
  if (file) args.push(`--file=${file}`);
273
276
  if (at) args.push(`--at=${at}`);
@@ -291,7 +294,8 @@ export function registerExtraDocsTools(server: McpServer): void {
291
294
  account: accountParam,
292
295
  }),
293
296
  }, async ({ docId, text, file, markdown, tab, account }) => {
294
- const args = ['docs', 'write', docId, '--append'];
297
+ if (file) confinePath(file, 'file');
298
+ const args: GogArg[] = ['docs', 'write', pos(docId), '--append'];
295
299
  if (text) args.push(`--text=${text}`);
296
300
  if (file) args.push(`--file=${file}`);
297
301
  if (markdown) args.push('--markdown');
@@ -307,7 +311,7 @@ export function registerExtraDocsTools(server: McpServer): void {
307
311
  account: accountParam,
308
312
  }),
309
313
  }, async ({ docId, account }) => {
310
- return runOrDiagnose(['docs', 'list-tabs', docId], { account });
314
+ return runOrDiagnose(['docs', 'list-tabs', pos(docId)], { account });
311
315
  });
312
316
 
313
317
  server.registerTool('gog_docs_sed', {
@@ -322,8 +326,9 @@ export function registerExtraDocsTools(server: McpServer): void {
322
326
  account: accountParam,
323
327
  }),
324
328
  }, async ({ docId, expression, expressions, file, tab, account }) => {
325
- const args = ['docs', 'sed', docId];
326
- if (expression) args.push(expression);
329
+ if (file) confinePath(file, 'file');
330
+ const args: GogArg[] = ['docs', 'sed', pos(docId)];
331
+ if (expression) args.push(pos(expression));
327
332
  if (expressions) {
328
333
  for (const expr of expressions) {
329
334
  args.push(`--expressions=${expr}`);
@@ -354,7 +359,8 @@ export function registerExtraDocsTools(server: McpServer): void {
354
359
  account: accountParam,
355
360
  }),
356
361
  }, async ({ docId, text, file, index, replaceRange, markdown, at, occurrence, matchCase, tabId, segment, pageless, batch, account }) => {
357
- const args = ['docs', 'update', docId];
362
+ if (file) confinePath(file, 'file');
363
+ const args: GogArg[] = ['docs', 'update', pos(docId)];
358
364
  if (text) args.push(`--text=${text}`);
359
365
  if (file) args.push(`--file=${file}`);
360
366
  if (index !== undefined) args.push(`--index=${index}`);
@@ -390,7 +396,7 @@ export function registerExtraDocsTools(server: McpServer): void {
390
396
  account: accountParam,
391
397
  }),
392
398
  }, async ({ docId, includeResolved, since, locate, tab, max, page, all, account }) => {
393
- const args = ['docs', 'comments', 'list', docId];
399
+ const args: GogArg[] = ['docs', 'comments', 'list', pos(docId)];
394
400
  if (includeResolved) args.push('--include-resolved');
395
401
  if (since) args.push(`--since=${since}`);
396
402
  if (locate) args.push('--locate');
@@ -408,7 +414,7 @@ export function registerExtraDocsTools(server: McpServer): void {
408
414
  account: accountParam,
409
415
  }),
410
416
  }, async ({ docId, commentId, account }) => {
411
- return runOrDiagnose(['docs', 'comments', 'get', docId, commentId], { account });
417
+ return runOrDiagnose(['docs', 'comments', 'get', pos(docId), pos(commentId)], { account });
412
418
  });
413
419
 
414
420
  server.registerTool('gog_docs_comments_add', {
@@ -422,7 +428,7 @@ export function registerExtraDocsTools(server: McpServer): void {
422
428
  account: accountParam,
423
429
  }),
424
430
  }, async ({ docId, content, quoted, account }) => {
425
- const args = ['docs', 'comments', 'add', docId, content];
431
+ const args: GogArg[] = ['docs', 'comments', 'add', pos(docId), pos(content)];
426
432
  if (quoted) args.push(`--quoted=${quoted}`);
427
433
  return runOrDiagnose(args, { account });
428
434
  });
@@ -437,7 +443,7 @@ export function registerExtraDocsTools(server: McpServer): void {
437
443
  account: accountParam,
438
444
  }),
439
445
  }, async ({ docId, commentId, content, account }) => {
440
- return runOrDiagnose(['docs', 'comments', 'reply', docId, commentId, content], { account });
446
+ return runOrDiagnose(['docs', 'comments', 'reply', pos(docId), pos(commentId), pos(content)], { account });
441
447
  });
442
448
 
443
449
  server.registerTool('gog_docs_comments_resolve', {
@@ -450,7 +456,7 @@ export function registerExtraDocsTools(server: McpServer): void {
450
456
  account: accountParam,
451
457
  }),
452
458
  }, async ({ docId, commentId, message, account }) => {
453
- const args = ['docs', 'comments', 'resolve', docId, commentId];
459
+ const args: GogArg[] = ['docs', 'comments', 'resolve', pos(docId), pos(commentId)];
454
460
  if (message) args.push(`--message=${message}`);
455
461
  return runOrDiagnose(args, { account });
456
462
  });
@@ -465,7 +471,7 @@ export function registerExtraDocsTools(server: McpServer): void {
465
471
  }),
466
472
  }, async ({ docId, commentId, account }) => {
467
473
  // --force: gog refuses this delete under the runner's --no-input without it.
468
- return runOrDiagnose(['docs', 'comments', 'delete', docId, commentId, '--force'], { account });
474
+ return runOrDiagnose(['docs', 'comments', 'delete', pos(docId), pos(commentId), '--force'], { account });
469
475
  });
470
476
 
471
477
  server.registerTool('gog_docs_comments_reopen', {
@@ -477,7 +483,7 @@ export function registerExtraDocsTools(server: McpServer): void {
477
483
  account: accountParam,
478
484
  }),
479
485
  }, async ({ docId, commentId, account }) => {
480
- return runOrDiagnose(['docs', 'comments', 'reopen', docId, commentId], { account });
486
+ return runOrDiagnose(['docs', 'comments', 'reopen', pos(docId), pos(commentId)], { account });
481
487
  });
482
488
 
483
489
  server.registerTool('gog_docs_comments_locate', {
@@ -492,7 +498,7 @@ export function registerExtraDocsTools(server: McpServer): void {
492
498
  account: accountParam,
493
499
  }),
494
500
  }, async ({ docId, commentId, matchCase, normalizeWhitespace, tab, account }) => {
495
- const args = ['docs', 'comments', 'locate', docId, commentId];
501
+ const args: GogArg[] = ['docs', 'comments', 'locate', pos(docId), pos(commentId)];
496
502
  if (matchCase) args.push('--match-case');
497
503
  if (normalizeWhitespace) args.push('--normalize-whitespace');
498
504
  if (tab) args.push(`--tab=${tab}`);
@@ -515,7 +521,7 @@ export function registerExtraDocsTools(server: McpServer): void {
515
521
  account: accountParam,
516
522
  }),
517
523
  }, async ({ docId, text, occurrence, matchCase, normalizeWhitespace, all, failEmpty, tab, segment, account }) => {
518
- const args = ['docs', 'find-range', docId, text];
524
+ const args: GogArg[] = ['docs', 'find-range', pos(docId), pos(text)];
519
525
  if (occurrence !== undefined) args.push(`--occurrence=${occurrence}`);
520
526
  if (matchCase) args.push('--match-case');
521
527
  if (normalizeWhitespace) args.push('--normalize-whitespace');
@@ -538,7 +544,7 @@ export function registerExtraDocsTools(server: McpServer): void {
538
544
  account: accountParam,
539
545
  }),
540
546
  }, async ({ docId, name, account }) => {
541
- const args = ['batch', 'begin', `--doc=${docId}`];
547
+ const args: GogArg[] = ['batch', 'begin', `--doc=${docId}`];
542
548
  if (name) args.push(`--name=${name}`);
543
549
  return runOrDiagnose(args, { account });
544
550
  });
@@ -553,7 +559,7 @@ export function registerExtraDocsTools(server: McpServer): void {
553
559
  account: accountParam,
554
560
  }),
555
561
  }, async ({ batchId, autoSplit, continueOnError, account }) => {
556
- const args = ['batch', 'end', batchId];
562
+ const args: GogArg[] = ['batch', 'end', pos(batchId)];
557
563
  if (autoSplit) args.push('--auto-split');
558
564
  if (continueOnError) args.push('--continue-on-error');
559
565
  return runOrDiagnose(args, { account });
@@ -567,7 +573,7 @@ export function registerExtraDocsTools(server: McpServer): void {
567
573
  account: accountParam,
568
574
  }),
569
575
  }, async ({ batchId, account }) => {
570
- return runOrDiagnose(['batch', 'abort', batchId], { account });
576
+ return runOrDiagnose(['batch', 'abort', pos(batchId)], { account });
571
577
  });
572
578
 
573
579
  server.registerTool('gog_batch_list', {
@@ -588,7 +594,7 @@ export function registerExtraDocsTools(server: McpServer): void {
588
594
  account: accountParam,
589
595
  }),
590
596
  }, async ({ batchId, account }) => {
591
- return runOrDiagnose(['batch', 'show', batchId], { account });
597
+ return runOrDiagnose(['batch', 'show', pos(batchId)], { account });
592
598
  });
593
599
 
594
600
  server.registerTool('gog_batch_prune', {
@@ -599,7 +605,7 @@ export function registerExtraDocsTools(server: McpServer): void {
599
605
  account: accountParam,
600
606
  }),
601
607
  }, async ({ olderThan, account }) => {
602
- const args = ['batch', 'prune'];
608
+ const args: GogArg[] = ['batch', 'prune'];
603
609
  if (olderThan) args.push(`--older-than=${olderThan}`);
604
610
  return runOrDiagnose(args, { account });
605
611
  });
@@ -618,7 +624,7 @@ export function registerExtraDocsTools(server: McpServer): void {
618
624
  account: accountParam,
619
625
  }),
620
626
  }, async ({ docId, col, width, evenlyDistributed, tableIndex, tab, batch, account }) => {
621
- const args = ['docs', 'table-column-width', docId];
627
+ const args: GogArg[] = ['docs', 'table-column-width', pos(docId)];
622
628
  if (col !== undefined) args.push(`--col=${col}`);
623
629
  if (width !== undefined) args.push(`--width=${width}`);
624
630
  if (evenlyDistributed) args.push('--evenly-distributed');
@@ -644,7 +650,7 @@ export function registerExtraDocsTools(server: McpServer): void {
644
650
  account: accountParam,
645
651
  }),
646
652
  }, async ({ docId, table, at, valuesJson, tab, account }) => {
647
- const args = ['docs', 'table-row', 'insert', docId];
653
+ const args: GogArg[] = ['docs', 'table-row', 'insert', pos(docId)];
648
654
  if (table) args.push(`--table=${table}`);
649
655
  if (at) args.push(`--at=${at}`);
650
656
  if (valuesJson) args.push(`--values-json=${valuesJson}`);
@@ -663,7 +669,7 @@ export function registerExtraDocsTools(server: McpServer): void {
663
669
  account: accountParam,
664
670
  }),
665
671
  }, async ({ docId, row, table, tab, account }) => {
666
- const args = ['docs', 'table-row', 'delete', docId, `--row=${row}`];
672
+ const args: GogArg[] = ['docs', 'table-row', 'delete', pos(docId), `--row=${row}`];
667
673
  if (table) args.push(`--table=${table}`);
668
674
  if (tab) args.push(`--tab=${tab}`);
669
675
  return runOrDiagnose(args, { account });
@@ -680,7 +686,7 @@ export function registerExtraDocsTools(server: McpServer): void {
680
686
  account: accountParam,
681
687
  }),
682
688
  }, async ({ docId, table, at, tab, account }) => {
683
- const args = ['docs', 'table-column', 'insert', docId];
689
+ const args: GogArg[] = ['docs', 'table-column', 'insert', pos(docId)];
684
690
  if (at) args.push(`--at=${at}`);
685
691
  if (table) args.push(`--table=${table}`);
686
692
  if (tab) args.push(`--tab=${tab}`);
@@ -698,7 +704,7 @@ export function registerExtraDocsTools(server: McpServer): void {
698
704
  account: accountParam,
699
705
  }),
700
706
  }, async ({ docId, col, table, tab, account }) => {
701
- const args = ['docs', 'table-column', 'delete', docId, `--col=${col}`];
707
+ const args: GogArg[] = ['docs', 'table-column', 'delete', pos(docId), `--col=${col}`];
702
708
  if (table) args.push(`--table=${table}`);
703
709
  if (tab) args.push(`--tab=${tab}`);
704
710
  return runOrDiagnose(args, { account });
@@ -715,7 +721,7 @@ export function registerExtraDocsTools(server: McpServer): void {
715
721
  account: accountParam,
716
722
  }),
717
723
  }, async ({ docId, range, table, tab, account }) => {
718
- const args = ['docs', 'table-merge', docId, `--range=${range}`];
724
+ const args: GogArg[] = ['docs', 'table-merge', pos(docId), `--range=${range}`];
719
725
  if (table) args.push(`--table=${table}`);
720
726
  if (tab) args.push(`--tab=${tab}`);
721
727
  return runOrDiagnose(args, { account });
@@ -732,7 +738,7 @@ export function registerExtraDocsTools(server: McpServer): void {
732
738
  account: accountParam,
733
739
  }),
734
740
  }, async ({ docId, cell, table, tab, account }) => {
735
- const args = ['docs', 'table-unmerge', docId, `--cell=${cell}`];
741
+ const args: GogArg[] = ['docs', 'table-unmerge', pos(docId), `--cell=${cell}`];
736
742
  if (table) args.push(`--table=${table}`);
737
743
  if (tab) args.push(`--tab=${tab}`);
738
744
  return runOrDiagnose(args, { account });
@@ -753,7 +759,7 @@ export function registerExtraDocsTools(server: McpServer): void {
753
759
  account: accountParam,
754
760
  }),
755
761
  }, async ({ docId, name, at, occurrence, matchCase, start, end, tab, account }) => {
756
- const args = ['docs', 'named-range', 'create', docId, `--name=${name}`];
762
+ const args: GogArg[] = ['docs', 'named-range', 'create', pos(docId), `--name=${name}`];
757
763
  if (at) args.push(`--at=${at}`);
758
764
  if (occurrence !== undefined) args.push(`--occurrence=${occurrence}`);
759
765
  if (matchCase) args.push('--match-case');
@@ -773,7 +779,7 @@ export function registerExtraDocsTools(server: McpServer): void {
773
779
  account: accountParam,
774
780
  }),
775
781
  }, async ({ docId, name, tab, account }) => {
776
- const args = ['docs', 'named-range', 'list', docId];
782
+ const args: GogArg[] = ['docs', 'named-range', 'list', pos(docId)];
777
783
  if (name) args.push(`--name=${name}`);
778
784
  if (tab) args.push(`--tab=${tab}`);
779
785
  return runOrDiagnose(args, { account });
@@ -789,7 +795,7 @@ export function registerExtraDocsTools(server: McpServer): void {
789
795
  account: accountParam,
790
796
  }),
791
797
  }, async ({ docId, nameOrId, tab, account }) => {
792
- const args = ['docs', 'named-range', 'delete', docId, nameOrId];
798
+ const args: GogArg[] = ['docs', 'named-range', 'delete', pos(docId), pos(nameOrId)];
793
799
  if (tab) args.push(`--tab=${tab}`);
794
800
  return runOrDiagnose(args, { account });
795
801
  });
@@ -806,7 +812,8 @@ export function registerExtraDocsTools(server: McpServer): void {
806
812
  account: accountParam,
807
813
  }),
808
814
  }, async ({ docId, nameOrId, text, file, tab, account }) => {
809
- const args = ['docs', 'named-range', 'replace', docId, nameOrId];
815
+ if (file) confinePath(file, 'file');
816
+ const args: GogArg[] = ['docs', 'named-range', 'replace', pos(docId), pos(nameOrId)];
810
817
  if (text !== undefined) args.push(`--text=${text}`);
811
818
  if (file) args.push(`--file=${file}`);
812
819
  if (tab) args.push(`--tab=${tab}`);
@@ -822,7 +829,7 @@ export function registerExtraDocsTools(server: McpServer): void {
822
829
  account: accountParam,
823
830
  }),
824
831
  }, async ({ docId, tab, account }) => {
825
- const args = ['docs', 'tables', 'list', docId];
832
+ const args: GogArg[] = ['docs', 'tables', 'list', pos(docId)];
826
833
  if (tab) args.push(`--tab=${tab}`);
827
834
  return runOrDiagnose(args, { account });
828
835
  });
@@ -836,7 +843,7 @@ export function registerExtraDocsTools(server: McpServer): void {
836
843
  account: accountParam,
837
844
  }),
838
845
  }, async ({ docId, tab, account }) => {
839
- const args = ['docs', 'images', 'list', docId];
846
+ const args: GogArg[] = ['docs', 'images', 'list', pos(docId)];
840
847
  if (tab) args.push(`--tab=${tab}`);
841
848
  return runOrDiagnose(args, { account });
842
849
  });
@@ -851,7 +858,7 @@ export function registerExtraDocsTools(server: McpServer): void {
851
858
  account: accountParam,
852
859
  }),
853
860
  }, async ({ docId, level, tab, account }) => {
854
- const args = ['docs', 'headings', 'list', docId];
861
+ const args: GogArg[] = ['docs', 'headings', 'list', pos(docId)];
855
862
  if (level !== undefined) args.push(`--level=${level}`);
856
863
  if (tab) args.push(`--tab=${tab}`);
857
864
  return runOrDiagnose(args, { account });
@@ -867,7 +874,7 @@ export function registerExtraDocsTools(server: McpServer): void {
867
874
  account: accountParam,
868
875
  }),
869
876
  }, async ({ docId, style, tab, account }) => {
870
- const args = ['docs', 'paragraphs', 'list', docId];
877
+ const args: GogArg[] = ['docs', 'paragraphs', 'list', pos(docId)];
871
878
  if (style) args.push(`--style=${style}`);
872
879
  if (tab) args.push(`--tab=${tab}`);
873
880
  return runOrDiagnose(args, { account });
@@ -888,7 +895,7 @@ export function registerExtraDocsTools(server: McpServer): void {
888
895
  account: accountParam,
889
896
  }),
890
897
  }, async ({ docId, index, atEnd, at, occurrence, matchCase, tab, batch, account }) => {
891
- const args = ['docs', 'insert-page-break', docId];
898
+ const args: GogArg[] = ['docs', 'insert-page-break', pos(docId)];
892
899
  if (index !== undefined) args.push(`--index=${index}`);
893
900
  if (atEnd) args.push('--at-end');
894
901
  if (at) args.push(`--at=${at}`);
@@ -915,7 +922,7 @@ export function registerExtraDocsTools(server: McpServer): void {
915
922
  account: accountParam,
916
923
  }),
917
924
  }, async ({ docId, layout, pageSize, pageWidth, pageHeight, marginTop, marginBottom, marginLeft, marginRight, account }) => {
918
- const args = ['docs', 'page-layout', docId];
925
+ const args: GogArg[] = ['docs', 'page-layout', pos(docId)];
919
926
  if (layout) args.push(`--layout=${layout}`);
920
927
  if (pageSize) args.push(`--page-size=${pageSize}`);
921
928
  if (pageWidth) args.push(`--page-width=${pageWidth}`);
@@ -941,7 +948,7 @@ export function registerExtraDocsTools(server: McpServer): void {
941
948
  account: accountParam,
942
949
  }),
943
950
  }, async ({ docId, rows, cols, index, atEnd, valuesJson, tab, account }) => {
944
- const args = ['docs', 'insert-table', docId, `--rows=${rows}`, `--cols=${cols}`];
951
+ const args: GogArg[] = ['docs', 'insert-table', pos(docId), `--rows=${rows}`, `--cols=${cols}`];
945
952
  if (index !== undefined) args.push(`--index=${index}`);
946
953
  if (atEnd) args.push('--at-end');
947
954
  if (valuesJson !== undefined) args.push(`--values-json=${valuesJson}`);
@@ -965,6 +972,7 @@ export function registerExtraDocsTools(server: McpServer): void {
965
972
  account: accountParam,
966
973
  }),
967
974
  }, async ({ docId, row, col, content, contentFile, append, format, tableIndex, tab, account }) => {
975
+ if (contentFile) confinePath(contentFile, 'contentFile');
968
976
  // gog HARD-ERRORS on both forms ("cannot use both --content and
969
977
  // --content-file"), so reject here with a clearer message before gog runs.
970
978
  // (The slides commands are the opposite: they accept both and the file
@@ -975,7 +983,7 @@ export function registerExtraDocsTools(server: McpServer): void {
975
983
  '("cannot use both --content and --content-file"). Drop one of them.',
976
984
  );
977
985
  }
978
- const args: GogArg[] = ['docs', 'cell-update', docId, `--row=${row}`, `--col=${col}`];
986
+ const args: GogArg[] = ['docs', 'cell-update', pos(docId), `--row=${row}`, `--col=${col}`];
979
987
  // `content !== undefined` (not truthiness) is deliberate: an empty string is
980
988
  // a meaningful value that clears the cell, so it must reach gog as
981
989
  // `--content=`. contentFile stays on truthiness — an empty path is nothing.
@@ -1019,7 +1027,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1019
1027
  account: accountParam,
1020
1028
  }),
1021
1029
  }, async ({ docId, row, col, rowSpan, colSpan, backgroundColor, textColor, bold, italic, underline, borderAll, borderTop, borderBottom, borderLeft, borderRight, paddingAll, paddingTop, paddingBottom, paddingLeft, paddingRight, contentAlign, tableIndex, tab, batch, account }) => {
1022
- const args = ['docs', 'cell-style', docId, `--row=${row}`, `--col=${col}`];
1030
+ const args: GogArg[] = ['docs', 'cell-style', pos(docId), `--row=${row}`, `--col=${col}`];
1023
1031
  if (rowSpan !== undefined) args.push(`--row-span=${rowSpan}`);
1024
1032
  if (colSpan !== undefined) args.push(`--col-span=${colSpan}`);
1025
1033
  if (backgroundColor) args.push(`--background-color=${backgroundColor}`);
@@ -1063,7 +1071,8 @@ export function registerExtraDocsTools(server: McpServer): void {
1063
1071
  account: accountParam,
1064
1072
  }),
1065
1073
  }, async ({ docId, file, url, at, before, after, width, height, name, parent, onRestricted, tab, account }) => {
1066
- const args = ['docs', 'insert-image', docId];
1074
+ if (file) confinePath(file, 'file');
1075
+ const args: GogArg[] = ['docs', 'insert-image', pos(docId)];
1067
1076
  if (file) args.push(`--file=${file}`);
1068
1077
  if (url) args.push(`--url=${url}`);
1069
1078
  if (at) args.push(`--at=${at}`);
@@ -1095,7 +1104,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1095
1104
  account: accountParam,
1096
1105
  }),
1097
1106
  }, async ({ docId, email, index, atEnd, at, occurrence, matchCase, tab, batch, account }) => {
1098
- const args = ['docs', 'insert-person', docId, `--email=${email}`];
1107
+ const args: GogArg[] = ['docs', 'insert-person', pos(docId), `--email=${email}`];
1099
1108
  if (index !== undefined) args.push(`--index=${index}`);
1100
1109
  if (atEnd) args.push('--at-end');
1101
1110
  if (at) args.push(`--at=${at}`);
@@ -1120,7 +1129,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1120
1129
  account: accountParam,
1121
1130
  }),
1122
1131
  }, async ({ docId, date, format, index, atEnd, tab, batch, account }) => {
1123
- const args = ['docs', 'insert-date-chip', docId];
1132
+ const args: GogArg[] = ['docs', 'insert-date-chip', pos(docId)];
1124
1133
  if (date) args.push(`--date=${date}`);
1125
1134
  if (format) args.push(`--format=${format}`);
1126
1135
  if (index !== undefined) args.push(`--index=${index}`);
@@ -1142,7 +1151,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1142
1151
  account: accountParam,
1143
1152
  }),
1144
1153
  }, async ({ docId, title, index, parentTab, iconEmoji, account }) => {
1145
- const args = ['docs', 'add-tab', docId];
1154
+ const args: GogArg[] = ['docs', 'add-tab', pos(docId)];
1146
1155
  if (title) args.push(`--title=${title}`);
1147
1156
  if (index !== undefined) args.push(`--index=${index}`);
1148
1157
  if (parentTab) args.push(`--parent-tab=${parentTab}`);
@@ -1160,7 +1169,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1160
1169
  account: accountParam,
1161
1170
  }),
1162
1171
  }, async ({ docId, tab, title, account }) => {
1163
- const args = ['docs', 'rename-tab', docId, `--tab=${tab}`, `--title=${title}`];
1172
+ const args: GogArg[] = ['docs', 'rename-tab', pos(docId), `--tab=${tab}`, `--title=${title}`];
1164
1173
  return runOrDiagnose(args, { account });
1165
1174
  });
1166
1175
 
@@ -1173,7 +1182,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1173
1182
  account: accountParam,
1174
1183
  }),
1175
1184
  }, async ({ docId, tab, account }) => {
1176
- const args = ['docs', 'delete-tab', docId, `--tab=${tab}`, '--force']; // gog gates this op; without --force the runner's --no-input makes it refuse
1185
+ const args: GogArg[] = ['docs', 'delete-tab', pos(docId), `--tab=${tab}`, '--force']; // gog gates this op; without --force the runner's --no-input makes it refuse
1177
1186
  return runOrDiagnose(args, { account });
1178
1187
  });
1179
1188
 
@@ -1185,7 +1194,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1185
1194
  account: accountParam,
1186
1195
  }),
1187
1196
  }, async ({ docId, account }) => {
1188
- return runOrDiagnose(['docs', 'clear', docId], { account });
1197
+ return runOrDiagnose(['docs', 'clear', pos(docId)], { account });
1189
1198
  });
1190
1199
 
1191
1200
  // --- gog 0.30 structural authoring: footnotes, section breaks, rules, columns ---
@@ -1206,7 +1215,8 @@ export function registerExtraDocsTools(server: McpServer): void {
1206
1215
  account: accountParam,
1207
1216
  }),
1208
1217
  }, async ({ docId, text, file, index, atEnd, at, occurrence, matchCase, tab, account }) => {
1209
- const args = ['docs', 'insert-footnote', docId];
1218
+ if (file) confinePath(file, 'file');
1219
+ const args: GogArg[] = ['docs', 'insert-footnote', pos(docId)];
1210
1220
  if (text !== undefined) args.push(`--text=${text}`);
1211
1221
  if (file) args.push(`--file=${file}`);
1212
1222
  if (index !== undefined) args.push(`--index=${index}`);
@@ -1234,7 +1244,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1234
1244
  account: accountParam,
1235
1245
  }),
1236
1246
  }, async ({ docId, type, index, atEnd, at, occurrence, matchCase, tab, batch, account }) => {
1237
- const args = ['docs', 'insert-section-break', docId];
1247
+ const args: GogArg[] = ['docs', 'insert-section-break', pos(docId)];
1238
1248
  if (type) args.push(`--type=${type}`);
1239
1249
  if (index !== undefined) args.push(`--index=${index}`);
1240
1250
  if (atEnd) args.push('--at-end');
@@ -1261,7 +1271,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1261
1271
  account: accountParam,
1262
1272
  }),
1263
1273
  }, async ({ docId, index, atEnd, at, occurrence, matchCase, tab, batch, account }) => {
1264
- const args = ['docs', 'insert-horizontal-rule', docId];
1274
+ const args: GogArg[] = ['docs', 'insert-horizontal-rule', pos(docId)];
1265
1275
  if (index !== undefined) args.push(`--index=${index}`);
1266
1276
  if (atEnd) args.push('--at-end');
1267
1277
  if (at) args.push(`--at=${at}`);
@@ -1289,7 +1299,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1289
1299
  account: accountParam,
1290
1300
  }),
1291
1301
  }, async ({ docId, count, separator, index, atEnd, at, occurrence, matchCase, tab, batch, account }) => {
1292
- const args = ['docs', 'section-columns', docId, `--count=${count}`];
1302
+ const args: GogArg[] = ['docs', 'section-columns', pos(docId), `--count=${count}`];
1293
1303
  if (separator) args.push(`--separator=${separator}`);
1294
1304
  if (index !== undefined) args.push(`--index=${index}`);
1295
1305
  if (atEnd) args.push('--at-end');
@@ -1313,7 +1323,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1313
1323
  account: accountParam,
1314
1324
  }),
1315
1325
  }, async ({ docId, tab, account }) => {
1316
- const args = ['docs', 'header', 'list', docId];
1326
+ const args: GogArg[] = ['docs', 'header', 'list', pos(docId)];
1317
1327
  if (tab) args.push(`--tab=${tab}`);
1318
1328
  return runOrDiagnose(args, { account });
1319
1329
  });
@@ -1334,7 +1344,8 @@ export function registerExtraDocsTools(server: McpServer): void {
1334
1344
  account: accountParam,
1335
1345
  }),
1336
1346
  }, async ({ docId, text, file, index, atEnd, at, occurrence, matchCase, tab, account }) => {
1337
- const args = ['docs', 'header', 'create', docId];
1347
+ if (file) confinePath(file, 'file');
1348
+ const args: GogArg[] = ['docs', 'header', 'create', pos(docId)];
1338
1349
  if (text !== undefined) args.push(`--text=${text}`);
1339
1350
  if (file) args.push(`--file=${file}`);
1340
1351
  if (index !== undefined) args.push(`--index=${index}`);
@@ -1356,7 +1367,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1356
1367
  account: accountParam,
1357
1368
  }),
1358
1369
  }, async ({ docId, headerId, tab, account }) => {
1359
- const args = ['docs', 'header', 'delete', docId, headerId];
1370
+ const args: GogArg[] = ['docs', 'header', 'delete', pos(docId), pos(headerId)];
1360
1371
  if (tab) args.push(`--tab=${tab}`);
1361
1372
  args.push('--force'); // gog refuses this delete under the runner's --no-input without it
1362
1373
  return runOrDiagnose(args, { account });
@@ -1371,7 +1382,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1371
1382
  account: accountParam,
1372
1383
  }),
1373
1384
  }, async ({ docId, tab, account }) => {
1374
- const args = ['docs', 'footer', 'list', docId];
1385
+ const args: GogArg[] = ['docs', 'footer', 'list', pos(docId)];
1375
1386
  if (tab) args.push(`--tab=${tab}`);
1376
1387
  return runOrDiagnose(args, { account });
1377
1388
  });
@@ -1392,7 +1403,8 @@ export function registerExtraDocsTools(server: McpServer): void {
1392
1403
  account: accountParam,
1393
1404
  }),
1394
1405
  }, async ({ docId, text, file, index, atEnd, at, occurrence, matchCase, tab, account }) => {
1395
- const args = ['docs', 'footer', 'create', docId];
1406
+ if (file) confinePath(file, 'file');
1407
+ const args: GogArg[] = ['docs', 'footer', 'create', pos(docId)];
1396
1408
  if (text !== undefined) args.push(`--text=${text}`);
1397
1409
  if (file) args.push(`--file=${file}`);
1398
1410
  if (index !== undefined) args.push(`--index=${index}`);
@@ -1414,7 +1426,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1414
1426
  account: accountParam,
1415
1427
  }),
1416
1428
  }, async ({ docId, footerId, tab, account }) => {
1417
- const args = ['docs', 'footer', 'delete', docId, footerId];
1429
+ const args: GogArg[] = ['docs', 'footer', 'delete', pos(docId), pos(footerId)];
1418
1430
  if (tab) args.push(`--tab=${tab}`);
1419
1431
  args.push('--force'); // gog refuses this delete under the runner's --no-input without it
1420
1432
  return runOrDiagnose(args, { account });
@@ -1437,7 +1449,8 @@ export function registerExtraDocsTools(server: McpServer): void {
1437
1449
  account: accountParam,
1438
1450
  }),
1439
1451
  }, async ({ docId, file, url, objectId, matchAlt, name, parent, tab, account }) => {
1440
- const args = ['docs', 'replace-image', docId];
1452
+ if (file) confinePath(file, 'file');
1453
+ const args: GogArg[] = ['docs', 'replace-image', pos(docId)];
1441
1454
  if (file) args.push(`--file=${file}`);
1442
1455
  if (url) args.push(`--url=${url}`);
1443
1456
  if (objectId) args.push(`--object-id=${objectId}`);
@@ -1460,7 +1473,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1460
1473
  account: accountParam,
1461
1474
  }),
1462
1475
  }, async ({ docId, rows, table, tab, account }) => {
1463
- const args = ['docs', 'table-row', 'pin-header', docId, `--rows=${rows}`];
1476
+ const args: GogArg[] = ['docs', 'table-row', 'pin-header', pos(docId), `--rows=${rows}`];
1464
1477
  if (table) args.push(`--table=${table}`);
1465
1478
  if (tab) args.push(`--tab=${tab}`);
1466
1479
  return runOrDiagnose(args, { account });
@@ -1479,7 +1492,7 @@ export function registerExtraDocsTools(server: McpServer): void {
1479
1492
  account: accountParam,
1480
1493
  }),
1481
1494
  }, async ({ docId, row, minHeight, preventOverflow, table, tab, account }) => {
1482
- const args = ['docs', 'table-row', 'style', docId];
1495
+ const args: GogArg[] = ['docs', 'table-row', 'style', pos(docId)];
1483
1496
  if (row !== undefined) args.push(`--row=${row}`);
1484
1497
  if (minHeight) args.push(`--min-height=${minHeight}`);
1485
1498
  if (preventOverflow !== undefined) args.push(preventOverflow ? '--prevent-overflow' : '--no-prevent-overflow');