gogcli-mcp-sheets 4.2.4 → 4.3.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.
@@ -2,7 +2,8 @@ import { McpServer } from '@modelcontextprotocol/server';
2
2
  import type { CallToolResult } from '@modelcontextprotocol/server';
3
3
  import { z } from 'zod';
4
4
  import { rawTextResult } from '@chrischall/mcp-utils';
5
- import { accountParam, runOrDiagnose, run, diagnose, errorText, payloadArg } from '../../../gogcli-mcp/src/lib.js';
5
+ import { accountParam, runOrDiagnose, run, diagnose, errorText, payloadArg, pos, confinePath, confineAtFile } from '../../../gogcli-mcp/src/lib.js';
6
+ import type { GogArg } from '../../../gogcli-mcp/src/lib.js';
6
7
 
7
8
  // Pull the text out of a single-text-block tool result; undefined for any
8
9
  // other shape (error results are still text blocks, so they parse below).
@@ -44,7 +45,7 @@ async function checkDateFormatTarget(
44
45
  account: string | undefined,
45
46
  ): Promise<string | null> {
46
47
  const peek = await runOrDiagnose(
47
- ['sheets', 'get', spreadsheetId, range, '--render=UNFORMATTED_VALUE'],
48
+ ['sheets', 'get', pos(spreadsheetId), pos(range), '--render=UNFORMATTED_VALUE'],
48
49
  { account },
49
50
  );
50
51
  let parsed: { values?: unknown[][] };
@@ -88,7 +89,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
88
89
  }, async ({ spreadsheetId, account }) => {
89
90
  // jq projection keeps the response compact: sheetId, title, index, gridProperties only.
90
91
  return runOrDiagnose(
91
- ['sheets', 'metadata', spreadsheetId, '--select=sheets.properties.sheetId,sheets.properties.title,sheets.properties.index,sheets.properties.gridProperties'],
92
+ ['sheets', 'metadata', pos(spreadsheetId), '--select=sheets.properties.sheetId,sheets.properties.title,sheets.properties.index,sheets.properties.gridProperties'],
92
93
  { account },
93
94
  );
94
95
  });
@@ -102,7 +103,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
102
103
  account: accountParam,
103
104
  }),
104
105
  }, async ({ spreadsheetId, tabName, account }) => {
105
- return runOrDiagnose(['sheets', 'add-tab', spreadsheetId, tabName], { account });
106
+ return runOrDiagnose(['sheets', 'add-tab', pos(spreadsheetId), pos(tabName)], { account });
106
107
  });
107
108
 
108
109
  server.registerTool('gog_sheets_delete_tab', {
@@ -114,7 +115,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
114
115
  account: accountParam,
115
116
  }),
116
117
  }, async ({ spreadsheetId, tabName, account }) => {
117
- return runOrDiagnose(['sheets', 'delete-tab', spreadsheetId, tabName, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
118
+ return runOrDiagnose(['sheets', 'delete-tab', pos(spreadsheetId), pos(tabName), '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
118
119
  });
119
120
 
120
121
  server.registerTool('gog_sheets_rename_tab', {
@@ -127,7 +128,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
127
128
  account: accountParam,
128
129
  }),
129
130
  }, async ({ spreadsheetId, oldName, newName, account }) => {
130
- return runOrDiagnose(['sheets', 'rename-tab', spreadsheetId, oldName, newName], { account });
131
+ return runOrDiagnose(['sheets', 'rename-tab', pos(spreadsheetId), pos(oldName), pos(newName)], { account });
131
132
  });
132
133
 
133
134
  server.registerTool('gog_sheets_copy', {
@@ -140,14 +141,15 @@ export function registerExtraSheetsTools(server: McpServer): void {
140
141
  account: accountParam,
141
142
  }),
142
143
  }, async ({ spreadsheetId, title, parent, account }) => {
143
- const args = ['sheets', 'copy', spreadsheetId, title];
144
+ const args: GogArg[] = ['sheets', 'copy', pos(spreadsheetId), pos(title)];
144
145
  if (parent) args.push(`--parent=${parent}`);
145
146
  return runOrDiagnose(args, { account });
146
147
  });
147
148
 
148
149
  server.registerTool('gog_sheets_export', {
149
150
  description: 'Export a spreadsheet as CSV, TSV, or PDF.',
150
- annotations: { readOnlyHint: true },
151
+ // Writes a file on the gog host and can overwrite one: not read-only (audit SEC-4).
152
+ annotations: { readOnlyHint: false, destructiveHint: true },
151
153
  inputSchema: z.object({
152
154
  spreadsheetId: z.string().describe('Spreadsheet ID'),
153
155
  format: z.string().optional().describe('Export format: csv, tsv, pdf (default: csv)'),
@@ -156,7 +158,8 @@ export function registerExtraSheetsTools(server: McpServer): void {
156
158
  account: accountParam,
157
159
  }),
158
160
  }, async ({ spreadsheetId, format, out, overwrite, account }) => {
159
- const args = ['sheets', 'export', spreadsheetId];
161
+ if (out) confinePath(out, 'out');
162
+ const args: GogArg[] = ['sheets', 'export', pos(spreadsheetId)];
160
163
  if (format) args.push(`--format=${format}`);
161
164
  if (out) args.push(`--out=${out}`);
162
165
  if (overwrite) args.push('--overwrite');
@@ -174,7 +177,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
174
177
  account: accountParam,
175
178
  }),
176
179
  }, async ({ spreadsheetId, rows, cols, sheet, account }) => {
177
- const args = ['sheets', 'freeze', spreadsheetId];
180
+ const args: GogArg[] = ['sheets', 'freeze', pos(spreadsheetId)];
178
181
  if (rows !== undefined) args.push(`--rows=${rows}`);
179
182
  if (cols !== undefined) args.push(`--cols=${cols}`);
180
183
  if (sheet) args.push(`--sheet=${sheet}`);
@@ -201,7 +204,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
201
204
  // and the contract is: after:false lands at start_index=start, after:true at start_index=start+1.
202
205
  // Both cases reduce to sending positional = start + 1 (issue #42 + the off-by-one this fixes).
203
206
  const effectiveStart = start + 1;
204
- const args = ['sheets', 'insert', spreadsheetId, sheet, dimension, String(effectiveStart)];
207
+ const args: GogArg[] = ['sheets', 'insert', pos(spreadsheetId), pos(sheet), pos(dimension), pos(String(effectiveStart))];
205
208
  if (count !== undefined) args.push(`--count=${count}`);
206
209
  if (after) args.push('--after');
207
210
  if (inheritFromBefore !== undefined) args.push(`--inherit-from-before=${inheritFromBefore}`);
@@ -220,7 +223,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
220
223
  account: accountParam,
221
224
  }),
222
225
  }, async ({ spreadsheetId, source, dest, type, transpose, account }) => {
223
- const args = ['sheets', 'copy-paste', spreadsheetId, source, dest];
226
+ const args: GogArg[] = ['sheets', 'copy-paste', pos(spreadsheetId), pos(source), pos(dest)];
224
227
  if (type) args.push(`--type=${type}`);
225
228
  if (transpose) args.push('--transpose');
226
229
  return runOrDiagnose(args, { account });
@@ -236,7 +239,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
236
239
  account: accountParam,
237
240
  }),
238
241
  }, async ({ spreadsheetId, range, type, account }) => {
239
- const args = ['sheets', 'merge', spreadsheetId, range];
242
+ const args: GogArg[] = ['sheets', 'merge', pos(spreadsheetId), pos(range)];
240
243
  if (type) args.push(`--type=${type}`);
241
244
  return runOrDiagnose(args, { account });
242
245
  });
@@ -250,7 +253,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
250
253
  account: accountParam,
251
254
  }),
252
255
  }, async ({ spreadsheetId, range, account }) => {
253
- return runOrDiagnose(['sheets', 'unmerge', spreadsheetId, range], { account });
256
+ return runOrDiagnose(['sheets', 'unmerge', pos(spreadsheetId), pos(range)], { account });
254
257
  });
255
258
 
256
259
  server.registerTool('gog_sheets_format', {
@@ -337,7 +340,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
337
340
  formatJson = JSON.stringify(cellFormat);
338
341
  if (!formatFields) formatFields = fields.join(',');
339
342
  }
340
- const args = ['sheets', 'format', a.spreadsheetId, a.range, `--format-json=${formatJson}`];
343
+ const args: GogArg[] = ['sheets', 'format', pos(a.spreadsheetId), pos(a.range), `--format-json=${formatJson}`];
341
344
  if (formatFields) args.push(`--format-fields=${formatFields}`);
342
345
  return runOrDiagnose(args, { account: a.account });
343
346
  });
@@ -358,7 +361,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
358
361
  const warning = isDateType && !force
359
362
  ? await checkDateFormatTarget(spreadsheetId, range, account)
360
363
  : null;
361
- const args = ['sheets', 'number-format', spreadsheetId, range];
364
+ const args: GogArg[] = ['sheets', 'number-format', pos(spreadsheetId), pos(range)];
362
365
  if (type) args.push(`--type=${type}`);
363
366
  if (pattern) args.push(`--pattern=${pattern}`);
364
367
  const result = await runOrDiagnose(args, { account });
@@ -378,7 +381,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
378
381
  account: accountParam,
379
382
  }),
380
383
  }, async ({ spreadsheetId, range, effective, account }) => {
381
- const args = ['sheets', 'read-format', spreadsheetId, range];
384
+ const args: GogArg[] = ['sheets', 'read-format', pos(spreadsheetId), pos(range)];
382
385
  if (effective) args.push('--effective');
383
386
  return runOrDiagnose(args, { account });
384
387
  });
@@ -394,7 +397,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
394
397
  account: accountParam,
395
398
  }),
396
399
  }, async ({ spreadsheetId, columns, width, auto, account }) => {
397
- const args = ['sheets', 'resize-columns', spreadsheetId, columns];
400
+ const args: GogArg[] = ['sheets', 'resize-columns', pos(spreadsheetId), pos(columns)];
398
401
  if (width !== undefined) args.push(`--width=${width}`);
399
402
  if (auto) args.push('--auto');
400
403
  return runOrDiagnose(args, { account });
@@ -411,7 +414,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
411
414
  account: accountParam,
412
415
  }),
413
416
  }, async ({ spreadsheetId, rows, height, auto, account }) => {
414
- const args = ['sheets', 'resize-rows', spreadsheetId, rows];
417
+ const args: GogArg[] = ['sheets', 'resize-rows', pos(spreadsheetId), pos(rows)];
415
418
  if (height !== undefined) args.push(`--height=${height}`);
416
419
  if (auto) args.push('--auto');
417
420
  return runOrDiagnose(args, { account });
@@ -426,7 +429,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
426
429
  account: accountParam,
427
430
  }),
428
431
  }, async ({ spreadsheetId, range, account }) => {
429
- return runOrDiagnose(['sheets', 'notes', spreadsheetId, range], { account });
432
+ return runOrDiagnose(['sheets', 'notes', pos(spreadsheetId), pos(range)], { account });
430
433
  });
431
434
 
432
435
  server.registerTool('gog_sheets_update_note', {
@@ -444,7 +447,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
444
447
  // The wrapper exposes no noteFile param, so there is no both-flags case to
445
448
  // guard here (gog would accept both anyway, letting the file win).
446
449
  return runOrDiagnose(
447
- ['sheets', 'update-note', spreadsheetId, range, payloadArg('note', 'note-file', note)],
450
+ ['sheets', 'update-note', pos(spreadsheetId), pos(range), payloadArg('note', 'note-file', note)],
448
451
  { account },
449
452
  );
450
453
  });
@@ -458,7 +461,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
458
461
  account: accountParam,
459
462
  }),
460
463
  }, async ({ spreadsheetId, range, account }) => {
461
- return runOrDiagnose(['sheets', 'links', spreadsheetId, range], { account });
464
+ return runOrDiagnose(['sheets', 'links', pos(spreadsheetId), pos(range)], { account });
462
465
  });
463
466
 
464
467
  server.registerTool('gog_sheets_links_set', {
@@ -477,10 +480,11 @@ export function registerExtraSheetsTools(server: McpServer): void {
477
480
  account: accountParam,
478
481
  }),
479
482
  }, async ({ spreadsheetId, cell, url, text, runsJson, cellsJson, account }) => {
480
- const args = ['sheets', 'links', 'set', spreadsheetId];
481
- if (cell) args.push(cell);
482
- if (url) args.push(url);
483
- if (text) args.push(text);
483
+ if (cellsJson) confineAtFile(cellsJson, 'cellsJson');
484
+ const args: GogArg[] = ['sheets', 'links', 'set', pos(spreadsheetId)];
485
+ if (cell) args.push(pos(cell));
486
+ if (url) args.push(pos(url));
487
+ if (text) args.push(pos(text));
484
488
  if (runsJson) args.push(`--runs-json=${runsJson}`);
485
489
  if (cellsJson) args.push(`--cells-json=${cellsJson}`);
486
490
  return runOrDiagnose(args, { account });
@@ -495,7 +499,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
495
499
  account: accountParam,
496
500
  }),
497
501
  }, async ({ spreadsheetId, range, account }) => {
498
- return runOrDiagnose(['sheets', 'validation', 'get', spreadsheetId, range], { account });
502
+ return runOrDiagnose(['sheets', 'validation', 'get', pos(spreadsheetId), pos(range)], { account });
499
503
  });
500
504
 
501
505
  server.registerTool('gog_sheets_validation_set', {
@@ -513,7 +517,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
513
517
  account: accountParam,
514
518
  }),
515
519
  }, async ({ spreadsheetId, range, type, values, strict, inputMessage, showCustomUi, filteredRowsIncluded, account }) => {
516
- const args = ['sheets', 'validation', 'set', spreadsheetId, range, `--type=${type}`];
520
+ const args: GogArg[] = ['sheets', 'validation', 'set', pos(spreadsheetId), pos(range), `--type=${type}`];
517
521
  if (values) for (const v of values) args.push(`--value=${v}`);
518
522
  if (strict) args.push('--strict');
519
523
  if (inputMessage) args.push(`--input-message=${inputMessage}`);
@@ -532,7 +536,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
532
536
  account: accountParam,
533
537
  }),
534
538
  }, async ({ spreadsheetId, range, filteredRowsIncluded, account }) => {
535
- const args = ['sheets', 'validation', 'clear', spreadsheetId, range];
539
+ const args: GogArg[] = ['sheets', 'validation', 'clear', pos(spreadsheetId), pos(range)];
536
540
  if (filteredRowsIncluded) args.push('--filtered-rows-included');
537
541
  return runOrDiagnose(args, { account });
538
542
  });
@@ -549,7 +553,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
549
553
  account: accountParam,
550
554
  }),
551
555
  }, async ({ spreadsheetId, rangeOrSheet, dimension, start, end, account }) => {
552
- const args = ['sheets', 'delete-dimension', spreadsheetId, rangeOrSheet, `--dimension=${dimension}`];
556
+ const args: GogArg[] = ['sheets', 'delete-dimension', pos(spreadsheetId), pos(rangeOrSheet), `--dimension=${dimension}`];
553
557
  if (start !== undefined) args.push(`--start=${start}`);
554
558
  if (end !== undefined) args.push(`--end=${end}`);
555
559
  args.push('--force'); // gog gates this op; without --force the runner's --no-input makes it refuse
@@ -564,7 +568,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
564
568
  account: accountParam,
565
569
  }),
566
570
  }, async ({ spreadsheetId, account }) => {
567
- return runOrDiagnose(['sheets', 'named-ranges', 'list', spreadsheetId], { account });
571
+ return runOrDiagnose(['sheets', 'named-ranges', 'list', pos(spreadsheetId)], { account });
568
572
  });
569
573
 
570
574
  server.registerTool('gog_sheets_named_ranges_get', {
@@ -576,7 +580,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
576
580
  account: accountParam,
577
581
  }),
578
582
  }, async ({ spreadsheetId, nameOrId, account }) => {
579
- return runOrDiagnose(['sheets', 'named-ranges', 'get', spreadsheetId, nameOrId], { account });
583
+ return runOrDiagnose(['sheets', 'named-ranges', 'get', pos(spreadsheetId), pos(nameOrId)], { account });
580
584
  });
581
585
 
582
586
  server.registerTool('gog_sheets_named_ranges_add', {
@@ -589,7 +593,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
589
593
  account: accountParam,
590
594
  }),
591
595
  }, async ({ spreadsheetId, name, range, account }) => {
592
- return runOrDiagnose(['sheets', 'named-ranges', 'add', spreadsheetId, name, range], { account });
596
+ return runOrDiagnose(['sheets', 'named-ranges', 'add', pos(spreadsheetId), pos(name), pos(range)], { account });
593
597
  });
594
598
 
595
599
  server.registerTool('gog_sheets_named_ranges_update', {
@@ -603,7 +607,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
603
607
  account: accountParam,
604
608
  }),
605
609
  }, async ({ spreadsheetId, nameOrId, name, range, account }) => {
606
- const args = ['sheets', 'named-ranges', 'update', spreadsheetId, nameOrId];
610
+ const args: GogArg[] = ['sheets', 'named-ranges', 'update', pos(spreadsheetId), pos(nameOrId)];
607
611
  if (name) args.push(`--name=${name}`);
608
612
  if (range) args.push(`--range=${range}`);
609
613
  return runOrDiagnose(args, { account });
@@ -618,7 +622,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
618
622
  account: accountParam,
619
623
  }),
620
624
  }, async ({ spreadsheetId, nameOrId, account }) => {
621
- return runOrDiagnose(['sheets', 'named-ranges', 'delete', spreadsheetId, nameOrId], { account });
625
+ return runOrDiagnose(['sheets', 'named-ranges', 'delete', pos(spreadsheetId), pos(nameOrId)], { account });
622
626
  });
623
627
 
624
628
  server.registerTool('gog_sheets_batch_update', {
@@ -634,7 +638,8 @@ export function registerExtraSheetsTools(server: McpServer): void {
634
638
  account: accountParam,
635
639
  }),
636
640
  }, async ({ spreadsheetId, dataJson, input, includeValuesInResponse, responseRender, responseDateTimeRender, account }) => {
637
- const args = ['sheets', 'batch-update', spreadsheetId, `--data-json=${dataJson}`];
641
+ confineAtFile(dataJson, 'dataJson');
642
+ const args: GogArg[] = ['sheets', 'batch-update', pos(spreadsheetId), `--data-json=${dataJson}`];
638
643
  if (input) args.push(`--input=${input}`);
639
644
  if (includeValuesInResponse) args.push('--include-values-in-response');
640
645
  if (responseRender) args.push(`--response-render=${responseRender}`);
@@ -653,7 +658,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
653
658
  }),
654
659
  }, async ({ spreadsheetId, tab, to, account }) => {
655
660
  return runOrDiagnose(
656
- ['sheets', 'reorder-tab', spreadsheetId, `--tab=${tab}`, `--to=${to}`],
661
+ ['sheets', 'reorder-tab', pos(spreadsheetId), `--tab=${tab}`, `--to=${to}`],
657
662
  { account },
658
663
  );
659
664
  });
@@ -668,7 +673,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
668
673
  account: accountParam,
669
674
  }),
670
675
  }, async ({ spreadsheetId, account }) => {
671
- return runOrDiagnose(['sheets', 'chart', 'list', spreadsheetId], { account });
676
+ return runOrDiagnose(['sheets', 'chart', 'list', pos(spreadsheetId)], { account });
672
677
  });
673
678
 
674
679
  server.registerTool('gog_sheets_chart_get', {
@@ -680,7 +685,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
680
685
  account: accountParam,
681
686
  }),
682
687
  }, async ({ spreadsheetId, chartId, account }) => {
683
- return runOrDiagnose(['sheets', 'chart', 'get', spreadsheetId, chartId], { account });
688
+ return runOrDiagnose(['sheets', 'chart', 'get', pos(spreadsheetId), pos(chartId)], { account });
684
689
  });
685
690
 
686
691
  server.registerTool('gog_sheets_chart_create', {
@@ -696,7 +701,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
696
701
  account: accountParam,
697
702
  }),
698
703
  }, async ({ spreadsheetId, specJson, sheet, anchor, width, height, account }) => {
699
- const args = ['sheets', 'chart', 'create', spreadsheetId, `--spec-json=${specJson}`];
704
+ const args: GogArg[] = ['sheets', 'chart', 'create', pos(spreadsheetId), `--spec-json=${specJson}`];
700
705
  if (sheet) args.push(`--sheet=${sheet}`);
701
706
  if (anchor) args.push(`--anchor=${anchor}`);
702
707
  if (width !== undefined) args.push(`--width=${width}`);
@@ -715,7 +720,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
715
720
  }),
716
721
  }, async ({ spreadsheetId, chartId, specJson, account }) => {
717
722
  return runOrDiagnose(
718
- ['sheets', 'chart', 'update', spreadsheetId, chartId, `--spec-json=${specJson}`],
723
+ ['sheets', 'chart', 'update', pos(spreadsheetId), pos(chartId), `--spec-json=${specJson}`],
719
724
  { account },
720
725
  );
721
726
  });
@@ -729,7 +734,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
729
734
  account: accountParam,
730
735
  }),
731
736
  }, async ({ spreadsheetId, chartId, account }) => {
732
- return runOrDiagnose(['sheets', 'chart', 'delete', spreadsheetId, chartId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
737
+ return runOrDiagnose(['sheets', 'chart', 'delete', pos(spreadsheetId), pos(chartId), '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
733
738
  });
734
739
 
735
740
  // ---- Tables (gog 0.19.0) ----
@@ -742,7 +747,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
742
747
  account: accountParam,
743
748
  }),
744
749
  }, async ({ spreadsheetId, account }) => {
745
- return runOrDiagnose(['sheets', 'table', 'list', spreadsheetId], { account });
750
+ return runOrDiagnose(['sheets', 'table', 'list', pos(spreadsheetId)], { account });
746
751
  });
747
752
 
748
753
  server.registerTool('gog_sheets_table_get', {
@@ -754,7 +759,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
754
759
  account: accountParam,
755
760
  }),
756
761
  }, async ({ spreadsheetId, tableId, account }) => {
757
- return runOrDiagnose(['sheets', 'table', 'get', spreadsheetId, tableId], { account });
762
+ return runOrDiagnose(['sheets', 'table', 'get', pos(spreadsheetId), pos(tableId)], { account });
758
763
  });
759
764
 
760
765
  server.registerTool('gog_sheets_table_create', {
@@ -769,7 +774,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
769
774
  }),
770
775
  }, async ({ spreadsheetId, range, name, columnsJson, account }) => {
771
776
  return runOrDiagnose(
772
- ['sheets', 'table', 'create', spreadsheetId, range, `--name=${name}`, `--columns-json=${columnsJson}`],
777
+ ['sheets', 'table', 'create', pos(spreadsheetId), pos(range), `--name=${name}`, `--columns-json=${columnsJson}`],
773
778
  { account },
774
779
  );
775
780
  });
@@ -785,7 +790,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
785
790
  account: accountParam,
786
791
  }),
787
792
  }, async ({ spreadsheetId, tableId, valuesJson, input, account }) => {
788
- const args = ['sheets', 'table', 'append', spreadsheetId, tableId, `--values-json=${valuesJson}`];
793
+ const args: GogArg[] = ['sheets', 'table', 'append', pos(spreadsheetId), pos(tableId), `--values-json=${valuesJson}`];
789
794
  if (input) args.push(`--input=${input}`);
790
795
  return runOrDiagnose(args, { account });
791
796
  });
@@ -799,7 +804,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
799
804
  account: accountParam,
800
805
  }),
801
806
  }, async ({ spreadsheetId, tableId, account }) => {
802
- return runOrDiagnose(['sheets', 'table', 'clear', spreadsheetId, tableId, '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
807
+ return runOrDiagnose(['sheets', 'table', 'clear', pos(spreadsheetId), pos(tableId), '--force'], { account }); // gog gates this op; without --force the runner's --no-input makes it refuse
803
808
  });
804
809
 
805
810
  server.registerTool('gog_sheets_table_delete', {
@@ -822,7 +827,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
822
827
  // Raw destructive delete: removes the table and its cell data. gog ≥ 0.23
823
828
  // requires --discard-data to confirm the cell wipe (--force only skips the
824
829
  // interactive confirmation; it does not authorize the data loss).
825
- return runOrDiagnose(['sheets', 'table', 'delete', spreadsheetId, tableId, '--discard-data', '--force'], { account });
830
+ return runOrDiagnose(['sheets', 'table', 'delete', pos(spreadsheetId), pos(tableId), '--discard-data', '--force'], { account });
826
831
  }
827
832
 
828
833
  // keep_data: emulate "Convert to range". Read the full table range with
@@ -832,10 +837,10 @@ export function registerExtraSheetsTools(server: McpServer): void {
832
837
  let values: unknown[][];
833
838
  try {
834
839
  // `gog sheets table get` wraps the table under a top-level "table" key.
835
- const parsed = JSON.parse(await run(['sheets', 'table', 'get', spreadsheetId, tableId], { account }));
840
+ const parsed = JSON.parse(await run(['sheets', 'table', 'get', pos(spreadsheetId), pos(tableId)], { account }));
836
841
  range = parsed.table?.a1;
837
842
  if (!range) throw new Error(`could not determine the table's range (no "a1" in table get output) for table ${tableId}`);
838
- const read = JSON.parse(await run(['sheets', 'get', spreadsheetId, range, '--render=FORMULA'], { account }));
843
+ const read = JSON.parse(await run(['sheets', 'get', pos(spreadsheetId), pos(range), '--render=FORMULA'], { account }));
839
844
  values = read.values ?? [];
840
845
  } catch (err) {
841
846
  return diagnose(err);
@@ -845,7 +850,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
845
850
  // We have already backed up the cells above, so --discard-data (required
846
851
  // by gog ≥ 0.23) is the intended path here — we re-write the data right
847
852
  // after.
848
- await run(['sheets', 'table', 'delete', spreadsheetId, tableId, '--discard-data', '--force'], { account });
853
+ await run(['sheets', 'table', 'delete', pos(spreadsheetId), pos(tableId), '--discard-data', '--force'], { account });
849
854
  } catch (err) {
850
855
  // Table not deleted; cell data is untouched.
851
856
  return diagnose(err);
@@ -853,7 +858,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
853
858
 
854
859
  if (values.length > 0) {
855
860
  try {
856
- await run(['sheets', 'update', spreadsheetId, range, `--values-json=${JSON.stringify(values)}`], { account });
861
+ await run(['sheets', 'update', pos(spreadsheetId), pos(range), `--values-json=${JSON.stringify(values)}`], { account });
857
862
  } catch (err) {
858
863
  // The table is already gone but the restore write failed. Hand the
859
864
  // read-back data straight back so it can be re-applied manually rather
@@ -880,7 +885,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
880
885
  account: accountParam,
881
886
  }),
882
887
  }, async ({ spreadsheetId, sheet, account }) => {
883
- const args = ['sheets', 'banding', 'list', spreadsheetId];
888
+ const args: GogArg[] = ['sheets', 'banding', 'list', pos(spreadsheetId)];
884
889
  if (sheet) args.push(`--sheet=${sheet}`);
885
890
  return runOrDiagnose(args, { account });
886
891
  });
@@ -896,7 +901,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
896
901
  account: accountParam,
897
902
  }),
898
903
  }, async ({ spreadsheetId, range, rowPropertiesJson, columnPropertiesJson, account }) => {
899
- const args = ['sheets', 'banding', 'set', spreadsheetId, range];
904
+ const args: GogArg[] = ['sheets', 'banding', 'set', pos(spreadsheetId), pos(range)];
900
905
  if (rowPropertiesJson) args.push(`--row-properties-json=${rowPropertiesJson}`);
901
906
  if (columnPropertiesJson) args.push(`--column-properties-json=${columnPropertiesJson}`);
902
907
  return runOrDiagnose(args, { account });
@@ -913,7 +918,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
913
918
  account: accountParam,
914
919
  }),
915
920
  }, async ({ spreadsheetId, id, all, sheet, account }) => {
916
- const args = ['sheets', 'banding', 'clear', spreadsheetId];
921
+ const args: GogArg[] = ['sheets', 'banding', 'clear', pos(spreadsheetId)];
917
922
  if (id !== undefined) args.push(`--id=${id}`);
918
923
  if (all) args.push('--all');
919
924
  if (sheet) args.push(`--sheet=${sheet}`);
@@ -933,7 +938,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
933
938
  account: accountParam,
934
939
  }),
935
940
  }, async ({ spreadsheetId, range, replace, account }) => {
936
- const args = ['sheets', 'filter', 'set', spreadsheetId, range];
941
+ const args: GogArg[] = ['sheets', 'filter', 'set', pos(spreadsheetId), pos(range)];
937
942
  if (replace) args.push('--force');
938
943
  return runOrDiagnose(args, { account });
939
944
  });
@@ -949,7 +954,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
949
954
  account: accountParam,
950
955
  }),
951
956
  }, async ({ spreadsheetId, sheet, account }) => {
952
- const args = ['sheets', 'conditional-format', 'list', spreadsheetId];
957
+ const args: GogArg[] = ['sheets', 'conditional-format', 'list', pos(spreadsheetId)];
953
958
  if (sheet) args.push(`--sheet=${sheet}`);
954
959
  return runOrDiagnose(args, { account });
955
960
  });
@@ -972,7 +977,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
972
977
  account: accountParam,
973
978
  }),
974
979
  }, async ({ spreadsheetId, range, type, formatJson, expr, formatFields, gradientRuleJson, account }) => {
975
- const args = ['sheets', 'conditional-format', 'add', spreadsheetId, range];
980
+ const args: GogArg[] = ['sheets', 'conditional-format', 'add', pos(spreadsheetId), pos(range)];
976
981
  if (type) args.push(`--type=${type}`);
977
982
  if (formatJson !== undefined) args.push(`--format-json=${formatJson}`);
978
983
  if (expr !== undefined) args.push(`--expr=${expr}`);
@@ -992,7 +997,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
992
997
  account: accountParam,
993
998
  }),
994
999
  }, async ({ spreadsheetId, sheet, index, all, account }) => {
995
- const args = ['sheets', 'conditional-format', 'clear', spreadsheetId, `--sheet=${sheet}`];
1000
+ const args: GogArg[] = ['sheets', 'conditional-format', 'clear', pos(spreadsheetId), `--sheet=${sheet}`];
996
1001
  if (index !== undefined) args.push(`--index=${index}`);
997
1002
  if (all) args.push('--all');
998
1003
  args.push('--force'); // gog gates this op; without --force the runner's --no-input makes it refuse
@@ -1011,7 +1016,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1011
1016
  account: accountParam,
1012
1017
  }),
1013
1018
  }, async ({ spreadsheetId, name, parent, account }) => {
1014
- const args = ['drive', 'copy', spreadsheetId, name];
1019
+ const args: GogArg[] = ['drive', 'copy', pos(spreadsheetId), pos(name)];
1015
1020
  if (parent) args.push(`--parent=${parent}`);
1016
1021
  return runOrDiagnose(args, { account });
1017
1022
  });
@@ -1047,7 +1052,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1047
1052
  account: accountParam,
1048
1053
  }),
1049
1054
  }, async ({ spreadsheetId, account }) => {
1050
- return runOrDiagnose(['sheets', 'datasource', 'list', spreadsheetId], { account });
1055
+ return runOrDiagnose(['sheets', 'datasource', 'list', pos(spreadsheetId)], { account });
1051
1056
  });
1052
1057
 
1053
1058
  server.registerTool('gog_sheets_datasource_describe', {
@@ -1063,7 +1068,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1063
1068
  account: accountParam,
1064
1069
  }),
1065
1070
  }, async ({ spreadsheetId, dataSourceId, account }) => {
1066
- return runOrDiagnose(['sheets', 'datasource', 'describe', spreadsheetId, dataSourceId], { account });
1071
+ return runOrDiagnose(['sheets', 'datasource', 'describe', pos(spreadsheetId), pos(dataSourceId)], { account });
1067
1072
  });
1068
1073
 
1069
1074
  server.registerTool('gog_sheets_datasource_table_list', {
@@ -1079,7 +1084,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1079
1084
  account: accountParam,
1080
1085
  }),
1081
1086
  }, async ({ spreadsheetId, dataSourceId, account }) => {
1082
- const args = ['sheets', 'datasource', 'table', 'list', spreadsheetId];
1087
+ const args: GogArg[] = ['sheets', 'datasource', 'table', 'list', pos(spreadsheetId)];
1083
1088
  if (dataSourceId) args.push(`--data-source-id=${dataSourceId}`);
1084
1089
  return runOrDiagnose(args, { account });
1085
1090
  });
@@ -1096,7 +1101,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1096
1101
  account: accountParam,
1097
1102
  }),
1098
1103
  }, async ({ spreadsheetId, anchor, account }) => {
1099
- return runOrDiagnose(['sheets', 'datasource', 'table', 'describe', spreadsheetId, anchor], { account });
1104
+ return runOrDiagnose(['sheets', 'datasource', 'table', 'describe', pos(spreadsheetId), pos(anchor)], { account });
1100
1105
  });
1101
1106
 
1102
1107
  server.registerTool('gog_sheets_datasource_table_read', {
@@ -1115,7 +1120,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1115
1120
  account: accountParam,
1116
1121
  }),
1117
1122
  }, async ({ spreadsheetId, anchor, maxRows, render, account }) => {
1118
- const args = ['sheets', 'datasource', 'table', 'read', spreadsheetId, anchor];
1123
+ const args: GogArg[] = ['sheets', 'datasource', 'table', 'read', pos(spreadsheetId), pos(anchor)];
1119
1124
  if (maxRows !== undefined) args.push(`--max-rows=${maxRows}`);
1120
1125
  if (render) args.push(`--render=${render}`);
1121
1126
  return runOrDiagnose(args, { account });
@@ -1166,7 +1171,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1166
1171
  if (query === undefined && !(dataset && table)) {
1167
1172
  throw new Error('Pass query, or both --dataset and --table (tableProject alone is not a table).');
1168
1173
  }
1169
- const args = ['sheets', 'datasource', 'add', spreadsheetId, `--billing-project=${billingProject}`];
1174
+ const args: GogArg[] = ['sheets', 'datasource', 'add', pos(spreadsheetId), `--billing-project=${billingProject}`];
1170
1175
  if (query !== undefined) args.push(`--query=${query}`);
1171
1176
  if (tableProject) args.push(`--table-project=${tableProject}`);
1172
1177
  if (dataset) args.push(`--dataset=${dataset}`);
@@ -1200,7 +1205,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1200
1205
  if (billingProject === undefined && query === undefined && !tableFlags) {
1201
1206
  throw new Error('nothing to update: pass billingProject, query, dataset, table or tableProject.');
1202
1207
  }
1203
- const args = ['sheets', 'datasource', 'update', spreadsheetId, dataSourceId];
1208
+ const args: GogArg[] = ['sheets', 'datasource', 'update', pos(spreadsheetId), pos(dataSourceId)];
1204
1209
  if (billingProject !== undefined) args.push(`--billing-project=${billingProject}`);
1205
1210
  if (query !== undefined) args.push(`--query=${query}`);
1206
1211
  if (tableProject !== undefined) args.push(`--table-project=${tableProject}`);
@@ -1237,7 +1242,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1237
1242
  account: accountParam,
1238
1243
  }),
1239
1244
  }, async ({ spreadsheetId, dataSourceId, forceRefresh, account }) => {
1240
- const args = ['sheets', 'datasource', 'refresh', spreadsheetId, dataSourceId];
1245
+ const args: GogArg[] = ['sheets', 'datasource', 'refresh', pos(spreadsheetId), pos(dataSourceId)];
1241
1246
  if (forceRefresh) args.push('--force-refresh');
1242
1247
  return runOrDiagnose(args, { account });
1243
1248
  });
@@ -1259,7 +1264,7 @@ export function registerExtraSheetsTools(server: McpServer): void {
1259
1264
  // --no-input, so without --force it refuses at runtime. Verified live
1260
1265
  // against gog 0.38.0: without --force it answers "refusing to delete
1261
1266
  // Connected Sheets data source … without --force (non-interactive)".
1262
- return runOrDiagnose(['sheets', 'datasource', 'delete', spreadsheetId, dataSourceId, '--force'], { account });
1267
+ return runOrDiagnose(['sheets', 'datasource', 'delete', pos(spreadsheetId), pos(dataSourceId), '--force'], { account });
1263
1268
  });
1264
1269
 
1265
1270
  }