google-tools-mcp 1.2.12 → 2.0.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.
Files changed (97) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +537 -276
  3. package/dist/cachedToolsList.js +52 -52
  4. package/dist/googleDocsApiHelpers.js +76 -12
  5. package/dist/helpers.js +572 -252
  6. package/dist/httpAuth.js +296 -0
  7. package/dist/index.js +162 -11
  8. package/dist/logger.js +87 -87
  9. package/dist/markdown-transformer/docsToMarkdown.js +128 -0
  10. package/dist/markdown-transformer/index.js +17 -7
  11. package/dist/markdown-transformer/markdownToDocs.js +185 -27
  12. package/dist/readTracker.js +136 -17
  13. package/dist/sessionContext.js +37 -0
  14. package/dist/setup.js +187 -9
  15. package/dist/tools/calendar/getBusy.js +64 -64
  16. package/dist/tools/calendar/getEvents.js +141 -141
  17. package/dist/tools/calendar/getFree.js +225 -225
  18. package/dist/tools/calendar/index.js +19 -19
  19. package/dist/tools/calendar/listCalendars.js +38 -38
  20. package/dist/tools/calendar/listRecurringInstances.js +83 -83
  21. package/dist/tools/calendar/manageCalendar.js +121 -121
  22. package/dist/tools/calendar/manageEvent.js +258 -258
  23. package/dist/tools/calendar/moveEvent.js +66 -66
  24. package/dist/tools/docs/addTab.js +10 -12
  25. package/dist/tools/docs/appendToGoogleDoc.js +9 -4
  26. package/dist/tools/docs/deleteRange.js +9 -4
  27. package/dist/tools/docs/findAndReplace.js +9 -4
  28. package/dist/tools/docs/formatting/applyParagraphStyle.js +4 -1
  29. package/dist/tools/docs/formatting/getFormatting.js +171 -171
  30. package/dist/tools/docs/insertImage.js +15 -2
  31. package/dist/tools/docs/insertPageBreak.js +4 -1
  32. package/dist/tools/docs/insertTable.js +4 -1
  33. package/dist/tools/docs/insertTableWithData.js +4 -1
  34. package/dist/tools/docs/modifyText.js +14 -4
  35. package/dist/tools/docs/modifyText.test.js +84 -84
  36. package/dist/tools/docs/readGoogleDoc.js +71 -11
  37. package/dist/tools/docs/renameTab.js +12 -14
  38. package/dist/tools/drafts.js +165 -165
  39. package/dist/tools/drive/createDocument.js +12 -0
  40. package/dist/tools/drive/downloadFile.js +268 -268
  41. package/dist/tools/drive/getFileInfo.js +48 -48
  42. package/dist/tools/drive/getFilePath.js +50 -50
  43. package/dist/tools/drive/listDriveFiles.js +112 -112
  44. package/dist/tools/drive/listSharedDrives.js +52 -52
  45. package/dist/tools/drive/listSharedWithMe.js +97 -97
  46. package/dist/tools/drive/uploadFile.js +111 -111
  47. package/dist/tools/extras/index.js +9 -9
  48. package/dist/tools/extras/readDriveFile.js +197 -196
  49. package/dist/tools/extras/readFile.js +84 -84
  50. package/dist/tools/extras/searchFileContents.js +81 -81
  51. package/dist/tools/forms/batchUpdateForm.js +81 -81
  52. package/dist/tools/forms/createForm.js +54 -54
  53. package/dist/tools/forms/getForm.js +118 -118
  54. package/dist/tools/forms/getFormResponse.js +45 -45
  55. package/dist/tools/forms/index.js +15 -15
  56. package/dist/tools/forms/listFormResponses.js +56 -56
  57. package/dist/tools/forms/setPublishSettings.js +59 -59
  58. package/dist/tools/gmail/drafts.js +165 -165
  59. package/dist/tools/gmail/labels.js +54 -83
  60. package/dist/tools/gmail/messages.js +444 -441
  61. package/dist/tools/gmail/settings.js +358 -528
  62. package/dist/tools/gmail/threads.js +286 -164
  63. package/dist/tools/index.js +511 -473
  64. package/dist/tools/labels.js +103 -103
  65. package/dist/tools/legacyAliases.js +426 -0
  66. package/dist/tools/maps/directions.js +72 -0
  67. package/dist/tools/maps/geocode.js +16 -0
  68. package/dist/tools/maps/index.js +15 -0
  69. package/dist/tools/maps/mapsClient.js +83 -0
  70. package/dist/tools/maps/placeDetails.js +16 -0
  71. package/dist/tools/maps/reverseGeocode.js +19 -0
  72. package/dist/tools/maps/searchNearby.js +54 -0
  73. package/dist/tools/maps/searchPlaces.js +24 -0
  74. package/dist/tools/messages.js +448 -448
  75. package/dist/tools/settings.js +528 -528
  76. package/dist/tools/slides/createPresentation.js +104 -104
  77. package/dist/tools/slides/createShape.js +92 -92
  78. package/dist/tools/slides/createTextBox.js +82 -82
  79. package/dist/tools/slides/deleteSlide.js +30 -30
  80. package/dist/tools/slides/duplicateSlide.js +37 -37
  81. package/dist/tools/slides/exportThumbnail.js +42 -42
  82. package/dist/tools/slides/formatParagraph.js +72 -72
  83. package/dist/tools/slides/formatText.js +84 -84
  84. package/dist/tools/slides/getPresentation.js +87 -87
  85. package/dist/tools/slides/index.js +33 -33
  86. package/dist/tools/slides/reorderSlides.js +41 -41
  87. package/dist/tools/slides/replaceAllText.js +46 -46
  88. package/dist/tools/slides/setBackground.js +58 -58
  89. package/dist/tools/slides/speakerNotes.js +102 -102
  90. package/dist/tools/slides/styleShape.js +111 -111
  91. package/dist/tools/slides/updatePresentation.js +128 -128
  92. package/dist/tools/threads.js +145 -145
  93. package/dist/tools/utils/appendMarkdownToGoogleDoc.js +30 -6
  94. package/dist/tools/utils/replaceDocumentWithMarkdown.js +71 -8
  95. package/dist/updateCheck.js +202 -0
  96. package/dist/workspace.js +122 -0
  97. package/package.json +82 -81
@@ -1,103 +1,103 @@
1
- // Gmail Label tools
2
- import { z } from 'zod';
3
- import { getGmailClient } from '../clients.js';
4
-
5
- export function register(server) {
6
- server.addTool({
7
- name: 'create_label',
8
- description: 'Create a new label',
9
- parameters: z.object({
10
- name: z.string().describe("The display name of the label"),
11
- messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label in the message list"),
12
- labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
13
- color: z.object({
14
- textColor: z.string().describe("The text color as hex string"),
15
- backgroundColor: z.string().describe("The background color as hex string"),
16
- }).optional().describe("The color settings for the label"),
17
- }),
18
- execute: async (params) => {
19
- const gmail = await getGmailClient();
20
- const { data } = await gmail.users.labels.create({ userId: 'me', requestBody: params });
21
- return JSON.stringify(data);
22
- },
23
- });
24
-
25
- server.addTool({
26
- name: 'delete_label',
27
- description: 'Delete a label',
28
- parameters: z.object({
29
- id: z.string().describe("The ID of the label to delete"),
30
- }),
31
- execute: async (params) => {
32
- const gmail = await getGmailClient();
33
- const { data } = await gmail.users.labels.delete({ userId: 'me', id: params.id });
34
- return JSON.stringify(data || { success: true });
35
- },
36
- });
37
-
38
- server.addTool({
39
- name: 'get_label',
40
- description: 'Get a specific label by ID',
41
- parameters: z.object({
42
- id: z.string().describe("The ID of the label to retrieve"),
43
- }),
44
- execute: async (params) => {
45
- const gmail = await getGmailClient();
46
- const { data } = await gmail.users.labels.get({ userId: 'me', id: params.id });
47
- return JSON.stringify(data);
48
- },
49
- });
50
-
51
- server.addTool({
52
- name: 'list_labels',
53
- description: 'List all labels in the user\'s mailbox',
54
- parameters: z.object({}),
55
- execute: async () => {
56
- const gmail = await getGmailClient();
57
- const { data } = await gmail.users.labels.list({ userId: 'me' });
58
- return JSON.stringify(data);
59
- },
60
- });
61
-
62
- server.addTool({
63
- name: 'patch_label',
64
- description: 'Patch an existing label (partial update)',
65
- parameters: z.object({
66
- id: z.string().describe("The ID of the label to patch"),
67
- name: z.string().optional().describe("The display name of the label"),
68
- messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label"),
69
- labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
70
- color: z.object({
71
- textColor: z.string().describe("The text color as hex string"),
72
- backgroundColor: z.string().describe("The background color as hex string"),
73
- }).optional().describe("The color settings for the label"),
74
- }),
75
- execute: async (params) => {
76
- const { id, ...labelData } = params;
77
- const gmail = await getGmailClient();
78
- const { data } = await gmail.users.labels.patch({ userId: 'me', id, requestBody: labelData });
79
- return JSON.stringify(data);
80
- },
81
- });
82
-
83
- server.addTool({
84
- name: 'update_label',
85
- description: 'Update an existing label',
86
- parameters: z.object({
87
- id: z.string().describe("The ID of the label to update"),
88
- name: z.string().optional().describe("The display name of the label"),
89
- messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label"),
90
- labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
91
- color: z.object({
92
- textColor: z.string().describe("The text color as hex string"),
93
- backgroundColor: z.string().describe("The background color as hex string"),
94
- }).optional().describe("The color settings for the label"),
95
- }),
96
- execute: async (params) => {
97
- const { id, ...labelData } = params;
98
- const gmail = await getGmailClient();
99
- const { data } = await gmail.users.labels.update({ userId: 'me', id, requestBody: labelData });
100
- return JSON.stringify(data);
101
- },
102
- });
103
- }
1
+ // Gmail Label tools
2
+ import { z } from 'zod';
3
+ import { getGmailClient } from '../clients.js';
4
+
5
+ export function register(server) {
6
+ server.addTool({
7
+ name: 'create_label',
8
+ description: 'Create a new label',
9
+ parameters: z.object({
10
+ name: z.string().describe("The display name of the label"),
11
+ messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label in the message list"),
12
+ labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
13
+ color: z.object({
14
+ textColor: z.string().describe("The text color as hex string"),
15
+ backgroundColor: z.string().describe("The background color as hex string"),
16
+ }).optional().describe("The color settings for the label"),
17
+ }),
18
+ execute: async (params) => {
19
+ const gmail = await getGmailClient();
20
+ const { data } = await gmail.users.labels.create({ userId: 'me', requestBody: params });
21
+ return JSON.stringify(data);
22
+ },
23
+ });
24
+
25
+ server.addTool({
26
+ name: 'delete_label',
27
+ description: 'Delete a label',
28
+ parameters: z.object({
29
+ id: z.string().describe("The ID of the label to delete"),
30
+ }),
31
+ execute: async (params) => {
32
+ const gmail = await getGmailClient();
33
+ const { data } = await gmail.users.labels.delete({ userId: 'me', id: params.id });
34
+ return JSON.stringify(data || { success: true });
35
+ },
36
+ });
37
+
38
+ server.addTool({
39
+ name: 'get_label',
40
+ description: 'Get a specific label by ID',
41
+ parameters: z.object({
42
+ id: z.string().describe("The ID of the label to retrieve"),
43
+ }),
44
+ execute: async (params) => {
45
+ const gmail = await getGmailClient();
46
+ const { data } = await gmail.users.labels.get({ userId: 'me', id: params.id });
47
+ return JSON.stringify(data);
48
+ },
49
+ });
50
+
51
+ server.addTool({
52
+ name: 'list_labels',
53
+ description: 'List all labels in the user\'s mailbox',
54
+ parameters: z.object({}),
55
+ execute: async () => {
56
+ const gmail = await getGmailClient();
57
+ const { data } = await gmail.users.labels.list({ userId: 'me' });
58
+ return JSON.stringify(data);
59
+ },
60
+ });
61
+
62
+ server.addTool({
63
+ name: 'patch_label',
64
+ description: 'Patch an existing label (partial update)',
65
+ parameters: z.object({
66
+ id: z.string().describe("The ID of the label to patch"),
67
+ name: z.string().optional().describe("The display name of the label"),
68
+ messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label"),
69
+ labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
70
+ color: z.object({
71
+ textColor: z.string().describe("The text color as hex string"),
72
+ backgroundColor: z.string().describe("The background color as hex string"),
73
+ }).optional().describe("The color settings for the label"),
74
+ }),
75
+ execute: async (params) => {
76
+ const { id, ...labelData } = params;
77
+ const gmail = await getGmailClient();
78
+ const { data } = await gmail.users.labels.patch({ userId: 'me', id, requestBody: labelData });
79
+ return JSON.stringify(data);
80
+ },
81
+ });
82
+
83
+ server.addTool({
84
+ name: 'update_label',
85
+ description: 'Update an existing label',
86
+ parameters: z.object({
87
+ id: z.string().describe("The ID of the label to update"),
88
+ name: z.string().optional().describe("The display name of the label"),
89
+ messageListVisibility: z.enum(['show', 'hide']).optional().describe("Visibility of messages with this label"),
90
+ labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"),
91
+ color: z.object({
92
+ textColor: z.string().describe("The text color as hex string"),
93
+ backgroundColor: z.string().describe("The background color as hex string"),
94
+ }).optional().describe("The color settings for the label"),
95
+ }),
96
+ execute: async (params) => {
97
+ const { id, ...labelData } = params;
98
+ const gmail = await getGmailClient();
99
+ const { data } = await gmail.users.labels.update({ userId: 'me', id, requestBody: labelData });
100
+ return JSON.stringify(data);
101
+ },
102
+ });
103
+ }
@@ -0,0 +1,426 @@
1
+ // Legacy alias layer (issue #31/#32/#33).
2
+ //
3
+ // Registers the pre-consolidation snake_case tool names as thin, working aliases
4
+ // so existing agents/configs can still call them after the camelCase + dispatch
5
+ // reshape. Each alias forwards to its new implementation:
6
+ // - Pure renames (e.g. list_messages -> listMessages) forward unchanged.
7
+ // - Consolidated tools (e.g. get_imap -> manageGmailSettings resource=imap
8
+ // action=get) wrap the old parameters into the new dispatch shape.
9
+ //
10
+ // Opt-in, OFF by default: the entire point of issues #31/#33 is shrinking the
11
+ // tool surface loaded into every turn. Registering these 72 aliases by default
12
+ // would add them back on top of the new camelCase + dispatch tools, growing the
13
+ // default surface instead of shrinking it. Set
14
+ // GOOGLE_MCP_ENABLE_LEGACY_ALIASES=true to register them for callers that still
15
+ // depend on the old snake_case names.
16
+ import { z } from 'zod';
17
+ import { logger } from '../logger.js';
18
+
19
+ export const ENABLE_LEGACY_ALIASES_ENV = 'GOOGLE_MCP_ENABLE_LEGACY_ALIASES';
20
+
21
+ export function legacyAliasesEnabled() {
22
+ return process.env[ENABLE_LEGACY_ALIASES_ENV] === 'true';
23
+ }
24
+
25
+ // ---------------------------------------------------------------------------
26
+ // Pure renames: old snake_case name -> new camelCase name.
27
+ // These aliases reuse the target tool's parameters and execute verbatim.
28
+ // ---------------------------------------------------------------------------
29
+ export const PURE_RENAMES = {
30
+ // Gmail messages
31
+ send_message: 'sendMessage',
32
+ reply_message: 'replyMessage',
33
+ forward_message: 'forwardMessage',
34
+ get_message: 'getMessage',
35
+ list_messages: 'listMessages',
36
+ modify_message: 'modifyMessage',
37
+ delete_message: 'deleteMessage',
38
+ trash_message: 'trashMessage',
39
+ batch_get_messages: 'batchGetMessages',
40
+ get_attachment: 'getAttachment',
41
+ // Gmail drafts
42
+ create_draft: 'createDraft',
43
+ update_draft: 'updateDraft',
44
+ delete_draft: 'deleteDraft',
45
+ get_draft: 'getDraft',
46
+ list_drafts: 'listDrafts',
47
+ send_draft: 'sendDraft',
48
+ // Gmail threads
49
+ get_thread: 'getThread',
50
+ list_threads: 'listThreads',
51
+ batch_get_threads: 'batchGetThreads',
52
+ modify_thread: 'modifyThread',
53
+ delete_thread: 'deleteThread',
54
+ trash_thread: 'trashThread',
55
+ // Gmail profile & watch
56
+ get_profile: 'getProfile',
57
+ watch_mailbox: 'watchMailbox',
58
+ stop_mail_watch: 'stopMailWatch',
59
+ // Calendar
60
+ list_calendars: 'listCalendars',
61
+ get_events: 'getEvents',
62
+ manage_event: 'manageEvent',
63
+ get_busy: 'getBusy',
64
+ get_free: 'getFree',
65
+ move_event: 'moveEvent',
66
+ list_recurring_event_instances: 'listRecurringEventInstances',
67
+ manage_calendar: 'manageCalendar',
68
+ };
69
+
70
+ // ---------------------------------------------------------------------------
71
+ // Reusable zod pieces for consolidated-alias parameters (preserve the original
72
+ // granular schemas so deprecated callers keep their typed inputs).
73
+ // ---------------------------------------------------------------------------
74
+ const empty = z.object({});
75
+ const sendAsBody = z.object({
76
+ sendAsEmail: z.string().describe("Email address for the 'From:' header"),
77
+ displayName: z.string().optional().describe("Name for the 'From:' header"),
78
+ replyToAddress: z.string().optional().describe("Email for 'Reply-To:' header"),
79
+ signature: z.string().optional().describe('Optional HTML signature'),
80
+ isPrimary: z.boolean().optional().describe('Whether this is the primary address'),
81
+ treatAsAlias: z.boolean().optional().describe('Whether Gmail treats this as an alias'),
82
+ });
83
+ const labelBody = {
84
+ name: z.string().describe('The display name of the label'),
85
+ messageListVisibility: z.enum(['show', 'hide']).optional().describe('Visibility of messages with this label in the message list'),
86
+ labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe('Visibility of the label in the label list'),
87
+ color: z.object({
88
+ textColor: z.string().describe('The text color as hex string'),
89
+ backgroundColor: z.string().describe('The background color as hex string'),
90
+ }).optional().describe('The color settings for the label'),
91
+ };
92
+ const filterCriteria = z.object({
93
+ from: z.string().optional(),
94
+ to: z.string().optional(),
95
+ subject: z.string().optional(),
96
+ query: z.string().optional(),
97
+ negatedQuery: z.string().optional(),
98
+ hasAttachment: z.boolean().optional(),
99
+ excludeChats: z.boolean().optional(),
100
+ size: z.number().optional(),
101
+ sizeComparison: z.enum(['smaller', 'larger']).optional(),
102
+ }).describe('Filter criteria');
103
+ const filterActionObj = z.object({
104
+ addLabelIds: z.array(z.string()).optional(),
105
+ removeLabelIds: z.array(z.string()).optional(),
106
+ forward: z.string().optional(),
107
+ }).describe('Actions on matching messages');
108
+
109
+ // ---------------------------------------------------------------------------
110
+ // Consolidated aliases: old name -> { target dispatch tool, original schema,
111
+ // description, and a mapParams that reshapes old args into the dispatch shape }.
112
+ // ---------------------------------------------------------------------------
113
+ const settingGet = (resource) => ({
114
+ target: 'manageGmailSettings',
115
+ parameters: empty,
116
+ mapParams: () => ({ resource, action: 'get' }),
117
+ });
118
+ const settingUpdate = (resource, parameters) => ({
119
+ target: 'manageGmailSettings',
120
+ parameters,
121
+ mapParams: (args) => ({ resource, action: 'update', payload: args }),
122
+ });
123
+
124
+ export const CONSOLIDATED_ALIASES = {
125
+ // --- Core settings -> manageGmailSettings ---
126
+ get_auto_forwarding: { ...settingGet('autoForwarding'), description: 'Gets auto-forwarding settings' },
127
+ update_auto_forwarding: {
128
+ ...settingUpdate('autoForwarding', z.object({
129
+ enabled: z.boolean().describe('Whether all incoming mail is automatically forwarded'),
130
+ emailAddress: z.string().describe('Email address to forward to'),
131
+ disposition: z.enum(['leaveInInbox', 'archive', 'trash', 'markRead']).describe('What to do with forwarded messages'),
132
+ })),
133
+ description: 'Updates automatic forwarding settings',
134
+ },
135
+ get_imap: { ...settingGet('imap'), description: 'Gets IMAP settings' },
136
+ update_imap: {
137
+ ...settingUpdate('imap', z.object({
138
+ enabled: z.boolean().describe('Whether IMAP is enabled'),
139
+ expungeBehavior: z.enum(['archive', 'trash', 'deleteForever']).optional().describe('Action on deleted+expunged messages'),
140
+ maxFolderSize: z.number().optional().describe('Max messages accessible through IMAP'),
141
+ })),
142
+ description: 'Updates IMAP settings',
143
+ },
144
+ get_language: { ...settingGet('language'), description: 'Gets language settings' },
145
+ update_language: {
146
+ ...settingUpdate('language', z.object({
147
+ displayLanguage: z.string().describe('Language to display Gmail in (RFC 3066 Language Tag)'),
148
+ })),
149
+ description: 'Updates language settings',
150
+ },
151
+ get_pop: { ...settingGet('pop'), description: 'Gets POP settings' },
152
+ update_pop: {
153
+ ...settingUpdate('pop', z.object({
154
+ accessWindow: z.enum(['disabled', 'allMail', 'fromNowOn']).describe('Range of messages accessible via POP'),
155
+ disposition: z.enum(['archive', 'trash', 'leaveInInbox']).describe('Action after POP fetch'),
156
+ })),
157
+ description: 'Updates POP settings',
158
+ },
159
+ get_vacation: { ...settingGet('vacation'), description: 'Get vacation responder settings' },
160
+ update_vacation: {
161
+ ...settingUpdate('vacation', z.object({
162
+ enableAutoReply: z.boolean().describe('Whether the vacation responder is enabled'),
163
+ responseSubject: z.string().optional().describe('Subject line for auto-reply'),
164
+ responseBodyPlainText: z.string().describe('Response body in plain text'),
165
+ restrictToContacts: z.boolean().optional().describe('Only send to contacts'),
166
+ restrictToDomain: z.boolean().optional().describe('Only send to same domain'),
167
+ startTime: z.string().optional().describe('Start time (epoch ms)'),
168
+ endTime: z.string().optional().describe('End time (epoch ms)'),
169
+ })),
170
+ description: 'Update vacation responder settings',
171
+ },
172
+
173
+ // --- Delegates -> manageGmailSettings resource=delegate ---
174
+ add_delegate: {
175
+ target: 'manageGmailSettings',
176
+ parameters: z.object({ delegateEmail: z.string().describe('Email address of delegate to add') }),
177
+ mapParams: (a) => ({ resource: 'delegate', action: 'create', payload: { delegateEmail: a.delegateEmail } }),
178
+ description: 'Adds a delegate to the specified account',
179
+ },
180
+ remove_delegate: {
181
+ target: 'manageGmailSettings',
182
+ parameters: z.object({ delegateEmail: z.string().describe('Email address of delegate to remove') }),
183
+ mapParams: (a) => ({ resource: 'delegate', action: 'delete', payload: { delegateEmail: a.delegateEmail } }),
184
+ description: 'Removes the specified delegate',
185
+ },
186
+ get_delegate: {
187
+ target: 'manageGmailSettings',
188
+ parameters: z.object({ delegateEmail: z.string().describe('The email address of the delegate') }),
189
+ mapParams: (a) => ({ resource: 'delegate', action: 'get', payload: { delegateEmail: a.delegateEmail } }),
190
+ description: 'Gets the specified delegate',
191
+ },
192
+ list_delegates: {
193
+ target: 'manageGmailSettings',
194
+ parameters: empty,
195
+ mapParams: () => ({ resource: 'delegate', action: 'list' }),
196
+ description: 'Lists the delegates for the specified account',
197
+ },
198
+
199
+ // --- Forwarding addresses -> manageGmailSettings resource=forwardingAddress ---
200
+ create_forwarding_address: {
201
+ target: 'manageGmailSettings',
202
+ parameters: z.object({ forwardingEmail: z.string().describe('An email address to forward messages to') }),
203
+ mapParams: (a) => ({ resource: 'forwardingAddress', action: 'create', payload: { forwardingEmail: a.forwardingEmail } }),
204
+ description: 'Creates a forwarding address',
205
+ },
206
+ delete_forwarding_address: {
207
+ target: 'manageGmailSettings',
208
+ parameters: z.object({ forwardingEmail: z.string().describe('The forwarding address to delete') }),
209
+ mapParams: (a) => ({ resource: 'forwardingAddress', action: 'delete', payload: { forwardingEmail: a.forwardingEmail } }),
210
+ description: 'Deletes the specified forwarding address',
211
+ },
212
+ get_forwarding_address: {
213
+ target: 'manageGmailSettings',
214
+ parameters: z.object({ forwardingEmail: z.string().describe('The forwarding address to retrieve') }),
215
+ mapParams: (a) => ({ resource: 'forwardingAddress', action: 'get', payload: { forwardingEmail: a.forwardingEmail } }),
216
+ description: 'Gets the specified forwarding address',
217
+ },
218
+ list_forwarding_addresses: {
219
+ target: 'manageGmailSettings',
220
+ parameters: empty,
221
+ mapParams: () => ({ resource: 'forwardingAddress', action: 'list' }),
222
+ description: 'Lists the forwarding addresses for the specified account',
223
+ },
224
+
225
+ // --- Send-as -> manageGmailSettings resource=sendAs ---
226
+ create_send_as: {
227
+ target: 'manageGmailSettings',
228
+ parameters: sendAsBody,
229
+ mapParams: (a) => ({ resource: 'sendAs', action: 'create', payload: a }),
230
+ description: 'Creates a custom send-as alias',
231
+ },
232
+ delete_send_as: {
233
+ target: 'manageGmailSettings',
234
+ parameters: z.object({ sendAsEmail: z.string().describe('The send-as alias to delete') }),
235
+ mapParams: (a) => ({ resource: 'sendAs', action: 'delete', payload: { sendAsEmail: a.sendAsEmail } }),
236
+ description: 'Deletes the specified send-as alias',
237
+ },
238
+ get_send_as: {
239
+ target: 'manageGmailSettings',
240
+ parameters: z.object({ sendAsEmail: z.string().describe('The send-as alias to retrieve') }),
241
+ mapParams: (a) => ({ resource: 'sendAs', action: 'get', payload: { sendAsEmail: a.sendAsEmail } }),
242
+ description: 'Gets the specified send-as alias',
243
+ },
244
+ list_send_as: {
245
+ target: 'manageGmailSettings',
246
+ parameters: empty,
247
+ mapParams: () => ({ resource: 'sendAs', action: 'list' }),
248
+ description: 'Lists the send-as aliases for the specified account',
249
+ },
250
+ patch_send_as: {
251
+ target: 'manageGmailSettings',
252
+ parameters: sendAsBody,
253
+ mapParams: (a) => ({ resource: 'sendAs', action: 'patch', payload: a }),
254
+ description: 'Patches the specified send-as alias',
255
+ },
256
+ update_send_as: {
257
+ target: 'manageGmailSettings',
258
+ parameters: sendAsBody,
259
+ mapParams: (a) => ({ resource: 'sendAs', action: 'update', payload: a }),
260
+ description: 'Updates a send-as alias',
261
+ },
262
+ verify_send_as: {
263
+ target: 'manageGmailSettings',
264
+ parameters: z.object({ sendAsEmail: z.string().describe('The send-as alias to verify') }),
265
+ mapParams: (a) => ({ resource: 'sendAs', action: 'verify', payload: { sendAsEmail: a.sendAsEmail } }),
266
+ description: 'Sends a verification email to the specified send-as alias',
267
+ },
268
+
269
+ // --- S/MIME -> manageSmime ---
270
+ delete_smime_info: {
271
+ target: 'manageSmime',
272
+ parameters: z.object({
273
+ sendAsEmail: z.string().describe("The email address in the 'From:' header"),
274
+ id: z.string().describe('The S/MIME config ID'),
275
+ }),
276
+ mapParams: (a) => ({ action: 'delete', sendAsEmail: a.sendAsEmail, id: a.id }),
277
+ description: 'Deletes the specified S/MIME config for a send-as alias',
278
+ },
279
+ get_smime_info: {
280
+ target: 'manageSmime',
281
+ parameters: z.object({
282
+ sendAsEmail: z.string().describe("The email address in the 'From:' header"),
283
+ id: z.string().describe('The S/MIME config ID'),
284
+ }),
285
+ mapParams: (a) => ({ action: 'get', sendAsEmail: a.sendAsEmail, id: a.id }),
286
+ description: 'Gets the specified S/MIME config for a send-as alias',
287
+ },
288
+ insert_smime_info: {
289
+ target: 'manageSmime',
290
+ parameters: z.object({
291
+ sendAsEmail: z.string().describe("The email address in the 'From:' header"),
292
+ encryptedKeyPassword: z.string().describe('Encrypted key password'),
293
+ pkcs12: z.string().describe('PKCS#12 format key pair and certificate chain'),
294
+ }),
295
+ mapParams: (a) => ({ action: 'insert', sendAsEmail: a.sendAsEmail, encryptedKeyPassword: a.encryptedKeyPassword, pkcs12: a.pkcs12 }),
296
+ description: 'Insert (upload) S/MIME config for a send-as alias',
297
+ },
298
+ list_smime_info: {
299
+ target: 'manageSmime',
300
+ parameters: z.object({ sendAsEmail: z.string().describe("The email address in the 'From:' header") }),
301
+ mapParams: (a) => ({ action: 'list', sendAsEmail: a.sendAsEmail }),
302
+ description: 'Lists S/MIME configs for a send-as alias',
303
+ },
304
+ set_default_smime_info: {
305
+ target: 'manageSmime',
306
+ parameters: z.object({
307
+ sendAsEmail: z.string().describe("The email address in the 'From:' header"),
308
+ id: z.string().describe('The S/MIME config ID'),
309
+ }),
310
+ mapParams: (a) => ({ action: 'setDefault', sendAsEmail: a.sendAsEmail, id: a.id }),
311
+ description: 'Sets the default S/MIME config for a send-as alias',
312
+ },
313
+
314
+ // --- Filters -> manageFilter ---
315
+ create_filter: {
316
+ target: 'manageFilter',
317
+ parameters: z.object({ criteria: filterCriteria, action: filterActionObj }),
318
+ mapParams: (a) => ({ action: 'create', criteria: a.criteria, filterAction: a.action }),
319
+ description: 'Creates a filter',
320
+ },
321
+ delete_filter: {
322
+ target: 'manageFilter',
323
+ parameters: z.object({ id: z.string().describe('The ID of the filter to delete') }),
324
+ mapParams: (a) => ({ action: 'delete', id: a.id }),
325
+ description: 'Deletes a filter',
326
+ },
327
+ get_filter: {
328
+ target: 'manageFilter',
329
+ parameters: z.object({ id: z.string().describe('The ID of the filter to retrieve') }),
330
+ mapParams: (a) => ({ action: 'get', id: a.id }),
331
+ description: 'Gets a filter',
332
+ },
333
+ list_filters: {
334
+ target: 'manageFilter',
335
+ parameters: empty,
336
+ mapParams: () => ({ action: 'list' }),
337
+ description: 'Lists the message filters of a Gmail user',
338
+ },
339
+
340
+ // --- Labels -> manageLabel ---
341
+ create_label: {
342
+ target: 'manageLabel',
343
+ parameters: z.object(labelBody),
344
+ mapParams: (a) => ({ action: 'create', ...a }),
345
+ description: 'Create a new label',
346
+ },
347
+ delete_label: {
348
+ target: 'manageLabel',
349
+ parameters: z.object({ id: z.string().describe('The ID of the label to delete') }),
350
+ mapParams: (a) => ({ action: 'delete', id: a.id }),
351
+ description: 'Delete a label',
352
+ },
353
+ get_label: {
354
+ target: 'manageLabel',
355
+ parameters: z.object({ id: z.string().describe('The ID of the label to retrieve') }),
356
+ mapParams: (a) => ({ action: 'get', id: a.id }),
357
+ description: 'Get a specific label by ID',
358
+ },
359
+ list_labels: {
360
+ target: 'manageLabel',
361
+ parameters: empty,
362
+ mapParams: () => ({ action: 'list' }),
363
+ description: "List all labels in the user's mailbox",
364
+ },
365
+ patch_label: {
366
+ target: 'manageLabel',
367
+ parameters: z.object({
368
+ id: z.string().describe('The ID of the label to patch'),
369
+ name: z.string().optional().describe('The display name of the label'),
370
+ messageListVisibility: z.enum(['show', 'hide']).optional().describe('Visibility of messages with this label'),
371
+ labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe('Visibility of the label in the label list'),
372
+ color: z.object({
373
+ textColor: z.string().describe('The text color as hex string'),
374
+ backgroundColor: z.string().describe('The background color as hex string'),
375
+ }).optional().describe('The color settings for the label'),
376
+ }),
377
+ mapParams: (a) => ({ action: 'patch', ...a }),
378
+ description: 'Patch an existing label (partial update)',
379
+ },
380
+ };
381
+
382
+ // ---------------------------------------------------------------------------
383
+ // Register all legacy aliases on `server`. `registeredTools` is a Map of
384
+ // name -> toolDef for the already-registered new tools (used to look up the
385
+ // target's execute/parameters). No-op if aliases are disabled via env var.
386
+ // ---------------------------------------------------------------------------
387
+ export function registerLegacyAliases(server, registeredTools) {
388
+ if (!legacyAliasesEnabled()) {
389
+ logger.info(`Legacy snake_case tool aliases are opt-in — set ${ENABLE_LEGACY_ALIASES_ENV}=true to register them.`);
390
+ return 0;
391
+ }
392
+ let count = 0;
393
+
394
+ for (const [alias, targetName] of Object.entries(PURE_RENAMES)) {
395
+ const target = registeredTools.get(targetName);
396
+ if (!target) {
397
+ logger.warn(`Legacy alias "${alias}" skipped: target "${targetName}" not registered.`);
398
+ continue;
399
+ }
400
+ server.addTool({
401
+ name: alias,
402
+ description: `[Deprecated alias of ${targetName}] ${target.description}`,
403
+ parameters: target.parameters,
404
+ execute: (args, ctx) => target.execute(args, ctx),
405
+ });
406
+ count++;
407
+ }
408
+
409
+ for (const [alias, spec] of Object.entries(CONSOLIDATED_ALIASES)) {
410
+ const target = registeredTools.get(spec.target);
411
+ if (!target) {
412
+ logger.warn(`Legacy alias "${alias}" skipped: target "${spec.target}" not registered.`);
413
+ continue;
414
+ }
415
+ server.addTool({
416
+ name: alias,
417
+ description: `[Deprecated alias of ${spec.target}] ${spec.description}. Dispatches to ${spec.target}.`,
418
+ parameters: spec.parameters,
419
+ execute: (args, ctx) => target.execute(spec.mapParams(args), ctx),
420
+ });
421
+ count++;
422
+ }
423
+
424
+ logger.info(`Registered ${count} legacy tool aliases (${ENABLE_LEGACY_ALIASES_ENV}=true).`);
425
+ return count;
426
+ }