gmcp 0.3.0 → 0.5.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 (3) hide show
  1. package/README.md +4 -2
  2. package/dist/index.js +360 -160
  3. package/package.json +6 -6
package/README.md CHANGED
@@ -148,7 +148,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
148
148
 
149
149
  ## Tools
150
150
 
151
- ### Gmail (15 tools)
151
+ ### Gmail (17 tools)
152
152
 
153
153
  | Tool | Description |
154
154
  |------|-------------|
@@ -160,6 +160,8 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
160
160
  | `gmcp_gmail_send_email` | Send new email |
161
161
  | `gmcp_gmail_reply` | Reply to email in thread |
162
162
  | `gmcp_gmail_create_draft` | Create draft message |
163
+ | `gmcp_gmail_delete_email` | Permanently delete email (bypasses trash) |
164
+ | `gmcp_gmail_archive_email` | Archive email (remove from inbox) |
163
165
  | `gmcp_gmail_list_labels` | List all labels |
164
166
  | `gmcp_gmail_get_label` | Get label details |
165
167
  | `gmcp_gmail_create_label` | Create custom label |
@@ -193,7 +195,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
193
195
  |-------|--------|
194
196
  | `gmail.readonly` | Read emails and labels |
195
197
  | `gmail.send` | Send emails |
196
- | `gmail.modify` | Read, modify labels |
198
+ | `gmail.modify` | Read, modify labels, delete emails |
197
199
  | `gmail.labels` | Manage labels |
198
200
  | `gmail.compose` | Create drafts and send |
199
201
  | `calendar.readonly` | Read calendars and events |
package/dist/index.js CHANGED
@@ -647,6 +647,16 @@ function createGmailClient(auth, logger) {
647
647
  } catch (error) {
648
648
  throw new Error(`Failed to delete label ${labelId}: ${error}`);
649
649
  }
650
+ },
651
+ async deleteEmail(messageId) {
652
+ try {
653
+ await gmail.users.messages.delete({
654
+ userId: "me",
655
+ id: messageId
656
+ });
657
+ } catch (error) {
658
+ throw new Error(`Failed to delete message ${messageId}: ${error}`);
659
+ }
650
660
  }
651
661
  };
652
662
  }
@@ -729,7 +739,7 @@ function registerTools(server, client, tools, logger) {
729
739
  }
730
740
  }
731
741
 
732
- // src/tools/batch-modify.ts
742
+ // src/tools/archive-email.ts
733
743
  import json2md from "json2md";
734
744
  import { z } from "zod";
735
745
 
@@ -765,13 +775,108 @@ function createErrorResponse(context, error, logger) {
765
775
  };
766
776
  }
767
777
 
768
- // src/tools/batch-modify.ts
769
- var BatchModifyInputSchema = z.object({
770
- message_ids: z.array(z.string()).min(1, "Must provide at least one message ID").max(1000, "Maximum 1000 messages per batch").describe("Array of Gmail message IDs to modify (max 1000)"),
771
- add_labels: z.array(z.string()).optional().describe("Label IDs to add to all messages (e.g., ['STARRED', 'IMPORTANT'])"),
772
- remove_labels: z.array(z.string()).optional().describe("Label IDs to remove from all messages (e.g., ['UNREAD', 'INBOX'])"),
778
+ // src/tools/archive-email.ts
779
+ var ArchiveEmailInputSchema = z.object({
780
+ message_id: z.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to archive"),
773
781
  output_format: z.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
774
782
  });
783
+ function archiveToMarkdown(email) {
784
+ const sections = [
785
+ { h1: "Email Archived Successfully" },
786
+ { h2: "Message Details" },
787
+ {
788
+ ul: [
789
+ `**Subject:** ${email.subject}`,
790
+ `**From:** ${email.from}`,
791
+ `**Message ID:** ${email.id}`
792
+ ]
793
+ },
794
+ { h2: "Current Labels" },
795
+ {
796
+ p: email.labels.length > 0 ? email.labels.join(", ") : "*No labels on this message*"
797
+ },
798
+ { h2: "Notes" },
799
+ {
800
+ ul: [
801
+ "The email has been removed from your inbox",
802
+ "The email is still accessible in All Mail",
803
+ "To unarchive, add the INBOX label back to the message"
804
+ ]
805
+ }
806
+ ];
807
+ return json2md(sections);
808
+ }
809
+ async function archiveEmailTool(gmailClient, params) {
810
+ try {
811
+ const email = await gmailClient.modifyLabels(params.message_id, undefined, [
812
+ "INBOX"
813
+ ]);
814
+ const formattedEmail = formatEmailForOutput(email);
815
+ const output = {
816
+ message_id: params.message_id,
817
+ subject: email.subject,
818
+ archived: true,
819
+ removed_labels: ["INBOX"],
820
+ current_labels: email.labels || []
821
+ };
822
+ const textContent = params.output_format === "json" ? JSON.stringify(output, null, 2) : archiveToMarkdown({
823
+ ...formattedEmail,
824
+ labels: email.labels || []
825
+ });
826
+ return {
827
+ content: [{ type: "text", text: textContent }],
828
+ structuredContent: output
829
+ };
830
+ } catch (error) {
831
+ return createErrorResponse("archiving email", error);
832
+ }
833
+ }
834
+ var ARCHIVE_EMAIL_DESCRIPTION = `Archive a Gmail email by removing it from the inbox.
835
+
836
+ This tool archives an email message by removing the INBOX label. The email remains accessible in "All Mail" and can be unarchived by adding the INBOX label back.
837
+
838
+ **Parameters**:
839
+ - \`message_id\` (string, required): The Gmail message ID to archive
840
+ - \`output_format\` (string, optional): Output format: "markdown" (default) or "json"
841
+
842
+ **Returns**:
843
+ - \`message_id\`: The archived message ID
844
+ - \`subject\`: Email subject
845
+ - \`archived\`: Always true on success
846
+ - \`removed_labels\`: Labels that were removed (always ["INBOX"])
847
+ - \`current_labels\`: All current labels on the message after archiving
848
+
849
+ **Examples**:
850
+ - Archive email: \`{ "message_id": "18f3c5d4e8a2b1c0" }\`
851
+ - Archive with JSON output: \`{ "message_id": "18f3c5d4e8a2b1c0", "output_format": "json" }\`
852
+
853
+ **Important Notes**:
854
+ - This is a reversible operation - archived emails can be unarchived
855
+ - The email is moved out of the inbox but remains in "All Mail"
856
+ - To unarchive, use \`modify_labels\` with \`add_labels: ["INBOX"]\`
857
+ - This is different from \`delete_email\` which permanently removes the message
858
+
859
+ **Use Cases**:
860
+ - Clean up inbox without deleting emails
861
+ - Archive emails after reading/processing them
862
+ - Remove emails from inbox while keeping them for reference
863
+
864
+ **Error Handling**:
865
+ - Returns error if message ID doesn't exist
866
+ - Returns error if authentication lacks sufficient permissions
867
+
868
+ **Scope Requirements**:
869
+ - Requires \`gmail.modify\` or full \`mail.google.com\` scope`;
870
+
871
+ // src/tools/batch-modify.ts
872
+ import json2md2 from "json2md";
873
+ import { z as z2 } from "zod";
874
+ var BatchModifyInputSchema = z2.object({
875
+ message_ids: z2.array(z2.string()).min(1, "Must provide at least one message ID").max(1000, "Maximum 1000 messages per batch").describe("Array of Gmail message IDs to modify (max 1000)"),
876
+ add_labels: z2.array(z2.string()).optional().describe("Label IDs to add to all messages (e.g., ['STARRED', 'IMPORTANT'])"),
877
+ remove_labels: z2.array(z2.string()).optional().describe("Label IDs to remove from all messages (e.g., ['UNREAD', 'INBOX'])"),
878
+ output_format: z2.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
879
+ });
775
880
  function batchModificationToMarkdown(messageCount, addedLabels, removedLabels) {
776
881
  const sections = [
777
882
  { h1: "Batch Label Modification Successful" },
@@ -788,7 +893,7 @@ function batchModificationToMarkdown(messageCount, addedLabels, removedLabels) {
788
893
  sections.push({
789
894
  p: `All ${messageCount} messages have been updated successfully.`
790
895
  });
791
- return json2md(sections);
896
+ return json2md2(sections);
792
897
  }
793
898
  async function batchModifyTool(gmailClient, params) {
794
899
  try {
@@ -880,10 +985,10 @@ This tool allows you to efficiently add or remove labels from multiple Gmail mes
880
985
  - Recommended for operations affecting more than 5 messages`;
881
986
 
882
987
  // src/tools/calendar-create.ts
883
- import { z as z2 } from "zod";
988
+ import { z as z3 } from "zod";
884
989
 
885
990
  // src/utils/markdown.ts
886
- import json2md2 from "json2md";
991
+ import json2md3 from "json2md";
887
992
  function emailToJson2md(email) {
888
993
  const elements = [
889
994
  { h2: email.subject },
@@ -925,7 +1030,7 @@ function searchResultsToMarkdown(query, data) {
925
1030
  });
926
1031
  }
927
1032
  }
928
- return json2md2(elements);
1033
+ return json2md3(elements);
929
1034
  }
930
1035
  function calendarListToMarkdown(data) {
931
1036
  const sections = [
@@ -951,7 +1056,7 @@ function calendarListToMarkdown(data) {
951
1056
  sections.push({ ul: details });
952
1057
  }
953
1058
  }
954
- return json2md2(sections);
1059
+ return json2md3(sections);
955
1060
  }
956
1061
  function formatEventTime(time) {
957
1062
  if (time.date) {
@@ -1018,7 +1123,7 @@ function eventListToMarkdown(data) {
1018
1123
  sections.push({ hr: "" });
1019
1124
  }
1020
1125
  }
1021
- return json2md2(sections);
1126
+ return json2md3(sections);
1022
1127
  }
1023
1128
  function formatAttendeeDetailed(att) {
1024
1129
  const name = att.display_name || att.email;
@@ -1066,23 +1171,23 @@ function eventToMarkdown(event, successMessage) {
1066
1171
  sections.push({ ul: event.attendees.map(formatAttendeeDetailed) });
1067
1172
  }
1068
1173
  addEventMetadata(sections, event);
1069
- return json2md2(sections);
1174
+ return json2md3(sections);
1070
1175
  }
1071
1176
 
1072
1177
  // src/tools/calendar-create.ts
1073
- var CalendarCreateEventInputSchema = z2.object({
1074
- calendar_id: z2.string().default("primary").describe('Calendar ID to create event in (default: "primary")'),
1075
- summary: z2.string().min(1, "Event title is required").describe("Event title/summary (required)"),
1076
- start: z2.string().min(1, "Start time is required").describe('Start time: RFC3339 (e.g., "2024-01-15T09:00:00-08:00") or date for all-day (e.g., "2024-01-15")'),
1077
- end: z2.string().min(1, "End time is required").describe('End time: RFC3339 (e.g., "2024-01-15T10:00:00-08:00") or date for all-day (e.g., "2024-01-15")'),
1078
- description: z2.string().optional().describe("Event description (optional)"),
1079
- location: z2.string().optional().describe("Event location (optional)"),
1080
- attendees: z2.array(z2.string().email()).optional().describe("Array of attendee email addresses (optional)"),
1081
- timezone: z2.string().optional().describe('IANA timezone (e.g., "America/Los_Angeles", optional)'),
1082
- recurrence: z2.array(z2.string()).optional().describe('Recurrence rules as RRULE strings (e.g., ["RRULE:FREQ=WEEKLY;COUNT=10"], optional)'),
1083
- add_meet: z2.boolean().default(false).describe("Auto-create Google Meet conference link (default: false)"),
1084
- confirm: z2.boolean().default(false).describe("Must be true to create the event (safety check)"),
1085
- output_format: z2.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1178
+ var CalendarCreateEventInputSchema = z3.object({
1179
+ calendar_id: z3.string().default("primary").describe('Calendar ID to create event in (default: "primary")'),
1180
+ summary: z3.string().min(1, "Event title is required").describe("Event title/summary (required)"),
1181
+ start: z3.string().min(1, "Start time is required").describe('Start time: RFC3339 (e.g., "2024-01-15T09:00:00-08:00") or date for all-day (e.g., "2024-01-15")'),
1182
+ end: z3.string().min(1, "End time is required").describe('End time: RFC3339 (e.g., "2024-01-15T10:00:00-08:00") or date for all-day (e.g., "2024-01-15")'),
1183
+ description: z3.string().optional().describe("Event description (optional)"),
1184
+ location: z3.string().optional().describe("Event location (optional)"),
1185
+ attendees: z3.array(z3.string().email()).optional().describe("Array of attendee email addresses (optional)"),
1186
+ timezone: z3.string().optional().describe('IANA timezone (e.g., "America/Los_Angeles", optional)'),
1187
+ recurrence: z3.array(z3.string()).optional().describe('Recurrence rules as RRULE strings (e.g., ["RRULE:FREQ=WEEKLY;COUNT=10"], optional)'),
1188
+ add_meet: z3.boolean().default(false).describe("Auto-create Google Meet conference link (default: false)"),
1189
+ confirm: z3.boolean().default(false).describe("Must be true to create the event (safety check)"),
1190
+ output_format: z3.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1086
1191
  });
1087
1192
  async function calendarCreateEventTool(calendarClient, params) {
1088
1193
  if (!params.confirm) {
@@ -1233,16 +1338,16 @@ Created event object containing:
1233
1338
  - Returns error if Calendar API request fails`;
1234
1339
 
1235
1340
  // src/tools/calendar-events.ts
1236
- import { z as z3 } from "zod";
1237
- var CalendarEventsInputSchema = z3.object({
1238
- calendar_id: z3.string().default("primary").describe('Calendar ID to list events from (default: "primary")'),
1239
- time_min: z3.string().optional().describe("Lower bound for event start time (RFC3339, e.g., 2024-01-01T00:00:00Z)"),
1240
- time_max: z3.string().optional().describe("Upper bound for event start time (RFC3339, e.g., 2024-12-31T23:59:59Z)"),
1241
- max_results: z3.number().int().min(1).max(250).default(10).describe("Maximum number of events to return (default: 10, max: 250)"),
1242
- query: z3.string().optional().describe("Free text search query to filter events"),
1243
- single_events: z3.boolean().default(true).describe("Expand recurring events into individual instances (default: true)"),
1244
- order_by: z3.enum(["startTime", "updated"]).default("startTime").describe('Sort order: "startTime" (default) or "updated"'),
1245
- output_format: z3.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1341
+ import { z as z4 } from "zod";
1342
+ var CalendarEventsInputSchema = z4.object({
1343
+ calendar_id: z4.string().default("primary").describe('Calendar ID to list events from (default: "primary")'),
1344
+ time_min: z4.string().optional().describe("Lower bound for event start time (RFC3339, e.g., 2024-01-01T00:00:00Z)"),
1345
+ time_max: z4.string().optional().describe("Upper bound for event start time (RFC3339, e.g., 2024-12-31T23:59:59Z)"),
1346
+ max_results: z4.number().int().min(1).max(250).default(10).describe("Maximum number of events to return (default: 10, max: 250)"),
1347
+ query: z4.string().optional().describe("Free text search query to filter events"),
1348
+ single_events: z4.boolean().default(true).describe("Expand recurring events into individual instances (default: true)"),
1349
+ order_by: z4.enum(["startTime", "updated"]).default("startTime").describe('Sort order: "startTime" (default) or "updated"'),
1350
+ output_format: z4.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1246
1351
  });
1247
1352
  async function calendarEventsTool(calendarClient, params) {
1248
1353
  try {
@@ -1340,11 +1445,11 @@ This tool retrieves events from a specified calendar with support for time range
1340
1445
  - Returns empty array if no events match filters`;
1341
1446
 
1342
1447
  // src/tools/calendar-get-event.ts
1343
- import { z as z4 } from "zod";
1344
- var CalendarGetEventInputSchema = z4.object({
1345
- calendar_id: z4.string().default("primary").describe('Calendar ID (default: "primary")'),
1346
- event_id: z4.string().min(1, "Event ID is required").describe("Event ID to retrieve"),
1347
- output_format: z4.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1448
+ import { z as z5 } from "zod";
1449
+ var CalendarGetEventInputSchema = z5.object({
1450
+ calendar_id: z5.string().default("primary").describe('Calendar ID (default: "primary")'),
1451
+ event_id: z5.string().min(1, "Event ID is required").describe("Event ID to retrieve"),
1452
+ output_format: z5.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1348
1453
  });
1349
1454
  async function calendarGetEventTool(calendarClient, params) {
1350
1455
  try {
@@ -1436,10 +1541,10 @@ Complete event object containing:
1436
1541
  - Returns error if Calendar API request fails`;
1437
1542
 
1438
1543
  // src/tools/calendar-list.ts
1439
- import { z as z5 } from "zod";
1440
- var CalendarListInputSchema = z5.object({
1441
- show_hidden: z5.boolean().default(false).describe("Include hidden calendars in the results (default: false)"),
1442
- output_format: z5.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1544
+ import { z as z6 } from "zod";
1545
+ var CalendarListInputSchema = z6.object({
1546
+ show_hidden: z6.boolean().default(false).describe("Include hidden calendars in the results (default: false)"),
1547
+ output_format: z6.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1443
1548
  });
1444
1549
  async function calendarListTool(calendarClient, params) {
1445
1550
  try {
@@ -1501,16 +1606,16 @@ This tool retrieves all calendars accessible by the authenticated user, includin
1501
1606
  - Returns error if Calendar API request fails`;
1502
1607
 
1503
1608
  // src/tools/create-draft.ts
1504
- import json2md3 from "json2md";
1505
- import { z as z6 } from "zod";
1506
- var CreateDraftInputSchema = z6.object({
1507
- to: z6.email("Must be a valid email address").describe("Recipient email address"),
1508
- subject: z6.string().min(1, "Subject cannot be empty").describe("Email subject"),
1509
- body: z6.string().min(1, "Body cannot be empty").describe("Email body content"),
1510
- content_type: z6.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML emails"),
1511
- cc: z6.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
1512
- bcc: z6.email("BCC must be a valid email address").optional().describe("BCC (blind carbon copy) email address"),
1513
- output_format: z6.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1609
+ import json2md4 from "json2md";
1610
+ import { z as z7 } from "zod";
1611
+ var CreateDraftInputSchema = z7.object({
1612
+ to: z7.email("Must be a valid email address").describe("Recipient email address"),
1613
+ subject: z7.string().min(1, "Subject cannot be empty").describe("Email subject"),
1614
+ body: z7.string().min(1, "Body cannot be empty").describe("Email body content"),
1615
+ content_type: z7.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML emails"),
1616
+ cc: z7.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
1617
+ bcc: z7.email("BCC must be a valid email address").optional().describe("BCC (blind carbon copy) email address"),
1618
+ output_format: z7.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1514
1619
  });
1515
1620
  function draftCreatedToMarkdown(params, result) {
1516
1621
  const sections = [
@@ -1530,7 +1635,7 @@ function draftCreatedToMarkdown(params, result) {
1530
1635
  p: "The draft has been saved and will appear in your Drafts folder. You can edit and send it later from Gmail."
1531
1636
  }
1532
1637
  ];
1533
- return json2md3(sections);
1638
+ return json2md4(sections);
1534
1639
  }
1535
1640
  async function createDraftTool(gmailClient, params) {
1536
1641
  try {
@@ -1624,15 +1729,15 @@ This tool creates a draft email in your Gmail Drafts folder. Unlike sending an e
1624
1729
  - Collaborative: Others with access can review drafts`;
1625
1730
 
1626
1731
  // src/tools/create-label.ts
1627
- import json2md4 from "json2md";
1628
- import { z as z7 } from "zod";
1629
- var CreateLabelInputSchema = z7.object({
1630
- name: z7.string().min(1, "Label name cannot be empty").describe("The label name (e.g., 'Work', 'Personal/Family'). Use '/' for nested labels."),
1631
- message_list_visibility: z7.enum(["show", "hide"]).optional().describe("How label appears in message list. Default: 'show'. Use 'hide' to hide messages with this label from message list."),
1632
- label_list_visibility: z7.enum(["labelShow", "labelShowIfUnread", "labelHide"]).optional().describe("How label appears in label list. Default: 'labelShow'. Options: 'labelShow' (always visible), 'labelShowIfUnread' (only when unread), 'labelHide' (hidden)."),
1633
- background_color: z7.string().optional().describe("Background color in hex format (e.g., '#ff0000'). Must provide both background and text color together."),
1634
- text_color: z7.string().optional().describe("Text color in hex format (e.g., '#ffffff'). Must provide both background and text color together."),
1635
- output_format: z7.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1732
+ import json2md5 from "json2md";
1733
+ import { z as z8 } from "zod";
1734
+ var CreateLabelInputSchema = z8.object({
1735
+ name: z8.string().min(1, "Label name cannot be empty").describe("The label name (e.g., 'Work', 'Personal/Family'). Use '/' for nested labels."),
1736
+ message_list_visibility: z8.enum(["show", "hide"]).optional().describe("How label appears in message list. Default: 'show'. Use 'hide' to hide messages with this label from message list."),
1737
+ label_list_visibility: z8.enum(["labelShow", "labelShowIfUnread", "labelHide"]).optional().describe("How label appears in label list. Default: 'labelShow'. Options: 'labelShow' (always visible), 'labelShowIfUnread' (only when unread), 'labelHide' (hidden)."),
1738
+ background_color: z8.string().optional().describe("Background color in hex format (e.g., '#ff0000'). Must provide both background and text color together."),
1739
+ text_color: z8.string().optional().describe("Text color in hex format (e.g., '#ffffff'). Must provide both background and text color together."),
1740
+ output_format: z8.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1636
1741
  });
1637
1742
  function createdLabelToMarkdown(label) {
1638
1743
  const sections = [
@@ -1669,7 +1774,7 @@ function createdLabelToMarkdown(label) {
1669
1774
  sections.push({
1670
1775
  p: `You can now use this label ID (${label.id}) with other tools like modify_labels or batch_modify.`
1671
1776
  });
1672
- return json2md4(sections);
1777
+ return json2md5(sections);
1673
1778
  }
1674
1779
  async function createLabelTool(gmailClient, params) {
1675
1780
  try {
@@ -1760,9 +1865,88 @@ This tool creates a new label with customizable visibility and color settings. L
1760
1865
  **Scope Requirements**:
1761
1866
  - Requires \`gmail.labels\` or \`gmail.modify\` scope`;
1762
1867
 
1868
+ // src/tools/delete-email.ts
1869
+ import json2md6 from "json2md";
1870
+ import { z as z9 } from "zod";
1871
+ var DeleteEmailInputSchema = z9.object({
1872
+ message_id: z9.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to permanently delete"),
1873
+ output_format: z9.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1874
+ });
1875
+ function deletionToMarkdown(messageId) {
1876
+ const sections = [
1877
+ { h1: "Email Deleted Successfully" },
1878
+ {
1879
+ p: `Message with ID **${messageId}** has been permanently deleted from your Gmail account.`
1880
+ },
1881
+ { h2: "Important Notes" },
1882
+ {
1883
+ ul: [
1884
+ "The email has been permanently deleted (not moved to trash)",
1885
+ "This action cannot be undone",
1886
+ "The email cannot be recovered"
1887
+ ]
1888
+ }
1889
+ ];
1890
+ return json2md6(sections);
1891
+ }
1892
+ async function deleteEmailTool(gmailClient, params) {
1893
+ try {
1894
+ await gmailClient.deleteEmail(params.message_id);
1895
+ const output = {
1896
+ message_id: params.message_id,
1897
+ deleted: true,
1898
+ message: "Email permanently deleted. This action cannot be undone."
1899
+ };
1900
+ const textContent = params.output_format === "json" ? JSON.stringify(output, null, 2) : deletionToMarkdown(params.message_id);
1901
+ return {
1902
+ content: [{ type: "text", text: textContent }],
1903
+ structuredContent: output
1904
+ };
1905
+ } catch (error) {
1906
+ return createErrorResponse("deleting email", error);
1907
+ }
1908
+ }
1909
+ var DELETE_EMAIL_DESCRIPTION = `Permanently delete a Gmail email message.
1910
+
1911
+ **WARNING: This is a destructive operation that CANNOT be undone. The email is permanently deleted and bypasses the trash folder.**
1912
+
1913
+ This tool permanently deletes an email message from your Gmail account. Unlike moving to trash, this operation immediately and permanently removes the email.
1914
+
1915
+ **Parameters**:
1916
+ - \`message_id\` (string, required): The Gmail message ID to delete
1917
+ - \`output_format\` (string, optional): Output format: "markdown" (default) or "json"
1918
+
1919
+ **Returns**:
1920
+ - \`message_id\`: The deleted message ID
1921
+ - \`deleted\`: Always true on success
1922
+ - \`message\`: Confirmation message
1923
+
1924
+ **Examples**:
1925
+ - Delete email: \`{ "message_id": "18f3c5d4e8a2b1c0" }\`
1926
+ - Delete with JSON output: \`{ "message_id": "18f3c5d4e8a2b1c0", "output_format": "json" }\`
1927
+
1928
+ **Safety Considerations**:
1929
+ - This is a destructive operation marked with \`destructiveHint: true\`
1930
+ - The email is permanently deleted, not moved to trash
1931
+ - This action cannot be undone - the email cannot be recovered
1932
+ - Consider using \`modify_labels\` with \`add_labels: ["TRASH"]\` if you want recoverable deletion
1933
+ - Use \`get_email\` first to verify which email you're deleting
1934
+
1935
+ **Use Cases**:
1936
+ - Permanently remove sensitive emails
1937
+ - Clean up emails that should not be recoverable
1938
+ - Remove emails that are already in trash permanently
1939
+
1940
+ **Error Handling**:
1941
+ - Returns error if message ID doesn't exist
1942
+ - Returns error if authentication lacks sufficient permissions
1943
+
1944
+ **Scope Requirements**:
1945
+ - Requires \`gmail.modify\` or full \`mail.google.com\` scope`;
1946
+
1763
1947
  // src/tools/delete-label.ts
1764
- import json2md5 from "json2md";
1765
- import { z as z8 } from "zod";
1948
+ import json2md7 from "json2md";
1949
+ import { z as z10 } from "zod";
1766
1950
  var SYSTEM_LABELS = [
1767
1951
  "INBOX",
1768
1952
  "SENT",
@@ -1778,11 +1962,11 @@ var SYSTEM_LABELS = [
1778
1962
  "CATEGORY_UPDATES",
1779
1963
  "CATEGORY_FORUMS"
1780
1964
  ];
1781
- var DeleteLabelInputSchema = z8.object({
1782
- label_id: z8.string().min(1, "Label ID cannot be empty").describe("The label ID to delete (e.g., 'Label_123'). Cannot delete system labels."),
1783
- output_format: z8.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1965
+ var DeleteLabelInputSchema = z10.object({
1966
+ label_id: z10.string().min(1, "Label ID cannot be empty").describe("The label ID to delete (e.g., 'Label_123'). Cannot delete system labels."),
1967
+ output_format: z10.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
1784
1968
  });
1785
- function deletionToMarkdown(labelId) {
1969
+ function deletionToMarkdown2(labelId) {
1786
1970
  const sections = [
1787
1971
  { h1: "Label Deleted Successfully" },
1788
1972
  {
@@ -1798,7 +1982,7 @@ function deletionToMarkdown(labelId) {
1798
1982
  ]
1799
1983
  }
1800
1984
  ];
1801
- return json2md5(sections);
1985
+ return json2md7(sections);
1802
1986
  }
1803
1987
  async function deleteLabelTool(gmailClient, params) {
1804
1988
  try {
@@ -1830,7 +2014,7 @@ async function deleteLabelTool(gmailClient, params) {
1830
2014
  deleted: true,
1831
2015
  message: "Label deleted successfully. The label has been removed from all messages."
1832
2016
  };
1833
- const textContent = params.output_format === "json" ? JSON.stringify(output, null, 2) : deletionToMarkdown(params.label_id);
2017
+ const textContent = params.output_format === "json" ? JSON.stringify(output, null, 2) : deletionToMarkdown2(params.label_id);
1834
2018
  return {
1835
2019
  content: [{ type: "text", text: textContent }],
1836
2020
  structuredContent: output
@@ -1920,11 +2104,11 @@ This tool permanently deletes a user-created label from your Gmail account. Syst
1920
2104
  If you want to hide a label instead of deleting it, consider using the \`update_label\` tool to set \`label_list_visibility\` to "labelHide" instead.`;
1921
2105
 
1922
2106
  // src/tools/get-attachment.ts
1923
- import { z as z9 } from "zod";
1924
- var GetAttachmentInputSchema = z9.object({
1925
- message_id: z9.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID containing the attachment"),
1926
- attachment_id: z9.string().min(1, "Attachment ID cannot be empty").describe("The attachment ID to download (from list_attachments)"),
1927
- output_format: z9.enum(["base64", "json"]).default("base64").describe("Output format: base64 (default, returns raw base64url string) or json (returns structured object)")
2107
+ import { z as z11 } from "zod";
2108
+ var GetAttachmentInputSchema = z11.object({
2109
+ message_id: z11.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID containing the attachment"),
2110
+ attachment_id: z11.string().min(1, "Attachment ID cannot be empty").describe("The attachment ID to download (from list_attachments)"),
2111
+ output_format: z11.enum(["base64", "json"]).default("base64").describe("Output format: base64 (default, returns raw base64url string) or json (returns structured object)")
1928
2112
  });
1929
2113
  async function getAttachmentTool(gmailClient, params) {
1930
2114
  try {
@@ -1991,12 +2175,12 @@ To decode:
1991
2175
  3. Decode base64url data to get original file content`;
1992
2176
 
1993
2177
  // src/tools/get-email.ts
1994
- import json2md6 from "json2md";
1995
- import { z as z10 } from "zod";
1996
- var GetEmailInputSchema = z10.object({
1997
- message_id: z10.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to retrieve"),
1998
- include_body: z10.boolean().default(true).describe("Whether to include full email body in results (default: true)"),
1999
- output_format: z10.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2178
+ import json2md8 from "json2md";
2179
+ import { z as z12 } from "zod";
2180
+ var GetEmailInputSchema = z12.object({
2181
+ message_id: z12.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to retrieve"),
2182
+ include_body: z12.boolean().default(true).describe("Whether to include full email body in results (default: true)"),
2183
+ output_format: z12.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2000
2184
  });
2001
2185
  function emailToMarkdown(email) {
2002
2186
  const sections = [
@@ -2023,7 +2207,7 @@ function emailToMarkdown(email) {
2023
2207
  sections.push({ h2: "Snippet" });
2024
2208
  sections.push({ p: email.snippet });
2025
2209
  }
2026
- return json2md6(sections);
2210
+ return json2md8(sections);
2027
2211
  }
2028
2212
  async function getEmailTool(gmailClient, params) {
2029
2213
  try {
@@ -2074,11 +2258,11 @@ This tool retrieves a specific email message from Gmail using its unique message
2074
2258
  - Retrieve email for further processing or analysis`;
2075
2259
 
2076
2260
  // src/tools/get-label.ts
2077
- import json2md7 from "json2md";
2078
- import { z as z11 } from "zod";
2079
- var GetLabelInputSchema = z11.object({
2080
- label_id: z11.string().min(1, "Label ID cannot be empty").describe("The label ID to retrieve (e.g., 'INBOX', 'Label_123')"),
2081
- output_format: z11.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2261
+ import json2md9 from "json2md";
2262
+ import { z as z13 } from "zod";
2263
+ var GetLabelInputSchema = z13.object({
2264
+ label_id: z13.string().min(1, "Label ID cannot be empty").describe("The label ID to retrieve (e.g., 'INBOX', 'Label_123')"),
2265
+ output_format: z13.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2082
2266
  });
2083
2267
  function labelToMarkdown(label) {
2084
2268
  const sections = [
@@ -2113,7 +2297,7 @@ function labelToMarkdown(label) {
2113
2297
  ]
2114
2298
  });
2115
2299
  }
2116
- return json2md7(sections);
2300
+ return json2md9(sections);
2117
2301
  }
2118
2302
  async function getLabelTool(gmailClient, params) {
2119
2303
  try {
@@ -2180,12 +2364,12 @@ This tool retrieves comprehensive details about a label, including its name, typ
2180
2364
  - System labels and custom labels are both supported`;
2181
2365
 
2182
2366
  // src/tools/get-thread.ts
2183
- import json2md8 from "json2md";
2184
- import { z as z12 } from "zod";
2185
- var GetThreadInputSchema = z12.object({
2186
- thread_id: z12.string().min(1, "Thread ID cannot be empty").describe("The Gmail thread ID to retrieve"),
2187
- include_body: z12.boolean().default(false).describe("Whether to include full email body for all messages (default: false)"),
2188
- output_format: z12.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2367
+ import json2md10 from "json2md";
2368
+ import { z as z14 } from "zod";
2369
+ var GetThreadInputSchema = z14.object({
2370
+ thread_id: z14.string().min(1, "Thread ID cannot be empty").describe("The Gmail thread ID to retrieve"),
2371
+ include_body: z14.boolean().default(false).describe("Whether to include full email body for all messages (default: false)"),
2372
+ output_format: z14.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2189
2373
  });
2190
2374
  function threadToMarkdown(threadId, messages) {
2191
2375
  const sections = [
@@ -2220,7 +2404,7 @@ function threadToMarkdown(threadId, messages) {
2220
2404
  sections.push({ p: "---" });
2221
2405
  }
2222
2406
  }
2223
- return json2md8(sections);
2407
+ return json2md10(sections);
2224
2408
  }
2225
2409
  async function getThreadTool(gmailClient, params) {
2226
2410
  try {
@@ -2278,11 +2462,11 @@ This tool retrieves all messages in a Gmail conversation thread (email chain). T
2278
2462
  - Extract all messages from a discussion thread`;
2279
2463
 
2280
2464
  // src/tools/list-attachments.ts
2281
- import json2md9 from "json2md";
2282
- import { z as z13 } from "zod";
2283
- var ListAttachmentsInputSchema = z13.object({
2284
- message_id: z13.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to list attachments from"),
2285
- output_format: z13.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2465
+ import json2md11 from "json2md";
2466
+ import { z as z15 } from "zod";
2467
+ var ListAttachmentsInputSchema = z15.object({
2468
+ message_id: z15.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to list attachments from"),
2469
+ output_format: z15.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2286
2470
  });
2287
2471
  function formatBytes(bytes) {
2288
2472
  if (bytes === 0) {
@@ -2314,7 +2498,7 @@ function attachmentsToMarkdown(messageId, attachments) {
2314
2498
  });
2315
2499
  }
2316
2500
  }
2317
- return json2md9(sections);
2501
+ return json2md11(sections);
2318
2502
  }
2319
2503
  async function listAttachmentsTool(gmailClient, params) {
2320
2504
  try {
@@ -2372,10 +2556,10 @@ This tool retrieves metadata about all attachments in a specific email message,
2372
2556
  - List attachment IDs for use with get_attachment tool`;
2373
2557
 
2374
2558
  // src/tools/list-labels.ts
2375
- import json2md10 from "json2md";
2376
- import { z as z14 } from "zod";
2377
- var ListLabelsInputSchema = z14.object({
2378
- output_format: z14.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2559
+ import json2md12 from "json2md";
2560
+ import { z as z16 } from "zod";
2561
+ var ListLabelsInputSchema = z16.object({
2562
+ output_format: z16.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2379
2563
  });
2380
2564
  function labelsToMarkdown(labels) {
2381
2565
  const sections = [{ h1: "Gmail Labels" }];
@@ -2392,7 +2576,7 @@ function labelsToMarkdown(labels) {
2392
2576
  if (labels.system.length === 0 && labels.user.length === 0) {
2393
2577
  sections.push({ p: "*No labels found*" });
2394
2578
  }
2395
- return json2md10(sections);
2579
+ return json2md12(sections);
2396
2580
  }
2397
2581
  async function listLabelsTool(gmailClient, params) {
2398
2582
  try {
@@ -2465,13 +2649,13 @@ Custom labels are created by users for organizing emails. They have IDs like \`L
2465
2649
  - Returns error if Gmail API is unreachable`;
2466
2650
 
2467
2651
  // src/tools/modify-labels.ts
2468
- import json2md11 from "json2md";
2469
- import { z as z15 } from "zod";
2470
- var ModifyLabelsInputSchema = z15.object({
2471
- message_id: z15.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to modify labels for"),
2472
- add_labels: z15.array(z15.string()).optional().describe("Label IDs to add (e.g., ['STARRED', 'INBOX', 'UNREAD'] or custom label IDs)"),
2473
- remove_labels: z15.array(z15.string()).optional().describe("Label IDs to remove (e.g., ['UNREAD', 'INBOX'] to mark read and archive)"),
2474
- output_format: z15.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2652
+ import json2md13 from "json2md";
2653
+ import { z as z17 } from "zod";
2654
+ var ModifyLabelsInputSchema = z17.object({
2655
+ message_id: z17.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to modify labels for"),
2656
+ add_labels: z17.array(z17.string()).optional().describe("Label IDs to add (e.g., ['STARRED', 'INBOX', 'UNREAD'] or custom label IDs)"),
2657
+ remove_labels: z17.array(z17.string()).optional().describe("Label IDs to remove (e.g., ['UNREAD', 'INBOX'] to mark read and archive)"),
2658
+ output_format: z17.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2475
2659
  });
2476
2660
  function labelModificationToMarkdown(email, addedLabels, removedLabels) {
2477
2661
  const sections = [
@@ -2497,7 +2681,7 @@ function labelModificationToMarkdown(email, addedLabels, removedLabels) {
2497
2681
  sections.push({
2498
2682
  p: email.labels.length > 0 ? email.labels.join(", ") : "*No labels on this message*"
2499
2683
  });
2500
- return json2md11(sections);
2684
+ return json2md13(sections);
2501
2685
  }
2502
2686
  async function modifyLabelsTool(gmailClient, params) {
2503
2687
  try {
@@ -2588,15 +2772,15 @@ This tool allows you to add or remove labels from a Gmail message. Labels are us
2588
2772
  - Move messages to trash or spam`;
2589
2773
 
2590
2774
  // src/tools/reply.ts
2591
- import json2md12 from "json2md";
2592
- import { z as z16 } from "zod";
2593
- var ReplyInputSchema = z16.object({
2594
- message_id: z16.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to reply to"),
2595
- body: z16.string().min(1, "Reply body cannot be empty").describe("Reply message body"),
2596
- content_type: z16.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML replies"),
2597
- cc: z16.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
2598
- confirm: z16.boolean().default(false).describe("Set to true to confirm and send the reply. If false, returns preview only."),
2599
- output_format: z16.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2775
+ import json2md14 from "json2md";
2776
+ import { z as z18 } from "zod";
2777
+ var ReplyInputSchema = z18.object({
2778
+ message_id: z18.string().min(1, "Message ID cannot be empty").describe("The Gmail message ID to reply to"),
2779
+ body: z18.string().min(1, "Reply body cannot be empty").describe("Reply message body"),
2780
+ content_type: z18.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML replies"),
2781
+ cc: z18.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
2782
+ confirm: z18.boolean().default(false).describe("Set to true to confirm and send the reply. If false, returns preview only."),
2783
+ output_format: z18.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2600
2784
  });
2601
2785
  function replyPreviewToMarkdown(originalEmail, replyBody, contentType, cc) {
2602
2786
  const sections = [
@@ -2624,7 +2808,7 @@ function replyPreviewToMarkdown(originalEmail, replyBody, contentType, cc) {
2624
2808
  { h2: "Reply Body" },
2625
2809
  { p: replyBody }
2626
2810
  ];
2627
- return json2md12(sections);
2811
+ return json2md14(sections);
2628
2812
  }
2629
2813
  function replySentToMarkdown(originalEmail, result, cc) {
2630
2814
  const sections = [
@@ -2643,7 +2827,7 @@ function replySentToMarkdown(originalEmail, result, cc) {
2643
2827
  p: "Your reply has been sent and added to the conversation thread."
2644
2828
  }
2645
2829
  ];
2646
- return json2md12(sections);
2830
+ return json2md14(sections);
2647
2831
  }
2648
2832
  async function replyTool(gmailClient, params) {
2649
2833
  try {
@@ -2767,13 +2951,13 @@ This tool sends a reply to an existing email, automatically threading it in the
2767
2951
  4. Call with \`confirm: true\` to send`;
2768
2952
 
2769
2953
  // src/tools/search.ts
2770
- import { z as z17 } from "zod";
2771
- var SearchEmailsInputSchema = z17.object({
2772
- query: z17.string().min(1, "Query cannot be empty").describe('Gmail search query using Gmail search syntax (e.g., "from:user@example.com subject:test is:unread")'),
2773
- max_results: z17.number().int().min(1).max(100).default(10).describe("Maximum number of emails to return (default: 10, max: 100)"),
2774
- include_body: z17.boolean().default(false).describe("Whether to include full email body in results (default: false)"),
2775
- page_token: z17.string().optional().describe("Token for pagination to fetch next page of results"),
2776
- output_format: z17.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2954
+ import { z as z19 } from "zod";
2955
+ var SearchEmailsInputSchema = z19.object({
2956
+ query: z19.string().min(1, "Query cannot be empty").describe('Gmail search query using Gmail search syntax (e.g., "from:user@example.com subject:test is:unread")'),
2957
+ max_results: z19.number().int().min(1).max(100).default(10).describe("Maximum number of emails to return (default: 10, max: 100)"),
2958
+ include_body: z19.boolean().default(false).describe("Whether to include full email body in results (default: false)"),
2959
+ page_token: z19.string().optional().describe("Token for pagination to fetch next page of results"),
2960
+ output_format: z19.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2777
2961
  });
2778
2962
  async function searchEmailsTool(gmailClient, params) {
2779
2963
  try {
@@ -2843,17 +3027,17 @@ This tool allows you to search through your Gmail messages using the same query
2843
3027
  - Empty results if no emails match the query`;
2844
3028
 
2845
3029
  // src/tools/send-email.ts
2846
- import json2md13 from "json2md";
2847
- import { z as z18 } from "zod";
2848
- var SendEmailInputSchema = z18.object({
2849
- to: z18.email("Must be a valid email address").describe("Recipient email address"),
2850
- subject: z18.string().min(1, "Subject cannot be empty").describe("Email subject"),
2851
- body: z18.string().min(1, "Body cannot be empty").describe("Email body content"),
2852
- content_type: z18.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML emails"),
2853
- cc: z18.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
2854
- bcc: z18.email("BCC must be a valid email address").optional().describe("BCC (blind carbon copy) email address"),
2855
- confirm: z18.boolean().default(false).describe("Set to true to confirm and send the email. If false, returns preview only."),
2856
- output_format: z18.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
3030
+ import json2md15 from "json2md";
3031
+ import { z as z20 } from "zod";
3032
+ var SendEmailInputSchema = z20.object({
3033
+ to: z20.email("Must be a valid email address").describe("Recipient email address"),
3034
+ subject: z20.string().min(1, "Subject cannot be empty").describe("Email subject"),
3035
+ body: z20.string().min(1, "Body cannot be empty").describe("Email body content"),
3036
+ content_type: z20.enum(["text/plain", "text/html"]).default("text/plain").describe("Content type: text/plain (default) or text/html for HTML emails"),
3037
+ cc: z20.email("CC must be a valid email address").optional().describe("CC (carbon copy) email address"),
3038
+ bcc: z20.email("BCC must be a valid email address").optional().describe("BCC (blind carbon copy) email address"),
3039
+ confirm: z20.boolean().default(false).describe("Set to true to confirm and send the email. If false, returns preview only."),
3040
+ output_format: z20.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
2857
3041
  });
2858
3042
  function emailPreviewToMarkdown(params) {
2859
3043
  const sections = [
@@ -2874,7 +3058,7 @@ function emailPreviewToMarkdown(params) {
2874
3058
  { h2: "Body" },
2875
3059
  { p: params.body }
2876
3060
  ];
2877
- return json2md13(sections);
3061
+ return json2md15(sections);
2878
3062
  }
2879
3063
  function emailSentToMarkdown(params, result) {
2880
3064
  const sections = [
@@ -2894,7 +3078,7 @@ function emailSentToMarkdown(params, result) {
2894
3078
  p: "The email has been sent and will appear in your Sent folder."
2895
3079
  }
2896
3080
  ];
2897
- return json2md13(sections);
3081
+ return json2md15(sections);
2898
3082
  }
2899
3083
  async function sendEmailTool(gmailClient, params) {
2900
3084
  try {
@@ -3000,8 +3184,8 @@ This tool sends email through your Gmail account. It includes a safety feature:
3000
3184
  3. Call again with \`confirm: true\` to send`;
3001
3185
 
3002
3186
  // src/tools/update-label.ts
3003
- import json2md14 from "json2md";
3004
- import { z as z19 } from "zod";
3187
+ import json2md16 from "json2md";
3188
+ import { z as z21 } from "zod";
3005
3189
  var SYSTEM_LABELS2 = [
3006
3190
  "INBOX",
3007
3191
  "SENT",
@@ -3012,14 +3196,14 @@ var SYSTEM_LABELS2 = [
3012
3196
  "IMPORTANT",
3013
3197
  "UNREAD"
3014
3198
  ];
3015
- var UpdateLabelInputSchema = z19.object({
3016
- label_id: z19.string().min(1, "Label ID cannot be empty").describe("The label ID to update (e.g., 'Label_123' or 'INBOX')"),
3017
- name: z19.string().optional().describe("New label name. Cannot rename system labels. Use '/' for nested labels."),
3018
- message_list_visibility: z19.enum(["show", "hide"]).optional().describe("How label appears in message list"),
3019
- label_list_visibility: z19.enum(["labelShow", "labelShowIfUnread", "labelHide"]).optional().describe("How label appears in label list (sidebar)"),
3020
- background_color: z19.string().optional().describe("Background color in hex format (e.g., '#ff0000'). Must provide both background and text color together."),
3021
- text_color: z19.string().optional().describe("Text color in hex format (e.g., '#ffffff'). Must provide both background and text color together."),
3022
- output_format: z19.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
3199
+ var UpdateLabelInputSchema = z21.object({
3200
+ label_id: z21.string().min(1, "Label ID cannot be empty").describe("The label ID to update (e.g., 'Label_123' or 'INBOX')"),
3201
+ name: z21.string().optional().describe("New label name. Cannot rename system labels. Use '/' for nested labels."),
3202
+ message_list_visibility: z21.enum(["show", "hide"]).optional().describe("How label appears in message list"),
3203
+ label_list_visibility: z21.enum(["labelShow", "labelShowIfUnread", "labelHide"]).optional().describe("How label appears in label list (sidebar)"),
3204
+ background_color: z21.string().optional().describe("Background color in hex format (e.g., '#ff0000'). Must provide both background and text color together."),
3205
+ text_color: z21.string().optional().describe("Text color in hex format (e.g., '#ffffff'). Must provide both background and text color together."),
3206
+ output_format: z21.enum(["markdown", "json"]).default("markdown").describe("Output format: markdown (default) or json")
3023
3207
  });
3024
3208
  function updatedLabelToMarkdown(label, updates) {
3025
3209
  const sections = [
@@ -3067,7 +3251,7 @@ function updatedLabelToMarkdown(label, updates) {
3067
3251
  ]
3068
3252
  });
3069
3253
  }
3070
- return json2md14(sections);
3254
+ return json2md16(sections);
3071
3255
  }
3072
3256
  async function updateLabelTool(gmailClient, params) {
3073
3257
  try {
@@ -3337,6 +3521,22 @@ async function startServer() {
3337
3521
  inputSchema: DeleteLabelInputSchema,
3338
3522
  annotations: DESTRUCTIVE_ANNOTATIONS,
3339
3523
  handler: deleteLabelTool
3524
+ },
3525
+ {
3526
+ name: "gmcp_gmail_delete_email",
3527
+ title: "Delete Gmail Email",
3528
+ description: DELETE_EMAIL_DESCRIPTION,
3529
+ inputSchema: DeleteEmailInputSchema,
3530
+ annotations: DESTRUCTIVE_ANNOTATIONS,
3531
+ handler: deleteEmailTool
3532
+ },
3533
+ {
3534
+ name: "gmcp_gmail_archive_email",
3535
+ title: "Archive Gmail Email",
3536
+ description: ARCHIVE_EMAIL_DESCRIPTION,
3537
+ inputSchema: ArchiveEmailInputSchema,
3538
+ annotations: MODIFY_ANNOTATIONS,
3539
+ handler: archiveEmailTool
3340
3540
  }
3341
3541
  ];
3342
3542
  const calendarTools = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gmcp",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "GMCP Server for Google Workspace with OAuth2 authentication",
5
5
  "module": "src/index.ts",
6
6
  "main": "dist/index.js",
@@ -50,19 +50,19 @@
50
50
  "googleapis": "^170.1.0",
51
51
  "json2md": "^2.0.3",
52
52
  "kleur": "^4.1.5",
53
- "pino": "^9.7.0",
54
- "pino-pretty": "^13.0.0",
53
+ "pino": "^10.3.0",
54
+ "pino-pretty": "^13.1.3",
55
55
  "zod": "^4.3.6"
56
56
  },
57
57
  "devDependencies": {
58
- "@biomejs/biome": "2.3.12",
58
+ "@biomejs/biome": "2.3.13",
59
59
  "@changesets/changelog-github": "^0.5.2",
60
60
  "@changesets/cli": "^2.29.8",
61
61
  "@types/bun": "latest",
62
62
  "@types/json2md": "^1.5.4",
63
63
  "bunup": "^0.16.20",
64
- "lefthook": "^2.0.15",
65
- "ultracite": "7.0.12",
64
+ "lefthook": "^2.0.16",
65
+ "ultracite": "7.1.1",
66
66
  "vitest": "^4.0.18"
67
67
  },
68
68
  "peerDependencies": {