# Apple Mail Mcp

> MCP server for Apple Mail - read, search, send, and manage emails via Claude and other AI assistants

- **Type:** MCP server
- **Install:** `agentstack add mcp-sweetrb-apple-mail-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [sweetrb](https://agentstack.voostack.com/s/sweetrb)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [sweetrb](https://github.com/sweetrb)
- **Source:** https://github.com/sweetrb/apple-mail-mcp

## Install

```sh
agentstack add mcp-sweetrb-apple-mail-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Apple Mail MCP Server

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 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`](https://github.com/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](https://claude.com/product/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:

```bash
/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:

```bash
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](https://hermes-agent.nousresearch.com/)** (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](https://antigravity.google/)** (Google) — add the server entry from [`.antigravity-plugin/mcp_config.json`](.antigravity-plugin/mcp_config.json) to `~/.gemini/config/mcp_config.json` (or via Antigravity's MCP settings).

### Manual Installation

**1. Install the server:**
```bash
npm install -g github:sweetrb/apple-mail-mcp
```

**2. Add to Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```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](https://github.com/sweetrb/apple-mail-mcp/issues/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:**
```json
{
  "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.
- **`account` is 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`:

```bash
# 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:
```json
{
  "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:

```bash
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](https://github.com/sweetrb/apple-mail-mcp/issues/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](https://github.com/sweetrb)
- **Source:** [sweetrb/apple-mail-mcp](https://github.com/sweetrb/apple-mail-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-sweetrb-apple-mail-mcp
- Seller: https://agentstack.voostack.com/s/sweetrb
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
