Install
$ agentstack add mcp-sweetrb-apple-mail-mcp ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Apple Mail MCP Server
A Model Context Protocol (MCP) server that enables AI assistants like Claude to read, send, search, and manage emails in Apple Mail on macOS.
[](https://www.npmjs.com/package/apple-mail-mcp) [](https://www.npmjs.com/package/apple-mail-mcp) [](https://www.npmjs.com/package/apple-mail-mcp) [](https://github.com/sweetrb/apple-mail-mcp/actions/workflows/ci.yml) [](https://scorecard.dev/viewer/?uri=github.com/sweetrb/apple-mail-mcp) [](https://www.apple.com/macos/) [](https://opensource.org/licenses/MIT) [](https://modelcontextprotocol.io)
> Note: This is the npm/Node.js package — install with npx or npm. There is an unrelated Python project of the same name on PyPI (imdinu/apple-mail-mcp) installed via pipx/uvx. If you're using uvx and seeing a cyclopts dependency error, you're looking for that project, not this one.
What is This?
This server acts as a bridge between AI assistants and Apple Mail. Once configured, you can ask Claude (or any MCP-compatible AI) to:
- "Check my inbox for unread messages"
- "Find emails from john@example.com"
- "Send an email to the team about the meeting"
- "Create a draft email for me to review"
- "Reply to that message"
- "Forward this to my colleague"
- "Move old newsletters to the Archive folder"
The AI assistant communicates with this server, which then uses AppleScript to interact with the Mail app on your Mac. All data stays local on your machine.
Quick Start
Using Claude Code (Easiest)
If you're using Claude Code (in Terminal or VS Code), just ask Claude to install it:
Install the sweetrb/apple-mail-mcp MCP server so you can help me manage my Apple Mail
Claude will handle the installation and configuration automatically.
Using the Plugin Marketplace
Install as a Claude Code plugin for automatic configuration and enhanced AI behavior:
/plugin marketplace add sweetrb/apple-mail-mcp
/plugin install apple-mail
This method also installs a skill that teaches Claude when and how to use Apple Mail effectively.
Using the Codex Marketplace
Install the same public marketplace in Codex:
codex plugin marketplace add sweetrb/apple-mail-mcp
codex plugin add apple-mail@apple-mail-mcp
The Codex package registers the same apple-mail MCP server through npx -y apple-mail-mcp and includes the Apple Mail skill guidance.
Other Hosts (Hermes, Antigravity)
Configuration for two more hosts is included — each registers the same apple-mail MCP server (npx -y apple-mail-mcp):
- Hermes Agent (NousResearch) — Hermes has no plugin/marketplace drop-in. Add the server with
hermes mcp add apple-mail --command npx --args -y apple-mail-mcp, or merge [.hermes-plugin/config.yaml](.hermes-plugin/config.yaml) into~/.hermes/config.yaml. Details: [.hermes-plugin/README.md](.hermes-plugin/README.md). - Antigravity (Google) — add the server entry from [
.antigravity-plugin/mcp_config.json](.antigravity-plugin/mcpconfig.json) to~/.gemini/config/mcp_config.json(or via Antigravity's MCP settings).
Manual Installation
1. Install the server:
npm install -g github:sweetrb/apple-mail-mcp
2. Add to Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"apple-mail": {
"command": "npx",
"args": ["apple-mail-mcp"]
}
}
}
3. Restart Claude Desktop and start using natural language:
"Show me my unread emails"
On first use, macOS will ask for permission to automate Mail.app. Click "OK" to allow.
Requirements
- macOS - Apple Mail and AppleScript are macOS-only
- Node.js 20+ - Required for the MCP server
- Apple Mail - Must have at least one account configured (iCloud, Gmail, Exchange, etc.)
Features
Messages
| Feature | Description | |---------|-------------| | List Messages | List messages with pagination, sender filter, date display | | Search Messages | Search by sender, subject, content, date range, read/flagged status — across all accounts | | Read Messages | Get full email content (plain text or HTML) | | Send Email | Compose and send new emails (attach by file path or inline base64 content) | | Send Serial Email | Mail merge — send personalized emails to a list of recipients with {{placeholder}} support | | Create Draft | Save emails to Drafts folder (attach by file path or inline base64 content) | | Reply | Reply to messages (with reply-all support) | | Forward | Forward messages to new recipients | | Get Thread | Group a conversation by normalized subject (across AppleScript or IMAP) | | Mark Read/Unread | Change read status (single or batch) | | Flag/Unflag | Flag or unflag messages (single or batch) | | Delete Messages | Move messages to trash (single or batch) | | Move Messages | Organize into mailboxes (single or batch) | | List Attachments | View attachment metadata (name, type, size) | | Save Attachment | Save attachments to disk | | Fetch Attachment | Get an attachment's bytes as base64 (no disk write) |
Read/list/get tools also return structured JSON (structuredContent) alongside the text, so agents can consume results without parsing prose.
Mailbox & Account Management
| Feature | Description | |---------|-------------| | List Mailboxes | Show all folders with message/unread counts | | Create/Delete/Rename Mailbox | Full mailbox lifecycle management | | List Accounts | Show configured accounts | | Unread Count | Get unread counts per mailbox |
Rules, Contacts & Templates
| Feature | Description | |---------|-------------| | List Rules | View all mail rules and their enabled status | | Enable/Disable Rules | Toggle mail rules on or off | | Create/Delete Rules | Create rules with conditions + actions, or delete by name | | Search Contacts | Look up contacts from Contacts.app by name | | Email Templates | Save, list, use, and delete reusable email templates (persisted to disk across restarts) |
Diagnostics
| Feature | Description | |---------|-------------| | Health Check | Verify Mail.app connectivity | | Doctor | Diagnose Mail permission, account state, and each IMAP/SMTP backend with actionable messages | | Statistics | Message and unread counts per account, recently received stats | | Sync Status | Check if Mail.app is actively syncing |
MCP resources & prompts
Resources expose read-only context the client can attach without a tool call: mail://accounts, mail://templates, and mail://mailboxes/{account}. Prompts package common workflows: triage-inbox, compose-reply, weekly-summary.
Tool Reference
This section documents all available tools. AI agents should use these tool names and parameters exactly as specified.
Message Operations
search-messages
Search for messages matching criteria. Searches all accounts by default.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | query | string | No | Text to search in subject/sender | | from | string | No | Filter by sender email address | | subject | string | No | Filter by subject line | | mailbox | string | No | Mailbox to search in (omit to search all mailboxes) | | account | string | No | Account to search in (omit to search all accounts) | | isRead | boolean | No | Filter by read status | | isFlagged | boolean | No | Filter by flagged status | | dateFrom | string | No | Start date filter (e.g., "January 1, 2026") | | dateTo | string | No | End date filter (e.g., "March 1, 2026") | | limit | number | No | Max results (default: 50) |
Large mailboxes & partial results. Apple Mail's AppleScript bridge cannot search very large IMAP/Gmail mailboxes (tens of thousands of messages) before the Apple Event times out — empirically even reading the newest 20 messages of a 44k-message mailbox takes ~45s. To avoid burning minutes only to return a misleading empty result, an unscoped (all-mailboxes) search skips mailboxes whose message count exceeds a threshold (default 5000), enforces a per-account time budget, and reports anything it skipped or that timed out rather than silently returning nothing. When coverage is incomplete the result includes an explicit warning, e.g.:
⚠️ Partial results — this is NOT a confirmed "no such mail":
- skipped mailbox(es) too large to search via AppleScript: Gmail / All Mail (44287) — scope the search with `mailbox` + a `dateFrom`/`dateTo` window to target them
To search inside a large mailbox, scope the call with mailbox (and ideally a dateFrom/dateTo window). Tune or disable the skip threshold with the APPLE_MAIL_MAX_SEARCH_MAILBOX environment variable (default 5000; set to 0 to disable the guard and attempt every mailbox regardless of size). (#24)
get-message
Get the full content of a message.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | Yes | Message ID | | preferHtml | boolean | No | Return HTML source instead of plain text |
Returns: Subject line and message body (plain text by default, HTML if preferHtml is true and HTML content is available).
list-messages
List messages in a mailbox.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | mailbox | string | No | Mailbox name (omit to list from all mailboxes) | | account | string | No | Account name | | limit | number | No | Max messages (default: 50) | | offset | number | No | Number of messages to skip (for pagination) | | from | string | No | Filter by sender email address or name | | unreadOnly | boolean | No | Only show unread messages |
Returns: List of messages with ID, date, subject, and sender.
send-email
Send a new email immediately.
⚠️ Safety: Sends real mail immediately and cannot be unsent. Confirm the recipients, subject, and body with the user before calling.
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | to | string[] | Yes | Recipient addresses | | subject | string | Yes | Email subject | | body | string | Yes | Email body (plain text) | | cc | string[] | No | CC recipients | | bcc | string[] | No | BCC recipients | | account | string | No | Send from specific account (with transport: "smtp", overrides the From address) | | attachments | (string \| {filename, contentBase64})[] | No | Up to 20 attachments: absolute file paths (e.g., "/Users/me/report.pdf") and/or inline {filename, contentBase64} objects for content not on disk | | transport | "applescript" \| "smtp" | No | Send transport. If omitted, SMTP is used automatically when configured (otherwise AppleScript). Pass "smtp" to require clean MIME, or "applescript" to force the Mail.app path — see [SMTP transport](#smtp-transport) |
Example:
{
"to": ["colleague@company.com"],
"subject": "Meeting Tomorrow",
"body": "Hi, just confirming our meeting at 2pm tomorrow.",
"account": "Work",
"attachments": ["/Users/me/Documents/agenda.pdf"]
}
SMTP transport
On macOS 15+ (Sequoia/Tahoe), Mail.app wraps any AppleScript-injected body in ` under the Apple-Mail-URLShareWrapperClass template, so emails sent through the default applescript transport render to recipients as if they were quoted/forwarded (Apple radar **FB11734014**, open since Ventura). The SMTP transport bypasses Mail.app entirely and submits clean MIME directly. **Once SMTP is configured, send-email uses it automatically** (no need to pass transport per call); pass transport: "applescript"` to force the Mail.app path.
Two differences to know when SMTP is auto-preferred:
- No Sent-folder copy. SMTP submission does not file the message in Mail.app's
Sent mailbox (the server's own "save to Sent" may, depending on provider). Use transport: "applescript" if you need the local Sent copy.
accountis a From override, not account selection. Over SMTP,account
is used as the From address only when it is an email address; a Mail.app account label (e.g. "Work") can't select an account over SMTP, so a call that passes one is left on the AppleScript path automatically. To force account selection, pass transport: "applescript" explicitly.
Both plain-text and HTML bodies are supported — over SMTP an HTML body (CLI --html-body-file) is sent as multipart/alternative with the plain-text fallback.
Configure SMTP via environment variables on the MCP server. The password is read from the macOS Keychain by default, so no secret goes in config:
| Variable | Required | Default | Description | |----------|----------|---------|-------------| | APPLE_MAIL_MCP_SMTP_HOST | Yes | — | SMTP server hostname (e.g. smtp.fastmail.com) | | APPLE_MAIL_MCP_SMTP_USER | Yes | — | SMTP username | | APPLE_MAIL_MCP_SMTP_PORT | No | 465 if secure, else 587 | SMTP port | | APPLE_MAIL_MCP_SMTP_SECURE | No | false | true for implicit TLS (port 465); otherwise STARTTLS | | APPLE_MAIL_MCP_SMTP_FROM | No | = user | From address | | APPLE_MAIL_MCP_SMTP_PASSWORD | No | — | Password (if set, used instead of the Keychain) | | APPLE_MAIL_MCP_SMTP_KEYCHAIN_SERVICE | No | = host | Keychain item service/server name | | APPLE_MAIL_MCP_SMTP_KEYCHAIN_ACCOUNT | No | = user | Keychain item account |
Store the password in the Keychain once (an app-specific password for Gmail/ iCloud). A generic-password item with an explicit service name keeps it from colliding with the system mail account password, and matches APPLE_MAIL_MCP_SMTP_KEYCHAIN_SERVICE:
# Fastmail (Keychain service defaults to the host)
security add-internet-password -s smtp.fastmail.com -a you@example.com -w
# Gmail / Google Workspace, using a dedicated Keychain service name:
# APPLE_MAIL_MCP_SMTP_HOST=smtp.gmail.com
# APPLE_MAIL_MCP_SMTP_USER=you@gmail.com
# APPLE_MAIL_MCP_SMTP_KEYCHAIN_SERVICE=apple-mail-mcp-smtp
security add-generic-password -s apple-mail-mcp-smtp -a you@gmail.com -w
Once the env vars are set, a plain send-email (no transport) already goes out clean:
{
"to": ["colleague@company.com"],
"subject": "Standings",
"body": "Plain body — no blockquote wrapping."
}
apple-mail-send CLI (no MCP server required)
The package also installs an apple-mail-send binary — a standalone CLI over the same SMTP path, for cron jobs, scheduled tasks, and scripts that can't run an MCP session. It reads the identical APPLE_MAIL_MCP_SMTP_* env + Keychain config:
apple-mail-send \
--from you@example.com --to colleague@company.com \
--subject "Standings" --body-file /tmp/body.txt \
[--html-body-file /tmp/body.html] [--attach /tmp/report.pdf]
Repeatable --to/--cc/--bcc/--attach; an --html-body-file is sent as a multipart/alternative alongside the plain --body-file. Exit codes follow sysexits.h: 0 success, 64 usage error, 66 unreadable body file, 78 SMTP not configured.
IMAP backend — opt-in
> 📘 For step-by-step setup (app passwords, Keychain, config methods, multi-account, upgrading, troubleshooting), see the [IMAP / SMTP Setup Guide](docs/IMAP-SETUP.md). The summary below is the reference; the guide is the walkthrough.
AppleScript runs search/list predicates client-side over the Apple Event bridge, which is slow and can time out (false-empty) on large Gmail/IMAP mailboxes (see #24), and it
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sweetrb
- Source: sweetrb/apple-mail-mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.