Skip to content

Commit c2b4fe4

Browse files
authored
Merge pull request #75 from elijahr/elijahr/rename-tab
feat: add renameTab tool for renaming document tabs
2 parents bb2c961 + a922f9c commit c2b4fe4

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/tools/docs/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { FastMCP } from 'fastmcp';
33
// Core read/write
44
import { register as readGoogleDoc } from './readGoogleDoc.js';
55
import { register as listDocumentTabs } from './listDocumentTabs.js';
6+
import { register as renameTab } from './renameTab.js';
67
import { register as appendToGoogleDoc } from './appendToGoogleDoc.js';
78
import { register as insertText } from './insertText.js';
89
import { register as deleteRange } from './deleteRange.js';
@@ -21,6 +22,7 @@ export function registerDocsTools(server: FastMCP) {
2122
// Core read/write
2223
readGoogleDoc(server);
2324
listDocumentTabs(server);
25+
renameTab(server);
2426
appendToGoogleDoc(server);
2527
insertText(server);
2628
deleteRange(server);

src/tools/docs/renameTab.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { FastMCP } from 'fastmcp';
2+
import { UserError } from 'fastmcp';
3+
import { z } from 'zod';
4+
import { getDocsClient } from '../../clients.js';
5+
import { DocumentIdParameter } from '../../types.js';
6+
import * as GDocsHelpers from '../../googleDocsApiHelpers.js';
7+
8+
export function register(server: FastMCP) {
9+
server.addTool({
10+
name: 'renameTab',
11+
description:
12+
'Renames a tab in a Google Docs document. Use listDocumentTabs to get tab IDs first.',
13+
parameters: DocumentIdParameter.extend({
14+
tabId: z
15+
.string()
16+
.describe('The ID of the tab to rename. Use listDocumentTabs to get tab IDs.'),
17+
newTitle: z.string().min(1).describe('The new title for the tab.'),
18+
}),
19+
execute: async (args, { log }) => {
20+
const docs = await getDocsClient();
21+
22+
log.info(`Renaming tab ${args.tabId} to "${args.newTitle}" in doc ${args.documentId}`);
23+
24+
try {
25+
// Verify the tab exists
26+
const docInfo = await docs.documents.get({
27+
documentId: args.documentId,
28+
includeTabsContent: true,
29+
fields: 'tabs(tabProperties,documentTab)',
30+
});
31+
const targetTab = GDocsHelpers.findTabById(docInfo.data, args.tabId);
32+
if (!targetTab) {
33+
throw new UserError(`Tab with ID "${args.tabId}" not found in document.`);
34+
}
35+
36+
const oldTitle = targetTab.tabProperties?.title || '(untitled)';
37+
38+
await docs.documents.batchUpdate({
39+
documentId: args.documentId,
40+
requestBody: {
41+
requests: [
42+
{
43+
updateDocumentTabProperties: {
44+
tabProperties: {
45+
tabId: args.tabId,
46+
title: args.newTitle,
47+
},
48+
fields: 'title',
49+
},
50+
},
51+
],
52+
},
53+
});
54+
55+
return `Successfully renamed tab from "${oldTitle}" to "${args.newTitle}".`;
56+
} catch (error: any) {
57+
log.error(
58+
`Error renaming tab ${args.tabId} in doc ${args.documentId}: ${error.message || error}`
59+
);
60+
if (error instanceof UserError) throw error;
61+
if (error.code === 404) throw new UserError(`Document not found (ID: ${args.documentId}).`);
62+
if (error.code === 403)
63+
throw new UserError(`Permission denied for document (ID: ${args.documentId}).`);
64+
throw new UserError(`Failed to rename tab: ${error.message || 'Unknown error'}`);
65+
}
66+
},
67+
});
68+
}

0 commit comments

Comments
 (0)