gogcli-mcp-docs 4.6.3 → 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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +3 -3
- package/dist/index.js +158 -95
- package/manifest.json +23 -2
- package/package.json +2 -2
- package/server.json +20 -2
- package/src/tools/docs-extra.ts +70 -68
- package/tests/tool-annotations.test.ts +10 -0
package/src/tools/docs-extra.ts
CHANGED
|
@@ -32,7 +32,7 @@ export function docTitle(raw: string): string | undefined {
|
|
|
32
32
|
export function registerExtraDocsTools(server: McpServer): void {
|
|
33
33
|
server.registerTool('gog_docs_copy', {
|
|
34
34
|
description: 'Copy a Google Doc to a new document with the given title.',
|
|
35
|
-
annotations: { destructiveHint: true },
|
|
35
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
36
36
|
inputSchema: z.object({
|
|
37
37
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
38
38
|
title: z.string().describe('Title for the new copy'),
|
|
@@ -47,7 +47,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
47
47
|
|
|
48
48
|
server.registerTool('gog_docs_delete', {
|
|
49
49
|
description: 'Delete content within a Google Doc by character index range. To remove the entire document (move to Drive trash), use gog_docs_trash.',
|
|
50
|
-
annotations: { destructiveHint: true },
|
|
50
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
51
51
|
inputSchema: z.object({
|
|
52
52
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
53
53
|
start: z.number().optional().describe('Start index (character position, 1-based). Required unless `at` is set.'),
|
|
@@ -76,7 +76,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
76
76
|
|
|
77
77
|
server.registerTool('gog_docs_trash', {
|
|
78
78
|
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.',
|
|
79
|
-
annotations: { destructiveHint: true },
|
|
79
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
80
80
|
inputSchema: z.object({
|
|
81
81
|
docId: z.string().describe('Doc ID to move to trash'),
|
|
82
82
|
account: accountParam,
|
|
@@ -87,7 +87,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
87
87
|
|
|
88
88
|
server.registerTool('gog_docs_edit', {
|
|
89
89
|
description: 'Edit a Google Doc by finding and replacing text (stream-edit style).',
|
|
90
|
-
annotations: { destructiveHint: true },
|
|
90
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
91
91
|
inputSchema: z.object({
|
|
92
92
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
93
93
|
find: z.string().describe('Text to find'),
|
|
@@ -103,7 +103,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
103
103
|
|
|
104
104
|
server.registerTool('gog_docs_read', {
|
|
105
105
|
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" — it writes to a file. Use gog_docs_structure to see paragraph-by-paragraph layout with indices.',
|
|
106
|
-
annotations: { readOnlyHint: true },
|
|
106
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
107
107
|
inputSchema: z.object({
|
|
108
108
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
109
109
|
format: z.enum(['text', 'json']).optional().describe('Output format (default: text)'),
|
|
@@ -131,7 +131,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
131
131
|
|
|
132
132
|
server.registerTool('gog_docs_format', {
|
|
133
133
|
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.',
|
|
134
|
-
annotations: { destructiveHint: true },
|
|
134
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
135
135
|
inputSchema: z.object({
|
|
136
136
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
137
137
|
match: z.string().optional().describe('Format only the first text match'),
|
|
@@ -245,7 +245,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
245
245
|
|
|
246
246
|
server.registerTool('gog_docs_suggestions_list', {
|
|
247
247
|
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.',
|
|
248
|
-
annotations: { readOnlyHint: true },
|
|
248
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
249
249
|
inputSchema: z.object({
|
|
250
250
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
251
251
|
tab: z.string().optional().describe('Tab title or ID (omit for the first tab)'),
|
|
@@ -260,7 +260,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
260
260
|
server.registerTool('gog_docs_export', {
|
|
261
261
|
description: 'Export a Google Doc as PDF, plain text, HTML, DOCX, or other format.',
|
|
262
262
|
// Writes a file on the gog host and can overwrite one: not read-only (audit SEC-4).
|
|
263
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
263
|
+
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
|
|
264
264
|
inputSchema: z.object({
|
|
265
265
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
266
266
|
format: z.string().optional().describe('Export format: pdf, txt, html, docx, rtf, odt, epub (default: pdf)'),
|
|
@@ -279,7 +279,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
279
279
|
|
|
280
280
|
server.registerTool('gog_docs_insert', {
|
|
281
281
|
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 — 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.',
|
|
282
|
-
annotations: { destructiveHint: true },
|
|
282
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
283
283
|
inputSchema: z.object({
|
|
284
284
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
285
285
|
content: z.string().optional().describe('Text content to insert'),
|
|
@@ -310,7 +310,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
310
310
|
|
|
311
311
|
server.registerTool('gog_docs_append', {
|
|
312
312
|
description: 'Append text to the end of a Google Doc. This is the right tool for iterative document construction — 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 — split into multiple calls with ≤2 tables each (openclaw/gogcli#607); (b) inline **bold** / *italic* / `code` inside table cells renders as literal characters — 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 — always supply a non-empty header (openclaw/gogcli#609).',
|
|
313
|
-
annotations: { destructiveHint: true },
|
|
313
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
314
314
|
inputSchema: z.object({
|
|
315
315
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
316
316
|
text: z.string().optional().describe('Text content to append'),
|
|
@@ -331,7 +331,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
331
331
|
|
|
332
332
|
server.registerTool('gog_docs_list_tabs', {
|
|
333
333
|
description: 'List all tabs in a Google Doc.',
|
|
334
|
-
annotations: { readOnlyHint: true },
|
|
334
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
335
335
|
inputSchema: z.object({
|
|
336
336
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
337
337
|
account: accountParam,
|
|
@@ -342,7 +342,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
342
342
|
|
|
343
343
|
server.registerTool('gog_docs_sed', {
|
|
344
344
|
description: 'Stream-edit a Google Doc with sed-like regex expressions (s/find/replace/ syntax).',
|
|
345
|
-
annotations: { destructiveHint: true },
|
|
345
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
346
346
|
inputSchema: z.object({
|
|
347
347
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
348
348
|
expression: z.string().optional().describe('Single sed expression (e.g. "s/old/new/g")'),
|
|
@@ -367,7 +367,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
367
367
|
|
|
368
368
|
server.registerTool('gog_docs_update', {
|
|
369
369
|
description: 'Update a Google Doc — insert or replace text at a specific position.',
|
|
370
|
-
annotations: { destructiveHint: true },
|
|
370
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
371
371
|
inputSchema: z.object({
|
|
372
372
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
373
373
|
text: z.string().optional().describe('Text content to write'),
|
|
@@ -411,7 +411,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
411
411
|
'Either flag additionally requires the Docs scope; the plain listing needs only Drive. ' +
|
|
412
412
|
'matches[] always spans every tab, so a quote appearing in two tabs is visible as an ambiguity rather than silently resolved. ' +
|
|
413
413
|
'tab keeps only comments with a match in that tab, which drops orphaned comments and comments that quote nothing.',
|
|
414
|
-
annotations: { readOnlyHint: true },
|
|
414
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
415
415
|
inputSchema: z.object({
|
|
416
416
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
417
417
|
includeResolved: z.boolean().optional().describe('Include resolved comments (default: false, open only)'),
|
|
@@ -433,7 +433,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
433
433
|
|
|
434
434
|
server.registerTool('gog_docs_comments_get', {
|
|
435
435
|
description: 'Get a single comment by ID, including its replies.',
|
|
436
|
-
annotations: { readOnlyHint: true },
|
|
436
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
437
437
|
inputSchema: z.object({
|
|
438
438
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
439
439
|
commentId: z.string().describe('Comment ID'),
|
|
@@ -449,7 +449,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
449
449
|
+ 'The Doc\'s owner and everyone the text +mentions are notified, so this reads the Doc and asks the MCP host to show '
|
|
450
450
|
+ 'the user a confirmation prompt with the Doc, the text and who is mentioned first; nothing is posted unless they '
|
|
451
451
|
+ 'accept.' + CONFIRM_FALLBACK_DESCRIPTION,
|
|
452
|
-
annotations: { destructiveHint: false },
|
|
452
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
453
453
|
inputSchema: z.object({
|
|
454
454
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
455
455
|
content: z.string().describe('Comment text'),
|
|
@@ -472,6 +472,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
472
472
|
details: { doc, textPreview: bodyPreview(content), quoted, mentions },
|
|
473
473
|
unsupportedNote: 'Ask the user to comment from Google Docs.',
|
|
474
474
|
fallback: {
|
|
475
|
+
args: { docId, content, quoted, account },
|
|
475
476
|
tool: 'gog_docs_comments_add',
|
|
476
477
|
account,
|
|
477
478
|
confirmToken,
|
|
@@ -489,7 +490,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
489
490
|
description: 'Reply to an existing comment on a Google Doc. Everyone on the thread and anyone the reply +mentions is '
|
|
490
491
|
+ 'notified, so this reads the Doc and the comment and asks the MCP host to show the user a confirmation prompt '
|
|
491
492
|
+ 'with both and the reply first; nothing is posted unless they accept.' + CONFIRM_FALLBACK_DESCRIPTION,
|
|
492
|
-
annotations: { destructiveHint: false },
|
|
493
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
493
494
|
inputSchema: z.object({
|
|
494
495
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
495
496
|
commentId: z.string().describe('Comment ID to reply to'),
|
|
@@ -513,6 +514,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
513
514
|
details: { doc, replyingTo, textPreview: bodyPreview(content), mentions },
|
|
514
515
|
unsupportedNote: 'Ask the user to reply from Google Docs.',
|
|
515
516
|
fallback: {
|
|
517
|
+
args: { docId, commentId, content, account },
|
|
516
518
|
tool: 'gog_docs_comments_reply',
|
|
517
519
|
account,
|
|
518
520
|
confirmToken,
|
|
@@ -528,7 +530,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
528
530
|
|
|
529
531
|
server.registerTool('gog_docs_comments_resolve', {
|
|
530
532
|
description: 'Resolve a comment (mark as done). Optionally include a closing message.',
|
|
531
|
-
annotations: { destructiveHint: true },
|
|
533
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
532
534
|
inputSchema: z.object({
|
|
533
535
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
534
536
|
commentId: z.string().describe('Comment ID to resolve'),
|
|
@@ -543,7 +545,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
543
545
|
|
|
544
546
|
server.registerTool('gog_docs_comments_delete', {
|
|
545
547
|
description: 'Delete a comment from a Google Doc. This action is permanent.',
|
|
546
|
-
annotations: { destructiveHint: true },
|
|
548
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
547
549
|
inputSchema: z.object({
|
|
548
550
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
549
551
|
commentId: z.string().describe('Comment ID to delete'),
|
|
@@ -556,7 +558,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
556
558
|
|
|
557
559
|
server.registerTool('gog_docs_comments_reopen', {
|
|
558
560
|
description: 'Reopen a previously resolved comment (flip resolved → open).',
|
|
559
|
-
annotations: { destructiveHint: true },
|
|
561
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
560
562
|
inputSchema: z.object({
|
|
561
563
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
562
564
|
commentId: z.string().describe('Comment ID to reopen'),
|
|
@@ -568,7 +570,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
568
570
|
|
|
569
571
|
server.registerTool('gog_docs_comments_locate', {
|
|
570
572
|
description: 'Locate a comment\'s anchor in a Google Doc — 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.',
|
|
571
|
-
annotations: { readOnlyHint: true },
|
|
573
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
572
574
|
inputSchema: z.object({
|
|
573
575
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
574
576
|
commentId: z.string().describe('Comment ID to locate'),
|
|
@@ -587,7 +589,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
587
589
|
|
|
588
590
|
server.registerTool('gog_docs_find_range', {
|
|
589
591
|
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.',
|
|
590
|
-
annotations: { readOnlyHint: true },
|
|
592
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
591
593
|
inputSchema: z.object({
|
|
592
594
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
593
595
|
text: z.string().describe('Literal text to locate'),
|
|
@@ -617,7 +619,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
617
619
|
// end to submit them atomically against the locked revision.
|
|
618
620
|
server.registerTool('gog_batch_begin', {
|
|
619
621
|
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.',
|
|
620
|
-
annotations: { destructiveHint: false },
|
|
622
|
+
annotations: { destructiveHint: false, openWorldHint: false },
|
|
621
623
|
inputSchema: z.object({
|
|
622
624
|
docId: z.string().describe('Google Doc ID the batch is locked to'),
|
|
623
625
|
name: z.string().optional().describe('Optional batch label'),
|
|
@@ -631,7 +633,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
631
633
|
|
|
632
634
|
server.registerTool('gog_batch_end', {
|
|
633
635
|
description: 'Submit a persisted batch: applies every composed request to the doc in one atomic batchUpdate against the locked revision. Atomic by default — 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.',
|
|
634
|
-
annotations: { destructiveHint: true },
|
|
636
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
635
637
|
inputSchema: z.object({
|
|
636
638
|
batchId: z.string().describe('Batch ID (from gog_batch_begin)'),
|
|
637
639
|
autoSplit: z.boolean().optional().describe('Submit batches over 500 requests as ordered chunks (non-atomic)'),
|
|
@@ -647,7 +649,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
647
649
|
|
|
648
650
|
server.registerTool('gog_batch_abort', {
|
|
649
651
|
description: 'Discard a persisted batch and its composed requests without applying anything to the doc.',
|
|
650
|
-
annotations: { destructiveHint: true },
|
|
652
|
+
annotations: { destructiveHint: true, openWorldHint: false },
|
|
651
653
|
inputSchema: z.object({
|
|
652
654
|
batchId: z.string().describe('Batch ID to discard'),
|
|
653
655
|
account: accountParam,
|
|
@@ -658,7 +660,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
658
660
|
|
|
659
661
|
server.registerTool('gog_batch_list', {
|
|
660
662
|
description: 'List persisted Docs request batches (id, doc, label, request count, status).',
|
|
661
|
-
annotations: { readOnlyHint: true },
|
|
663
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
662
664
|
inputSchema: z.object({
|
|
663
665
|
account: accountParam,
|
|
664
666
|
}),
|
|
@@ -668,7 +670,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
668
670
|
|
|
669
671
|
server.registerTool('gog_batch_show', {
|
|
670
672
|
description: 'Show one persisted batch: its doc, locked revision, and the composed requests awaiting submission.',
|
|
671
|
-
annotations: { readOnlyHint: true },
|
|
673
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
672
674
|
inputSchema: z.object({
|
|
673
675
|
batchId: z.string().describe('Batch ID'),
|
|
674
676
|
account: accountParam,
|
|
@@ -679,7 +681,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
679
681
|
|
|
680
682
|
server.registerTool('gog_batch_prune', {
|
|
681
683
|
description: 'Delete stale persisted batches (not updated within olderThan).',
|
|
682
|
-
annotations: { destructiveHint: true },
|
|
684
|
+
annotations: { destructiveHint: true, openWorldHint: false },
|
|
683
685
|
inputSchema: z.object({
|
|
684
686
|
olderThan: z.string().optional().describe('Delete batches not updated within this duration (e.g. 72h, 7d)'),
|
|
685
687
|
account: accountParam,
|
|
@@ -692,7 +694,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
692
694
|
|
|
693
695
|
server.registerTool('gog_docs_table_column_width', {
|
|
694
696
|
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.',
|
|
695
|
-
annotations: { destructiveHint: true },
|
|
697
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
696
698
|
inputSchema: z.object({
|
|
697
699
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
698
700
|
col: z.number().int().optional().describe('1-based column number. Omit with evenlyDistributed to reset all columns.'),
|
|
@@ -720,7 +722,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
720
722
|
|
|
721
723
|
server.registerTool('gog_docs_table_row_insert', {
|
|
722
724
|
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 — the default).',
|
|
723
|
-
annotations: { destructiveHint: true },
|
|
725
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
724
726
|
inputSchema: z.object({
|
|
725
727
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
726
728
|
table: tableSelectorParam,
|
|
@@ -740,7 +742,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
740
742
|
|
|
741
743
|
server.registerTool('gog_docs_table_row_delete', {
|
|
742
744
|
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.',
|
|
743
|
-
annotations: { destructiveHint: true },
|
|
745
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
744
746
|
inputSchema: z.object({
|
|
745
747
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
746
748
|
row: z.number().int().describe('1-based row number; negative indexes count from the end'),
|
|
@@ -757,7 +759,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
757
759
|
|
|
758
760
|
server.registerTool('gog_docs_table_column_insert', {
|
|
759
761
|
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 — the default).',
|
|
760
|
-
annotations: { destructiveHint: true },
|
|
762
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
761
763
|
inputSchema: z.object({
|
|
762
764
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
763
765
|
table: tableSelectorParam,
|
|
@@ -775,7 +777,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
775
777
|
|
|
776
778
|
server.registerTool('gog_docs_table_column_delete', {
|
|
777
779
|
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.',
|
|
778
|
-
annotations: { destructiveHint: true },
|
|
780
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
779
781
|
inputSchema: z.object({
|
|
780
782
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
781
783
|
col: z.number().int().describe('1-based column number; negative indexes count from the end'),
|
|
@@ -792,7 +794,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
792
794
|
|
|
793
795
|
server.registerTool('gog_docs_table_merge', {
|
|
794
796
|
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 — use gog_docs_table_unmerge to split back.',
|
|
795
|
-
annotations: { destructiveHint: true },
|
|
797
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
796
798
|
inputSchema: z.object({
|
|
797
799
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
798
800
|
range: z.string().describe('1-based cell range r1,c1:r2,c2 (e.g. "1,1:2,3")'),
|
|
@@ -809,7 +811,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
809
811
|
|
|
810
812
|
server.registerTool('gog_docs_table_unmerge', {
|
|
811
813
|
description: 'Unmerge (split) the merged region containing a given cell in a native Google Docs table.',
|
|
812
|
-
annotations: { destructiveHint: true },
|
|
814
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
813
815
|
inputSchema: z.object({
|
|
814
816
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
815
817
|
cell: z.string().describe('1-based cell r,c inside the merged region (e.g. "1,1")'),
|
|
@@ -826,7 +828,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
826
828
|
|
|
827
829
|
server.registerTool('gog_docs_named_range_create', {
|
|
828
830
|
description: 'Create a named range — 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.',
|
|
829
|
-
annotations: { destructiveHint: true },
|
|
831
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
830
832
|
inputSchema: z.object({
|
|
831
833
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
832
834
|
name: z.string().describe('Unique named range name'),
|
|
@@ -851,7 +853,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
851
853
|
|
|
852
854
|
server.registerTool('gog_docs_named_range_list', {
|
|
853
855
|
description: 'List named ranges in a Google Doc, optionally filtered by name.',
|
|
854
|
-
annotations: { readOnlyHint: true },
|
|
856
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
855
857
|
inputSchema: z.object({
|
|
856
858
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
857
859
|
name: z.string().optional().describe('Only return ranges with this name'),
|
|
@@ -867,7 +869,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
867
869
|
|
|
868
870
|
server.registerTool('gog_docs_named_range_delete', {
|
|
869
871
|
description: 'Delete a named range (the anchor only — the underlying document text is untouched).',
|
|
870
|
-
annotations: { destructiveHint: true },
|
|
872
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
871
873
|
inputSchema: z.object({
|
|
872
874
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
873
875
|
nameOrId: z.string().describe('Named range name or ID'),
|
|
@@ -882,7 +884,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
882
884
|
|
|
883
885
|
server.registerTool('gog_docs_named_range_replace', {
|
|
884
886
|
description: 'Replace the text inside a named range with new content (inline or from a file), keeping the anchor for future updates — the templated-update workhorse.',
|
|
885
|
-
annotations: { destructiveHint: true },
|
|
887
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
886
888
|
inputSchema: z.object({
|
|
887
889
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
888
890
|
nameOrId: z.string().describe('Named range name or ID'),
|
|
@@ -902,7 +904,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
902
904
|
|
|
903
905
|
server.registerTool('gog_docs_tables_list', {
|
|
904
906
|
description: 'Enumerate the native tables in a Google Doc (dimensions, position) — the index/first-cell-text it reports feeds the `table` selector on the table-row/column/merge tools.',
|
|
905
|
-
annotations: { readOnlyHint: true },
|
|
907
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
906
908
|
inputSchema: z.object({
|
|
907
909
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
908
910
|
tab: z.string().optional().describe('Tab title or ID (omit for default)'),
|
|
@@ -916,7 +918,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
916
918
|
|
|
917
919
|
server.registerTool('gog_docs_images_list', {
|
|
918
920
|
description: 'Enumerate inline/positioned images in a Google Doc.',
|
|
919
|
-
annotations: { readOnlyHint: true },
|
|
921
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
920
922
|
inputSchema: z.object({
|
|
921
923
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
922
924
|
tab: z.string().optional().describe('Tab title or ID (omit for default)'),
|
|
@@ -930,7 +932,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
930
932
|
|
|
931
933
|
server.registerTool('gog_docs_headings_list', {
|
|
932
934
|
description: 'Enumerate headings in a Google Doc (a lightweight outline view), optionally filtered to one heading level.',
|
|
933
|
-
annotations: { readOnlyHint: true },
|
|
935
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
934
936
|
inputSchema: z.object({
|
|
935
937
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
936
938
|
level: z.number().int().optional().describe('Only return this heading level (1-6)'),
|
|
@@ -946,7 +948,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
946
948
|
|
|
947
949
|
server.registerTool('gog_docs_paragraphs_list', {
|
|
948
950
|
description: 'Enumerate paragraphs in a Google Doc with emptiness, text-run ranges, styles, and links — richer than gog_docs_structure when you need per-run detail. Optionally filter to one named style.',
|
|
949
|
-
annotations: { readOnlyHint: true },
|
|
951
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
950
952
|
inputSchema: z.object({
|
|
951
953
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
952
954
|
style: z.string().optional().describe('Only return this named style (e.g. NORMAL_TEXT or HEADING_2)'),
|
|
@@ -962,7 +964,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
962
964
|
|
|
963
965
|
server.registerTool('gog_docs_insert_page_break', {
|
|
964
966
|
description: 'Insert a Google Docs page break via InsertPageBreakRequest — 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.',
|
|
965
|
-
annotations: { destructiveHint: true },
|
|
967
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
966
968
|
inputSchema: z.object({
|
|
967
969
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
968
970
|
index: z.number().int().optional().describe('Character index to insert at (1 = beginning). Omit or use atEnd for end-of-doc.'),
|
|
@@ -988,7 +990,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
988
990
|
|
|
989
991
|
server.registerTool('gog_docs_page_layout', {
|
|
990
992
|
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.',
|
|
991
|
-
annotations: { destructiveHint: true },
|
|
993
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
992
994
|
inputSchema: z.object({
|
|
993
995
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
994
996
|
layout: z.enum(['pageless', 'pages']).optional().describe('Page layout (default: pageless)'),
|
|
@@ -1016,7 +1018,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1016
1018
|
|
|
1017
1019
|
server.registerTool('gog_docs_insert_table', {
|
|
1018
1020
|
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.',
|
|
1019
|
-
annotations: { destructiveHint: true },
|
|
1021
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1020
1022
|
inputSchema: z.object({
|
|
1021
1023
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1022
1024
|
rows: z.number().int().min(1).describe('Number of rows (>=1)'),
|
|
@@ -1038,7 +1040,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1038
1040
|
|
|
1039
1041
|
server.registerTool('gog_docs_cell_update', {
|
|
1040
1042
|
description: 'Replace (or append to) the content of a single table cell, addressed by table / row / column — 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.',
|
|
1041
|
-
annotations: { destructiveHint: true },
|
|
1043
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1042
1044
|
inputSchema: z.object({
|
|
1043
1045
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1044
1046
|
row: z.number().int().describe('1-based row number'),
|
|
@@ -1078,7 +1080,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1078
1080
|
|
|
1079
1081
|
server.registerTool('gog_docs_cell_style', {
|
|
1080
1082
|
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.',
|
|
1081
|
-
annotations: { destructiveHint: true },
|
|
1083
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1082
1084
|
inputSchema: z.object({
|
|
1083
1085
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1084
1086
|
row: z.number().int().describe('0-based row number'),
|
|
@@ -1134,7 +1136,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1134
1136
|
|
|
1135
1137
|
server.registerTool('gog_docs_insert_image', {
|
|
1136
1138
|
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.',
|
|
1137
|
-
annotations: { destructiveHint: true },
|
|
1139
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1138
1140
|
inputSchema: z.object({
|
|
1139
1141
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1140
1142
|
file: z.string().optional().describe('Local PNG, JPEG, or GIF image to upload and insert (exactly one of file or url)'),
|
|
@@ -1170,7 +1172,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1170
1172
|
|
|
1171
1173
|
server.registerTool('gog_docs_insert_person', {
|
|
1172
1174
|
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.',
|
|
1173
|
-
annotations: { destructiveHint: true },
|
|
1175
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1174
1176
|
inputSchema: z.object({
|
|
1175
1177
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1176
1178
|
email: z.string().describe('Email address for the person chip'),
|
|
@@ -1197,7 +1199,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1197
1199
|
|
|
1198
1200
|
server.registerTool('gog_docs_insert_date_chip', {
|
|
1199
1201
|
description: 'Insert a native Google Docs date smart chip, at a character index or end-of-doc.',
|
|
1200
|
-
annotations: { destructiveHint: true },
|
|
1202
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1201
1203
|
inputSchema: z.object({
|
|
1202
1204
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1203
1205
|
date: z.string().optional().describe('Date to insert as YYYY-MM-DD (default: today)'),
|
|
@@ -1221,7 +1223,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1221
1223
|
|
|
1222
1224
|
server.registerTool('gog_docs_add_tab', {
|
|
1223
1225
|
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.',
|
|
1224
|
-
annotations: { destructiveHint: false },
|
|
1226
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
1225
1227
|
inputSchema: z.object({
|
|
1226
1228
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1227
1229
|
title: z.string().optional().describe('User-visible tab title'),
|
|
@@ -1241,7 +1243,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1241
1243
|
|
|
1242
1244
|
server.registerTool('gog_docs_rename_tab', {
|
|
1243
1245
|
description: 'Rename a tab in a Google Doc. Identify the existing tab by title or ID and give it a new title.',
|
|
1244
|
-
annotations: { destructiveHint: false },
|
|
1246
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
1245
1247
|
inputSchema: z.object({
|
|
1246
1248
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1247
1249
|
tab: z.string().describe('Existing tab title or ID to rename'),
|
|
@@ -1255,7 +1257,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1255
1257
|
|
|
1256
1258
|
server.registerTool('gog_docs_delete_tab', {
|
|
1257
1259
|
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.',
|
|
1258
|
-
annotations: { destructiveHint: true },
|
|
1260
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1259
1261
|
inputSchema: z.object({
|
|
1260
1262
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1261
1263
|
tab: z.string().describe('Existing tab title or ID to delete'),
|
|
@@ -1268,7 +1270,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1268
1270
|
|
|
1269
1271
|
server.registerTool('gog_docs_clear', {
|
|
1270
1272
|
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.',
|
|
1271
|
-
annotations: { destructiveHint: true },
|
|
1273
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1272
1274
|
inputSchema: z.object({
|
|
1273
1275
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1274
1276
|
account: accountParam,
|
|
@@ -1281,7 +1283,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1281
1283
|
|
|
1282
1284
|
server.registerTool('gog_docs_insert_footnote', {
|
|
1283
1285
|
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.',
|
|
1284
|
-
annotations: { destructiveHint: true },
|
|
1286
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1285
1287
|
inputSchema: z.object({
|
|
1286
1288
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1287
1289
|
text: z.string().optional().describe('Footnote text'),
|
|
@@ -1310,7 +1312,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1310
1312
|
|
|
1311
1313
|
server.registerTool('gog_docs_insert_section_break', {
|
|
1312
1314
|
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).',
|
|
1313
|
-
annotations: { destructiveHint: true },
|
|
1315
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1314
1316
|
inputSchema: z.object({
|
|
1315
1317
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1316
1318
|
type: z.enum(['next-page', 'continuous']).optional().describe('Section break type (default: next-page)'),
|
|
@@ -1338,7 +1340,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1338
1340
|
|
|
1339
1341
|
server.registerTool('gog_docs_insert_horizontal_rule', {
|
|
1340
1342
|
description: 'Insert a horizontal rule (paragraph border) at a character index (or end-of-doc).',
|
|
1341
|
-
annotations: { destructiveHint: true },
|
|
1343
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1342
1344
|
inputSchema: z.object({
|
|
1343
1345
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1344
1346
|
index: z.number().int().optional().describe('Character index to insert at (1 = beginning). Omit or use atEnd for end-of-doc.'),
|
|
@@ -1364,7 +1366,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1364
1366
|
|
|
1365
1367
|
server.registerTool('gog_docs_section_columns', {
|
|
1366
1368
|
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.',
|
|
1367
|
-
annotations: { destructiveHint: true },
|
|
1369
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1368
1370
|
inputSchema: z.object({
|
|
1369
1371
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1370
1372
|
count: z.number().int().min(1).max(3).describe('Number of columns (1-3; 1 resets to one column)'),
|
|
@@ -1396,7 +1398,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1396
1398
|
|
|
1397
1399
|
server.registerTool('gog_docs_header_list', {
|
|
1398
1400
|
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.',
|
|
1399
|
-
annotations: { readOnlyHint: true },
|
|
1401
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
1400
1402
|
inputSchema: z.object({
|
|
1401
1403
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1402
1404
|
tab: z.string().optional().describe('Limit results to a tab title or ID'),
|
|
@@ -1410,7 +1412,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1410
1412
|
|
|
1411
1413
|
server.registerTool('gog_docs_header_create', {
|
|
1412
1414
|
description: 'Create a header in a Google Doc and optionally populate its initial text. Returns the new header segment ID.',
|
|
1413
|
-
annotations: { destructiveHint: false },
|
|
1415
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
1414
1416
|
inputSchema: z.object({
|
|
1415
1417
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1416
1418
|
text: z.string().optional().describe('Initial header text'),
|
|
@@ -1439,7 +1441,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1439
1441
|
|
|
1440
1442
|
server.registerTool('gog_docs_header_delete', {
|
|
1441
1443
|
description: 'Delete a header from a Google Doc by its segment ID (from gog_docs_header_list).',
|
|
1442
|
-
annotations: { destructiveHint: true },
|
|
1444
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1443
1445
|
inputSchema: z.object({
|
|
1444
1446
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1445
1447
|
headerId: z.string().describe('Header segment ID (from gog_docs_header_list)'),
|
|
@@ -1455,7 +1457,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1455
1457
|
|
|
1456
1458
|
server.registerTool('gog_docs_footer_list', {
|
|
1457
1459
|
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.',
|
|
1458
|
-
annotations: { readOnlyHint: true },
|
|
1460
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
1459
1461
|
inputSchema: z.object({
|
|
1460
1462
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1461
1463
|
tab: z.string().optional().describe('Limit results to a tab title or ID'),
|
|
@@ -1469,7 +1471,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1469
1471
|
|
|
1470
1472
|
server.registerTool('gog_docs_footer_create', {
|
|
1471
1473
|
description: 'Create a footer in a Google Doc and optionally populate its initial text. Returns the new footer segment ID.',
|
|
1472
|
-
annotations: { destructiveHint: false },
|
|
1474
|
+
annotations: { destructiveHint: false, openWorldHint: true },
|
|
1473
1475
|
inputSchema: z.object({
|
|
1474
1476
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1475
1477
|
text: z.string().optional().describe('Initial footer text'),
|
|
@@ -1498,7 +1500,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1498
1500
|
|
|
1499
1501
|
server.registerTool('gog_docs_footer_delete', {
|
|
1500
1502
|
description: 'Delete a footer from a Google Doc by its segment ID (from gog_docs_footer_list).',
|
|
1501
|
-
annotations: { destructiveHint: true },
|
|
1503
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1502
1504
|
inputSchema: z.object({
|
|
1503
1505
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1504
1506
|
footerId: z.string().describe('Footer segment ID (from gog_docs_footer_list)'),
|
|
@@ -1516,7 +1518,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1516
1518
|
|
|
1517
1519
|
server.registerTool('gog_docs_replace_image', {
|
|
1518
1520
|
description: 'Replace an existing image in a Google Doc in place — keeping its position and bounds — 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.',
|
|
1519
|
-
annotations: { destructiveHint: true },
|
|
1521
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1520
1522
|
inputSchema: z.object({
|
|
1521
1523
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1522
1524
|
file: z.string().optional().describe('Local PNG, JPEG, or GIF image to upload and use (exactly one of file or url)'),
|
|
@@ -1544,7 +1546,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1544
1546
|
|
|
1545
1547
|
server.registerTool('gog_docs_table_row_pin_header', {
|
|
1546
1548
|
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.',
|
|
1547
|
-
annotations: { destructiveHint: true },
|
|
1549
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1548
1550
|
inputSchema: z.object({
|
|
1549
1551
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1550
1552
|
rows: z.number().int().min(0).describe('Number of leading rows to pin as headers; 0 unpins all header rows'),
|
|
@@ -1561,7 +1563,7 @@ export function registerExtraDocsTools(server: McpServer): void {
|
|
|
1561
1563
|
|
|
1562
1564
|
server.registerTool('gog_docs_table_row_style', {
|
|
1563
1565
|
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.',
|
|
1564
|
-
annotations: { destructiveHint: true },
|
|
1566
|
+
annotations: { destructiveHint: true, openWorldHint: true },
|
|
1565
1567
|
inputSchema: z.object({
|
|
1566
1568
|
docId: z.string().describe('Doc ID (from the URL)'),
|
|
1567
1569
|
row: z.number().int().optional().describe('1-based row number; negative indexes count from the end; omit to style all rows'),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { authToolsFor, registerDocsTools } from '../../gogcli-mcp/src/lib.js';
|
|
2
|
+
import { registerExtraDocsTools } from '../src/tools/docs-extra.js';
|
|
3
|
+
import { describeToolAnnotations, LOCAL_AUTH_TOOLS } from '../../gogcli-mcp/tests/support/tool-annotations.js';
|
|
4
|
+
|
|
5
|
+
// The same registrar list src/index.ts hands to runMcp.
|
|
6
|
+
describeToolAnnotations([authToolsFor('docs'), registerDocsTools, registerExtraDocsTools] as never, {
|
|
7
|
+
tools: 83,
|
|
8
|
+
destructive: 52,
|
|
9
|
+
local: [...LOCAL_AUTH_TOOLS, 'gog_batch_abort', 'gog_batch_begin', 'gog_batch_list', 'gog_batch_prune', 'gog_batch_show'],
|
|
10
|
+
});
|