npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

macos-mail-mcp

v1.1.0

Published

MCP server connecting Claude to macOS Mail.app via AppleScript

Downloads

388

Readme

macos-mail-mcp

npm version License: MIT Node.js 18+ macOS

An MCP server for Apple Mail (macOS Mail.app) that connects Claude to your email via AppleScript. Provides 20 tools for reading, searching, managing, and composing emails.

Supported Accounts

Works with any email account configured in macOS Mail.app — iCloud, Gmail, Outlook/Exchange, Yahoo, Fastmail, custom IMAP/POP, etc. No code changes needed; just add the account in Mail.app and it becomes available through all 20 tools.

Requirements

  • macOS with Mail.app configured (with at least one email account)
  • Node.js 18+
  • Claude Code or Claude Desktop app

Installation

Quick Install (npm)

The easiest way — no cloning or building required:

Claude Code (CLI):

claude mcp add macos-mail-mcp -- npx macos-mail-mcp

Claude Desktop:

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "macos-mail-mcp": {
      "command": "npx",
      "args": ["macos-mail-mcp"]
    }
  }
}

Restart the Claude desktop app after adding the config.

Install from Source

If you prefer to build locally or want to contribute:

git clone https://github.com/marius-cetanas/macos-mail-mcp.git
cd macos-mail-mcp
npm install
npm run build

Then register with Claude Code:

claude mcp add --transport stdio --scope user macos-mail-mcp -- node /path/to/macos-mail-mcp/build/index.js

Or add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "macos-mail-mcp": {
      "command": "node",
      "args": ["/path/to/macos-mail-mcp/build/index.js"]
    }
  }
}

macOS Permissions

On first use, macOS will prompt to grant automation permission for controlling Mail.app. Go to System Settings > Privacy & Security > Automation to manage this.

Tools

Accounts (2)

| Tool | Description | |---|---| | list_accounts | List all mail accounts (name, type, enabled, emails) | | get_account_detail | Get full account details (server, port, SSL, mailbox count) |

Mailboxes (3)

| Tool | Description | |---|---| | list_mailboxes | List mailboxes for an account or all accounts | | get_mailbox_info | Get mailbox details (message count, unread count) | | create_mailbox | Create a new mailbox (top-level or nested under a parent) |

Messages (8)

| Tool | Description | |---|---| | list_messages | List messages with pagination (limit/offset) and optional date filtering (after/before) | | get_message | Get full message content, headers, recipients, attachments. Mailbox name is optional — omit to search all mailboxes in the account. | | search_messages | Search by subject, sender, or content with optional date filtering (after/before). Results include the mailbox name. | | move_message | Move a message to a different mailbox | | move_messages | Bulk move multiple messages to a different mailbox in a single operation | | delete_message | Delete a message (moves to Trash) | | flag_message | Set/clear flag with optional color index (0-6) | | mark_read | Mark message as read or unread |

Attachments (4)

| Tool | Description | |---|---| | list_attachments | List attachments with filename, MIME type, size, download status | | save_attachment | Save a specific attachment to disk | | save_all_attachments | Save all attachments from a message | | read_attachment | Read text-based attachment content inline (.txt, .csv, .json, .html, .md, .xml, .log) |

Compose (3)

| Tool | Description | |---|---| | send_message | Send a new email with optional CC, BCC, and attachments | | reply_to_message | Reply or reply-all to a message | | forward_message | Forward a message to a new recipient |

Architecture

src/
  index.ts                          # MCP server entry point
  types.ts                          # TypeScript interfaces
  utils.ts                          # Shared utilities (sanitize, expandTilde, toolError)
  bridge/
    applescript-runner.ts            # AppleScript execution engine
    escape-for-json.applescript      # Shared JSON escaping handler (auto-prepended)
  domains/
    accounts/
      accounts.tools.ts             # Tool registration & handlers
      scripts/*.applescript          # AppleScript templates
    mailboxes/
      mailboxes.tools.ts
      scripts/*.applescript
    messages/
      messages.tools.ts
      scripts/*.applescript
    compose/
      compose.tools.ts
      scripts/*.applescript
tests/
  utils.test.ts                     # Shared utility tests
  bridge/applescript-runner.test.ts  # Bridge unit tests
  domains/*/                         # Domain handler tests

Domain-driven layered architecture:

  • Tools layer — Registers MCP tools with Zod schemas, validates input, calls the bridge
  • Bridge layer — Reads AppleScript templates, substitutes parameters (with injection-safe escaping), prepends the shared escapeForJson handler, executes via osascript, parses JSON output
  • Script layer — AppleScript templates with {{param}} placeholders, returning JSON strings. The escapeForJson handler is defined once in bridge/escape-for-json.applescript and automatically prepended to every script at runtime.

Known Limitations

AppleScript Foundation

This MCP communicates with Mail.app via AppleScript, which is a stable but legacy automation layer. Mail.app's scripting dictionary has been largely unchanged for years, but future macOS updates could require script adjustments. This is an inherent trade-off of the approach — AppleScript is the only officially supported way to automate Mail.app without writing a native plugin.

Performance

  • Large mailbox searchessearch_messages uses Mail.app's whose clause, which performs a linear scan and loads all matching messages into memory before applying the limit. Searching by content (message bodies) on very large IMAP mailboxes (50K+ messages) can be slow or timeout. Prefer searching by subject or sender when possible, and narrow results with accountName and mailboxName.
  • IMAP attachment downloads — Attachments on IMAP accounts may not be downloaded locally. The tools check download status and report clearly when an attachment needs to be opened in Mail.app first.

Message IDs

Mail.app's internal message IDs are volatile — they can change when the app reindexes, or after move/delete operations. This means multi-step workflows (e.g., list → flag → move) should re-fetch message IDs between mutations. For single-step operations this is not an issue.

Provider-Specific Behavior

  • Exchange accounts — Server details (hostname, port, SSL) are not exposed via AppleScript for Exchange/EWS accounts. Mailbox and message operations work normally.
  • Gmail labelsmove_message adds the destination label but may not remove the original (Gmail uses labels, not folders).

Other Limitations

  • Attachments on replies/forwards — AppleScript does not support adding new attachments to reply/forward messages (Mail.app limitation).
  • MIME type detection — Uses extension-based fallback when Mail.app's native MIME type property returns missing value.
  • Mailbox management — Creating mailboxes is supported, but deleting and renaming mailboxes is not possible via AppleScript (Mail.app limitation).

Roadmap

  • get_thread — Retrieve all messages in a conversation thread. Mail.app has no native threading support; implementation would require parsing RFC headers (Message-ID, In-Reply-To, References) which is slow on large mailboxes. Planned for v2.

Development

npm run dev          # Watch mode (TypeScript compiler)
npm test             # Run tests
npm run test:watch   # Watch mode tests
npm run build        # Build for production

License

MIT