Skip to main content
Glama
Apple Mail MCP Server

Apple Mail MCP Server

by isityael

Apple Mail MCP Server

License: MIT PyPI Python 3.10+ MCP GitHub stars

Star History

An MCP server that gives AI assistants full access to Apple Mail -- read, search, compose, organize, and analyze emails via natural language. Built with FastMCP.

Related MCP server: cloudflare-email

Quick Install

Prerequisites: macOS with Apple Mail configured, Python 3.10+

Two commands — gets you the MCP server, /email-management slash command, and the Email Management Expert skill:

claude plugin marketplace add patrickfreyer/apple-mail-mcp
claude plugin install apple-mail@apple-mail-mcp

Then restart Claude Code.

Other Install Methods

claude mcp add apple-mail -- uvx mcp-apple-mail

Or for Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "apple-mail": {
      "command": "uvx",
      "args": ["mcp-apple-mail"]
    }
  }
}
pip install mcp-apple-mail
claude mcp add apple-mail -- mcp-apple-mail

Installs the Email Management Expert skill via the open skills CLI. The skill does not include the MCP server, so install that too (e.g. with uvx above):

npx skills add patrickfreyer/apple-mail-mcp
claude mcp add apple-mail -- uvx mcp-apple-mail

Add -g to install the skill globally, or -a <agent> to target a specific agent.

  1. Download the latest apple-mail-mcp-vX.Y.Z.mcpb from Releases

  2. Open Claude Desktop → Settings → Developer → MCP Servers → Install from file

  3. Select the .mcpb file and grant Mail.app permissions

git clone https://github.com/patrickfreyer/apple-mail-mcp.git
cd apple-mail-mcp/plugin
python3 -m venv venv
venv/bin/pip install -r requirements.txt

claude mcp add apple-mail -- /bin/bash $(pwd)/start_mcp.sh

Tools (23)

Tool

Description

get_inbox_overview

Dashboard with unread counts, folders, and recent emails

list_inbox_emails

List emails with account/read-status filtering and optional content preview

get_mailbox_unread_counts

Unread counts per mailbox or per-account summary

list_accounts

List all configured Mail accounts

search_emails

Unified search — subject, sender, body text, dates, attachments, flag status/color, cross-account

read_email

Read one message by numeric id — headers, capped plain-text body and attachment metadata (text or JSON)

get_email_thread

Conversation thread view

Organization

Tool

Description

list_mailboxes

Folder hierarchy with message counts

create_mailbox

Create new mailboxes (supports nested paths)

move_email

Move/archive emails with filters (subject, sender, date, read status, dry-run)

update_email_status

Mark read/unread, flag/unflag (optional flag color) — by filters or message IDs

manage_trash

Soft delete, permanent delete, empty trash (with dry-run)

Composition

Tool

Description

compose_email

Send new emails (plain text or HTML body)

reply_to_email

Reply or reply-all with optional HTML body

forward_email

Forward with optional message, CC/BCC

manage_drafts

Create, list, send, and delete drafts

create_rich_email_draft

Build a rich HTML .eml draft, open it in Mail, and optionally save it to Drafts

Attachments

Tool

Description

list_email_attachments

List attachments with names and sizes

save_email_attachment

Save attachments to disk

Smart Inbox

Tool

Description

get_awaiting_reply

Find sent emails that haven't received a reply

get_needs_response

Identify emails that likely need your response

get_top_senders

Analyse most frequent senders by count or domain

Analytics & Export

Tool

Description

get_statistics

Email analytics (volume, top senders, read ratios)

export_emails

Export single emails or mailboxes to TXT/HTML

inbox_dashboard

Interactive UI dashboard (requires mcp-ui-server)

Configuration

Read-Only Mode

Pass --read-only to block delivery. Nothing leaves the machine: compose_email and reply_to_email refuse mode="send", manage_drafts refuses action="send", and forward_email is removed entirely because it has no non-sending mode.

The composing tools stay registered so that mode="draft" and mode="open" keep working. Those never deliver anything, and they are the only place in the compose surface that supports attachments — manage_drafts and create_rich_email_draft cannot attach files.

{
  "mcpServers": {
    "apple-mail": {
      "command": "/path/to/venv/bin/python3",
      "args": ["/path/to/apple_mail_mcp.py", "--read-only"]
    }
  }
}

User Preferences (Optional)

Set the USER_EMAIL_PREFERENCES environment variable to give the assistant context about your workflow:

{
  "mcpServers": {
    "apple-mail": {
      "command": "/path/to/venv/bin/python3",
      "args": ["/path/to/apple_mail_mcp.py"],
      "env": {
        "USER_EMAIL_PREFERENCES": "Default to BCG account, show max 50 emails, prefer Archive and Projects folders"
      }
    }
  }
}

For .mcpb installs, configure this in Claude Desktop under Developer > MCP Servers > Apple Mail MCP.

Safety Limits

Batch operations have conservative defaults to prevent accidental bulk actions:

Operation

Default Limit

update_email_status

10 emails

manage_trash

5 emails

move_email

1 email

Override via function parameters when needed.

File Access

By default the server can write and attach files anywhere your user account can, except a hardened denylist of locations an attacker could use for code execution or credential theft. (Attachment bytes come from whoever emailed you, and a prompt-injected email can steer tool arguments.)

Writes (save_email_attachment, export_emails, create_rich_email_draft's output_path) are refused for:

  • any dotfile or dot-folder directly in your home folder: shell startup files (~/.zshrc, ~/.zshenv, ~/.zprofile, ~/.zlogin, ~/.bashrc, ~/.bash_profile, ~/.profile), ~/.ssh, ~/.gnupg, ~/.aws, ~/.config (incl. ~/.config/git), ~/.gitconfig, ~/.netrc, ~/.envrc, ~/.local/bin, ...

  • .git/hooks, .git/config and .envrc in any folder

  • autostart, persistence and app-config folders: ~/Library/LaunchAgents, ~/Library/LaunchDaemons, /Library/LaunchAgents, /Library/LaunchDaemons, ~/Library/Application Support (incl. com.apple.backgroundtaskmanagementagent), ~/Library/Application Scripts, ~/Library/Preferences, ~/Library/Keychains, ~/Library/Mail, ~/Library/Containers, ...

  • folders on PATH: ~/bin, /usr/local/bin, /opt/homebrew/bin, and /etc

Attachments (compose_email, reply_to_email, ...) may be any readable file except secrets: ~/.ssh, ~/.gnupg, ~/.aws, ~/.netrc, ~/.git-credentials, ~/.config/gh, .env files, ~/Library/Keychains, and browser profiles and cookie stores (Safari, Chrome, Firefox, Edge, Brave, Arc, ...).

Paths are resolved (~, .., symlinks) before checking, and matching is case-insensitive like APFS.

Restricting further (opt-in). To confine writes or attachments to specific folders, list them (colon-separated) in the server's env, or pass --write-dir / --attach-dir (repeatable) as arguments. Once set, only those folders are allowed for that side, and the denylist still applies inside them. The tool's own cache (~/Library/Caches/apple-mail-mcp, the default rich-draft location) stays writable.

"env": {
  "APPLE_MAIL_MCP_WRITE_DIRS": "~/Downloads:~/Documents/mail-exports",
  "APPLE_MAIL_MCP_ATTACH_DIRS": "~/Documents:~/Desktop"
}

Usage Examples

Show me an overview of my inbox
Search for emails about "project update" in my Gmail
Reply to the email about "Domain name" with "Thanks for the update!"
Move emails with "invoice" in the subject to my Archive folder
Show me email statistics for the last 30 days
Create a rich HTML draft for a weekly update and open it in Mail

Rich HTML Drafts

Use create_rich_email_draft when you need a visually formatted email, newsletter, or leadership update.

  • It generates an unsent .eml file with multipart plain-text + HTML bodies

  • It can open the draft directly in Mail for editing

  • It can optionally ask Mail to save the opened compose window into Drafts

  • It accepts partial details, so you can start with just an account and subject and fill in the rest later

This is more reliable than injecting raw HTML into AppleScript content, which Mail often stores as literal markup.

Email Management Skill

A companion Claude Code Skill is included that teaches Claude expert email workflows (Inbox Zero, daily triage, folder organization). When installed as a plugin, the skill is loaded automatically. For standalone MCP installs, add it with npx skills add patrickfreyer/apple-mail-mcp or copy it manually:

cp -r plugin/skills/email-management ~/.claude/skills/email-management

Requirements

  • macOS with Apple Mail configured

  • Python 3.7+

  • fastmcp (+ optional mcp-ui-server for dashboard)

  • Claude Desktop or any MCP-compatible client

  • Mail.app permissions: Automation + Mail Data Access (grant in System Settings > Privacy & Security > Automation)

Troubleshooting

Issue

Fix

Mail.app not responding

Ensure Mail.app is running; check Automation permissions in System Settings

Slow searches

Set include_content: false and lower max_results

Mailbox not found

Use exact folder names; nested folders use / separator (e.g., Projects/Alpha)

Permission errors

Grant access in System Settings > Privacy & Security > Automation

Rich draft shows raw HTML

Use create_rich_email_draft instead of pasting HTML into manage_drafts or AppleScript content

Project Structure

apple-mail-mcp/
├── .claude-plugin/
│   └── marketplace.json       # Marketplace manifest (for plugin distribution)
├── plugin/                    # Claude Code plugin
│   ├── .claude-plugin/
│   │   └── plugin.json        # Plugin manifest
│   ├── skills/                # Email Management Expert skill (also invocable as /email-management)
│   ├── apple_mail_mcp/        # Python MCP server package (24 tools)
│   ├── apple_mail_mcp.py      # Entry point
│   ├── start_mcp.sh           # Startup wrapper (auto-creates venv)
│   └── requirements.txt
├── apple-mail-mcpb/           # MCPB build files (Claude Desktop)
├── LICENSE
└── README.md

Contributing

  1. Fork the repository

  2. Create a feature branch (git checkout -b feature/my-feature)

  3. Commit and push

  4. Open a Pull Request

Releasing

Follow these steps when cutting a new release to keep all version strings in sync:

  1. Bump __version__ in plugin/apple_mail_mcp/__init__.py to the new version.

  2. Update apple-mail-mcpb/manifest.json ("version" field) to match.

  3. Update pyproject.toml (version = ... under [project]) to match.

  4. Update both version fields in server.json ("version" and "packages"[0]["version"]) to match.

  5. Run python3 scripts/check_versions.py — it must print OK before you proceed.

  6. Commit, tag, and push: git tag vX.Y.Z && git push origin vX.Y.Z.

  7. Create a GitHub release from the tag.

  8. Build and publish to PyPI: python -m build && twine upload dist/* (requires PyPI credentials).

The test suite also enforces version consistency (tests/test_version_consistency.py), so any CI run on a branch with mismatched versions will fail fast.

License

MIT -- see LICENSE.

Available Tools

38 tools
archive_emailsA

Archive emails matching criteria by moving them to an Archive mailbox.

Safety features:

  • At least one filter (subject_keyword, sender, or older_than_days) is required.

  • dry_run=True (default) previews what would be archived without moving.

  • only_read=True (default) skips unread emails.

  • max_archive caps the number of emails moved in one call.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Optional keyword to filter by subject sender: Optional sender to filter by older_than_days: Optional age filter - only archive emails older than N days only_read: If True (default), only archive emails that have been read from_mailbox: Source mailbox (default "INBOX") archive_mailbox: Destination mailbox (default "Archive") max_archive: Maximum emails to archive per call (default 50) dry_run: If True (default), only preview - do not actually move emails

Returns: Summary of archived (or previewed) emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), sender, dry_run, only_read, +5 more. Returns: result

bulk_move_emailsA

Move multiple emails matching filters to a destination mailbox.

Both from_mailbox (source) and to_mailbox (destination) are required. At least one filter (subject_keyword, sender, or older_than_days) is required.

Args: account: Account name (e.g., "Gmail", "Work") to_mailbox: Destination mailbox. Use "/" for nested mailboxes (e.g., "Projects/ClientX") subject_keyword: Optional keyword to filter emails by subject sender: Optional sender email/name to filter by from_mailbox: Source mailbox (default: "INBOX") older_than_days: Only affect emails older than N days max_emails: Maximum number of emails to move (safety limit, default: 50) dry_run: If True, preview what would be moved without acting (default: False)

Returns: Summary of moved emails with count

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), to_mailbox (required), sender, dry_run, +4 more. Returns: result

compose_emailA

Compose and send a new email from a specific account.

Args: account: Account name to send from (e.g., "Gmail", "Work", "Personal") to: Recipient email address(es), comma-separated for multiple subject: Email subject line body: Email body text (plain-text fallback when body_html is used) cc: Optional CC recipients, comma-separated for multiple bcc: Optional BCC recipients, comma-separated for multiple attachments: Optional file paths to attach, comma-separated for multiple (e.g., "/path/to/file1.png,/path/to/file2.pdf") mode: Delivery mode — "send" (send immediately, default), "draft" (save silently to Drafts), or "open" (open compose window for review before sending) body_html: Optional HTML email body for rich formatting

Returns: Confirmation message with details of the email

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: to (required), body (required), account (required), subject (required), +5 more. Returns: result

create_mailboxA

Create a new mailbox (folder) in the specified account.

Supports nested paths via the parent_mailbox parameter (e.g., parent_mailbox="Projects" + name="2024" creates Projects/2024). You can also pass a full slash-separated path as name (e.g., "Projects/2024/ClientName") and omit parent_mailbox.

Args: account: Account name (e.g., "Gmail", "Work") name: Name for the new mailbox. May contain "/" to create a nested path in one call (each segment is created if needed). parent_mailbox: Optional existing parent folder for nesting.

Returns: Confirmation with the new mailbox path.

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: name (required), account (required), parent_mailbox. Returns: result

delete_emailsA

Soft-delete emails (move to Trash) matching filters, with safety features.

IMPORTANT: dry_run=True by default -- shows what WOULD be deleted without acting. Set dry_run=False to actually move emails to Trash.

At least one filter (subject_keyword, sender, or older_than_days) is required. Emails are moved to Trash, never permanently deleted.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Optional keyword to filter emails by subject sender: Optional sender email/name to filter by older_than_days: Only affect emails older than N days mailbox: Source mailbox to search in (default: "INBOX") max_emails: Maximum number of emails to delete (safety limit, default: 25) dry_run: If True (default), only preview what would be deleted

Returns: List of affected email subjects and count

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), sender, dry_run, mailbox, +3 more. Returns: result

export_emailsA

Export emails to files for backup or analysis.

Args: account: Account name (e.g., "Gmail", "Work") scope: Export scope: "single_email" (requires subject_keyword) or "entire_mailbox" subject_keyword: Keyword to find email (required for single_email) mailbox: Mailbox to export from (default: "INBOX") save_directory: Directory to save exports (default: "~/Desktop") format: Export format: "txt", "html" (default: "txt") max_emails: Maximum number of emails to export for entire_mailbox (default: 1000, safety cap)

Returns: Confirmation message with export location

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: scope (required), account (required), format, mailbox, +3 more. Returns: result

forward_emailA

Forward an email to one or more recipients.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Keyword to search for in email subjects to: Recipient email address(es), comma-separated for multiple message: Optional message to add before forwarded content mailbox: Mailbox to search in (default: "INBOX") cc: Optional CC recipients, comma-separated for multiple bcc: Optional BCC recipients, comma-separated for multiple

Returns: Confirmation message with details of forwarded email

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: to (required), account (required), subject_keyword (required), cc, +3 more. Returns: result

get_awaiting_replyA

Find sent emails that haven't received a reply yet.

Scans the Sent mailbox for outgoing emails and cross-references with the Inbox to see if a reply (matching subject) was received from the same recipient. Useful for follow-up tracking.

Args: account: Account name (e.g., "Gmail", "Work", "Personal") days_back: How many days back to check sent emails (default: 7) exclude_noreply: Skip emails sent to noreply/no-reply addresses (default: True) max_results: Maximum results to return (default: 20)

Returns: List of sent emails still awaiting a reply with subject, recipient, and date sent

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), days_back, max_results, exclude_noreply. Returns: result

get_email_threadA

Get an email conversation thread - all messages with the same or similar subject.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Keyword to identify the thread (e.g., "Re: Project Update") mailbox: Mailbox to search in (default: "INBOX", use "All" for all mailboxes) max_messages: Maximum number of thread messages to return (default: 50)

Returns: Formatted thread view with all related messages sorted by date

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), subject_keyword (required), mailbox, max_messages. Returns: result

get_email_with_contentA

Search for emails by subject keyword and return with full content preview.

Args: account: Account name to search in (e.g., "Gmail", "Work") subject_keyword: Keyword to search for in email subjects max_results: Maximum number of matching emails to return (default: 5) max_content_length: Maximum content length in characters (default: 300, 0 = unlimited) mailbox: Mailbox to search (default: "INBOX", use "All" for all mailboxes)

Returns: Detailed email information including content preview

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), subject_keyword (required), mailbox, max_results, +1 more. Returns: result

get_inbox_overviewA

Get a comprehensive overview of your email inbox status across all accounts.

Returns: Comprehensive overview including: - Unread email counts by account - List of available mailboxes/folders - AI suggestions for actions (move emails, respond to messages, highlight action items, etc.)

This tool is designed to give you a complete picture of your inbox and prompt the assistant to suggest relevant actions based on the current state.

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: no named parameters. Returns: result

get_needs_responseA

Identify unread emails that likely need a response from you.

Filters out newsletters, automated emails, and noreply senders. Prioritises direct emails (To: you) with question marks as likely needing a reply.

Args: account: Account name (e.g., "Gmail", "Work", "Personal") mailbox: Mailbox to scan (default: "INBOX") days_back: How many days back to look (default: 7) max_results: Maximum results to return (default: 20)

Returns: Ranked list of emails likely needing a response, with priority hints

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), mailbox, days_back, max_results. Returns: result

get_newslettersB

Find newsletter and digest emails by detecting common patterns. Automatically identifies emails from newsletter services and digest senders.

Args: account: Account to search. If None, searches all accounts. days_back: Only search last N days (default: 7) max_results: Maximum newsletters to return (default: 25) include_content: Include content preview (default: True) max_content_length: Max preview length (default: 500)

Returns: List of detected newsletter emails sorted by date

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account, days_back, max_results, include_content, +1 more. Returns: result

get_recent_emailsA

Get the most recent emails from a specific account.

Args: account: Account name (e.g., "Gmail", "Work") count: Number of recent emails to retrieve (default: 10) include_content: Whether to include content preview (slower, default: False) output_format: "text" (default, human-readable) or "json" (structured list of email dicts)

Returns: Formatted list of recent emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), count, output_format, include_content. Returns: result

get_recent_from_senderA

Get recent emails from a specific sender with simple, human-friendly time filters.

Args: sender: Sender name or email to search for (partial match) account: Optional account. If None, searches all accounts. time_range: Human-friendly time filter: - "today" = last 24 hours - "yesterday" = yesterday only - "week" = last 7 days (default) - "month" = last 30 days - "all" = no time filter max_results: Maximum emails to return (default: 15) include_content: Include content preview (default: True) max_content_length: Max preview length (default: 400) mailbox: Mailbox to search (default: "INBOX", use "All" for all mailboxes)

Returns: Recent emails from the specified sender within the time range

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: sender (required), account, mailbox, time_range, +3 more. Returns: result

get_statisticsA

Get comprehensive email statistics and analytics.

Args: account: Account name (e.g., "Gmail", "Work") scope: Analysis scope: "account_overview", "sender_stats", "mailbox_breakdown" sender: Specific sender for "sender_stats" scope mailbox: Specific mailbox for "mailbox_breakdown" scope days_back: Number of days to analyze (default: 30, 0 = all time)

Returns: Formatted statistics report with metrics and insights

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), scope, sender, mailbox, +1 more. Returns: result

get_top_sendersA

Analyse a mailbox to find the most frequent senders.

Useful for identifying key contacts, high-volume senders to filter, or newsletter sources to unsubscribe from.

Args: account: Account name (e.g., "Gmail", "Work", "Personal") mailbox: Mailbox to analyse (default: "INBOX") days_back: How many days back to look (default: 30, 0 = all time) top_n: Number of top senders to return (default: 10) group_by_domain: Group results by domain instead of individual sender (default: False)

Returns: Ranked list of senders (or domains) with email counts

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), top_n, mailbox, days_back, +1 more. Returns: result

get_unread_countB

Get the count of unread emails for each account.

Returns: Dictionary mapping account names to unread email counts

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: no named parameters. Returns: object

imap_bulk_moveA

Move emails between IMAP folders directly (fast, for Proton Bridge).

Much faster than AppleScript for large mailboxes. Optionally filter by sender. Writes progress to /tmp/apple-mail-mcp-sort.log (tail -f to monitor).

Requires config: ~/.config/apple-mail-mcp/imap.json

Args: from_mailbox: Source mailbox (e.g., "INBOX", "Rechnungen", "IT/Netflix") to_mailbox: Destination mailbox (e.g., "Finanzen/Rechnungen") sender: Optional sender pattern to filter by (case-insensitive substring) max_moves: Maximum emails to move (safety limit, default: 100) dry_run: If True, only count matches without moving (default: True)

Returns: Summary of moved emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: to_mailbox (required), from_mailbox (required), sender, dry_run, +1 more. Returns: result

inbox_dashboardA

Get an interactive dashboard view of your email inbox.

Returns an interactive UI dashboard resource that displays:

  • Unread email counts by account (visual cards with badges)

  • Recent emails across all accounts (filterable list)

  • Quick action buttons for common operations (Mark Read, Archive, Delete)

  • Search functionality to filter emails

This tool returns a UIResource that can be rendered by compatible MCP clients (like Claude Desktop with MCP Apps support) to provide an interactive dashboard experience.

Note: Requires mcp-ui-server package and a compatible MCP client.

Returns: UIResource with uri "ui://apple-mail/inbox-dashboard" containing an interactive HTML dashboard, or error message if UI is unavailable.

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: no named parameters.

list_accountsA

List all available Mail accounts.

Returns: List of account names

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: no named parameters. Returns: result

list_email_attachmentsB

List attachments for emails matching a subject keyword.

Args: account: Account name (e.g., "Gmail", "Work", "Personal") subject_keyword: Keyword to search for in email subjects max_results: Maximum number of matching emails to check (default: 1)

Returns: List of attachments with their names and sizes

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), subject_keyword (required), max_results. Returns: result

list_inbox_emailsB

List all emails from inbox across all accounts or a specific account.

Args: account: Optional account name to filter (e.g., "Gmail", "Work"). If None, shows all accounts. max_emails: Maximum number of emails to return per account (0 = all) include_read: Whether to include read emails (default: True) output_format: "text" (default, human-readable) or "json" (structured list of email dicts)

Returns: Formatted list of emails with subject, sender, date, and read status

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account, max_emails, include_read, output_format. Returns: result

list_mailboxesA

List all mailboxes (folders) for a specific account or all accounts.

Args: account: Optional account name to filter (e.g., "Gmail", "Work"). If None, shows all accounts. include_counts: Whether to include message counts for each mailbox (default: True)

Returns: Formatted list of mailboxes with optional message counts. For nested mailboxes, shows both indented format and path format (e.g., "Projects/Amplify Impact")

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account, include_counts. Returns: result

manage_draftsA

Manage draft emails - list, create, send, open, or delete drafts.

Args: account: Account name (e.g., "Gmail", "Work") action: Action to perform: "list", "create", "send", "open", "delete". Use "open" to open a draft in a visible compose window for review before sending. subject: Email subject (required for create) to: Recipient email(s) for create (comma-separated) body: Email body (required for create) cc: Optional CC recipients for create bcc: Optional BCC recipients for create draft_subject: Subject keyword to find draft (required for send/open/delete)

Returns: Formatted output based on action

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: action (required), account (required), cc, to, +4 more. Returns: result

manage_trashA

Manage trash operations - delete emails or empty trash.

Args: account: Account name (e.g., "Gmail", "Work") action: Action to perform: "move_to_trash", "delete_permanent", "empty_trash" subject_keyword: Optional keyword to filter emails (not used for empty_trash) sender: Optional sender to filter emails (not used for empty_trash) mailbox: Source mailbox (default: "INBOX", not used for empty_trash or delete_permanent) max_deletes: Maximum number of emails to delete (safety limit, default: 5) confirm_empty: Must be True to execute "empty_trash" action (safety confirmation) apply_to_all: Must be True to allow operations without subject_keyword or sender filter

Returns: Confirmation message with details of deleted emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: action (required), account (required), sender, mailbox, +4 more. Returns: result

mark_emailsA

Batch mark emails as read/unread and/or flagged/unflagged.

At least one filter (subject_keyword, sender, or older_than_days) is required.

Args: account: Account name (e.g., "Gmail", "Work") action: Action to perform: "read", "unread", "flagged", "unflagged" subject_keyword: Optional keyword to filter emails by subject sender: Optional sender email/name to filter by mailbox: Mailbox to search in (default: "INBOX") older_than_days: Only affect emails older than N days max_emails: Maximum number of emails to update (safety limit, default: 50)

Returns: Summary of affected emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: action (required), account (required), sender, mailbox, +3 more. Returns: result

move_emailA

Move email(s) matching a subject keyword from one mailbox to another.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Keyword to search for in email subjects to_mailbox: Destination mailbox name. For nested mailboxes, use "/" separator (e.g., "Projects/Amplify Impact") from_mailbox: Source mailbox name (default: "INBOX") max_moves: Maximum number of emails to move (default: 1, safety limit) message_ids: Exact Apple Mail message ids to move; when provided, subject filtering is ignored

Returns: Confirmation message with details of moved emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), to_mailbox (required), subject_keyword (required), max_moves, +2 more. Returns: result

reply_to_emailA

Reply to an email matching a subject keyword.

Args: account: Account name (e.g., "Gmail", "Work") subject_keyword: Keyword to search for in email subjects reply_body: The body text of the reply reply_to_all: If True, reply to all recipients; if False, reply only to sender (default: False) cc: Optional CC recipients, comma-separated for multiple bcc: Optional BCC recipients, comma-separated for multiple send: If True (default), send immediately; if False, save as draft. Ignored if mode is set. mode: Delivery mode — "send" (send immediately), "draft" (save silently), or "open" (open compose window for review). Overrides send parameter when set. attachments: Optional file paths to attach, comma-separated for multiple (e.g., "/path/to/file1.png,/path/to/file2.pdf")

Returns: Confirmation message with details of the reply sent, saved draft, or opened draft

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), reply_body (required), subject_keyword (required), cc, +5 more. Returns: result

save_email_attachmentA

Save a specific attachment from an email to disk.

Args: account: Account name (e.g., "Gmail", "Work", "Personal") subject_keyword: Keyword to search for in email subjects attachment_name: Name of the attachment to save save_path: Full path where to save the attachment

Returns: Confirmation message with save location

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), save_path (required), attachment_name (required), subject_keyword (required). Returns: result

search_all_accountsA

Search across ALL email accounts at once.

Returns consolidated results sorted by date (newest first). Only searches INBOX mailboxes (skips Trash, Junk, Drafts, Sent).

Args: subject_keyword: Optional keyword to search in subject sender: Optional sender email or name to filter by days_back: Number of days to look back (default: 7, 0 = all time) max_results: Maximum total results across all accounts (default: 30) include_content: Whether to include email content preview (default: True) max_content_length: Maximum content length in characters (default: 400)

Returns: Formatted list of matching emails with account name for each

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: sender, days_back, max_results, include_content, +2 more. Returns: result

search_by_senderA

Find all emails from a specific sender across one or all accounts. Perfect for tracking newsletters, contacts, or communications from specific people/organizations.

Args: sender: Sender name or email to search for (partial match, e.g., "alphasignal" or "john@") account: Optional account name. If None, searches all accounts. days_back: Only search emails from the last N days (default: 30, 0 = all time) max_results: Maximum number of emails to return (default: 20) include_content: Whether to include email content preview (default: True) max_content_length: Maximum length of content preview (default: 500) mailbox: Mailbox to search (default: "INBOX", use "All" for all mailboxes)

Returns: Formatted list of emails from the sender, sorted by date (newest first)

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: sender (required), account, mailbox, days_back, +3 more. Returns: result

search_email_contentA

Search email body content (and optionally subject). This is slower than subject-only search but finds more relevant results.

Args: account: Account name to search in search_text: Text to search for in email content mailbox: Mailbox to search (default: "INBOX") search_subject: Also search in subject line (default: True) search_body: Search in email body (default: True) max_results: Maximum results to return (default: 10, keep low as this is slow) max_content_length: Max content preview length (default: 600)

Returns: Emails where the search text appears in body and/or subject

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), search_text (required), mailbox, max_results, +3 more. Returns: result

search_emailsA

Unified search tool - search emails with advanced filtering across any mailbox.

Args: account: Account name to search in (e.g., "Gmail", "Work") mailbox: Mailbox to search (default: "INBOX", use "All" for all mailboxes, or specific folder name) subject_keyword: Optional keyword to search in subject sender: Optional sender email or name to filter by has_attachments: Optional filter for emails with attachments (True/False/None) read_status: Filter by read status: "all", "read", "unread" (default: "all") date_from: Optional start date filter (format: "YYYY-MM-DD") date_to: Optional end date filter (format: "YYYY-MM-DD") include_content: Whether to include email content preview (slower) max_results: Maximum number of results to return (default: 20) output_format: "text" (default, human-readable) or "json" (structured list of email dicts) flag_color: Optional flag color filter: red, orange, yellow, green, blue, purple, gray

Returns: Formatted list of matching emails with all requested details

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account (required), sender, date_to, mailbox, +8 more. Returns: result

search_emails_advancedA

Powerful unified search across accounts and mailboxes with flexible filters.

Combines the capabilities of search_emails, search_by_sender, search_email_content, and search_all_accounts into one tool. When account is None, all accounts are searched.

Uses IMAP when available (much faster, no Mail.app freezes). Falls back to AppleScript for accounts without IMAP configuration.

Args: account: Account to search (None = all accounts) mailbox: Mailbox name (default "INBOX", "All" for all mailboxes) subject_contains: Filter by subject keyword (case-insensitive) body_contains: Filter by body text (slower, case-insensitive) sender_contains: Filter by sender name/email (case-insensitive) to_contains: Filter by To recipient address (case-insensitive, IMAP-accelerated) cc_contains: Filter by CC recipient address (case-insensitive, IMAP-accelerated) date_from: Start date "YYYY-MM-DD" (inclusive) date_to: End date "YYYY-MM-DD" (inclusive) is_read: Filter by read status (True/False/None for any) has_attachments: Filter by attachment presence (True/False/None) is_flagged: Filter by flagged status (True/False/None) max_results: Maximum results (default 50) offset: Skip first N results for pagination (default 0) output_format: "text" (human-readable) or "json" (structured)

Returns: Matching emails across the specified scope

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: offset, account, date_to, is_read, +11 more. Returns: result

sort_inboxA

Sort inbox emails into folders by sender using IMAP (fast, for Proton Bridge).

Reads sorting rules from ~/.config/apple-mail-mcp/sort_rules.json. Each rule maps a sender pattern to a destination folder.

Writes real-time progress to /tmp/apple-mail-mcp-sort.log (tail -f to monitor).

Supports batch processing: set batch_size to move N emails per call. Call repeatedly until inbox is clean — already-moved emails are skipped.

Requires config: ~/.config/apple-mail-mcp/imap.json

Args: dry_run: If True, only show what would happen without moving (default: True) max_emails: Maximum emails to scan (0 = all) batch_size: Max emails to move per call (0 = all matched). Use 100-200 to avoid timeouts. rules_path: Optional custom path to sort_rules.json create_folders: Auto-create destination folders that don't exist (default: True)

Returns: Summary of emails scanned, matched, and moved

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: dry_run, batch_size, max_emails, rules_path, +1 more. Returns: result

synchronize_accountA

Ask Apple Mail to synchronize one account or all accounts.

Args: account: Optional account name. When omitted, all accounts are synchronized.

Returns: Summary of synchronization requests. Mail may continue syncing after this tool returns.

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: account. Returns: result

update_email_statusA

Update email status - mark as read/unread or flag/unflag emails.

Args: account: Account name (e.g., "Gmail", "Work") action: Action to perform: "mark_read", "mark_unread", "flag", "unflag" subject_keyword: Optional keyword to filter emails by subject sender: Optional sender to filter emails by mailbox: Mailbox to search in (default: "INBOX") max_updates: Maximum number of emails to update (safety limit, default: 10) apply_to_all: Must be True to allow updates without subject_keyword or sender filter message_ids: Exact Apple Mail message ids to update; when provided, filters are ignored flag_color: Optional flag color for action="flag": red, orange, yellow, green, blue, purple, gray

Returns: Confirmation message with details of updated emails

User Preferences: {"workflow": "default", "notifications": "enabled"}

Inputs: action (required), account (required), sender, mailbox, +5 more. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 38 tools

    Disambiguation2/5

    Multiple tools have overlapping functionality (e.g., search_emails, search_by_sender, search_email_content, search_all_accounts, search_emails_advanced; mark_emails and update_email_status; move_email, bulk_move_emails, imap_bulk_move). Agents may struggle to select the right tool despite detailed descriptions.

    Naming Consistency3/5

    Tool names generally follow a verb_noun pattern in snake_case, but verbs are inconsistent: 'get', 'list', 'search', 'find' are used interchangeably for similar retrieval tasks. For example, 'get_recent_emails' vs 'get_recent_from_sender' vs 'search_by_sender'.

    Tool Count2/5

    38 tools is excessive for an email MCP server. Many tools are highly specialized (e.g., get_newsletters, get_top_senders, get_awaiting_reply), which inflates the count and could overwhelm agents. A more streamlined set of 15-20 tools would be more appropriate.

    Completeness4/5

    Core email operations are well-covered: reading, searching, composing, replying, forwarding, moving, archiving, deleting, trash management, drafts, mailboxes, statistics, and exports. Minor gaps exist (e.g., contact management, account setup), but the surface is largely complete for typical email workflows.

    Maintenance

    ActivityActive
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      A
      maintenance
      This MCP server allows AI assistants to read, send, search, and manage emails in Apple Mail on macOS. It uses AppleScript to interact with the Mail app locally.
      52
      4,105 npm
      107
      MIT
    • A
      license
      Not graded
      quality
      F
      maintenance
      An MCP server that receives emails on your domain and allows AI assistants to search, read, and manage them via natural language queries.
      1,191 npm
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that gives AI assistants comprehensive access to Apple Mail accounts, enabling email discovery, reading, flag management, and server-side message retrieval.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      An MCP server that provides programmatic access to Apple Mail, enabling AI assistants like Claude to read, send, search, and manage emails on macOS.
      25
      MIT