@sempervirens-labs/apple-mail-mcp 1.0.0 → 1.2.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.
@@ -7,7 +7,10 @@
7
7
  "WebFetch(domain:www.npmjs.com)",
8
8
  "Bash(bun install)",
9
9
  "Bash(osascript:*)",
10
- "Bash(npm publish:*)"
10
+ "Bash(npm publish:*)",
11
+ "Bash(bun run build)",
12
+ "Bash(npx tsc:*)",
13
+ "Bash(git push:*)"
11
14
  ]
12
15
  }
13
16
  }
package/README.md CHANGED
@@ -10,6 +10,11 @@ An MCP (Model Context Protocol) server for Apple Mail on macOS. Allows AI assist
10
10
  - **Search Emails** - Search by subject, sender, or content
11
11
  - **Unread Count** - Get unread email counts
12
12
  - **Send Email** - Compose and send emails with CC/BCC support
13
+ - **Archive Email** - Move emails to the Archive mailbox
14
+ - **Delete Email** - Move emails to Trash
15
+ - **Mark as Read/Unread** - Change read status of emails
16
+ - **Create Draft** - Create new draft emails
17
+ - **Create Draft Reply** - Create draft replies to existing emails
13
18
 
14
19
  ## Requirements
15
20
 
@@ -19,18 +24,22 @@ An MCP (Model Context Protocol) server for Apple Mail on macOS. Allows AI assist
19
24
 
20
25
  ## Installation
21
26
 
22
- ### From Source
27
+ ### From npm (Recommended)
23
28
 
24
29
  ```bash
25
- git clone https://github.com/yourusername/apple-mail-mcp.git
26
- cd apple-mail-mcp
27
- bun install
30
+ # Install globally
31
+ bun add -g @sempervirens-labs/apple-mail-mcp
32
+
33
+ # Or run directly without installation
34
+ bunx @sempervirens-labs/apple-mail-mcp
28
35
  ```
29
36
 
30
- ### Using bunx (no installation required)
37
+ ### From Source
31
38
 
32
39
  ```bash
33
- bunx @sempervirens-labs/apple-mail-mcp
40
+ git clone https://github.com/rbouschery/apple-mail-mcp.git
41
+ cd apple-mail-mcp
42
+ bun install
34
43
  ```
35
44
 
36
45
  ## Configuration
@@ -43,21 +52,21 @@ Add to your `~/.claude/settings.json`:
43
52
  {
44
53
  "mcpServers": {
45
54
  "apple-mail": {
46
- "command": "bun",
47
- "args": ["run", "/path/to/apple-mail-mcp/src/index.ts"]
55
+ "command": "bunx",
56
+ "args": ["@sempervirens-labs/apple-mail-mcp"]
48
57
  }
49
58
  }
50
59
  }
51
60
  ```
52
61
 
53
- Or if published to npm:
62
+ Or if running from source:
54
63
 
55
64
  ```json
56
65
  {
57
66
  "mcpServers": {
58
67
  "apple-mail": {
59
- "command": "bunx",
60
- "args": ["apple-mail-mcp"]
68
+ "command": "bun",
69
+ "args": ["run", "/path/to/apple-mail-mcp/src/index.ts"]
61
70
  }
62
71
  }
63
72
  }
@@ -73,8 +82,8 @@ Add to your Cursor MCP settings (Settings > MCP Servers):
73
82
  {
74
83
  "mcpServers": {
75
84
  "apple-mail": {
76
- "command": "bun",
77
- "args": ["run", "/path/to/apple-mail-mcp/src/index.ts"]
85
+ "command": "bunx",
86
+ "args": ["@sempervirens-labs/apple-mail-mcp"]
78
87
  }
79
88
  }
80
89
  }
@@ -86,8 +95,8 @@ Or via Cursor's settings UI:
86
95
  3. Click "Add Server"
87
96
  4. Enter:
88
97
  - **Name**: `apple-mail`
89
- - **Command**: `bun`
90
- - **Arguments**: `run`, `/path/to/apple-mail-mcp/src/index.ts`
98
+ - **Command**: `bunx`
99
+ - **Arguments**: `@sempervirens-labs/apple-mail-mcp`
91
100
 
92
101
  ### Claude Desktop
93
102
 
@@ -97,8 +106,8 @@ Add to your `~/Library/Application Support/Claude/claude_desktop_config.json`:
97
106
  {
98
107
  "mcpServers": {
99
108
  "apple-mail": {
100
- "command": "bun",
101
- "args": ["run", "/path/to/apple-mail-mcp/src/index.ts"]
109
+ "command": "bunx",
110
+ "args": ["@sempervirens-labs/apple-mail-mcp"]
102
111
  }
103
112
  }
104
113
  }
@@ -216,6 +225,120 @@ Send an email using Apple Mail.
216
225
  }
217
226
  ```
218
227
 
228
+ ### `mail_archive`
229
+
230
+ Archive an email by moving it to the Archive mailbox.
231
+
232
+ | Parameter | Type | Required | Default | Description |
233
+ |-----------|------|----------|---------|-------------|
234
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
235
+ | `account` | string | No | - | Account name |
236
+ | `mailbox` | string | No | "INBOX" | Current mailbox of the email |
237
+ | `archiveMailbox` | string | No | auto-detect | Name of the archive folder (auto-detects "Archive", "Archives", or "All Mail") |
238
+
239
+ **Example response:**
240
+ ```json
241
+ {
242
+ "success": true,
243
+ "message": "Message archived successfully"
244
+ }
245
+ ```
246
+
247
+ ### `mail_delete`
248
+
249
+ Delete an email by moving it to Trash.
250
+
251
+ | Parameter | Type | Required | Default | Description |
252
+ |-----------|------|----------|---------|-------------|
253
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
254
+ | `account` | string | No | - | Account name |
255
+ | `mailbox` | string | No | "INBOX" | Current mailbox of the email |
256
+
257
+ **Example response:**
258
+ ```json
259
+ {
260
+ "success": true,
261
+ "message": "Message deleted successfully"
262
+ }
263
+ ```
264
+
265
+ ### `mail_mark_read`
266
+
267
+ Mark an email as read.
268
+
269
+ | Parameter | Type | Required | Default | Description |
270
+ |-----------|------|----------|---------|-------------|
271
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
272
+ | `account` | string | No | - | Account name |
273
+ | `mailbox` | string | No | "INBOX" | Mailbox where the email is located |
274
+
275
+ **Example response:**
276
+ ```json
277
+ {
278
+ "success": true,
279
+ "message": "Message marked as read"
280
+ }
281
+ ```
282
+
283
+ ### `mail_mark_unread`
284
+
285
+ Mark an email as unread.
286
+
287
+ | Parameter | Type | Required | Default | Description |
288
+ |-----------|------|----------|---------|-------------|
289
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
290
+ | `account` | string | No | - | Account name |
291
+ | `mailbox` | string | No | "INBOX" | Mailbox where the email is located |
292
+
293
+ **Example response:**
294
+ ```json
295
+ {
296
+ "success": true,
297
+ "message": "Message marked as unread"
298
+ }
299
+ ```
300
+
301
+ ### `mail_create_draft`
302
+
303
+ Create a new draft email.
304
+
305
+ | Parameter | Type | Required | Description |
306
+ |-----------|------|----------|-------------|
307
+ | `to` | string or string[] | No | Recipient email(s) |
308
+ | `subject` | string | **Yes** | Email subject |
309
+ | `body` | string | **Yes** | Email body |
310
+ | `cc` | string or string[] | No | CC recipient(s) |
311
+ | `bcc` | string or string[] | No | BCC recipient(s) |
312
+ | `from` | string | No | Sender (must be configured account) |
313
+
314
+ **Example response:**
315
+ ```json
316
+ {
317
+ "success": true,
318
+ "message": "Draft created successfully"
319
+ }
320
+ ```
321
+
322
+ ### `mail_create_draft_reply`
323
+
324
+ Create a draft reply to an existing email.
325
+
326
+ | Parameter | Type | Required | Default | Description |
327
+ |-----------|------|----------|---------|-------------|
328
+ | `messageId` | number | **Yes** | - | Email ID to reply to (from mail_get_emails or mail_search) |
329
+ | `body` | string | **Yes** | - | Reply body content |
330
+ | `replyAll` | boolean | No | false | Reply to all recipients |
331
+ | `account` | string | No | - | Account name |
332
+ | `mailbox` | string | No | "INBOX" | Mailbox where the original email is located |
333
+
334
+ **Example response:**
335
+ ```json
336
+ {
337
+ "success": true,
338
+ "message": "Draft reply created successfully"
339
+ }
340
+ ```
341
+
219
342
  ## Permissions
220
343
 
221
344
  On first use, macOS will prompt you to grant permissions:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sempervirens-labs/apple-mail-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server for Apple Mail - list accounts, mailboxes, search emails, and send messages",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -354,3 +354,280 @@ end tell
354
354
  return { success: false, message: error.message };
355
355
  }
356
356
  }
357
+
358
+ /**
359
+ * Archive an email by moving it to the Archive mailbox
360
+ */
361
+ export function archiveEmail(options: {
362
+ messageId: number;
363
+ account?: string;
364
+ mailbox?: string;
365
+ archiveMailbox?: string;
366
+ }): { success: boolean; message: string } {
367
+ const { messageId, account, mailbox = "INBOX", archiveMailbox: customArchiveMailbox } = options;
368
+
369
+ const accountPart = account
370
+ ? `mailbox "${mailbox}" of account "${account}"`
371
+ : `mailbox "${mailbox}"`;
372
+
373
+ // If a custom archive mailbox is specified, use it directly
374
+ const archiveLogic = customArchiveMailbox
375
+ ? `
376
+ set archiveMailbox to missing value
377
+ repeat with mb in mailboxes of theAccount
378
+ if name of mb is "${customArchiveMailbox}" then
379
+ set archiveMailbox to mb
380
+ exit repeat
381
+ end if
382
+ end repeat
383
+
384
+ if archiveMailbox is missing value then
385
+ return "ERROR:Archive mailbox '${customArchiveMailbox}' not found for this account"
386
+ end if`
387
+ : `
388
+ -- Find the Archive mailbox for this account (try common names)
389
+ set archiveMailbox to missing value
390
+ repeat with mb in mailboxes of theAccount
391
+ if name of mb is "Archive" or name of mb is "Archives" or name of mb is "All Mail" then
392
+ set archiveMailbox to mb
393
+ exit repeat
394
+ end if
395
+ end repeat
396
+
397
+ if archiveMailbox is missing value then
398
+ return "ERROR:No Archive mailbox found for this account. Try specifying archiveMailbox parameter with the exact folder name."
399
+ end if`;
400
+
401
+ const script = `
402
+ tell application "Mail"
403
+ try
404
+ set theMailbox to ${accountPart}
405
+ set theMessage to (first message of theMailbox whose id is ${messageId})
406
+ set theAccount to account of theMailbox
407
+ ${archiveLogic}
408
+
409
+ move theMessage to archiveMailbox
410
+ return "Message archived successfully"
411
+ on error errMsg
412
+ return "ERROR:" & errMsg
413
+ end try
414
+ end tell
415
+ `;
416
+
417
+ try {
418
+ const result = runAppleScript(script);
419
+ if (result.startsWith("ERROR:")) {
420
+ return { success: false, message: result.substring(6) };
421
+ }
422
+ return { success: true, message: result || "Message archived successfully" };
423
+ } catch (error: any) {
424
+ return { success: false, message: error.message };
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Delete an email by moving it to the Trash mailbox
430
+ */
431
+ export function deleteEmail(options: {
432
+ messageId: number;
433
+ account?: string;
434
+ mailbox?: string;
435
+ }): { success: boolean; message: string } {
436
+ const { messageId, account, mailbox = "INBOX" } = options;
437
+
438
+ const accountPart = account
439
+ ? `mailbox "${mailbox}" of account "${account}"`
440
+ : `mailbox "${mailbox}"`;
441
+
442
+ const script = `
443
+ tell application "Mail"
444
+ try
445
+ set theMailbox to ${accountPart}
446
+ set theMessage to (first message of theMailbox whose id is ${messageId})
447
+ delete theMessage
448
+ return "Message deleted successfully"
449
+ on error errMsg
450
+ return "ERROR:" & errMsg
451
+ end try
452
+ end tell
453
+ `;
454
+
455
+ try {
456
+ const result = runAppleScript(script);
457
+ if (result.startsWith("ERROR:")) {
458
+ return { success: false, message: result.substring(6) };
459
+ }
460
+ return { success: true, message: result || "Message deleted successfully" };
461
+ } catch (error: any) {
462
+ return { success: false, message: error.message };
463
+ }
464
+ }
465
+
466
+ /**
467
+ * Mark an email as read
468
+ */
469
+ export function markAsRead(options: {
470
+ messageId: number;
471
+ account?: string;
472
+ mailbox?: string;
473
+ }): { success: boolean; message: string } {
474
+ const { messageId, account, mailbox = "INBOX" } = options;
475
+
476
+ const accountPart = account
477
+ ? `mailbox "${mailbox}" of account "${account}"`
478
+ : `mailbox "${mailbox}"`;
479
+
480
+ const script = `
481
+ tell application "Mail"
482
+ try
483
+ set theMailbox to ${accountPart}
484
+ set theMessage to (first message of theMailbox whose id is ${messageId})
485
+ set read status of theMessage to true
486
+ return "Message marked as read"
487
+ on error errMsg
488
+ return "ERROR:" & errMsg
489
+ end try
490
+ end tell
491
+ `;
492
+
493
+ try {
494
+ const result = runAppleScript(script);
495
+ if (result.startsWith("ERROR:")) {
496
+ return { success: false, message: result.substring(6) };
497
+ }
498
+ return { success: true, message: result || "Message marked as read" };
499
+ } catch (error: any) {
500
+ return { success: false, message: error.message };
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Mark an email as unread
506
+ */
507
+ export function markAsUnread(options: {
508
+ messageId: number;
509
+ account?: string;
510
+ mailbox?: string;
511
+ }): { success: boolean; message: string } {
512
+ const { messageId, account, mailbox = "INBOX" } = options;
513
+
514
+ const accountPart = account
515
+ ? `mailbox "${mailbox}" of account "${account}"`
516
+ : `mailbox "${mailbox}"`;
517
+
518
+ const script = `
519
+ tell application "Mail"
520
+ try
521
+ set theMailbox to ${accountPart}
522
+ set theMessage to (first message of theMailbox whose id is ${messageId})
523
+ set read status of theMessage to false
524
+ return "Message marked as unread"
525
+ on error errMsg
526
+ return "ERROR:" & errMsg
527
+ end try
528
+ end tell
529
+ `;
530
+
531
+ try {
532
+ const result = runAppleScript(script);
533
+ if (result.startsWith("ERROR:")) {
534
+ return { success: false, message: result.substring(6) };
535
+ }
536
+ return { success: true, message: result || "Message marked as unread" };
537
+ } catch (error: any) {
538
+ return { success: false, message: error.message };
539
+ }
540
+ }
541
+
542
+ /**
543
+ * Create a draft email
544
+ */
545
+ export function createDraft(options: {
546
+ to?: string | string[];
547
+ subject: string;
548
+ body: string;
549
+ cc?: string | string[];
550
+ bcc?: string | string[];
551
+ from?: string;
552
+ }): { success: boolean; message: string } {
553
+ const { to, subject, body, cc, bcc, from } = options;
554
+
555
+ const toList = to ? (Array.isArray(to) ? to : [to]) : [];
556
+ const ccList = cc ? (Array.isArray(cc) ? cc : [cc]) : [];
557
+ const bccList = bcc ? (Array.isArray(bcc) ? bcc : [bcc]) : [];
558
+
559
+ // Build recipient parts
560
+ const toRecipients = toList.map(addr => `make new to recipient at end of to recipients with properties {address:"${addr}"}`).join("\n ");
561
+ const ccRecipients = ccList.map(addr => `make new cc recipient at end of cc recipients with properties {address:"${addr}"}`).join("\n ");
562
+ const bccRecipients = bccList.map(addr => `make new bcc recipient at end of bcc recipients with properties {address:"${addr}"}`).join("\n ");
563
+
564
+ const fromPart = from ? `, sender:"${from}"` : "";
565
+
566
+ const script = `
567
+ tell application "Mail"
568
+ set newMessage to make new outgoing message with properties {subject:"${subject.replace(/"/g, '\\"')}", content:"${body.replace(/"/g, '\\"').replace(/\n/g, "\\n")}", visible:true${fromPart}}
569
+ tell newMessage
570
+ ${toRecipients}
571
+ ${ccRecipients ? ccRecipients : ""}
572
+ ${bccRecipients ? bccRecipients : ""}
573
+ end tell
574
+ -- Save as draft by not sending, just leaving it open
575
+ return "Draft created successfully"
576
+ end tell
577
+ `;
578
+
579
+ try {
580
+ const result = runAppleScript(script);
581
+ return { success: true, message: result || "Draft created successfully" };
582
+ } catch (error: any) {
583
+ return { success: false, message: error.message };
584
+ }
585
+ }
586
+
587
+ /**
588
+ * Create a draft reply to an existing email
589
+ */
590
+ export function createDraftReply(options: {
591
+ messageId: number;
592
+ body: string;
593
+ replyAll?: boolean;
594
+ account?: string;
595
+ mailbox?: string;
596
+ }): { success: boolean; message: string } {
597
+ const { messageId, body, replyAll = false, account, mailbox = "INBOX" } = options;
598
+
599
+ const accountPart = account
600
+ ? `mailbox "${mailbox}" of account "${account}"`
601
+ : `mailbox "${mailbox}"`;
602
+
603
+ const replyCommand = replyAll ? "reply theMessage with opening window and reply to all" : "reply theMessage with opening window";
604
+
605
+ const script = `
606
+ tell application "Mail"
607
+ try
608
+ set theMailbox to ${accountPart}
609
+ set theMessage to (first message of theMailbox whose id is ${messageId})
610
+
611
+ set replyMessage to ${replyCommand}
612
+
613
+ -- Prepend the new body to the reply
614
+ set currentContent to content of replyMessage
615
+ set content of replyMessage to "${body.replace(/"/g, '\\"').replace(/\n/g, "\\n")}" & return & return & currentContent
616
+
617
+ return "Draft reply created successfully"
618
+ on error errMsg
619
+ return "ERROR:" & errMsg
620
+ end try
621
+ end tell
622
+ `;
623
+
624
+ try {
625
+ const result = runAppleScript(script);
626
+ if (result.startsWith("ERROR:")) {
627
+ return { success: false, message: result.substring(6) };
628
+ }
629
+ return { success: true, message: result || "Draft reply created successfully" };
630
+ } catch (error: any) {
631
+ return { success: false, message: error.message };
632
+ }
633
+ }
package/src/index.ts CHANGED
@@ -15,6 +15,12 @@ import {
15
15
  searchEmails,
16
16
  getUnreadCount,
17
17
  sendEmail,
18
+ archiveEmail,
19
+ deleteEmail,
20
+ markAsRead,
21
+ markAsUnread,
22
+ createDraft,
23
+ createDraftReply,
18
24
  } from "./applescript/mail.js";
19
25
 
20
26
  // Create MCP server
@@ -147,6 +153,148 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
147
153
  };
148
154
  }
149
155
 
156
+ case "mail_archive": {
157
+ const messageId = args?.messageId as number;
158
+ if (!messageId) {
159
+ throw new Error("Required field: messageId");
160
+ }
161
+
162
+ const result = archiveEmail({
163
+ messageId,
164
+ account: args?.account as string | undefined,
165
+ mailbox: (args?.mailbox as string) || "INBOX",
166
+ archiveMailbox: args?.archiveMailbox as string | undefined,
167
+ });
168
+
169
+ return {
170
+ content: [
171
+ {
172
+ type: "text",
173
+ text: JSON.stringify(result, null, 2),
174
+ },
175
+ ],
176
+ };
177
+ }
178
+
179
+ case "mail_delete": {
180
+ const messageId = args?.messageId as number;
181
+ if (!messageId) {
182
+ throw new Error("Required field: messageId");
183
+ }
184
+
185
+ const result = deleteEmail({
186
+ messageId,
187
+ account: args?.account as string | undefined,
188
+ mailbox: (args?.mailbox as string) || "INBOX",
189
+ });
190
+
191
+ return {
192
+ content: [
193
+ {
194
+ type: "text",
195
+ text: JSON.stringify(result, null, 2),
196
+ },
197
+ ],
198
+ };
199
+ }
200
+
201
+ case "mail_mark_read": {
202
+ const messageId = args?.messageId as number;
203
+ if (!messageId) {
204
+ throw new Error("Required field: messageId");
205
+ }
206
+
207
+ const result = markAsRead({
208
+ messageId,
209
+ account: args?.account as string | undefined,
210
+ mailbox: (args?.mailbox as string) || "INBOX",
211
+ });
212
+
213
+ return {
214
+ content: [
215
+ {
216
+ type: "text",
217
+ text: JSON.stringify(result, null, 2),
218
+ },
219
+ ],
220
+ };
221
+ }
222
+
223
+ case "mail_mark_unread": {
224
+ const messageId = args?.messageId as number;
225
+ if (!messageId) {
226
+ throw new Error("Required field: messageId");
227
+ }
228
+
229
+ const result = markAsUnread({
230
+ messageId,
231
+ account: args?.account as string | undefined,
232
+ mailbox: (args?.mailbox as string) || "INBOX",
233
+ });
234
+
235
+ return {
236
+ content: [
237
+ {
238
+ type: "text",
239
+ text: JSON.stringify(result, null, 2),
240
+ },
241
+ ],
242
+ };
243
+ }
244
+
245
+ case "mail_create_draft": {
246
+ const subject = args?.subject as string;
247
+ const body = args?.body as string;
248
+
249
+ if (!subject || !body) {
250
+ throw new Error("Required fields: subject, body");
251
+ }
252
+
253
+ const result = createDraft({
254
+ to: args?.to as string | string[] | undefined,
255
+ subject,
256
+ body,
257
+ cc: args?.cc as string | string[] | undefined,
258
+ bcc: args?.bcc as string | string[] | undefined,
259
+ from: args?.from as string | undefined,
260
+ });
261
+
262
+ return {
263
+ content: [
264
+ {
265
+ type: "text",
266
+ text: JSON.stringify(result, null, 2),
267
+ },
268
+ ],
269
+ };
270
+ }
271
+
272
+ case "mail_create_draft_reply": {
273
+ const messageId = args?.messageId as number;
274
+ const body = args?.body as string;
275
+
276
+ if (!messageId || !body) {
277
+ throw new Error("Required fields: messageId, body");
278
+ }
279
+
280
+ const result = createDraftReply({
281
+ messageId,
282
+ body,
283
+ replyAll: (args?.replyAll as boolean) || false,
284
+ account: args?.account as string | undefined,
285
+ mailbox: (args?.mailbox as string) || "INBOX",
286
+ });
287
+
288
+ return {
289
+ content: [
290
+ {
291
+ type: "text",
292
+ text: JSON.stringify(result, null, 2),
293
+ },
294
+ ],
295
+ };
296
+ }
297
+
150
298
  default:
151
299
  throw new Error(`Unknown tool: ${name}`);
152
300
  }
package/src/tools.ts CHANGED
@@ -146,6 +146,183 @@ export const MAIL_SEND: Tool = {
146
146
  },
147
147
  };
148
148
 
149
+ export const MAIL_ARCHIVE: Tool = {
150
+ name: "mail_archive",
151
+ description: "Archive an email in Apple Mail by moving it to the Archive mailbox",
152
+ inputSchema: {
153
+ type: "object",
154
+ properties: {
155
+ messageId: {
156
+ type: "number",
157
+ description: "The ID of the email message to archive (obtained from mail_get_emails or mail_search)",
158
+ },
159
+ account: {
160
+ type: "string",
161
+ description: "The name of the email account",
162
+ },
163
+ mailbox: {
164
+ type: "string",
165
+ description: "The name of the mailbox/folder where the email currently is (default: INBOX)",
166
+ default: "INBOX",
167
+ },
168
+ archiveMailbox: {
169
+ type: "string",
170
+ description: "The name of the archive mailbox to move the email to (default: auto-detects 'Archive', 'Archives', or 'All Mail')",
171
+ },
172
+ },
173
+ required: ["messageId"],
174
+ },
175
+ };
176
+
177
+ export const MAIL_DELETE: Tool = {
178
+ name: "mail_delete",
179
+ description: "Delete an email in Apple Mail by moving it to the Trash mailbox",
180
+ inputSchema: {
181
+ type: "object",
182
+ properties: {
183
+ messageId: {
184
+ type: "number",
185
+ description: "The ID of the email message to delete (obtained from mail_get_emails or mail_search)",
186
+ },
187
+ account: {
188
+ type: "string",
189
+ description: "The name of the email account",
190
+ },
191
+ mailbox: {
192
+ type: "string",
193
+ description: "The name of the mailbox/folder where the email currently is (default: INBOX)",
194
+ default: "INBOX",
195
+ },
196
+ },
197
+ required: ["messageId"],
198
+ },
199
+ };
200
+
201
+ export const MAIL_MARK_READ: Tool = {
202
+ name: "mail_mark_read",
203
+ description: "Mark an email as read in Apple Mail",
204
+ inputSchema: {
205
+ type: "object",
206
+ properties: {
207
+ messageId: {
208
+ type: "number",
209
+ description: "The ID of the email message to mark as read (obtained from mail_get_emails or mail_search)",
210
+ },
211
+ account: {
212
+ type: "string",
213
+ description: "The name of the email account",
214
+ },
215
+ mailbox: {
216
+ type: "string",
217
+ description: "The name of the mailbox/folder where the email is (default: INBOX)",
218
+ default: "INBOX",
219
+ },
220
+ },
221
+ required: ["messageId"],
222
+ },
223
+ };
224
+
225
+ export const MAIL_MARK_UNREAD: Tool = {
226
+ name: "mail_mark_unread",
227
+ description: "Mark an email as unread in Apple Mail",
228
+ inputSchema: {
229
+ type: "object",
230
+ properties: {
231
+ messageId: {
232
+ type: "number",
233
+ description: "The ID of the email message to mark as unread (obtained from mail_get_emails or mail_search)",
234
+ },
235
+ account: {
236
+ type: "string",
237
+ description: "The name of the email account",
238
+ },
239
+ mailbox: {
240
+ type: "string",
241
+ description: "The name of the mailbox/folder where the email is (default: INBOX)",
242
+ default: "INBOX",
243
+ },
244
+ },
245
+ required: ["messageId"],
246
+ },
247
+ };
248
+
249
+ export const MAIL_CREATE_DRAFT: Tool = {
250
+ name: "mail_create_draft",
251
+ description: "Create a new draft email in Apple Mail",
252
+ inputSchema: {
253
+ type: "object",
254
+ properties: {
255
+ to: {
256
+ oneOf: [
257
+ { type: "string" },
258
+ { type: "array", items: { type: "string" } },
259
+ ],
260
+ description: "Email address(es) of the recipient(s)",
261
+ },
262
+ subject: {
263
+ type: "string",
264
+ description: "The email subject line",
265
+ },
266
+ body: {
267
+ type: "string",
268
+ description: "The email body content",
269
+ },
270
+ cc: {
271
+ oneOf: [
272
+ { type: "string" },
273
+ { type: "array", items: { type: "string" } },
274
+ ],
275
+ description: "Email address(es) for CC recipients",
276
+ },
277
+ bcc: {
278
+ oneOf: [
279
+ { type: "string" },
280
+ { type: "array", items: { type: "string" } },
281
+ ],
282
+ description: "Email address(es) for BCC recipients",
283
+ },
284
+ from: {
285
+ type: "string",
286
+ description: "The sender email address (must be a configured account)",
287
+ },
288
+ },
289
+ required: ["subject", "body"],
290
+ },
291
+ };
292
+
293
+ export const MAIL_CREATE_DRAFT_REPLY: Tool = {
294
+ name: "mail_create_draft_reply",
295
+ description: "Create a draft reply to an existing email in Apple Mail",
296
+ inputSchema: {
297
+ type: "object",
298
+ properties: {
299
+ messageId: {
300
+ type: "number",
301
+ description: "The ID of the email message to reply to (obtained from mail_get_emails or mail_search)",
302
+ },
303
+ body: {
304
+ type: "string",
305
+ description: "The reply body content",
306
+ },
307
+ replyAll: {
308
+ type: "boolean",
309
+ description: "Whether to reply to all recipients (default: false)",
310
+ default: false,
311
+ },
312
+ account: {
313
+ type: "string",
314
+ description: "The name of the email account",
315
+ },
316
+ mailbox: {
317
+ type: "string",
318
+ description: "The name of the mailbox/folder where the original email is (default: INBOX)",
319
+ default: "INBOX",
320
+ },
321
+ },
322
+ required: ["messageId", "body"],
323
+ },
324
+ };
325
+
149
326
  export const tools: Tool[] = [
150
327
  MAIL_LIST_ACCOUNTS,
151
328
  MAIL_LIST_MAILBOXES,
@@ -153,4 +330,10 @@ export const tools: Tool[] = [
153
330
  MAIL_SEARCH,
154
331
  MAIL_GET_UNREAD_COUNT,
155
332
  MAIL_SEND,
333
+ MAIL_ARCHIVE,
334
+ MAIL_DELETE,
335
+ MAIL_MARK_READ,
336
+ MAIL_MARK_UNREAD,
337
+ MAIL_CREATE_DRAFT,
338
+ MAIL_CREATE_DRAFT_REPLY,
156
339
  ];