apple-mail-mcp
This server gives Claude/LLMs full control over Apple Mail on macOS through AppleScript, with optional local AI and real-time MailKit events.
Discover accounts and mailboxes, create folders, and list/paginate emails newest-first.
Read full messages and search by sender, subject, or date range across mailboxes.
Compose or send emails, reply, move/archive/junk/delete, flag, and mark read/unread.
Bulk-move messages matching filters into an existing folder.
Create, list, and delete native Apple Mail rules that file incoming mail by sender domain.
Drain real-time new-mail events from the optional MailKit bridge.
Use local AI to summarize, classify, draft replies, and triage up to 20 inbox messages.
Provides full control over Apple Mail: read, search, compose, reply, move, flag, and delete messages using natural language, with access to folders, rules, and message management.
Supports Gmail accounts synced through Apple Mail, providing email management capabilities such as archive (All Mail), spam (Junk), and trash operations.
Integrates with iCloud email accounts via Apple Mail, enabling management of iCloud mail including archiving, junk, deletion, and folder operations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@apple-mail-mcp list all mail folders"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
apple-mail-mcp
The only way to give Claude (or any LLM) access to Apple Mail and iCloud.
Gmail and Outlook have APIs. iCloud doesn't. If you're a Mac user whose email lives in Apple Mail — iCloud, iCloud+, or any account synced through it — there's no web API an LLM can call. This server bridges that gap using AppleScript on your local machine.
It gives Claude full control over Apple Mail: read, search, compose, reply, move, flag, and delete messages using natural language, against your real inbox, with no cloud intermediary.
Built on AppleScript via osascript, with an optional MailKit extension for real-time new-mail events.
Tools
Tool | Description |
| List all accounts and their mailboxes |
| Create a new mailbox/folder in an account (idempotent) |
| Paginate messages in a mailbox (newest-first) |
| Read a message's full headers and body |
| Filter by sender, subject, date range across mailboxes |
| Create a draft or send a new message immediately |
| Reply to a message, open as draft or send immediately |
| Move a message to any mailbox |
| Bulk-move all messages matching a filter into a mailbox |
| Move to Archive (iCloud) or All Mail (Gmail) |
| Move to Junk (iCloud) or Spam (Gmail) |
| Set or clear the flag on a message |
| Mark a message as read or unread |
| Move to Deleted Messages (iCloud) or Trash (Gmail) |
| Create a native Mail rule filing sender domains into a folder (optionally sort existing mail too) |
| List all Mail rules with their move-target folder and matched sender domains |
| Delete a Mail rule by name |
| Drain real-time new-mail events from the MailKit bridge |
| Summarize a message in 2-3 sentences via local AI |
| Classify by category, priority, and action-required via local AI |
| Draft a reply body via local AI (review before sending) |
| Bulk-classify up to 20 messages, sorted by priority |
Related MCP server: Apple Mail MCP Server
Requirements
macOS (tested on Sonoma / Sequoia / macOS 26)
Apple Mail open and configured with at least one account
Node.js 18+
LM Studio (optional) — for local AI tools; any OpenAI-compatible server works
Installation
npx (recommended)
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"apple-mail": {
"command": "npx",
"args": ["-y", "@jdot6/apple-mail-mcp"]
}
}
}Restart Claude Desktop, then ask: "What folders do I have in my mail?"
Bootstrap script
Clones the repo, builds it, and patches the Claude config automatically:
curl -fsSL https://raw.githubusercontent.com/jayvee6/apple-mail-mcp/master/install.sh | bashManual
git clone https://github.com/jayvee6/apple-mail-mcp.git
cd apple-mail-mcp
npm install && npm run buildAdd to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"apple-mail": {
"command": "/opt/homebrew/bin/node",
"args": ["/path/to/apple-mail-mcp/dist/index.js"]
}
}
}Use which node to get the full path to your Node binary. Restart Claude Desktop.
Automation Permission
The first time you use a mail tool, macOS will ask whether to allow node to control Mail. Click Allow. If you accidentally deny it, go to System Settings → Privacy & Security → Automation and re-enable it for your terminal or Node.js runtime.
Local AI (optional)
The AI tools run against any local LLM via LM Studio or any OpenAI-compatible server. Email data never leaves your machine with the default config.
Configure via environment variables in claude_desktop_config.json:
{
"mcpServers": {
"apple-mail": {
"command": "npx",
"args": ["-y", "@jdot6/apple-mail-mcp"],
"env": {
"APPLE_MAIL_AI_PROVIDER": "lmstudio",
"APPLE_MAIL_AI_ENDPOINT": "http://localhost:1234",
"APPLE_MAIL_AI_MODEL": "google/gemma-4-e4b"
}
}
}
}Variable | Default | Description |
|
|
|
|
| Base URL for the AI server |
|
| Model id as LM Studio lists it ( |
| (none) | Bearer token for remote providers |
| (off) | Set to |
| (off) | Set to |
Privacy note: If you point
APPLE_MAIL_AI_ENDPOINTat a remote server (e.g. OpenAI), full email content will be sent to that server. The server blocks this by default — you must setAPPLE_MAIL_AI_ALLOW_REMOTE=1to acknowledge and enable it.
Companion Skill — Email Compose Review
The skill/SKILL.md file in this repo is a Claude skill that adds a multi-agent review pipeline to every email Claude drafts. Before opening a compose window, Claude runs the draft through five parallel reviewers:
Reviewer | Checks |
Slop detector | AI writing tells, filler phrases, corporate buzzwords |
Copy editor | Spelling, grammar, punctuation |
Active voice | Passive → active constructions |
Correctness | Names, dates, facts match the context |
Logic & clarity | Clear ask, logical structure, appropriate length |
An arbiter synthesizes the reviews into a revised draft and changelog. Claude shows you the result and waits for your approval before opening the draft in Mail. send: true is never used for LLM-drafted email — you send from Mail yourself.
To install the skill in Claude Code, copy it into your skills folder:
mkdir -p ~/.claude/skills/email-compose-review && cp skill/SKILL.md ~/.claude/skills/email-compose-review/How It Works
Claude ──stdio──▶ MCP server (Node.js)
│
├── runScript("list_messages", [...args])
│ │
│ └── osascript scripts/applescript/list_messages.applescript
│ │
│ └── Apple Mail (AppleScript dictionary)
│
└── HTTP bridge ◀── MailKit extension (optional)
localhost:27182Message references are composite keys that uniquely identify a message without a fragile integer index:
{account}::{mailbox}::{RFC 2822 Message-ID}
e.g. iCloud::INBOX::<CABx3f...@mail.gmail.com>Every list/search result includes a message_ref. Tools that operate on individual messages (get_email, reply_email, move_email, etc.) take this ref as input. The account and mailbox components scope the AppleScript lookup to the right mailbox; the RFC 2822 ID is the stable identifier. Mail's whose predicate makes the per-message lookup O(1).
MailKit Bridge (optional)
The MailKitBridge/ directory contains an Xcode project for a Mail extension that fires a local HTTP POST to localhost:27182/event when new messages arrive. This populates get_pending_events in real time rather than requiring a manual poll.
The MCP server starts the HTTP listener on startup regardless — it's a no-op if the extension isn't installed.
To build and install the extension: open MailKitBridge/MailKitBridge.xcodeproj in Xcode, build the MailKitBridgeApp scheme, run the app once to register the extension, then enable it in Mail → Settings → Extensions.
Development
npm run dev # run with tsx (no build step)
npm run build # compile TypeScript → dist/
npm run typecheck # type-check without emittingAppleScript files live in scripts/applescript/ and are invoked directly via osascript — no compilation needed. You can test them standalone:
osascript scripts/applescript/list_folders.applescript
osascript scripts/applescript/list_messages.applescript "iCloud" "INBOX" "1" "5"Security Notes
The HTTP bridge binds to
127.0.0.1only — not reachable from outside the machine.Script names are validated against
path.basename()before use to prevent path traversal.Arguments are passed to
osascriptviaexecFile(not a shell), so there is no shell-injection surface.AppleScript calls time out after 30 seconds to prevent hangs if Mail is frozen or showing a permission prompt.
Email content in AI prompts is enclosed in XML delimiters (
<email>…</email>) to guard against prompt-injection attacks in message bodies.Remote AI endpoints are blocked by default — set
APPLE_MAIL_AI_ALLOW_REMOTE=1to explicitly opt in to sending email data off-device.
License
MIT
Available Tools
22 toolsarchive_emailA
Move an email to the Archive mailbox of its account. Uses 'Archive' for iCloud, 'All Mail' for Gmail.
Inputs: message_ref (required).
classify_emailA
Classify an email by category and priority using the configured local AI model. Returns JSON with: category (string), priority (high/medium/low), action_required (boolean), tags (string[]).
Inputs: message_ref (required).
compose_emailA
Compose a new email. If send is false (default), opens the compose window with a draft. If send is true, sends immediately without confirmation.
Inputs: to (required), body (required), subject (required), cc, +1 more.
create_folderA
Create a new top-level mailbox/folder inside an account. Idempotent — reports success if the folder already exists. Pair with move_matching to file mail by rule.
Inputs: name (required), account (required).
create_ruleA
Create a native Apple Mail rule that files incoming mail from given sender domains into a folder. This is a REAL Mail rule: Mail applies it to new incoming mail automatically while Mail is running — no background process. Multiple domains are OR-combined into one rule. Native rules do not touch existing mail; set apply_to_existing=true to also sort what is already in the mailbox now. Idempotent: an existing rule with the same name is replaced. The destination folder must already exist (use create_folder).
Inputs: name (required), domains (required), dest_mailbox (required), account, +2 more.
delete_emailA
Move an email to the Trash (Deleted Messages for iCloud, Trash for Gmail).
Inputs: message_ref (required).
delete_ruleA
Delete an Apple Mail rule by name. Use list_rules to see rule names. Removes the rule only; it does not move any mail back.
Inputs: name (required).
draft_replyA
Draft a reply to an email using the configured local AI model. Returns plain text body ready to pass to reply_email. Does not send — use reply_email to review and send.
Inputs: message_ref (required), goal.
flag_emailA
Set or clear the flag on an email.
Inputs: flagged (required), message_ref (required).
get_emailA
Read the full content of a specific email including headers and body. The message_ref comes from list_emails or search_emails results.
Inputs: message_ref (required).
get_pending_eventsA
Return and clear all real-time incoming mail events pushed by the MailKit extension. Returns an empty array if the extension is not installed or no new mail has arrived since the last call. Each event includes: subject, from, date, messageId, preview, receivedAt.
Inputs: no named parameters.
list_emailsA
List emails in a specific mailbox with pagination. Returns message summaries including a message_ref that can be passed to get_email, reply_email, move_email, etc. Messages are returned newest-first (index 1 = most recent).
Inputs: account (required), mailbox (required), limit, offset.
list_foldersA
List all mail accounts and their folders/mailboxes. Returns a tree of account → [mailbox names]. Use this to discover exact mailbox names before calling list_emails or search_emails.
Inputs: no named parameters.
list_rulesA
List all Apple Mail rules: name, enabled state, move-target folder, and the sender domains each matches. Shows every rule in Mail, including ones created outside this tool.
Inputs: no named parameters.
mark_readA
Mark an email as read or unread.
Inputs: read (required), message_ref (required).
move_emailB
Move an email to a different mailbox. Use list_folders to see available mailbox names.
Inputs: message_ref (required), dest_account (required), dest_mailbox (required).
move_matchingA
Bulk-move every email in a source mailbox that matches the given criteria into a destination mailbox, in one pass. Each call matches a single from/subject substring; to file a sender that spans several unrelated addresses, issue one call per address into the same folder. At least one filter (from_filter, subject_filter, after_date, before_date) is required — this guards against accidentally moving an entire mailbox. The destination must already exist (call create_folder first if needed). Omit limit to move ALL matches (fast native bulk move); set limit to cap the count (slower, per-message). Returns the number of messages moved. On very large mailboxes this can take a few minutes.
Inputs: src_account (required), dest_account (required), dest_mailbox (required), limit, +5 more.
move_to_junkA
Move an email to the Junk/Spam mailbox of its account. Uses 'Junk' for iCloud, 'Spam' for Gmail.
Inputs: message_ref (required).
reply_emailA
Reply to an existing email. If send is false (default), opens the reply in a compose window. If send is true, sends immediately without confirmation.
Inputs: body (required), message_ref (required), send.
search_emailsA
Search for emails matching criteria across one or all mailboxes. Returns message summaries with message_ref fields for use with other tools. At least one filter (from_filter, subject_filter, after_date, before_date) should be provided.
Inputs: limit, account, mailbox, after_date, +3 more.
summarize_emailA
Summarize an email in 2-3 sentences using the configured local AI model (LM Studio / Gemma, or OpenAI-compat). Returns a concise plain-text summary of the message content and any required actions.
Inputs: message_ref (required).
triage_inboxA
Classify and summarize multiple emails from a mailbox in one call using the configured local AI model. Returns a JSON array sorted by priority. Useful for getting a quick overview of a busy inbox.
Inputs: account (required), limit, mailbox.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 22 tools
Most tools have clear, distinct purposes: list_emails vs search_emails differ in scope (mailbox vs. criteria-based), and move_email vs move_matching differ in single vs. bulk. A few special-case moves (archive, junk, delete) could be seen as subtypes of move_email, but their descriptions clarify the exact target mailbox. Overall, an agent can reliably select the right tool.
The vast majority follow a verb_noun pattern (list_emails, get_email, compose_email, create_folder, etc.). Minor deviations like move_to_junk, mark_read, and get_pending_events are still readable and verb-first, but break the strict noun-as-object convention. The inconsistency is not chaotic, only slightly mixed.
At 22 tools, this sits in the 'heavy' range (16-25) per calibration. Each tool does have a defined role, covering email reading/writing, rules, bulk actions, and AI assistance, which justifies the count for a full-featured mail server. However, some specialized move tools (archive, junk, delete) and the AI suite push it toward the upper bound, making the set feel slightly bloated.
The surface covers core email lifecycle: list, read, search, compose, reply, move, archive, flag, mark read, delete, plus folder management and rules. Notable gaps include attachment handling (no attach or download tool) and any permanent-delete/empty-trash function. These are workable gaps—agents can still perform most typical mail workflows without dead ends.
Maintenance
Related MCP Connectors
Connect any IMAP/SMTP mailbox to Claude & ChatGPT: search, read, sort, draft. Sends only with OK.
Connect any mailbox to Claude, ChatGPT & AI: read, send, reply, schedule & search emails.
Your mailboxes in ChatGPT and Claude: Gmail, iCloud, Fastmail, any IMAP. Passwords stay yours.
Give Claude, Cursor or any agent its own email address: send, read and reply in threads.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server that gives Claude and other MCP hosts full access to Mail.app on macOS — search, read, send, reply, flag, move, and more across all accounts configured in Mail.app.24115 npm1MIT
- AlicenseAqualityDmaintenanceA read-only MCP server that lets Claude Desktop interact with Apple Mail on macOS via AppleScript. It enables listing mailboxes, searching emails, and reading email content without making network calls.3MIT
- AlicenseAqualityCmaintenanceEnables Claude to control the macOS Mail app for reading, searching, drafting, sending, and managing emails directly from Claude Desktop.12MIT
- AlicenseNot gradedqualityBmaintenanceEnables using Apple Mail accounts to search, read, manage, draft, and send messages from Codex or Claude Code locally.MIT