Apple Mail MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| APPLE_MAIL_MCP_LOG_PATH | No | JSON log file path; rotates at 2 MB. | ~/Library/Logs/apple-mail-mcp.log |
| APPLE_MAIL_MCP_LOG_LEVEL | No | Log level: DEBUG, INFO, WARNING or ERROR. | INFO |
| APPLE_MAIL_MCP_DRAFT_VISIBLE | No | Set to true to open the compose window for each draft; false saves silently. | false |
| APPLE_MAIL_MCP_ATTACHMENTS_DIR | No | The only folder attachments may be saved into. | ~/Downloads/apple-mail-mcp |
| APPLE_MAIL_MCP_APPLESCRIPT_TIMEOUT_MS | No | Per-call timeout for Mail, in milliseconds. | 45000 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| pingA | Health check. Returns {ok: true, data: "OK"} if the MCP is reachable. |
| versionA | Return the MCP server version. |
| list_accountsA | List every account configured in Apple Mail. Returns a list of {id, name, user_name, account_type, email_addresses, enabled}.
The |
| list_mailboxesA | List mailboxes (folders) inside an account. Args:
account: Account name as returned by list_accounts.
with_counts: If true, include Returns a list of {name, unread_count?, total_count?}. |
| search_messagesA | Search messages in a mailbox. Returns lightweight summaries. Args:
account: Account name (from list_accounts).
mailbox: Mailbox name (from list_mailboxes). When omitted (or set to
"@inbox"), the server auto-detects the account's inbox by trying
the common localizations (INBOX, Bandeja de entrada, Posteingang,
Boîte de réception, Caixa de entrada, etc.).
since: ISO 8601 timestamp; only messages received at or after are returned.
Defaults to 7 days ago if not provided — without a date floor,
the script must materialize the entire mailbox, which is ruinous
on large iCloud inboxes. Pass an explicit older date if you need
to look further back.
before: ISO 8601 timestamp; only messages received strictly before are returned.
limit: Max results, capped at 500. Default 50.
unread_only: If true, only return unread messages.
query: Case-insensitive substring filter. Scope set by Returns a list of {id, message_id, account, mailbox, subject, sender,
date_received, read, snippet}. Use |
| get_threadA | Fetch the full content for a single message. v1 returns one message (no thread reconstruction). For triage this is sufficient; full threading lands in v1.5. Args: account: Account name. mailbox: Mailbox name (from search_messages output). id: Mail.app numeric message id (from search_messages output). Returns {messages: [{id, message_id, account, mailbox, subject, sender, to, cc, date_received, date_sent, read, body}]}. |
| create_draftA | Create a plain-text draft in Apple Mail's Drafts folder. Two modes:
Args:
account: Sender account name (from list_accounts).
body: Plain-text reply/message text. May be empty.
to: Recipient addresses. Required for new messages, optional for replies.
subject: Subject line. Required for new messages, optional for replies
(defaults to "Re: "). Pass an explicit value to override.
cc, bcc: Optional CC/BCC addresses.
reply_to: If set, creates a reply. {account, mailbox, id} of the original
message. Returns metadata about the created draft. Does NOT return a persisted Drafts-mailbox id — Mail commits drafts asynchronously. Drafts are reviewed in Mail.app. HTML body rendering is v1.5. |
| mark_readB | Mark a single message as read. Args: account, mailbox, id: As returned by search_messages. |
| mark_unreadB | Mark a single message as unread. Args: account, mailbox, id: As returned by search_messages. |
| move_to_mailboxA | [DESTRUCTIVE] Move a message from one mailbox to another within the same account. This tool refuses without Both Args:
account, mailbox, id: As returned by search_messages.
target_mailbox: Destination — exact name or |
| flag_messageA | Set or clear the flag color on a message. Args: account, mailbox, id: As returned by search_messages. color: 0..6 sets a color; -1 clears the flag. 0 red · 1 orange · 2 yellow · 3 green · 4 blue · 5 purple · 6 gray |
| list_attachmentsA | List attachments on a message. Args: account, mailbox, id: As returned by search_messages. Returns a list of {index, name, size, mime_type, downloaded}. Pass |
| save_attachmentA | Save one attachment to disk, inside the attachments folder. Files can only be written inside the attachments folder
(APPLE_MAIL_MCP_ATTACHMENTS_DIR, default ~/Downloads/apple-mail-mcp).
Paths outside it are refused. The attachment's filename comes from the
sender and is cleaned (no path separators, no leading dots); the result
reports both Args: account, mailbox, id: As returned by search_messages. index: 1-based index from list_attachments. target_dir: Optional subfolder. Relative paths are taken relative to the attachments folder; absolute paths must be inside it. Default: the folder itself. Created if missing. overwrite: If false (default), append " (2)", " (3)" etc. when the name is taken. True replaces existing files and requires confirm=true. confirm: Required with overwrite=true. Get the user's approval first. Returns {saved_path, name, original_name, size, downloaded}. |
| save_all_attachmentsA | Save every attachment on a message, inside the attachments folder. Same rules as save_attachment: writes only inside APPLE_MAIL_MCP_ATTACHMENTS_DIR, filenames cleaned, overwrite needs confirm. Args: account, mailbox, id: As returned by search_messages. target_dir: Optional subfolder (relative, or absolute inside the folder). overwrite: If false (default), taken names get a " (2)", " (3)" suffix. True replaces existing files and requires confirm=true. confirm: Required with overwrite=true. Get the user's approval first. Returns {saved: [{index, saved_path, name, original_name, size}],
skipped: [{index, name, reason}]}. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 14 tools
Each tool targets a distinct resource or action: search_messages returns summaries while get_thread fetches full bodies, mark_read/mark_unread are complementary opposites, and save_attachment vs save_all_attachments differ clearly in scope. The only mild overlap is version vs ping, but those are conventional and clearly differentiated (build info vs health probe).
The set is almost entirely consistent snake_case verb_noun (list_accounts, search_messages, create_draft, move_to_mailbox, save_attachment). The outliers are 'version' and 'ping', which are noun/verb-less utility names, but these are conventional and readable, so the deviation is minor.
Fourteen tools sit comfortably in the well-scoped 3-15 range, and each earns its place across account discovery, search, read, draft, move, flag, and attachment workflows. Nothing feels redundant or padded.
Core lifecycle is well covered: account/mailbox discovery, search, full-message fetch, drafting (including replies), moving (with @trash effectively enabling delete), flagging, and attachment save. Minor gaps remain—no explicit send or permanent-delete tool, no forward helper, and no batch mark-read—but these are arguably intentional safety choices and workable around.