mailmate-mcp
# mailmate-mcp
An [MCP](https://modelcontextprotocol.io/) server that gives Claude (and other MCP clients) direct access to [MailMate](https://freron.com/), the macOS email client. Search, read, move, tag, and link emails without leaving your conversation.
## Requirements
- macOS (MailMate is Mac-only)
- [MailMate](https://freron.com/) installed and configured with at least one IMAP account
- Python 3.11+
- [uv](https://docs.astral.sh/uv/)
## Installation
```bash
git clone https://github.com/huckncatch/mailmate-mcp
cd mailmate-mcp
uv sync
```
## MCP Registration
### Claude Code (global, all projects)
```bash
claude mcp add --scope user mailmate /path/to/mailmate-mcp/.venv/bin/mailmate-mcp
```
Or add manually to `~/.claude.json` under `"mcpServers"`:
```json
"mailmate": {
"type": "stdio",
"command": "/path/to/mailmate-mcp/.venv/bin/mailmate-mcp",
"args": [],
"env": {}
}
```
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"mailmate": {
"command": "/path/to/mailmate-mcp/.venv/bin/mailmate-mcp"
}
}
}
```
Restart Claude Desktop after any change to server code or config.
## Tools
| Tool | Description |
|------|-------------|
| `search_messages` | Search by query string, tag, account, or mailbox. Supports body search. |
| `get_message` | Fetch full details and body for a message by its `message://` URL. |
| `list_mailboxes` | List all mailboxes across all configured accounts with message counts. |
| `list_tags` | List all tags defined in MailMate Preferences → Tags. |
| `get_message_link` | Get the `message://` link for a message and open it in MailMate. |
| `open_message_in_mailmate` | Navigate MailMate to a specific message. |
| `move_message` | Move a message to a different mailbox (syncs via IMAP). |
| `tag_message` | Add or remove tags on a message (syncs as IMAP keywords). |
Messages are identified by `message://` URLs derived from the RFC 2822 `Message-ID` header, e.g. `message://%3Cabc123@example.com%3E`. Use `search_messages` to find them.
## How It Works
The server reads MailMate's on-disk message store at:
```
~/Library/Application Support/MailMate/Messages.noindex/IMAP/
<account>/
<mailbox>.mailbox/
Messages/
<uid>.eml
```
**`mailstore.py`** — filesystem and parsing layer. Walks the store, parses `.eml` files, and maintains an in-memory index for fast search. No MCP or AppleScript dependencies.
**`server.py`** — MCP boundary. Defines all tools via `fastmcp` and issues AppleScript calls to MailMate for actions that require IMAP sync (open, tag, activate).
## Development
```bash
# Run the server directly (stdio transport)
uv run mailmate-mcp
# Or via the module
uv run python -m mailmate_mcp.server
```
There is no automated test suite. Manual testing is done by registering the server with Claude Desktop or Claude Code and exercising the tools in a conversation.
TDQS
Scored across 8 tools
Most tools target distinct actions, but open_message_in_mailmate and get_message_link both open a message in MailMate, making their purposes fuzzy. get_message, get_message_link, and open_message_in_mailmate also form a confusingly similar group of message-URL tools.
The set mostly follows a verb_noun pattern: list_tags, list_mailboxes, get_message, move_message, tag_message. The main deviations are the awkward search_messages_tool suffix and the longer open_message_in_mailmate form, but the pattern remains predictable.
Eight tools is a well-scoped size for a MailMate server covering search, retrieval, navigation, mailbox listing, tagging, and moving messages. Each tool feels justified even if a couple overlap.
Retrieval and organization workflows are covered: search, read, move, tag, and open. However, an email client surface lacks obvious send/reply/delete and mark-read operations, and the search tool cannot filter by mailbox, which are notable gaps.