@sempervirens-labs/apple-mail-mcp 1.2.0 → 1.4.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.
@@ -10,7 +10,9 @@
10
10
  "Bash(npm publish:*)",
11
11
  "Bash(bun run build)",
12
12
  "Bash(npx tsc:*)",
13
- "Bash(git push:*)"
13
+ "Bash(git push:*)",
14
+ "Bash(git add:*)",
15
+ "Bash(git commit:*)"
14
16
  ]
15
17
  }
16
18
  }
package/README.md CHANGED
@@ -160,6 +160,7 @@ Get recent emails from a mailbox.
160
160
  | `mailbox` | string | No | "INBOX" | Mailbox name |
161
161
  | `limit` | number | No | 10 | Max emails to retrieve |
162
162
  | `includeContent` | boolean | No | false | Include email body |
163
+ | `unreadOnly` | boolean | No | false | Only return unread emails |
163
164
 
164
165
  **Example response:**
165
166
  ```json
@@ -169,6 +170,9 @@ Get recent emails from a mailbox.
169
170
  "id": 12345,
170
171
  "subject": "Meeting tomorrow",
171
172
  "sender": "John Doe <john@example.com>",
173
+ "to": ["you@example.com", "team@example.com"],
174
+ "cc": ["manager@example.com"],
175
+ "bcc": [],
172
176
  "dateSent": "Monday, 10. January 2025 at 09:30:00",
173
177
  "isRead": false
174
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sempervirens-labs/apple-mail-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.4.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",
@@ -100,6 +100,9 @@ export interface Email {
100
100
  id: number;
101
101
  subject: string;
102
102
  sender: string;
103
+ to: string[];
104
+ cc: string[];
105
+ bcc: string[];
103
106
  dateSent: string;
104
107
  isRead: boolean;
105
108
  content?: string;
@@ -113,8 +116,9 @@ export function getEmails(options: {
113
116
  mailbox?: string;
114
117
  limit?: number;
115
118
  includeContent?: boolean;
119
+ unreadOnly?: boolean;
116
120
  }): Email[] {
117
- const { account, mailbox = "INBOX", limit = 10, includeContent = false } = options;
121
+ const { account, mailbox = "INBOX", limit = 10, includeContent = false, unreadOnly = false } = options;
118
122
 
119
123
  const contentPart = includeContent
120
124
  ? `set msgContent to content of msg`
@@ -124,12 +128,17 @@ export function getEmails(options: {
124
128
  ? `mailbox "${mailbox}" of account "${account}"`
125
129
  : `mailbox "${mailbox}"`;
126
130
 
131
+ // If unreadOnly, filter messages by read status
132
+ const messageFilter = unreadOnly
133
+ ? `(messages of theMailbox whose read status is false)`
134
+ : `messages of theMailbox`;
135
+
127
136
  const script = `
128
137
  tell application "Mail"
129
138
  set results to ""
130
139
  try
131
140
  set theMailbox to ${accountPart}
132
- set msgList to messages of theMailbox
141
+ set msgList to ${messageFilter}
133
142
  set msgCount to count of msgList
134
143
  if msgCount > ${limit} then set msgCount to ${limit}
135
144
 
@@ -142,7 +151,26 @@ tell application "Mail"
142
151
  set msgRead to read status of msg
143
152
  ${contentPart}
144
153
 
145
- set results to results & msgId & "<<>>" & msgSubject & "<<>>" & msgSender & "<<>>" & (msgDate as string) & "<<>>" & msgRead & "<<>>" & msgContent & "|||"
154
+ -- Get recipients
155
+ set toList to ""
156
+ repeat with r in to recipients of msg
157
+ set toList to toList & address of r & ","
158
+ end repeat
159
+ if toList is not "" then set toList to text 1 thru -2 of toList
160
+
161
+ set ccList to ""
162
+ repeat with r in cc recipients of msg
163
+ set ccList to ccList & address of r & ","
164
+ end repeat
165
+ if ccList is not "" then set ccList to text 1 thru -2 of ccList
166
+
167
+ set bccList to ""
168
+ repeat with r in bcc recipients of msg
169
+ set bccList to bccList & address of r & ","
170
+ end repeat
171
+ if bccList is not "" then set bccList to text 1 thru -2 of bccList
172
+
173
+ set results to results & msgId & "<<>>" & msgSubject & "<<>>" & msgSender & "<<>>" & toList & "<<>>" & ccList & "<<>>" & bccList & "<<>>" & (msgDate as string) & "<<>>" & msgRead & "<<>>" & msgContent & "|||"
146
174
  end repeat
147
175
  on error errMsg
148
176
  return "ERROR:" & errMsg
@@ -161,11 +189,14 @@ end tell
161
189
  const parts = result.split("|||").filter(Boolean);
162
190
 
163
191
  for (const part of parts) {
164
- const [id, subject, sender, dateSent, isRead, content] = part.split("<<>>");
192
+ const [id, subject, sender, to, cc, bcc, dateSent, isRead, content] = part.split("<<>>");
165
193
  emails.push({
166
194
  id: parseInt(id) || 0,
167
195
  subject: subject || "(No Subject)",
168
196
  sender: sender || "(Unknown)",
197
+ to: to ? to.split(",").map(s => s.trim()).filter(Boolean) : [],
198
+ cc: cc ? cc.split(",").map(s => s.trim()).filter(Boolean) : [],
199
+ bcc: bcc ? bcc.split(",").map(s => s.trim()).filter(Boolean) : [],
169
200
  dateSent: dateSent || "",
170
201
  isRead: isRead === "true",
171
202
  content: content || undefined,
@@ -219,7 +250,26 @@ tell application "Mail"
219
250
  set msgDate to date sent of msg
220
251
  set msgRead to read status of msg
221
252
 
222
- set results to results & msgId & "<<>>" & msgSubject & "<<>>" & msgSender & "<<>>" & (msgDate as string) & "<<>>" & msgRead & "|||"
253
+ -- Get recipients
254
+ set toList to ""
255
+ repeat with r in to recipients of msg
256
+ set toList to toList & address of r & ","
257
+ end repeat
258
+ if toList is not "" then set toList to text 1 thru -2 of toList
259
+
260
+ set ccList to ""
261
+ repeat with r in cc recipients of msg
262
+ set ccList to ccList & address of r & ","
263
+ end repeat
264
+ if ccList is not "" then set ccList to text 1 thru -2 of ccList
265
+
266
+ set bccList to ""
267
+ repeat with r in bcc recipients of msg
268
+ set bccList to bccList & address of r & ","
269
+ end repeat
270
+ if bccList is not "" then set bccList to text 1 thru -2 of bccList
271
+
272
+ set results to results & msgId & "<<>>" & msgSubject & "<<>>" & msgSender & "<<>>" & toList & "<<>>" & ccList & "<<>>" & bccList & "<<>>" & (msgDate as string) & "<<>>" & msgRead & "|||"
223
273
  set foundCount to foundCount + 1
224
274
  end repeat
225
275
  end repeat
@@ -240,11 +290,14 @@ end tell
240
290
  const parts = result.split("|||").filter(Boolean);
241
291
 
242
292
  for (const part of parts) {
243
- const [id, subject, sender, dateSent, isRead] = part.split("<<>>");
293
+ const [id, subject, sender, to, cc, bcc, dateSent, isRead] = part.split("<<>>");
244
294
  emails.push({
245
295
  id: parseInt(id) || 0,
246
296
  subject: subject || "(No Subject)",
247
297
  sender: sender || "(Unknown)",
298
+ to: to ? to.split(",").map(s => s.trim()).filter(Boolean) : [],
299
+ cc: cc ? cc.split(",").map(s => s.trim()).filter(Boolean) : [],
300
+ bcc: bcc ? bcc.split(",").map(s => s.trim()).filter(Boolean) : [],
248
301
  dateSent: dateSent || "",
249
302
  isRead: isRead === "true",
250
303
  });
package/src/index.ts CHANGED
@@ -78,6 +78,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
78
78
  mailbox: (args?.mailbox as string) || "INBOX",
79
79
  limit: (args?.limit as number) || 10,
80
80
  includeContent: (args?.includeContent as boolean) || false,
81
+ unreadOnly: (args?.unreadOnly as boolean) || false,
81
82
  });
82
83
  return {
83
84
  content: [
package/src/tools.ts CHANGED
@@ -50,6 +50,11 @@ export const MAIL_GET_EMAILS: Tool = {
50
50
  description: "Whether to include the email body content (default: false)",
51
51
  default: false,
52
52
  },
53
+ unreadOnly: {
54
+ type: "boolean",
55
+ description: "Only return unread emails (default: false)",
56
+ default: false,
57
+ },
53
58
  },
54
59
  required: [],
55
60
  },