google-tools-mcp 1.0.0 → 1.0.2
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/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/auth.js +2 -0
- package/dist/clients.js +16 -0
- package/dist/index.js +3 -8
- package/dist/tools/calendar/getBusy.js +64 -0
- package/dist/tools/calendar/getEvents.js +140 -0
- package/dist/tools/calendar/getFree.js +225 -0
- package/dist/tools/calendar/index.js +19 -0
- package/dist/tools/calendar/listCalendars.js +38 -0
- package/dist/tools/calendar/listRecurringInstances.js +81 -0
- package/dist/tools/calendar/manageCalendar.js +121 -0
- package/dist/tools/calendar/manageEvent.js +250 -0
- package/dist/tools/calendar/moveEvent.js +60 -0
- package/dist/tools/drafts.js +165 -0
- package/dist/tools/gmail/drafts.js +165 -165
- package/dist/tools/gmail/labels.js +103 -103
- package/dist/tools/gmail/messages.js +448 -448
- package/dist/tools/gmail/settings.js +528 -528
- package/dist/tools/gmail/threads.js +145 -145
- package/dist/tools/index.js +15 -80
- package/dist/tools/labels.js +103 -0
- package/dist/tools/messages.js +448 -0
- package/dist/tools/settings.js +528 -0
- package/dist/tools/threads.js +145 -0
- package/package.json +1 -1
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
// Gmail Thread tools
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { getGmailClient } from '../../clients.js';
|
|
4
|
-
import { processMessagePart } from '../../helpers.js';
|
|
5
|
-
|
|
6
|
-
export function register(server) {
|
|
7
|
-
server.addTool({
|
|
8
|
-
name: 'get_thread',
|
|
9
|
-
description: 'Get a specific thread by ID',
|
|
10
|
-
parameters: z.object({
|
|
11
|
-
id: z.string().describe("The ID of the thread to retrieve"),
|
|
12
|
-
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
13
|
-
}),
|
|
14
|
-
execute: async (params) => {
|
|
15
|
-
const gmail = await getGmailClient();
|
|
16
|
-
const { data } = await gmail.users.threads.get({ userId: 'me', id: params.id, format: 'full' });
|
|
17
|
-
if (data.messages) {
|
|
18
|
-
data.messages = data.messages.map(message => {
|
|
19
|
-
if (message.payload) {
|
|
20
|
-
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
21
|
-
}
|
|
22
|
-
return message;
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
return JSON.stringify(data);
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
server.addTool({
|
|
30
|
-
name: 'list_threads',
|
|
31
|
-
description: 'List threads in the user\'s mailbox',
|
|
32
|
-
parameters: z.object({
|
|
33
|
-
maxResults: z.number().optional().describe("Maximum number of threads to return"),
|
|
34
|
-
pageToken: z.string().optional().describe("Page token to retrieve a specific page of results"),
|
|
35
|
-
q: z.string().optional().describe("Only return threads matching the specified query"),
|
|
36
|
-
labelIds: z.array(z.string()).optional().describe("Only return threads with labels that match all specified label IDs"),
|
|
37
|
-
includeSpamTrash: z.boolean().optional().describe("Include threads from SPAM and TRASH"),
|
|
38
|
-
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
39
|
-
}),
|
|
40
|
-
execute: async (params) => {
|
|
41
|
-
const gmail = await getGmailClient();
|
|
42
|
-
const { data } = await gmail.users.threads.list({ userId: 'me', ...params });
|
|
43
|
-
if (data.threads) {
|
|
44
|
-
data.threads = data.threads.map(thread => {
|
|
45
|
-
if (thread.messages) {
|
|
46
|
-
thread.messages = thread.messages.map(message => {
|
|
47
|
-
if (message.payload) {
|
|
48
|
-
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
49
|
-
}
|
|
50
|
-
return message;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return thread;
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
return JSON.stringify(data);
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
server.addTool({
|
|
61
|
-
name: 'batch_get_threads',
|
|
62
|
-
description: 'Get multiple threads by ID in parallel. More efficient than calling get_thread multiple times.',
|
|
63
|
-
parameters: z.object({
|
|
64
|
-
ids: z.array(z.string()).describe("The IDs of the threads to retrieve"),
|
|
65
|
-
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
66
|
-
}),
|
|
67
|
-
execute: async (params) => {
|
|
68
|
-
const gmail = await getGmailClient();
|
|
69
|
-
const results = await Promise.all(
|
|
70
|
-
params.ids.map(async (id) => {
|
|
71
|
-
try {
|
|
72
|
-
const { data } = await gmail.users.threads.get({ userId: 'me', id, format: 'full' });
|
|
73
|
-
if (data.messages) {
|
|
74
|
-
data.messages = data.messages.map(message => {
|
|
75
|
-
if (message.payload) {
|
|
76
|
-
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
77
|
-
}
|
|
78
|
-
return message;
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return data;
|
|
82
|
-
} catch (error) {
|
|
83
|
-
return { id, error: error.message || 'Failed to retrieve thread' };
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
);
|
|
87
|
-
return JSON.stringify(results);
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
server.addTool({
|
|
92
|
-
name: 'modify_thread',
|
|
93
|
-
description: 'Modify the labels applied to a thread',
|
|
94
|
-
parameters: z.object({
|
|
95
|
-
id: z.string().describe("The ID of the thread to modify"),
|
|
96
|
-
addLabelIds: z.array(z.string()).optional().describe("Label IDs to add"),
|
|
97
|
-
removeLabelIds: z.array(z.string()).optional().describe("Label IDs to remove"),
|
|
98
|
-
}),
|
|
99
|
-
execute: async (params) => {
|
|
100
|
-
const { id, ...threadData } = params;
|
|
101
|
-
const gmail = await getGmailClient();
|
|
102
|
-
const { data } = await gmail.users.threads.modify({ userId: 'me', id, requestBody: threadData });
|
|
103
|
-
return JSON.stringify(data);
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
server.addTool({
|
|
108
|
-
name: 'delete_thread',
|
|
109
|
-
description: 'Delete a thread',
|
|
110
|
-
parameters: z.object({
|
|
111
|
-
id: z.string().describe("The ID of the thread to delete"),
|
|
112
|
-
}),
|
|
113
|
-
execute: async (params) => {
|
|
114
|
-
const gmail = await getGmailClient();
|
|
115
|
-
const { data } = await gmail.users.threads.delete({ userId: 'me', id: params.id });
|
|
116
|
-
return JSON.stringify(data || { success: true });
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
server.addTool({
|
|
121
|
-
name: 'trash_thread',
|
|
122
|
-
description: 'Move a thread to the trash',
|
|
123
|
-
parameters: z.object({
|
|
124
|
-
id: z.string().describe("The ID of the thread to move to trash"),
|
|
125
|
-
}),
|
|
126
|
-
execute: async (params) => {
|
|
127
|
-
const gmail = await getGmailClient();
|
|
128
|
-
const { data } = await gmail.users.threads.trash({ userId: 'me', id: params.id });
|
|
129
|
-
return JSON.stringify(data);
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
server.addTool({
|
|
134
|
-
name: 'untrash_thread',
|
|
135
|
-
description: 'Remove a thread from the trash',
|
|
136
|
-
parameters: z.object({
|
|
137
|
-
id: z.string().describe("The ID of the thread to remove from trash"),
|
|
138
|
-
}),
|
|
139
|
-
execute: async (params) => {
|
|
140
|
-
const gmail = await getGmailClient();
|
|
141
|
-
const { data } = await gmail.users.threads.untrash({ userId: 'me', id: params.id });
|
|
142
|
-
return JSON.stringify(data);
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
}
|
|
1
|
+
// Gmail Thread tools
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { getGmailClient } from '../../clients.js';
|
|
4
|
+
import { processMessagePart } from '../../helpers.js';
|
|
5
|
+
|
|
6
|
+
export function register(server) {
|
|
7
|
+
server.addTool({
|
|
8
|
+
name: 'get_thread',
|
|
9
|
+
description: 'Get a specific thread by ID',
|
|
10
|
+
parameters: z.object({
|
|
11
|
+
id: z.string().describe("The ID of the thread to retrieve"),
|
|
12
|
+
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
13
|
+
}),
|
|
14
|
+
execute: async (params) => {
|
|
15
|
+
const gmail = await getGmailClient();
|
|
16
|
+
const { data } = await gmail.users.threads.get({ userId: 'me', id: params.id, format: 'full' });
|
|
17
|
+
if (data.messages) {
|
|
18
|
+
data.messages = data.messages.map(message => {
|
|
19
|
+
if (message.payload) {
|
|
20
|
+
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
21
|
+
}
|
|
22
|
+
return message;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return JSON.stringify(data);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
server.addTool({
|
|
30
|
+
name: 'list_threads',
|
|
31
|
+
description: 'List threads in the user\'s mailbox',
|
|
32
|
+
parameters: z.object({
|
|
33
|
+
maxResults: z.number().optional().describe("Maximum number of threads to return"),
|
|
34
|
+
pageToken: z.string().optional().describe("Page token to retrieve a specific page of results"),
|
|
35
|
+
q: z.string().optional().describe("Only return threads matching the specified query"),
|
|
36
|
+
labelIds: z.array(z.string()).optional().describe("Only return threads with labels that match all specified label IDs"),
|
|
37
|
+
includeSpamTrash: z.boolean().optional().describe("Include threads from SPAM and TRASH"),
|
|
38
|
+
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
39
|
+
}),
|
|
40
|
+
execute: async (params) => {
|
|
41
|
+
const gmail = await getGmailClient();
|
|
42
|
+
const { data } = await gmail.users.threads.list({ userId: 'me', ...params });
|
|
43
|
+
if (data.threads) {
|
|
44
|
+
data.threads = data.threads.map(thread => {
|
|
45
|
+
if (thread.messages) {
|
|
46
|
+
thread.messages = thread.messages.map(message => {
|
|
47
|
+
if (message.payload) {
|
|
48
|
+
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
49
|
+
}
|
|
50
|
+
return message;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return thread;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return JSON.stringify(data);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
server.addTool({
|
|
61
|
+
name: 'batch_get_threads',
|
|
62
|
+
description: 'Get multiple threads by ID in parallel. More efficient than calling get_thread multiple times.',
|
|
63
|
+
parameters: z.object({
|
|
64
|
+
ids: z.array(z.string()).describe("The IDs of the threads to retrieve"),
|
|
65
|
+
includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body"),
|
|
66
|
+
}),
|
|
67
|
+
execute: async (params) => {
|
|
68
|
+
const gmail = await getGmailClient();
|
|
69
|
+
const results = await Promise.all(
|
|
70
|
+
params.ids.map(async (id) => {
|
|
71
|
+
try {
|
|
72
|
+
const { data } = await gmail.users.threads.get({ userId: 'me', id, format: 'full' });
|
|
73
|
+
if (data.messages) {
|
|
74
|
+
data.messages = data.messages.map(message => {
|
|
75
|
+
if (message.payload) {
|
|
76
|
+
message.payload = processMessagePart(message.payload, params.includeBodyHtml);
|
|
77
|
+
}
|
|
78
|
+
return message;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return data;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return { id, error: error.message || 'Failed to retrieve thread' };
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
);
|
|
87
|
+
return JSON.stringify(results);
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
server.addTool({
|
|
92
|
+
name: 'modify_thread',
|
|
93
|
+
description: 'Modify the labels applied to a thread',
|
|
94
|
+
parameters: z.object({
|
|
95
|
+
id: z.string().describe("The ID of the thread to modify"),
|
|
96
|
+
addLabelIds: z.array(z.string()).optional().describe("Label IDs to add"),
|
|
97
|
+
removeLabelIds: z.array(z.string()).optional().describe("Label IDs to remove"),
|
|
98
|
+
}),
|
|
99
|
+
execute: async (params) => {
|
|
100
|
+
const { id, ...threadData } = params;
|
|
101
|
+
const gmail = await getGmailClient();
|
|
102
|
+
const { data } = await gmail.users.threads.modify({ userId: 'me', id, requestBody: threadData });
|
|
103
|
+
return JSON.stringify(data);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
server.addTool({
|
|
108
|
+
name: 'delete_thread',
|
|
109
|
+
description: 'Delete a thread',
|
|
110
|
+
parameters: z.object({
|
|
111
|
+
id: z.string().describe("The ID of the thread to delete"),
|
|
112
|
+
}),
|
|
113
|
+
execute: async (params) => {
|
|
114
|
+
const gmail = await getGmailClient();
|
|
115
|
+
const { data } = await gmail.users.threads.delete({ userId: 'me', id: params.id });
|
|
116
|
+
return JSON.stringify(data || { success: true });
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
server.addTool({
|
|
121
|
+
name: 'trash_thread',
|
|
122
|
+
description: 'Move a thread to the trash',
|
|
123
|
+
parameters: z.object({
|
|
124
|
+
id: z.string().describe("The ID of the thread to move to trash"),
|
|
125
|
+
}),
|
|
126
|
+
execute: async (params) => {
|
|
127
|
+
const gmail = await getGmailClient();
|
|
128
|
+
const { data } = await gmail.users.threads.trash({ userId: 'me', id: params.id });
|
|
129
|
+
return JSON.stringify(data);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
server.addTool({
|
|
134
|
+
name: 'untrash_thread',
|
|
135
|
+
description: 'Remove a thread from the trash',
|
|
136
|
+
parameters: z.object({
|
|
137
|
+
id: z.string().describe("The ID of the thread to remove from trash"),
|
|
138
|
+
}),
|
|
139
|
+
execute: async (params) => {
|
|
140
|
+
const gmail = await getGmailClient();
|
|
141
|
+
const { data } = await gmail.users.threads.untrash({ userId: 'me', id: params.id });
|
|
142
|
+
return JSON.stringify(data);
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
package/dist/tools/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
// Tool
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// When a category is loaded, its tools are dynamically registered and the
|
|
5
|
-
// client is notified via tools/list_changed so it picks them up.
|
|
1
|
+
// Tool registration — all categories loaded eagerly at startup.
|
|
2
|
+
// (Claude Code doesn't support notifications/tools/list_changed,
|
|
3
|
+
// so lazy-loading doesn't work.)
|
|
6
4
|
import { z } from 'zod';
|
|
7
5
|
import * as fs from 'fs/promises';
|
|
8
6
|
import { getTokenPath } from '../auth.js';
|
|
@@ -10,11 +8,8 @@ import { resetClients } from '../clients.js';
|
|
|
10
8
|
import { logger } from '../logger.js';
|
|
11
9
|
|
|
12
10
|
// --- Category registry ---
|
|
13
|
-
// Maps category names to { loader, description, toolCount }
|
|
14
11
|
const CATEGORIES = {
|
|
15
12
|
files: {
|
|
16
|
-
description: 'Google Drive file management — list, search, create, copy, move, rename, delete files/folders, read file contents (pdf, docx), search within files',
|
|
17
|
-
toolCount: 16,
|
|
18
13
|
async loader(server) {
|
|
19
14
|
const { registerDriveTools } = await import('./drive/index.js');
|
|
20
15
|
const { registerExtrasTools } = await import('./extras/index.js');
|
|
@@ -23,8 +18,6 @@ const CATEGORIES = {
|
|
|
23
18
|
},
|
|
24
19
|
},
|
|
25
20
|
documents: {
|
|
26
|
-
description: 'Google Docs — read, write, insert text/tables/images, formatting, comments, tabs, markdown conversion',
|
|
27
|
-
toolCount: 23,
|
|
28
21
|
async loader(server) {
|
|
29
22
|
const { registerDocsTools } = await import('./docs/index.js');
|
|
30
23
|
const { registerUtilsTools } = await import('./utils/index.js');
|
|
@@ -33,16 +26,12 @@ const CATEGORIES = {
|
|
|
33
26
|
},
|
|
34
27
|
},
|
|
35
28
|
spreadsheets: {
|
|
36
|
-
description: 'Google Sheets — read, write, format cells, charts, tables, conditional formatting, data validation',
|
|
37
|
-
toolCount: 30,
|
|
38
29
|
async loader(server) {
|
|
39
30
|
const { registerSheetsTools } = await import('./sheets/index.js');
|
|
40
31
|
registerSheetsTools(server);
|
|
41
32
|
},
|
|
42
33
|
},
|
|
43
34
|
email: {
|
|
44
|
-
description: 'Gmail — send, reply, forward, get, list, delete, trash messages, create/update/send drafts, attachments, batch operations',
|
|
45
|
-
toolCount: 19,
|
|
46
35
|
async loader(server) {
|
|
47
36
|
const { register: registerMessages } = await import('./gmail/messages.js');
|
|
48
37
|
const { register: registerDrafts } = await import('./gmail/drafts.js');
|
|
@@ -51,94 +40,40 @@ const CATEGORIES = {
|
|
|
51
40
|
},
|
|
52
41
|
},
|
|
53
42
|
email_threads: {
|
|
54
|
-
description: 'Gmail threads — get, list, batch get, modify, delete, trash/untrash conversation threads',
|
|
55
|
-
toolCount: 7,
|
|
56
43
|
async loader(server) {
|
|
57
44
|
const { register } = await import('./gmail/threads.js');
|
|
58
45
|
register(server);
|
|
59
46
|
},
|
|
60
47
|
},
|
|
61
48
|
email_labels: {
|
|
62
|
-
description: 'Gmail labels — create, delete, get, list, update labels for organizing email',
|
|
63
|
-
toolCount: 6,
|
|
64
49
|
async loader(server) {
|
|
65
50
|
const { register } = await import('./gmail/labels.js');
|
|
66
51
|
register(server);
|
|
67
52
|
},
|
|
68
53
|
},
|
|
69
54
|
email_settings: {
|
|
70
|
-
description: 'Gmail settings — auto-forwarding, IMAP, POP, vacation responder, delegates, filters, forwarding addresses, send-as aliases, S/MIME, profile, mailbox watch',
|
|
71
|
-
toolCount: 37,
|
|
72
55
|
async loader(server) {
|
|
73
56
|
const { register } = await import('./gmail/settings.js');
|
|
74
57
|
register(server);
|
|
75
58
|
},
|
|
76
59
|
},
|
|
60
|
+
calendar: {
|
|
61
|
+
async loader(server) {
|
|
62
|
+
const { registerCalendarTools } = await import('./calendar/index.js');
|
|
63
|
+
registerCalendarTools(server);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
77
66
|
};
|
|
78
67
|
|
|
79
|
-
// Track which categories have been loaded
|
|
80
|
-
const loadedCategories = new Set();
|
|
81
|
-
|
|
82
68
|
// ---------------------------------------------------------------------------
|
|
83
|
-
//
|
|
69
|
+
// Public: register all tools eagerly, plus the logout utility.
|
|
84
70
|
// ---------------------------------------------------------------------------
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
session.server.notification({ method: 'notifications/tools/list_changed' });
|
|
90
|
-
logger.debug('Sent tools/list_changed notification.');
|
|
91
|
-
} else {
|
|
92
|
-
logger.debug('No session available for tools/list_changed notification.');
|
|
93
|
-
}
|
|
94
|
-
} catch (err) {
|
|
95
|
-
logger.warn('Failed to send tools/list_changed notification:', err.message);
|
|
71
|
+
export async function registerAllTools(server) {
|
|
72
|
+
// Load every category
|
|
73
|
+
for (const [name, { loader }] of Object.entries(CATEGORIES)) {
|
|
74
|
+
await loader(server);
|
|
96
75
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
|
-
// Public: register the discovery tool (and logout)
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
export function registerAllTools(server) {
|
|
103
|
-
// --- Discovery tool ---
|
|
104
|
-
server.addTool({
|
|
105
|
-
name: 'load_google_tools',
|
|
106
|
-
description:
|
|
107
|
-
'Load Google Workspace tools by category. Call this first before using any Google service.\n\n' +
|
|
108
|
-
'Categories:\n' +
|
|
109
|
-
Object.entries(CATEGORIES)
|
|
110
|
-
.map(([name, { description, toolCount }]) => ` • ${name} (${toolCount} tools) — ${description}`)
|
|
111
|
-
.join('\n') +
|
|
112
|
-
'\n\nYou can load multiple categories at once by passing an array.',
|
|
113
|
-
parameters: z.object({
|
|
114
|
-
categories: z
|
|
115
|
-
.array(z.enum(Object.keys(CATEGORIES)))
|
|
116
|
-
.describe('One or more category names to load'),
|
|
117
|
-
}),
|
|
118
|
-
execute: async ({ categories }, { log }) => {
|
|
119
|
-
const results = [];
|
|
120
|
-
for (const cat of categories) {
|
|
121
|
-
if (loadedCategories.has(cat)) {
|
|
122
|
-
results.push({ category: cat, status: 'already_loaded' });
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
log.info(`Loading category: ${cat}`);
|
|
126
|
-
await CATEGORIES[cat].loader(server);
|
|
127
|
-
loadedCategories.add(cat);
|
|
128
|
-
results.push({
|
|
129
|
-
category: cat,
|
|
130
|
-
status: 'loaded',
|
|
131
|
-
toolCount: CATEGORIES[cat].toolCount,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
notifyToolsChanged(server);
|
|
135
|
-
return JSON.stringify({
|
|
136
|
-
loaded: results,
|
|
137
|
-
message: 'Tools are now available. You can call them directly.',
|
|
138
|
-
all_loaded_categories: [...loadedCategories],
|
|
139
|
-
});
|
|
140
|
-
},
|
|
141
|
-
});
|
|
76
|
+
logger.info(`Loaded all ${Object.keys(CATEGORIES).length} categories at startup.`);
|
|
142
77
|
|
|
143
78
|
// --- Logout tool (always available) ---
|
|
144
79
|
server.addTool({
|
|
@@ -0,0 +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
|
+
}
|