@sempervirens-labs/apple-mail-mcp 1.0.0 → 1.1.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,9 @@
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:*)"
11
13
  ]
12
14
  }
13
15
  }
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,119 @@ 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
+
238
+ **Example response:**
239
+ ```json
240
+ {
241
+ "success": true,
242
+ "message": "Message archived successfully"
243
+ }
244
+ ```
245
+
246
+ ### `mail_delete`
247
+
248
+ Delete an email by moving it to Trash.
249
+
250
+ | Parameter | Type | Required | Default | Description |
251
+ |-----------|------|----------|---------|-------------|
252
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
253
+ | `account` | string | No | - | Account name |
254
+ | `mailbox` | string | No | "INBOX" | Current mailbox of the email |
255
+
256
+ **Example response:**
257
+ ```json
258
+ {
259
+ "success": true,
260
+ "message": "Message deleted successfully"
261
+ }
262
+ ```
263
+
264
+ ### `mail_mark_read`
265
+
266
+ Mark an email as read.
267
+
268
+ | Parameter | Type | Required | Default | Description |
269
+ |-----------|------|----------|---------|-------------|
270
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
271
+ | `account` | string | No | - | Account name |
272
+ | `mailbox` | string | No | "INBOX" | Mailbox where the email is located |
273
+
274
+ **Example response:**
275
+ ```json
276
+ {
277
+ "success": true,
278
+ "message": "Message marked as read"
279
+ }
280
+ ```
281
+
282
+ ### `mail_mark_unread`
283
+
284
+ Mark an email as unread.
285
+
286
+ | Parameter | Type | Required | Default | Description |
287
+ |-----------|------|----------|---------|-------------|
288
+ | `messageId` | number | **Yes** | - | Email ID (from mail_get_emails or mail_search) |
289
+ | `account` | string | No | - | Account name |
290
+ | `mailbox` | string | No | "INBOX" | Mailbox where the email is located |
291
+
292
+ **Example response:**
293
+ ```json
294
+ {
295
+ "success": true,
296
+ "message": "Message marked as unread"
297
+ }
298
+ ```
299
+
300
+ ### `mail_create_draft`
301
+
302
+ Create a new draft email.
303
+
304
+ | Parameter | Type | Required | Description |
305
+ |-----------|------|----------|-------------|
306
+ | `to` | string or string[] | No | Recipient email(s) |
307
+ | `subject` | string | **Yes** | Email subject |
308
+ | `body` | string | **Yes** | Email body |
309
+ | `cc` | string or string[] | No | CC recipient(s) |
310
+ | `bcc` | string or string[] | No | BCC recipient(s) |
311
+ | `from` | string | No | Sender (must be configured account) |
312
+
313
+ **Example response:**
314
+ ```json
315
+ {
316
+ "success": true,
317
+ "message": "Draft created successfully"
318
+ }
319
+ ```
320
+
321
+ ### `mail_create_draft_reply`
322
+
323
+ Create a draft reply to an existing email.
324
+
325
+ | Parameter | Type | Required | Default | Description |
326
+ |-----------|------|----------|---------|-------------|
327
+ | `messageId` | number | **Yes** | - | Email ID to reply to (from mail_get_emails or mail_search) |
328
+ | `body` | string | **Yes** | - | Reply body content |
329
+ | `replyAll` | boolean | No | false | Reply to all recipients |
330
+ | `account` | string | No | - | Account name |
331
+ | `mailbox` | string | No | "INBOX" | Mailbox where the original email is located |
332
+
333
+ **Example response:**
334
+ ```json
335
+ {
336
+ "success": true,
337
+ "message": "Draft reply created successfully"
338
+ }
339
+ ```
340
+
219
341
  ## Permissions
220
342
 
221
343
  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.1.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,263 @@ 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
+ }): { success: boolean; message: string } {
366
+ const { messageId, account, mailbox = "INBOX" } = options;
367
+
368
+ const accountPart = account
369
+ ? `mailbox "${mailbox}" of account "${account}"`
370
+ : `mailbox "${mailbox}"`;
371
+
372
+ const script = `
373
+ tell application "Mail"
374
+ try
375
+ set theMailbox to ${accountPart}
376
+ set theMessage to (first message of theMailbox whose id is ${messageId})
377
+ set theAccount to account of theMailbox
378
+
379
+ -- Find the Archive mailbox for this account
380
+ set archiveMailbox to missing value
381
+ repeat with mb in mailboxes of theAccount
382
+ if name of mb is "Archive" or name of mb is "All Mail" then
383
+ set archiveMailbox to mb
384
+ exit repeat
385
+ end if
386
+ end repeat
387
+
388
+ if archiveMailbox is missing value then
389
+ return "ERROR:No Archive mailbox found for this account"
390
+ end if
391
+
392
+ move theMessage to archiveMailbox
393
+ return "Message archived successfully"
394
+ on error errMsg
395
+ return "ERROR:" & errMsg
396
+ end try
397
+ end tell
398
+ `;
399
+
400
+ try {
401
+ const result = runAppleScript(script);
402
+ if (result.startsWith("ERROR:")) {
403
+ return { success: false, message: result.substring(6) };
404
+ }
405
+ return { success: true, message: result || "Message archived successfully" };
406
+ } catch (error: any) {
407
+ return { success: false, message: error.message };
408
+ }
409
+ }
410
+
411
+ /**
412
+ * Delete an email by moving it to the Trash mailbox
413
+ */
414
+ export function deleteEmail(options: {
415
+ messageId: number;
416
+ account?: string;
417
+ mailbox?: string;
418
+ }): { success: boolean; message: string } {
419
+ const { messageId, account, mailbox = "INBOX" } = options;
420
+
421
+ const accountPart = account
422
+ ? `mailbox "${mailbox}" of account "${account}"`
423
+ : `mailbox "${mailbox}"`;
424
+
425
+ const script = `
426
+ tell application "Mail"
427
+ try
428
+ set theMailbox to ${accountPart}
429
+ set theMessage to (first message of theMailbox whose id is ${messageId})
430
+ delete theMessage
431
+ return "Message deleted successfully"
432
+ on error errMsg
433
+ return "ERROR:" & errMsg
434
+ end try
435
+ end tell
436
+ `;
437
+
438
+ try {
439
+ const result = runAppleScript(script);
440
+ if (result.startsWith("ERROR:")) {
441
+ return { success: false, message: result.substring(6) };
442
+ }
443
+ return { success: true, message: result || "Message deleted successfully" };
444
+ } catch (error: any) {
445
+ return { success: false, message: error.message };
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Mark an email as read
451
+ */
452
+ export function markAsRead(options: {
453
+ messageId: number;
454
+ account?: string;
455
+ mailbox?: string;
456
+ }): { success: boolean; message: string } {
457
+ const { messageId, account, mailbox = "INBOX" } = options;
458
+
459
+ const accountPart = account
460
+ ? `mailbox "${mailbox}" of account "${account}"`
461
+ : `mailbox "${mailbox}"`;
462
+
463
+ const script = `
464
+ tell application "Mail"
465
+ try
466
+ set theMailbox to ${accountPart}
467
+ set theMessage to (first message of theMailbox whose id is ${messageId})
468
+ set read status of theMessage to true
469
+ return "Message marked as read"
470
+ on error errMsg
471
+ return "ERROR:" & errMsg
472
+ end try
473
+ end tell
474
+ `;
475
+
476
+ try {
477
+ const result = runAppleScript(script);
478
+ if (result.startsWith("ERROR:")) {
479
+ return { success: false, message: result.substring(6) };
480
+ }
481
+ return { success: true, message: result || "Message marked as read" };
482
+ } catch (error: any) {
483
+ return { success: false, message: error.message };
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Mark an email as unread
489
+ */
490
+ export function markAsUnread(options: {
491
+ messageId: number;
492
+ account?: string;
493
+ mailbox?: string;
494
+ }): { success: boolean; message: string } {
495
+ const { messageId, account, mailbox = "INBOX" } = options;
496
+
497
+ const accountPart = account
498
+ ? `mailbox "${mailbox}" of account "${account}"`
499
+ : `mailbox "${mailbox}"`;
500
+
501
+ const script = `
502
+ tell application "Mail"
503
+ try
504
+ set theMailbox to ${accountPart}
505
+ set theMessage to (first message of theMailbox whose id is ${messageId})
506
+ set read status of theMessage to false
507
+ return "Message marked as unread"
508
+ on error errMsg
509
+ return "ERROR:" & errMsg
510
+ end try
511
+ end tell
512
+ `;
513
+
514
+ try {
515
+ const result = runAppleScript(script);
516
+ if (result.startsWith("ERROR:")) {
517
+ return { success: false, message: result.substring(6) };
518
+ }
519
+ return { success: true, message: result || "Message marked as unread" };
520
+ } catch (error: any) {
521
+ return { success: false, message: error.message };
522
+ }
523
+ }
524
+
525
+ /**
526
+ * Create a draft email
527
+ */
528
+ export function createDraft(options: {
529
+ to?: string | string[];
530
+ subject: string;
531
+ body: string;
532
+ cc?: string | string[];
533
+ bcc?: string | string[];
534
+ from?: string;
535
+ }): { success: boolean; message: string } {
536
+ const { to, subject, body, cc, bcc, from } = options;
537
+
538
+ const toList = to ? (Array.isArray(to) ? to : [to]) : [];
539
+ const ccList = cc ? (Array.isArray(cc) ? cc : [cc]) : [];
540
+ const bccList = bcc ? (Array.isArray(bcc) ? bcc : [bcc]) : [];
541
+
542
+ // Build recipient parts
543
+ const toRecipients = toList.map(addr => `make new to recipient at end of to recipients with properties {address:"${addr}"}`).join("\n ");
544
+ const ccRecipients = ccList.map(addr => `make new cc recipient at end of cc recipients with properties {address:"${addr}"}`).join("\n ");
545
+ const bccRecipients = bccList.map(addr => `make new bcc recipient at end of bcc recipients with properties {address:"${addr}"}`).join("\n ");
546
+
547
+ const fromPart = from ? `, sender:"${from}"` : "";
548
+
549
+ const script = `
550
+ tell application "Mail"
551
+ set newMessage to make new outgoing message with properties {subject:"${subject.replace(/"/g, '\\"')}", content:"${body.replace(/"/g, '\\"').replace(/\n/g, "\\n")}", visible:true${fromPart}}
552
+ tell newMessage
553
+ ${toRecipients}
554
+ ${ccRecipients ? ccRecipients : ""}
555
+ ${bccRecipients ? bccRecipients : ""}
556
+ end tell
557
+ -- Save as draft by not sending, just leaving it open
558
+ return "Draft created successfully"
559
+ end tell
560
+ `;
561
+
562
+ try {
563
+ const result = runAppleScript(script);
564
+ return { success: true, message: result || "Draft created successfully" };
565
+ } catch (error: any) {
566
+ return { success: false, message: error.message };
567
+ }
568
+ }
569
+
570
+ /**
571
+ * Create a draft reply to an existing email
572
+ */
573
+ export function createDraftReply(options: {
574
+ messageId: number;
575
+ body: string;
576
+ replyAll?: boolean;
577
+ account?: string;
578
+ mailbox?: string;
579
+ }): { success: boolean; message: string } {
580
+ const { messageId, body, replyAll = false, account, mailbox = "INBOX" } = options;
581
+
582
+ const accountPart = account
583
+ ? `mailbox "${mailbox}" of account "${account}"`
584
+ : `mailbox "${mailbox}"`;
585
+
586
+ const replyCommand = replyAll ? "reply theMessage with opening window and reply to all" : "reply theMessage with opening window";
587
+
588
+ const script = `
589
+ tell application "Mail"
590
+ try
591
+ set theMailbox to ${accountPart}
592
+ set theMessage to (first message of theMailbox whose id is ${messageId})
593
+
594
+ set replyMessage to ${replyCommand}
595
+
596
+ -- Prepend the new body to the reply
597
+ set currentContent to content of replyMessage
598
+ set content of replyMessage to "${body.replace(/"/g, '\\"').replace(/\n/g, "\\n")}" & return & return & currentContent
599
+
600
+ return "Draft reply created successfully"
601
+ on error errMsg
602
+ return "ERROR:" & errMsg
603
+ end try
604
+ end tell
605
+ `;
606
+
607
+ try {
608
+ const result = runAppleScript(script);
609
+ if (result.startsWith("ERROR:")) {
610
+ return { success: false, message: result.substring(6) };
611
+ }
612
+ return { success: true, message: result || "Draft reply created successfully" };
613
+ } catch (error: any) {
614
+ return { success: false, message: error.message };
615
+ }
616
+ }
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,147 @@ 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
+ });
167
+
168
+ return {
169
+ content: [
170
+ {
171
+ type: "text",
172
+ text: JSON.stringify(result, null, 2),
173
+ },
174
+ ],
175
+ };
176
+ }
177
+
178
+ case "mail_delete": {
179
+ const messageId = args?.messageId as number;
180
+ if (!messageId) {
181
+ throw new Error("Required field: messageId");
182
+ }
183
+
184
+ const result = deleteEmail({
185
+ messageId,
186
+ account: args?.account as string | undefined,
187
+ mailbox: (args?.mailbox as string) || "INBOX",
188
+ });
189
+
190
+ return {
191
+ content: [
192
+ {
193
+ type: "text",
194
+ text: JSON.stringify(result, null, 2),
195
+ },
196
+ ],
197
+ };
198
+ }
199
+
200
+ case "mail_mark_read": {
201
+ const messageId = args?.messageId as number;
202
+ if (!messageId) {
203
+ throw new Error("Required field: messageId");
204
+ }
205
+
206
+ const result = markAsRead({
207
+ messageId,
208
+ account: args?.account as string | undefined,
209
+ mailbox: (args?.mailbox as string) || "INBOX",
210
+ });
211
+
212
+ return {
213
+ content: [
214
+ {
215
+ type: "text",
216
+ text: JSON.stringify(result, null, 2),
217
+ },
218
+ ],
219
+ };
220
+ }
221
+
222
+ case "mail_mark_unread": {
223
+ const messageId = args?.messageId as number;
224
+ if (!messageId) {
225
+ throw new Error("Required field: messageId");
226
+ }
227
+
228
+ const result = markAsUnread({
229
+ messageId,
230
+ account: args?.account as string | undefined,
231
+ mailbox: (args?.mailbox as string) || "INBOX",
232
+ });
233
+
234
+ return {
235
+ content: [
236
+ {
237
+ type: "text",
238
+ text: JSON.stringify(result, null, 2),
239
+ },
240
+ ],
241
+ };
242
+ }
243
+
244
+ case "mail_create_draft": {
245
+ const subject = args?.subject as string;
246
+ const body = args?.body as string;
247
+
248
+ if (!subject || !body) {
249
+ throw new Error("Required fields: subject, body");
250
+ }
251
+
252
+ const result = createDraft({
253
+ to: args?.to as string | string[] | undefined,
254
+ subject,
255
+ body,
256
+ cc: args?.cc as string | string[] | undefined,
257
+ bcc: args?.bcc as string | string[] | undefined,
258
+ from: args?.from as string | undefined,
259
+ });
260
+
261
+ return {
262
+ content: [
263
+ {
264
+ type: "text",
265
+ text: JSON.stringify(result, null, 2),
266
+ },
267
+ ],
268
+ };
269
+ }
270
+
271
+ case "mail_create_draft_reply": {
272
+ const messageId = args?.messageId as number;
273
+ const body = args?.body as string;
274
+
275
+ if (!messageId || !body) {
276
+ throw new Error("Required fields: messageId, body");
277
+ }
278
+
279
+ const result = createDraftReply({
280
+ messageId,
281
+ body,
282
+ replyAll: (args?.replyAll as boolean) || false,
283
+ account: args?.account as string | undefined,
284
+ mailbox: (args?.mailbox as string) || "INBOX",
285
+ });
286
+
287
+ return {
288
+ content: [
289
+ {
290
+ type: "text",
291
+ text: JSON.stringify(result, null, 2),
292
+ },
293
+ ],
294
+ };
295
+ }
296
+
150
297
  default:
151
298
  throw new Error(`Unknown tool: ${name}`);
152
299
  }
package/src/tools.ts CHANGED
@@ -146,6 +146,179 @@ 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
+ },
169
+ required: ["messageId"],
170
+ },
171
+ };
172
+
173
+ export const MAIL_DELETE: Tool = {
174
+ name: "mail_delete",
175
+ description: "Delete an email in Apple Mail by moving it to the Trash mailbox",
176
+ inputSchema: {
177
+ type: "object",
178
+ properties: {
179
+ messageId: {
180
+ type: "number",
181
+ description: "The ID of the email message to delete (obtained from mail_get_emails or mail_search)",
182
+ },
183
+ account: {
184
+ type: "string",
185
+ description: "The name of the email account",
186
+ },
187
+ mailbox: {
188
+ type: "string",
189
+ description: "The name of the mailbox/folder where the email currently is (default: INBOX)",
190
+ default: "INBOX",
191
+ },
192
+ },
193
+ required: ["messageId"],
194
+ },
195
+ };
196
+
197
+ export const MAIL_MARK_READ: Tool = {
198
+ name: "mail_mark_read",
199
+ description: "Mark an email as read in Apple Mail",
200
+ inputSchema: {
201
+ type: "object",
202
+ properties: {
203
+ messageId: {
204
+ type: "number",
205
+ description: "The ID of the email message to mark as read (obtained from mail_get_emails or mail_search)",
206
+ },
207
+ account: {
208
+ type: "string",
209
+ description: "The name of the email account",
210
+ },
211
+ mailbox: {
212
+ type: "string",
213
+ description: "The name of the mailbox/folder where the email is (default: INBOX)",
214
+ default: "INBOX",
215
+ },
216
+ },
217
+ required: ["messageId"],
218
+ },
219
+ };
220
+
221
+ export const MAIL_MARK_UNREAD: Tool = {
222
+ name: "mail_mark_unread",
223
+ description: "Mark an email as unread in Apple Mail",
224
+ inputSchema: {
225
+ type: "object",
226
+ properties: {
227
+ messageId: {
228
+ type: "number",
229
+ description: "The ID of the email message to mark as unread (obtained from mail_get_emails or mail_search)",
230
+ },
231
+ account: {
232
+ type: "string",
233
+ description: "The name of the email account",
234
+ },
235
+ mailbox: {
236
+ type: "string",
237
+ description: "The name of the mailbox/folder where the email is (default: INBOX)",
238
+ default: "INBOX",
239
+ },
240
+ },
241
+ required: ["messageId"],
242
+ },
243
+ };
244
+
245
+ export const MAIL_CREATE_DRAFT: Tool = {
246
+ name: "mail_create_draft",
247
+ description: "Create a new draft email in Apple Mail",
248
+ inputSchema: {
249
+ type: "object",
250
+ properties: {
251
+ to: {
252
+ oneOf: [
253
+ { type: "string" },
254
+ { type: "array", items: { type: "string" } },
255
+ ],
256
+ description: "Email address(es) of the recipient(s)",
257
+ },
258
+ subject: {
259
+ type: "string",
260
+ description: "The email subject line",
261
+ },
262
+ body: {
263
+ type: "string",
264
+ description: "The email body content",
265
+ },
266
+ cc: {
267
+ oneOf: [
268
+ { type: "string" },
269
+ { type: "array", items: { type: "string" } },
270
+ ],
271
+ description: "Email address(es) for CC recipients",
272
+ },
273
+ bcc: {
274
+ oneOf: [
275
+ { type: "string" },
276
+ { type: "array", items: { type: "string" } },
277
+ ],
278
+ description: "Email address(es) for BCC recipients",
279
+ },
280
+ from: {
281
+ type: "string",
282
+ description: "The sender email address (must be a configured account)",
283
+ },
284
+ },
285
+ required: ["subject", "body"],
286
+ },
287
+ };
288
+
289
+ export const MAIL_CREATE_DRAFT_REPLY: Tool = {
290
+ name: "mail_create_draft_reply",
291
+ description: "Create a draft reply to an existing email in Apple Mail",
292
+ inputSchema: {
293
+ type: "object",
294
+ properties: {
295
+ messageId: {
296
+ type: "number",
297
+ description: "The ID of the email message to reply to (obtained from mail_get_emails or mail_search)",
298
+ },
299
+ body: {
300
+ type: "string",
301
+ description: "The reply body content",
302
+ },
303
+ replyAll: {
304
+ type: "boolean",
305
+ description: "Whether to reply to all recipients (default: false)",
306
+ default: false,
307
+ },
308
+ account: {
309
+ type: "string",
310
+ description: "The name of the email account",
311
+ },
312
+ mailbox: {
313
+ type: "string",
314
+ description: "The name of the mailbox/folder where the original email is (default: INBOX)",
315
+ default: "INBOX",
316
+ },
317
+ },
318
+ required: ["messageId", "body"],
319
+ },
320
+ };
321
+
149
322
  export const tools: Tool[] = [
150
323
  MAIL_LIST_ACCOUNTS,
151
324
  MAIL_LIST_MAILBOXES,
@@ -153,4 +326,10 @@ export const tools: Tool[] = [
153
326
  MAIL_SEARCH,
154
327
  MAIL_GET_UNREAD_COUNT,
155
328
  MAIL_SEND,
329
+ MAIL_ARCHIVE,
330
+ MAIL_DELETE,
331
+ MAIL_MARK_READ,
332
+ MAIL_MARK_UNREAD,
333
+ MAIL_CREATE_DRAFT,
334
+ MAIL_CREATE_DRAFT_REPLY,
156
335
  ];