@alanse/mcp-server-google-workspace 0.2.1 → 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/README.md +250 -17
- package/dist/auth.js +6 -0
- package/dist/index.js +1 -1
- package/dist/lib/calendar-helpers.js +197 -0
- package/dist/lib/document-id-resolver.js +76 -0
- package/dist/lib/drive-helpers.js +263 -0
- package/dist/lib/gmail-helpers.js +204 -0
- package/dist/lib/response-formatter.js +82 -0
- package/dist/lib/validation.js +112 -0
- package/dist/tools/calendar/acl/calendar_acl_insert.js +80 -0
- package/dist/tools/calendar/acl/calendar_acl_list.js +82 -0
- package/dist/tools/calendar/basic/calendar_create_event.js +113 -0
- package/dist/tools/calendar/basic/calendar_delete_event.js +52 -0
- package/dist/tools/calendar/basic/calendar_get_event.js +52 -0
- package/dist/tools/calendar/basic/calendar_list_events.js +86 -0
- package/dist/tools/calendar/basic/calendar_update_event.js +116 -0
- package/dist/tools/calendar/calendarlist/calendar_calendarlist_get.js +73 -0
- package/dist/tools/calendar/calendarlist/calendar_calendarlist_list.js +87 -0
- package/dist/tools/calendar/calendars/calendar_calendars_get.js +52 -0
- package/dist/tools/calendar/calendars/calendar_calendars_insert.js +66 -0
- package/dist/tools/calendar/calendars/calendar_calendars_update.js +85 -0
- package/dist/tools/calendar/colors/calendar_colors_get.js +46 -0
- package/dist/tools/calendar/events_advanced/calendar_events_instances.js +81 -0
- package/dist/tools/calendar/events_advanced/calendar_events_move.js +63 -0
- package/dist/tools/calendar/events_advanced/calendar_events_quickadd.js +52 -0
- package/dist/tools/calendar/freebusy/calendar_freebusy_query.js +69 -0
- package/dist/tools/calendar/settings/calendar_settings_list.js +81 -0
- package/dist/tools/docs/basic/gdocs_create.js +37 -0
- package/dist/tools/docs/basic/gdocs_get_metadata.js +45 -0
- package/dist/tools/docs/basic/gdocs_list_documents.js +59 -0
- package/dist/tools/docs/basic/gdocs_read.js +62 -0
- package/dist/tools/docs/content/gdocs_append_text.js +57 -0
- package/dist/tools/docs/content/gdocs_apply_style.js +86 -0
- package/dist/tools/docs/content/gdocs_create_heading.js +89 -0
- package/dist/tools/docs/content/gdocs_create_list.js +86 -0
- package/dist/tools/docs/content/gdocs_delete_text.js +64 -0
- package/dist/tools/docs/content/gdocs_format_text.js +137 -0
- package/dist/tools/docs/content/gdocs_insert_text.js +62 -0
- package/dist/tools/docs/content/gdocs_replace_text.js +64 -0
- package/dist/tools/docs/content/gdocs_set_alignment.js +76 -0
- package/dist/tools/docs/content/gdocs_update_text.js +78 -0
- package/dist/tools/docs/elements/gdocs_batch_update.js +108 -0
- package/dist/tools/docs/elements/gdocs_create_table.js +73 -0
- package/dist/tools/docs/elements/gdocs_export.js +62 -0
- package/dist/tools/docs/elements/gdocs_insert_image.js +96 -0
- package/dist/tools/docs/elements/gdocs_insert_link.js +77 -0
- package/dist/tools/docs/elements/gdocs_insert_page_break.js +55 -0
- package/dist/tools/docs/elements/gdocs_insert_toc.js +71 -0
- package/dist/tools/docs/elements/gdocs_merge_documents.js +104 -0
- package/dist/tools/docs/elements/gdocs_suggest_mode.js +41 -0
- package/dist/tools/drive/advanced/drive_empty_trash.js +56 -0
- package/dist/tools/drive/advanced/drive_export_file.js +158 -0
- package/dist/tools/drive/advanced/drive_list_revisions.js +80 -0
- package/dist/tools/drive/basic/drive_get_metadata.js +49 -0
- package/dist/tools/drive/basic/drive_list_files.js +76 -0
- package/dist/tools/drive/file/drive_copy_file.js +79 -0
- package/dist/tools/drive/file/drive_create_file.js +72 -0
- package/dist/tools/drive/file/drive_delete_file.js +48 -0
- package/dist/tools/drive/file/drive_move_file.js +79 -0
- package/dist/tools/drive/file/drive_rename_file.js +58 -0
- package/dist/tools/drive/file/drive_update_file.js +106 -0
- package/dist/tools/drive/file/drive_upload_file.js +80 -0
- package/dist/tools/drive/folder/drive_create_folder.js +67 -0
- package/dist/tools/drive/folder/drive_list_folder_contents.js +68 -0
- package/dist/tools/drive/folder/drive_move_to_folder.js +59 -0
- package/dist/tools/drive/permissions/drive_list_permissions.js +115 -0
- package/dist/tools/drive/permissions/drive_remove_permission.js +71 -0
- package/dist/tools/drive/permissions/drive_share_file.js +116 -0
- package/dist/tools/drive/permissions/drive_update_permission.js +79 -0
- package/dist/tools/gmail/basic/gmail_get_message.js +95 -0
- package/dist/tools/gmail/basic/gmail_get_thread.js +46 -0
- package/dist/tools/gmail/basic/gmail_list_labels.js +54 -0
- package/dist/tools/gmail/basic/gmail_search_messages.js +59 -0
- package/dist/tools/gmail/batch/gmail_batch_modify_labels.js +74 -0
- package/dist/tools/gmail/batch/gmail_get_messages_batch.js +120 -0
- package/dist/tools/gmail/batch/gmail_get_threads_batch.js +102 -0
- package/dist/tools/gmail/labels/gmail_manage_label.js +131 -0
- package/dist/tools/gmail/labels/gmail_modify_labels.js +65 -0
- package/dist/tools/gmail/send/gmail_draft_message.js +117 -0
- package/dist/tools/gmail/send/gmail_send_message.js +109 -0
- package/dist/tools/index.js +386 -3
- package/package.json +8 -3
- package/dist/tools/basic/gsheets_add_sheet.js +0 -65
- package/dist/tools/basic/gsheets_copy_sheet.js +0 -56
- package/dist/tools/basic/gsheets_copy_to.js +0 -113
- package/dist/tools/basic/gsheets_create_spreadsheet.js +0 -88
- package/dist/tools/basic/gsheets_delete_columns.js +0 -69
- package/dist/tools/basic/gsheets_delete_rows.js +0 -69
- package/dist/tools/basic/gsheets_delete_sheet.js +0 -56
- package/dist/tools/basic/gsheets_duplicate_sheet.js +0 -72
- package/dist/tools/basic/gsheets_insert_columns.js +0 -69
- package/dist/tools/basic/gsheets_insert_rows.js +0 -69
- package/dist/tools/basic/gsheets_list_sheets.js +0 -53
- package/dist/tools/basic/gsheets_read.js +0 -120
- package/dist/tools/basic/gsheets_rename_sheet.js +0 -64
- package/dist/tools/charts/gsheets_add_bubble.js +0 -176
- package/dist/tools/charts/gsheets_add_candlestick.js +0 -192
- package/dist/tools/charts/gsheets_add_chart.js +0 -162
- package/dist/tools/charts/gsheets_add_combo.js +0 -169
- package/dist/tools/charts/gsheets_add_histogram.js +0 -143
- package/dist/tools/charts/gsheets_add_org_chart.js +0 -160
- package/dist/tools/charts/gsheets_add_treemap.js +0 -177
- package/dist/tools/charts/gsheets_add_waterfall.js +0 -155
- package/dist/tools/charts/gsheets_delete_chart.js +0 -56
- package/dist/tools/charts/gsheets_update_chart.js +0 -118
- package/dist/tools/data/gsheets_append_data.js +0 -68
- package/dist/tools/data/gsheets_batch_clear.js +0 -53
- package/dist/tools/data/gsheets_batch_update.js +0 -81
- package/dist/tools/data/gsheets_clear_data.js +0 -53
- package/dist/tools/data/gsheets_create_filter.js +0 -81
- package/dist/tools/data/gsheets_find_replace.js +0 -124
- package/dist/tools/data/gsheets_set_data_validation.js +0 -153
- package/dist/tools/data/gsheets_sort_range.js +0 -102
- package/dist/tools/data/gsheets_update_cell.js +0 -44
- package/dist/tools/formatting/gsheets_auto_resize.js +0 -75
- package/dist/tools/formatting/gsheets_format_cells.js +0 -161
- package/dist/tools/formatting/gsheets_freeze_columns.js +0 -67
- package/dist/tools/formatting/gsheets_freeze_rows.js +0 -67
- package/dist/tools/formatting/gsheets_merge_cells.js +0 -85
- package/dist/tools/formatting/gsheets_set_number_format.js +0 -116
- package/dist/tools/formatting/gsheets_unmerge_cells.js +0 -79
- package/dist/tools/formatting/gsheets_update_borders.js +0 -212
- package/dist/tools/gdrive/gdrive_read_file.js +0 -77
- package/dist/tools/gdrive/gdrive_search.js +0 -71
- package/dist/tools/gdrive_read_file.js +0 -77
- package/dist/tools/gdrive_search.js +0 -71
- package/dist/tools/gsheets_add_bubble.js +0 -176
- package/dist/tools/gsheets_add_candlestick.js +0 -192
- package/dist/tools/gsheets_add_chart.js +0 -162
- package/dist/tools/gsheets_add_combo.js +0 -169
- package/dist/tools/gsheets_add_conditional_format.js +0 -175
- package/dist/tools/gsheets_add_histogram.js +0 -143
- package/dist/tools/gsheets_add_named_range.js +0 -87
- package/dist/tools/gsheets_add_org_chart.js +0 -160
- package/dist/tools/gsheets_add_protected_range.js +0 -127
- package/dist/tools/gsheets_add_sheet.js +0 -65
- package/dist/tools/gsheets_add_treemap.js +0 -177
- package/dist/tools/gsheets_add_waterfall.js +0 -155
- package/dist/tools/gsheets_append_data.js +0 -68
- package/dist/tools/gsheets_auto_resize.js +0 -75
- package/dist/tools/gsheets_batch_clear.js +0 -53
- package/dist/tools/gsheets_batch_update.js +0 -81
- package/dist/tools/gsheets_clear_data.js +0 -53
- package/dist/tools/gsheets_copy_sheet.js +0 -56
- package/dist/tools/gsheets_copy_to.js +0 -113
- package/dist/tools/gsheets_create_filter.js +0 -81
- package/dist/tools/gsheets_create_spreadsheet.js +0 -88
- package/dist/tools/gsheets_delete_chart.js +0 -56
- package/dist/tools/gsheets_delete_columns.js +0 -69
- package/dist/tools/gsheets_delete_named_range.js +0 -56
- package/dist/tools/gsheets_delete_protected_range.js +0 -56
- package/dist/tools/gsheets_delete_rows.js +0 -69
- package/dist/tools/gsheets_delete_sheet.js +0 -56
- package/dist/tools/gsheets_duplicate_sheet.js +0 -72
- package/dist/tools/gsheets_find_replace.js +0 -124
- package/dist/tools/gsheets_format_cells.js +0 -161
- package/dist/tools/gsheets_freeze_columns.js +0 -67
- package/dist/tools/gsheets_freeze_rows.js +0 -67
- package/dist/tools/gsheets_insert_columns.js +0 -69
- package/dist/tools/gsheets_insert_rows.js +0 -69
- package/dist/tools/gsheets_list_sheets.js +0 -53
- package/dist/tools/gsheets_merge_cells.js +0 -85
- package/dist/tools/gsheets_read.js +0 -120
- package/dist/tools/gsheets_rename_sheet.js +0 -64
- package/dist/tools/gsheets_set_data_validation.js +0 -153
- package/dist/tools/gsheets_set_number_format.js +0 -116
- package/dist/tools/gsheets_sort_range.js +0 -102
- package/dist/tools/gsheets_unmerge_cells.js +0 -79
- package/dist/tools/gsheets_update_borders.js +0 -212
- package/dist/tools/gsheets_update_cell.js +0 -44
- package/dist/tools/gsheets_update_chart.js +0 -118
- package/dist/tools/gsheets_update_named_range.js +0 -112
- package/dist/tools/gsheets_update_protected_range.js +0 -110
- package/dist/tools/protection/gsheets_add_conditional_format.js +0 -175
- package/dist/tools/protection/gsheets_add_named_range.js +0 -87
- package/dist/tools/protection/gsheets_add_protected_range.js +0 -127
- package/dist/tools/protection/gsheets_delete_named_range.js +0 -56
- package/dist/tools/protection/gsheets_delete_protected_range.js +0 -56
- package/dist/tools/protection/gsheets_update_named_range.js +0 -112
- package/dist/tools/protection/gsheets_update_protected_range.js +0 -110
- /package/dist/tools/drive/{drive_read_file.js → basic/drive_read_file.js} +0 -0
- /package/dist/tools/drive/{drive_search.js → basic/drive_search.js} +0 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { extractMessageBodies, formatBodyContent, extractAttachments, getHeader, generateGmailWebUrl, } from "../../../lib/gmail-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "gmail_get_message",
|
|
6
|
+
description: "Retrieve full content of a specific Gmail message including subject, sender, recipients, body (text/HTML), and attachments. Returns formatted message with metadata.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
messageId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "The Gmail message ID to retrieve",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["messageId"],
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export async function getMessage(args) {
|
|
19
|
+
try {
|
|
20
|
+
const gmail = google.gmail("v1");
|
|
21
|
+
const { messageId } = args;
|
|
22
|
+
// Fetch message with full format
|
|
23
|
+
const response = await gmail.users.messages.get({
|
|
24
|
+
userId: "me",
|
|
25
|
+
id: messageId,
|
|
26
|
+
format: "full",
|
|
27
|
+
});
|
|
28
|
+
const message = response.data;
|
|
29
|
+
const headers = message.payload?.headers || [];
|
|
30
|
+
// Extract metadata
|
|
31
|
+
const subject = getHeader(headers, "Subject");
|
|
32
|
+
const from = getHeader(headers, "From");
|
|
33
|
+
const to = getHeader(headers, "To");
|
|
34
|
+
const cc = getHeader(headers, "Cc");
|
|
35
|
+
const date = getHeader(headers, "Date");
|
|
36
|
+
const messageIdHeader = getHeader(headers, "Message-ID");
|
|
37
|
+
// Extract body
|
|
38
|
+
const { textBody, htmlBody } = extractMessageBodies(message.payload || {});
|
|
39
|
+
const bodyContent = formatBodyContent(textBody, htmlBody);
|
|
40
|
+
// Extract attachments
|
|
41
|
+
const attachments = extractAttachments(message.payload || {});
|
|
42
|
+
// Build output
|
|
43
|
+
let output = `Message ID: ${messageId}\n`;
|
|
44
|
+
output += `Thread ID: ${message.threadId}\n`;
|
|
45
|
+
output += `Web URL: ${generateGmailWebUrl(messageId)}\n\n`;
|
|
46
|
+
output += `Subject: ${subject}\n`;
|
|
47
|
+
output += `From: ${from}\n`;
|
|
48
|
+
output += `To: ${to}\n`;
|
|
49
|
+
if (cc)
|
|
50
|
+
output += `Cc: ${cc}\n`;
|
|
51
|
+
output += `Date: ${date}\n`;
|
|
52
|
+
if (messageIdHeader)
|
|
53
|
+
output += `Message-ID: ${messageIdHeader}\n`;
|
|
54
|
+
output += `\n${"=".repeat(80)}\n\n`;
|
|
55
|
+
// Truncate very long bodies
|
|
56
|
+
const maxBodyLength = 20000;
|
|
57
|
+
if (bodyContent.length > maxBodyLength) {
|
|
58
|
+
output += bodyContent.substring(0, maxBodyLength);
|
|
59
|
+
output += `\n\n[... truncated ${bodyContent.length - maxBodyLength} characters ...]`;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
output += bodyContent;
|
|
63
|
+
}
|
|
64
|
+
// Add attachments info
|
|
65
|
+
if (attachments.length > 0) {
|
|
66
|
+
output += `\n\n${"=".repeat(80)}\n\n`;
|
|
67
|
+
output += `📎 Attachments (${attachments.length}):\n`;
|
|
68
|
+
attachments.forEach((att, index) => {
|
|
69
|
+
output += ` ${index + 1}. ${att.filename} (${att.mimeType}, ${Math.round(att.size / 1024)}KB)\n`;
|
|
70
|
+
output += ` Attachment ID: ${att.attachmentId}\n`;
|
|
71
|
+
});
|
|
72
|
+
output += `\nUse 'gmail_get_attachment' tool to download attachments.\n`;
|
|
73
|
+
}
|
|
74
|
+
return ResponseFormatter.success({
|
|
75
|
+
messageId,
|
|
76
|
+
threadId: message.threadId,
|
|
77
|
+
subject,
|
|
78
|
+
from,
|
|
79
|
+
to,
|
|
80
|
+
cc,
|
|
81
|
+
date,
|
|
82
|
+
labels: message.labelIds,
|
|
83
|
+
attachments: attachments.map((a) => ({
|
|
84
|
+
filename: a.filename,
|
|
85
|
+
mimeType: a.mimeType,
|
|
86
|
+
size: a.size,
|
|
87
|
+
attachmentId: a.attachmentId,
|
|
88
|
+
})),
|
|
89
|
+
snippet: message.snippet,
|
|
90
|
+
}, output);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
return ResponseFormatter.error(error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatThreadContent } from "../../../lib/gmail-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "gmail_get_thread",
|
|
6
|
+
description: "Retrieve a complete Gmail thread (conversation) with all messages. Returns all messages in chronological order with full content, metadata, and attachments.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
threadId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "The Gmail thread ID to retrieve",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["threadId"],
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export async function getThread(args) {
|
|
19
|
+
try {
|
|
20
|
+
const gmail = google.gmail("v1");
|
|
21
|
+
const { threadId } = args;
|
|
22
|
+
// Fetch thread with full format
|
|
23
|
+
const response = await gmail.users.threads.get({
|
|
24
|
+
userId: "me",
|
|
25
|
+
id: threadId,
|
|
26
|
+
format: "full",
|
|
27
|
+
});
|
|
28
|
+
const thread = response.data;
|
|
29
|
+
const messages = thread.messages || [];
|
|
30
|
+
// Format thread content using helper
|
|
31
|
+
const formattedContent = formatThreadContent(thread);
|
|
32
|
+
// Build metadata for structured response
|
|
33
|
+
const messageCount = messages.length;
|
|
34
|
+
const messageIds = messages.map((m) => m.id);
|
|
35
|
+
const snippets = messages.map((m) => m.snippet || "");
|
|
36
|
+
return ResponseFormatter.success({
|
|
37
|
+
threadId,
|
|
38
|
+
messageCount,
|
|
39
|
+
messageIds,
|
|
40
|
+
snippets,
|
|
41
|
+
}, formattedContent);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return ResponseFormatter.error(error);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
export const schema = {
|
|
4
|
+
name: "gmail_list_labels",
|
|
5
|
+
description: "List all labels in the user's Gmail account. Returns both system labels (INBOX, SENT, TRASH, etc.) and user-created labels with their IDs and names.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {},
|
|
9
|
+
required: [],
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
export async function listLabels(args) {
|
|
13
|
+
try {
|
|
14
|
+
const gmail = google.gmail("v1");
|
|
15
|
+
const response = await gmail.users.labels.list({
|
|
16
|
+
userId: "me",
|
|
17
|
+
});
|
|
18
|
+
const labels = response.data.labels || [];
|
|
19
|
+
if (labels.length === 0) {
|
|
20
|
+
return ResponseFormatter.success({ count: 0, labels: [] }, "No labels found in Gmail account");
|
|
21
|
+
}
|
|
22
|
+
// Separate system and user labels
|
|
23
|
+
const systemLabels = labels.filter((l) => l.type === "system");
|
|
24
|
+
const userLabels = labels.filter((l) => l.type === "user");
|
|
25
|
+
let output = `Total labels: ${labels.length}\n\n`;
|
|
26
|
+
if (systemLabels.length > 0) {
|
|
27
|
+
output += `📌 System Labels (${systemLabels.length}):\n`;
|
|
28
|
+
systemLabels.forEach((label) => {
|
|
29
|
+
output += ` - ${label.name} (ID: ${label.id})\n`;
|
|
30
|
+
});
|
|
31
|
+
output += `\n`;
|
|
32
|
+
}
|
|
33
|
+
if (userLabels.length > 0) {
|
|
34
|
+
output += `🏷️ User Labels (${userLabels.length}):\n`;
|
|
35
|
+
userLabels.forEach((label) => {
|
|
36
|
+
output += ` - ${label.name} (ID: ${label.id})\n`;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return ResponseFormatter.success({
|
|
40
|
+
count: labels.length,
|
|
41
|
+
systemLabels: systemLabels.map((l) => ({
|
|
42
|
+
id: l.id,
|
|
43
|
+
name: l.name,
|
|
44
|
+
})),
|
|
45
|
+
userLabels: userLabels.map((l) => ({
|
|
46
|
+
id: l.id,
|
|
47
|
+
name: l.name,
|
|
48
|
+
})),
|
|
49
|
+
}, output);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return ResponseFormatter.error(error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { formatMessageList } from "../../../lib/gmail-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "gmail_search_messages",
|
|
6
|
+
description: "Search for messages in Gmail using Gmail query syntax. Supports operators like 'from:', 'to:', 'subject:', 'is:unread', 'has:attachment', date ranges, etc. Returns message IDs, thread IDs, and web URLs for each result.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
query: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Gmail search query using standard Gmail operators (e.g., 'from:user@example.com subject:invoice is:unread')",
|
|
13
|
+
},
|
|
14
|
+
pageSize: {
|
|
15
|
+
type: "number",
|
|
16
|
+
description: "Maximum number of results to return (default: 10, max: 100)",
|
|
17
|
+
},
|
|
18
|
+
pageToken: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Token for pagination to get the next page of results",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["query"],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
export async function searchMessages(args) {
|
|
27
|
+
try {
|
|
28
|
+
const gmail = google.gmail("v1");
|
|
29
|
+
const { query, pageSize = 10, pageToken } = args;
|
|
30
|
+
const response = await gmail.users.messages.list({
|
|
31
|
+
userId: "me",
|
|
32
|
+
q: query,
|
|
33
|
+
maxResults: Math.min(pageSize, 100),
|
|
34
|
+
pageToken: pageToken,
|
|
35
|
+
});
|
|
36
|
+
const messages = response.data.messages || [];
|
|
37
|
+
const nextPageToken = response.data.nextPageToken;
|
|
38
|
+
if (messages.length === 0) {
|
|
39
|
+
return ResponseFormatter.success({
|
|
40
|
+
count: 0,
|
|
41
|
+
messages: [],
|
|
42
|
+
query,
|
|
43
|
+
}, `No messages found matching query: "${query}"`);
|
|
44
|
+
}
|
|
45
|
+
const formattedOutput = formatMessageList(messages, nextPageToken);
|
|
46
|
+
return ResponseFormatter.success({
|
|
47
|
+
count: messages.length,
|
|
48
|
+
query,
|
|
49
|
+
messages: messages.map((m) => ({
|
|
50
|
+
id: m.id,
|
|
51
|
+
threadId: m.threadId,
|
|
52
|
+
})),
|
|
53
|
+
nextPageToken,
|
|
54
|
+
}, `Search results for: "${query}"\n\n${formattedOutput}`);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return ResponseFormatter.error(error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
export const schema = {
|
|
4
|
+
name: "gmail_batch_modify_labels",
|
|
5
|
+
description: "Modify labels on multiple Gmail messages in a single batch operation. More efficient than calling gmail_modify_labels multiple times. Can add and/or remove labels from many messages at once.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
messageIds: {
|
|
10
|
+
type: "array",
|
|
11
|
+
items: { type: "string" },
|
|
12
|
+
description: "Array of Gmail message IDs to modify (max recommended: 1000)",
|
|
13
|
+
},
|
|
14
|
+
addLabelIds: {
|
|
15
|
+
type: "array",
|
|
16
|
+
items: { type: "string" },
|
|
17
|
+
description: "Array of label IDs to add to all specified messages (e.g., ['INBOX', 'STARRED'])",
|
|
18
|
+
optional: true,
|
|
19
|
+
},
|
|
20
|
+
removeLabelIds: {
|
|
21
|
+
type: "array",
|
|
22
|
+
items: { type: "string" },
|
|
23
|
+
description: "Array of label IDs to remove from all specified messages (e.g., ['UNREAD', 'SPAM'])",
|
|
24
|
+
optional: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["messageIds"],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export async function batchModifyLabels(args) {
|
|
31
|
+
try {
|
|
32
|
+
const gmail = google.gmail("v1");
|
|
33
|
+
const { messageIds, addLabelIds = [], removeLabelIds = [] } = args;
|
|
34
|
+
if (messageIds.length === 0) {
|
|
35
|
+
return ResponseFormatter.error(new Error("messageIds array cannot be empty"));
|
|
36
|
+
}
|
|
37
|
+
if (messageIds.length > 1000) {
|
|
38
|
+
return ResponseFormatter.error(new Error("Too many message IDs. Maximum recommended is 1000 per batch request."));
|
|
39
|
+
}
|
|
40
|
+
// Validate at least one operation
|
|
41
|
+
if (addLabelIds.length === 0 && removeLabelIds.length === 0) {
|
|
42
|
+
return ResponseFormatter.error(new Error("At least one of addLabelIds or removeLabelIds must be provided"));
|
|
43
|
+
}
|
|
44
|
+
// Perform batch modify
|
|
45
|
+
await gmail.users.messages.batchModify({
|
|
46
|
+
userId: "me",
|
|
47
|
+
requestBody: {
|
|
48
|
+
ids: messageIds,
|
|
49
|
+
addLabelIds: addLabelIds.length > 0 ? addLabelIds : undefined,
|
|
50
|
+
removeLabelIds: removeLabelIds.length > 0 ? removeLabelIds : undefined,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
let output = `✅ Successfully modified labels on ${messageIds.length} message(s)\n\n`;
|
|
54
|
+
output += `📊 Operation Summary:\n`;
|
|
55
|
+
output += ` Messages affected: ${messageIds.length}\n`;
|
|
56
|
+
if (addLabelIds.length > 0) {
|
|
57
|
+
output += ` ➕ Added labels: ${addLabelIds.join(", ")}\n`;
|
|
58
|
+
}
|
|
59
|
+
if (removeLabelIds.length > 0) {
|
|
60
|
+
output += ` ➖ Removed labels: ${removeLabelIds.join(", ")}\n`;
|
|
61
|
+
}
|
|
62
|
+
output += `\n📝 Note: Changes applied to all specified messages.\n`;
|
|
63
|
+
output += `Use gmail_get_message to verify individual message labels.`;
|
|
64
|
+
return ResponseFormatter.success({
|
|
65
|
+
messageCount: messageIds.length,
|
|
66
|
+
messageIds,
|
|
67
|
+
addedLabels: addLabelIds,
|
|
68
|
+
removedLabels: removeLabelIds,
|
|
69
|
+
}, output);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
return ResponseFormatter.error(error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
import { extractMessageBodies, formatBodyContent, getHeader, generateGmailWebUrl, } from "../../../lib/gmail-helpers.js";
|
|
4
|
+
export const schema = {
|
|
5
|
+
name: "gmail_get_messages_batch",
|
|
6
|
+
description: "Retrieve multiple Gmail messages in a single batch request. More efficient than calling gmail_get_message multiple times. Returns message metadata and content for each message ID.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
messageIds: {
|
|
11
|
+
type: "array",
|
|
12
|
+
items: { type: "string" },
|
|
13
|
+
description: "Array of Gmail message IDs to retrieve (max recommended: 100)",
|
|
14
|
+
},
|
|
15
|
+
format: {
|
|
16
|
+
type: "string",
|
|
17
|
+
enum: ["full", "metadata"],
|
|
18
|
+
description: "Response format: 'full' includes body content, 'metadata' only headers (default: metadata)",
|
|
19
|
+
optional: true,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
required: ["messageIds"],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
export async function getMessagesBatch(args) {
|
|
26
|
+
try {
|
|
27
|
+
const gmail = google.gmail("v1");
|
|
28
|
+
const { messageIds, format = "metadata" } = args;
|
|
29
|
+
if (messageIds.length === 0) {
|
|
30
|
+
return ResponseFormatter.error(new Error("messageIds array cannot be empty"));
|
|
31
|
+
}
|
|
32
|
+
if (messageIds.length > 100) {
|
|
33
|
+
return ResponseFormatter.error(new Error("Too many message IDs. Maximum recommended is 100 per batch request."));
|
|
34
|
+
}
|
|
35
|
+
// Fetch all messages
|
|
36
|
+
const messagePromises = messageIds.map((messageId) => gmail.users.messages
|
|
37
|
+
.get({
|
|
38
|
+
userId: "me",
|
|
39
|
+
id: messageId,
|
|
40
|
+
format: format,
|
|
41
|
+
})
|
|
42
|
+
.catch((error) => ({
|
|
43
|
+
error: true,
|
|
44
|
+
messageId,
|
|
45
|
+
errorMessage: error.message,
|
|
46
|
+
})));
|
|
47
|
+
const results = await Promise.all(messagePromises);
|
|
48
|
+
// Process results
|
|
49
|
+
const messages = [];
|
|
50
|
+
const errors = [];
|
|
51
|
+
let output = `📬 Batch Message Retrieval Results\n`;
|
|
52
|
+
output += `${"=".repeat(80)}\n\n`;
|
|
53
|
+
output += `Requested: ${messageIds.length} messages\n`;
|
|
54
|
+
results.forEach((result, index) => {
|
|
55
|
+
if (result.error) {
|
|
56
|
+
errors.push({
|
|
57
|
+
messageId: result.messageId,
|
|
58
|
+
error: result.errorMessage,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const message = result.data;
|
|
63
|
+
const headers = message.payload?.headers || [];
|
|
64
|
+
const messageData = {
|
|
65
|
+
messageId: message.id,
|
|
66
|
+
threadId: message.threadId,
|
|
67
|
+
subject: getHeader(headers, "Subject"),
|
|
68
|
+
from: getHeader(headers, "From"),
|
|
69
|
+
to: getHeader(headers, "To"),
|
|
70
|
+
date: getHeader(headers, "Date"),
|
|
71
|
+
snippet: message.snippet,
|
|
72
|
+
labelIds: message.labelIds || [],
|
|
73
|
+
};
|
|
74
|
+
// Include body if format is 'full'
|
|
75
|
+
if (format === "full") {
|
|
76
|
+
const { textBody, htmlBody } = extractMessageBodies(message.payload || {});
|
|
77
|
+
messageData.bodyPreview = formatBodyContent(textBody, htmlBody).substring(0, 500);
|
|
78
|
+
}
|
|
79
|
+
messages.push(messageData);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
output += `Successful: ${messages.length}\n`;
|
|
83
|
+
output += `Failed: ${errors.length}\n\n`;
|
|
84
|
+
output += `${"=".repeat(80)}\n\n`;
|
|
85
|
+
// Display successful messages
|
|
86
|
+
if (messages.length > 0) {
|
|
87
|
+
output += `✅ Successfully Retrieved Messages:\n\n`;
|
|
88
|
+
messages.forEach((msg, index) => {
|
|
89
|
+
output += `${index + 1}. ${msg.subject}\n`;
|
|
90
|
+
output += ` From: ${msg.from}\n`;
|
|
91
|
+
output += ` Date: ${msg.date}\n`;
|
|
92
|
+
output += ` Message ID: ${msg.messageId}\n`;
|
|
93
|
+
output += ` URL: ${generateGmailWebUrl(msg.messageId)}\n`;
|
|
94
|
+
if (format === "full" && msg.bodyPreview) {
|
|
95
|
+
output += ` Preview: ${msg.bodyPreview.substring(0, 100)}...\n`;
|
|
96
|
+
}
|
|
97
|
+
output += `\n`;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Display errors
|
|
101
|
+
if (errors.length > 0) {
|
|
102
|
+
output += `\n❌ Failed Messages:\n\n`;
|
|
103
|
+
errors.forEach((err, index) => {
|
|
104
|
+
output += `${index + 1}. Message ID: ${err.messageId}\n`;
|
|
105
|
+
output += ` Error: ${err.error}\n\n`;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return ResponseFormatter.success({
|
|
109
|
+
totalRequested: messageIds.length,
|
|
110
|
+
successCount: messages.length,
|
|
111
|
+
errorCount: errors.length,
|
|
112
|
+
messages,
|
|
113
|
+
errors,
|
|
114
|
+
format,
|
|
115
|
+
}, output);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return ResponseFormatter.error(error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
export const schema = {
|
|
4
|
+
name: "gmail_get_threads_batch",
|
|
5
|
+
description: "Retrieve multiple Gmail threads (conversations) in a single batch request. More efficient than calling gmail_get_thread multiple times. Returns all messages in each thread.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
threadIds: {
|
|
10
|
+
type: "array",
|
|
11
|
+
items: { type: "string" },
|
|
12
|
+
description: "Array of Gmail thread IDs to retrieve (max recommended: 50)",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["threadIds"],
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export async function getThreadsBatch(args) {
|
|
19
|
+
try {
|
|
20
|
+
const gmail = google.gmail("v1");
|
|
21
|
+
const { threadIds } = args;
|
|
22
|
+
if (threadIds.length === 0) {
|
|
23
|
+
return ResponseFormatter.error(new Error("threadIds array cannot be empty"));
|
|
24
|
+
}
|
|
25
|
+
if (threadIds.length > 50) {
|
|
26
|
+
return ResponseFormatter.error(new Error("Too many thread IDs. Maximum recommended is 50 per batch request."));
|
|
27
|
+
}
|
|
28
|
+
// Fetch all threads
|
|
29
|
+
const threadPromises = threadIds.map((threadId) => gmail.users.threads
|
|
30
|
+
.get({
|
|
31
|
+
userId: "me",
|
|
32
|
+
id: threadId,
|
|
33
|
+
format: "full",
|
|
34
|
+
})
|
|
35
|
+
.catch((error) => ({
|
|
36
|
+
error: true,
|
|
37
|
+
threadId,
|
|
38
|
+
errorMessage: error.message,
|
|
39
|
+
})));
|
|
40
|
+
const results = await Promise.all(threadPromises);
|
|
41
|
+
// Process results
|
|
42
|
+
const threads = [];
|
|
43
|
+
const errors = [];
|
|
44
|
+
let output = `📬 Batch Thread Retrieval Results\n`;
|
|
45
|
+
output += `${"=".repeat(80)}\n\n`;
|
|
46
|
+
output += `Requested: ${threadIds.length} threads\n`;
|
|
47
|
+
results.forEach((result) => {
|
|
48
|
+
if (result.error) {
|
|
49
|
+
errors.push({
|
|
50
|
+
threadId: result.threadId,
|
|
51
|
+
error: result.errorMessage,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const thread = result.data;
|
|
56
|
+
const messages = thread.messages || [];
|
|
57
|
+
threads.push({
|
|
58
|
+
threadId: thread.id,
|
|
59
|
+
messageCount: messages.length,
|
|
60
|
+
snippet: thread.snippet || "",
|
|
61
|
+
messages: messages.map((m) => ({
|
|
62
|
+
messageId: m.id,
|
|
63
|
+
snippet: m.snippet,
|
|
64
|
+
labelIds: m.labelIds || [],
|
|
65
|
+
})),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
output += `Successful: ${threads.length}\n`;
|
|
70
|
+
output += `Failed: ${errors.length}\n\n`;
|
|
71
|
+
output += `${"=".repeat(80)}\n\n`;
|
|
72
|
+
// Display successful threads
|
|
73
|
+
if (threads.length > 0) {
|
|
74
|
+
output += `✅ Successfully Retrieved Threads:\n\n`;
|
|
75
|
+
threads.forEach((thread, index) => {
|
|
76
|
+
output += `${index + 1}. Thread ID: ${thread.threadId}\n`;
|
|
77
|
+
output += ` Messages: ${thread.messageCount}\n`;
|
|
78
|
+
output += ` Snippet: ${thread.snippet}\n`;
|
|
79
|
+
output += ` Message IDs: ${thread.messages.map((m) => m.messageId).join(", ")}\n`;
|
|
80
|
+
output += `\n`;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Display errors
|
|
84
|
+
if (errors.length > 0) {
|
|
85
|
+
output += `\n❌ Failed Threads:\n\n`;
|
|
86
|
+
errors.forEach((err, index) => {
|
|
87
|
+
output += `${index + 1}. Thread ID: ${err.threadId}\n`;
|
|
88
|
+
output += ` Error: ${err.error}\n\n`;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return ResponseFormatter.success({
|
|
92
|
+
totalRequested: threadIds.length,
|
|
93
|
+
successCount: threads.length,
|
|
94
|
+
errorCount: errors.length,
|
|
95
|
+
threads,
|
|
96
|
+
errors,
|
|
97
|
+
}, output);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return ResponseFormatter.error(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { google } from "googleapis";
|
|
2
|
+
import { ResponseFormatter } from "../../../lib/response-formatter.js";
|
|
3
|
+
export const schema = {
|
|
4
|
+
name: "gmail_manage_label",
|
|
5
|
+
description: "Create, update, or delete Gmail labels. Supports creating new labels with visibility settings, updating existing label properties, or deleting labels.",
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object",
|
|
8
|
+
properties: {
|
|
9
|
+
action: {
|
|
10
|
+
type: "string",
|
|
11
|
+
enum: ["create", "update", "delete"],
|
|
12
|
+
description: "The action to perform on the label",
|
|
13
|
+
},
|
|
14
|
+
name: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Label name (required for create, optional for update). The display name of the label.",
|
|
17
|
+
optional: true,
|
|
18
|
+
},
|
|
19
|
+
labelId: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Label ID (required for update and delete operations). Get this from gmail_list_labels.",
|
|
22
|
+
optional: true,
|
|
23
|
+
},
|
|
24
|
+
labelListVisibility: {
|
|
25
|
+
type: "string",
|
|
26
|
+
enum: ["labelShow", "labelHide"],
|
|
27
|
+
description: "Whether to show the label in the label list (optional for create/update)",
|
|
28
|
+
optional: true,
|
|
29
|
+
},
|
|
30
|
+
messageListVisibility: {
|
|
31
|
+
type: "string",
|
|
32
|
+
enum: ["show", "hide"],
|
|
33
|
+
description: "Whether to show the label in the message list (optional for create/update)",
|
|
34
|
+
optional: true,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
required: ["action"],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export async function manageLabel(args) {
|
|
41
|
+
try {
|
|
42
|
+
const gmail = google.gmail("v1");
|
|
43
|
+
const { action, name, labelId, labelListVisibility, messageListVisibility, } = args;
|
|
44
|
+
let output = "";
|
|
45
|
+
let resultData = {};
|
|
46
|
+
switch (action) {
|
|
47
|
+
case "create": {
|
|
48
|
+
if (!name) {
|
|
49
|
+
return ResponseFormatter.error(new Error("Label name is required for create action"));
|
|
50
|
+
}
|
|
51
|
+
const createResponse = await gmail.users.labels.create({
|
|
52
|
+
userId: "me",
|
|
53
|
+
requestBody: {
|
|
54
|
+
name,
|
|
55
|
+
labelListVisibility: labelListVisibility || "labelShow",
|
|
56
|
+
messageListVisibility: messageListVisibility || "show",
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const createdLabel = createResponse.data;
|
|
60
|
+
output = `✅ Successfully created label\n\n`;
|
|
61
|
+
output += `Label ID: ${createdLabel.id}\n`;
|
|
62
|
+
output += `Name: ${createdLabel.name}\n`;
|
|
63
|
+
output += `Label List Visibility: ${createdLabel.labelListVisibility}\n`;
|
|
64
|
+
output += `Message List Visibility: ${createdLabel.messageListVisibility}`;
|
|
65
|
+
resultData = {
|
|
66
|
+
action: "create",
|
|
67
|
+
labelId: createdLabel.id,
|
|
68
|
+
name: createdLabel.name,
|
|
69
|
+
labelListVisibility: createdLabel.labelListVisibility,
|
|
70
|
+
messageListVisibility: createdLabel.messageListVisibility,
|
|
71
|
+
};
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case "update": {
|
|
75
|
+
if (!labelId) {
|
|
76
|
+
return ResponseFormatter.error(new Error("Label ID is required for update action"));
|
|
77
|
+
}
|
|
78
|
+
const updateBody = {};
|
|
79
|
+
if (name)
|
|
80
|
+
updateBody.name = name;
|
|
81
|
+
if (labelListVisibility)
|
|
82
|
+
updateBody.labelListVisibility = labelListVisibility;
|
|
83
|
+
if (messageListVisibility)
|
|
84
|
+
updateBody.messageListVisibility = messageListVisibility;
|
|
85
|
+
if (Object.keys(updateBody).length === 0) {
|
|
86
|
+
return ResponseFormatter.error(new Error("At least one property (name, labelListVisibility, or messageListVisibility) must be provided for update"));
|
|
87
|
+
}
|
|
88
|
+
const updateResponse = await gmail.users.labels.update({
|
|
89
|
+
userId: "me",
|
|
90
|
+
id: labelId,
|
|
91
|
+
requestBody: updateBody,
|
|
92
|
+
});
|
|
93
|
+
const updatedLabel = updateResponse.data;
|
|
94
|
+
output = `✅ Successfully updated label\n\n`;
|
|
95
|
+
output += `Label ID: ${updatedLabel.id}\n`;
|
|
96
|
+
output += `Name: ${updatedLabel.name}\n`;
|
|
97
|
+
output += `Label List Visibility: ${updatedLabel.labelListVisibility}\n`;
|
|
98
|
+
output += `Message List Visibility: ${updatedLabel.messageListVisibility}`;
|
|
99
|
+
resultData = {
|
|
100
|
+
action: "update",
|
|
101
|
+
labelId: updatedLabel.id,
|
|
102
|
+
name: updatedLabel.name,
|
|
103
|
+
labelListVisibility: updatedLabel.labelListVisibility,
|
|
104
|
+
messageListVisibility: updatedLabel.messageListVisibility,
|
|
105
|
+
};
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case "delete": {
|
|
109
|
+
if (!labelId) {
|
|
110
|
+
return ResponseFormatter.error(new Error("Label ID is required for delete action"));
|
|
111
|
+
}
|
|
112
|
+
await gmail.users.labels.delete({
|
|
113
|
+
userId: "me",
|
|
114
|
+
id: labelId,
|
|
115
|
+
});
|
|
116
|
+
output = `✅ Successfully deleted label: ${labelId}`;
|
|
117
|
+
resultData = {
|
|
118
|
+
action: "delete",
|
|
119
|
+
labelId,
|
|
120
|
+
};
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
default:
|
|
124
|
+
return ResponseFormatter.error(new Error(`Invalid action: ${action}. Must be create, update, or delete.`));
|
|
125
|
+
}
|
|
126
|
+
return ResponseFormatter.success(resultData, output);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return ResponseFormatter.error(error);
|
|
130
|
+
}
|
|
131
|
+
}
|