apple-mail-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_accountsA | List all configured email accounts in Apple Mail. Returns each account's id (UUID), display name, email addresses, account type, and enabled state. Account ids are stable across name changes; prefer them over names for identifying accounts. Returns: Dictionary containing the accounts list. Example: >>> list_accounts() {"success": True, "accounts": [ {"id": "B21B254B-...", "name": "Gmail", "email_addresses": ["me@gmail.com"], "account_type": "imap", "enabled": True}, ... ]} |
| list_rulesA | List all Mail.app rules (read-only). Returns each rule's display name and enabled state. Rule names are NOT guaranteed unique — Mail allows duplicates — and rules have no stable id via AppleScript. This tool is read-only; mutation (enable/disable, create, delete) is tracked as a separate enhancement. Returns: Dictionary containing the rules list. Example: >>> list_rules() {"success": True, "rules": [ {"name": "Junk filter", "enabled": True}, {"name": "News From Apple", "enabled": False}, ... ], "count": 2} |
| delete_ruleA | Delete a Mail.app rule by 1-based positional index. Destructive — requires user confirmation via MCP elicitation before running. Cannot be undone (Mail.app does not version rule history). |
| create_ruleA | Create a new Mail.app rule. Rules with actions that can move, forward, or delete mail
(delete / forward_to / move_to / copy_to) require user confirmation —
a single create can install automation that auto-forwards or deletes
all future mail (#222). Organizational-only rules (mark_read,
mark_flagged, flag_color) are created without a prompt. Mail.app
appends new rules to the end of the rule list, so the returned
|
| update_ruleA | Update an existing Mail.app rule (patch semantics). Patch semantics: only fields you provide are changed. Conditional confirmation: prompts the user via MCP elicitation when the
patch touches Refuses to update any rule whose existing actions include something outside the supported schema (run-AppleScript, redirect, reply text, play sound, custom highlight color); raises MailUnsupportedRuleActionError. Edit such rules in Mail.app's UI. |
| list_mailboxesB | List all mailboxes for an account. |
| search_messagesA | Search for messages matching criteria. Returns metadata-only rows. Two corpus modes:
For thread retrieval, call |
| get_messagesA | Get full details of one or more messages, with bodies. Returns a list of message dicts (possibly of length 0 or 1). Pair with
|
| update_messageA | Update one or more messages: change read state, flag, and/or move, in one atomic call (#135). Patch semantics — caller specifies only the fields to change. All
specified mutations apply in a single AppleScript pass via the
bulk-update helper. Replaces the previous Order of operations (matters for IMAP): read-state and flag changes apply first (in source mailbox), then the move. IMAP requires the message to exist in the source folder for STORE before MOVE. |
| get_threadA | Return all messages in the thread containing the given message. Looks up the anchor message by its id, then reconstructs the
conversation via the connector's tiered IMAP threading dispatch
(Tier 1 X-GM-THRID for Gmail, Tier 3 header-search BFS fallback)
or the AppleScript path. Result rows are sorted by The returned ids can be piped into Known limitation: thread members whose subject was rewritten mid-conversation are missed on the AppleScript fallback path (subject prefilter tradeoff). |
| get_statisticsA | Aggregate inbox statistics over a mailbox and time window. A read-only analytics roll-up computed from a single The window defaults to the last ~30 days ( |
| save_attachmentsA | Save attachments from a message to a directory. |
| get_attachment_contentA | Read one attachment's content inline, without writing it to disk. For "triage" workflows where you want to inspect an attachment (a text
file, JSON, a small PDF) before deciding what to do with it — instead of
|
| create_mailboxA | Create a new mailbox/folder. |
| update_mailboxA | Rename and/or re-parent (move) an existing mailbox. Two delivery paths:
At least one of Refused (#164): operations targeting the bare |
| delete_mailboxA | Delete a mailbox via IMAP. Mail.app's AppleScript dictionary doesn't expose a working delete
primitive for mailboxes, so this operation goes through IMAP. Requires
IMAP credentials in Keychain (#73 opt-in flow) — returns
Always elicits user confirmation (destructive). By default refuses
non-empty mailboxes to prevent accidental data loss; pass
Refused (#164): targeting the bare |
| delete_messagesA | Delete messages (always moves to the account's Trash mailbox). Destructive: gated behind user confirmation via MCP elicitation (issue #239), matching delete_rule / delete_mailbox / delete_template. |
| list_templatesA | List all stored email templates. Templates live as files at ~/.apple_mail_mcp/templates/.md. Override the location with the APPLE_MAIL_MCP_HOME environment variable. Returns: Dictionary with each template's name and subject (or null if no subject header is set). |
| get_templateA | Read a single template by name. |
| save_templateA | Create or overwrite a template. |
| delete_templateA | Delete a template by name. Destructive — requires user confirmation via MCP elicitation before running. |
| render_templateA | Render a template into ready-to-send subject and body text. No side effects — caller is responsible for passing the rendered
text to With |
| create_draftA | Create a draft (fresh, reply, or forward). Optionally send immediately. Mail.app's actual primitive is the draft — every outgoing message is a draft until sent. This tool lets callers create one, optionally seeded from an existing message (reply or forward), and either save it for later or send it now. |
| update_draftA | Update an existing draft. Implemented as delete-and-recreate. Returns a NEW draft_id — Mail.app forbids mutating saved drafts, so update is implemented by reading the draft's current state, deleting it, and creating a new draft with the merged fields. Threading headers (for reply seeds) and forward anchor are preserved via persisted seed metadata. Field merge semantics: any non-None argument overrides the existing
value. For drafts created externally (not via |
| delete_draftA | Delete (move to Trash) an existing draft. Lifecycle endpoint for cancellation. Mail.app moves the message to the Deleted Messages mailbox; recovery is technically possible but Mail.app no longer treats trashed drafts as editable, so this is effectively a one-way discard. No elicitation (recoverable from Trash) and no rate limit (local operation). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/s-morgan-jeffries/apple-mail-fast-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server