emailsRboring
README.md
# emailsRboring-mcp
A **safe, redacting MCP server for Apple Mail** on macOS. It lets an LLM read, search, triage, draft, and (with confirmation) send email — while a single policy layer strips secrets, blocks dangerous actions, and refuses to send without your approval.
It's a thin **proxy** in front of two excellent existing servers, adding the safety layer neither has on its own:
- **[imdinu/apple-mail-mcp](https://github.com/imdinu/apple-mail-mcp)** (Python) — fast FTS5 full-body search over your whole mailbox. *Read/search.*
- **[sweetrb/apple-mail-mcp](https://github.com/sweetrb/apple-mail-mcp)** (TypeScript) — a 40-tool AppleScript write surface. *Draft/organize/send.*
> ⚠️ **Read [SECURITY.md](./SECURITY.md) before using.** This tool can read all your mail and send messages. Its protections are real but heuristic — the confirm-only send gate is **not** proof against prompt-injection, and it keeps a plaintext local cache of your email bodies.
**Status:** v0.1.0 — source on GitHub (not yet on npm), macOS only, requires the two upstream servers below. · Contributing or using a coding agent? See **[AGENTS.md](./AGENTS.md)**. · Changes: **[CHANGELOG.md](./CHANGELOG.md)**.
---
## What it does
```
MCP client (Claude Desktop / Claude Code)
│ one server: "emailsRboring"
▼
┌──────────────── emailsRboring-mcp (policy proxy) ─────────────────┐
│ • fail-closed allowlist (send-serial / delete / rules are hidden) │
│ • redaction chokepoint: strips structuredContent, masks OTPs/codes │
│ • confirm-only send; reply/forward default to drafts │
│ • untrusted-content fence on reads; attachment-exfil block │
│ • 25k char-limit truncation; per-tool safety annotations │
└──────────┬───────────────────────────────────────┬────────────────┘
read/search │ │ write/organize/send
▼ ▼
imdinu (serve -r) sweetrb (build/index.js)
```
**Tools (26, all `mail_*`):**
- **Read/search (8):** `mail_list_accounts`, `mail_list_mailboxes`, `mail_get_emails`, `mail_get_email`, `mail_search`, `mail_get_email_links`, `mail_get_email_attachment`, `mail_get_attachment`
- **Organize (10):** `mail_move_message`, `mail_batch_move_messages`, `mail_flag_message`, `mail_unflag_message`, `mail_batch_flag_messages`, `mail_batch_unflag_messages`, `mail_mark_as_read`, `mail_mark_as_unread`, `mail_batch_mark_as_read`, `mail_batch_mark_as_unread`
- **Mailboxes/info (5):** `mail_create_mailbox`, `mail_rename_mailbox`, `mail_get_unread_count`, `mail_list_attachments`, (+ reads above)
- **Compose (3):** `mail_create_draft`, `mail_reply_to_message`, `mail_forward_message` *(draft by default)*
- **Send (1, gated):** `mail_send_email` *(requires `confirm: true`)*
**Not exposed (by design):** mass/mail-merge send, delete/trash, and mail-rule editing.
---
## Requirements
- **macOS** with Apple Mail configured and running
- **Node.js ≥ 18**
- **Python ≥ 3.11** (for the imdinu upstream)
- **Full Disk Access** for the process that runs imdinu's indexer (it reads `~/Library/Mail`)
- **Automation permission** (Apple Events → Mail) — granted on first run via a macOS prompt
---
## Install
### 1. The read/search upstream (imdinu)
```bash
pipx install apple-mail-mcp # or: uv tool install apple-mail-mcp
# Grant Full Disk Access to your terminal/host, then build the index:
apple-mail-mcp index # one-time; ~40s for ~40k messages
```
### 2. The write/organize upstream (sweetrb)
```bash
git clone https://github.com/sweetrb/apple-mail-mcp sweetrb-apple-mail
cd sweetrb-apple-mail && npm install && npm run build
# note the absolute path to build/index.js
```
### 3. This proxy
```bash
git clone https://github.com/ahmadzafar-code/emailsRboring.git
cd emailsRboring && npm install && npm run build
```
### 4. Point the proxy at the two upstreams
Set these env vars (the proxy reads them at startup):
| Env var | Value |
|---|---|
| `EMAILSRBORING_IMDINU_CMD` | path to imdinu's `apple-mail-mcp` (e.g. `~/.local/bin/apple-mail-mcp`, or a venv path) |
| `EMAILSRBORING_SWEETRB_ENTRY` | absolute path to sweetrb's `build/index.js` |
### 5. Wire into a client
**Claude Code:**
```bash
claude mcp add emailsRboring -s user \
--env EMAILSRBORING_IMDINU_CMD=/path/to/apple-mail-mcp \
--env EMAILSRBORING_SWEETRB_ENTRY=/path/to/sweetrb/build/index.js \
-- node /path/to/emailsRboring-mcp/build/index.js
```
**Claude Desktop** — add to `~/Library/Application Support/Claude/claude_desktop_config.json` (merge into any existing `mcpServers`):
```json
{
"mcpServers": {
"emailsRboring": {
"command": "/ABSOLUTE/PATH/TO/node",
"args": ["/path/to/emailsRboring/build/index.js"],
"env": {
"EMAILSRBORING_IMDINU_CMD": "/path/to/apple-mail-mcp",
"EMAILSRBORING_SWEETRB_ENTRY": "/path/to/sweetrb/build/index.js"
}
}
}
}
```
> ⚠️ **Use the absolute path to `node`, not bare `"node"`.** Claude Desktop (a GUI app) launches with a minimal `PATH` that usually doesn't include your Node install (e.g. nvm), so `"command": "node"` fails to start. Get the path with `command -v node` (e.g. `/Users/you/.nvm/versions/node/vX.Y.Z/bin/node`). The same applies to `EMAILSRBORING_IMDINU_CMD` — use a full path, not `apple-mail-mcp`.
Then:
1. **Fully quit** Claude Desktop (⌘Q) and reopen — closing the window isn't enough.
2. **Verify:** Settings → Developer should list `emailsRboring` as *running* (or show the error if it failed); the tools control in a chat shows the `mail_*` tools.
3. On the first Mail action, **approve** the macOS "Claude wants to control Mail" (Automation) prompt.
4. Troubleshooting: logs are at `~/Library/Logs/Claude/mcp-server-emailsRboring.log`.
**Claude Code** uses the same idea via `claude mcp add` (above), which also accepts absolute paths.
---
## Configuration
`emailsRboring.config.json` (next to `build/`) carries optional policy knobs (the tool allowlist and redaction rules are baked into code and **cannot** be loosened by config):
```json
{
"sendAllowlist": [],
"fullBodyDefault": false
}
```
- **`sendAllowlist`** — empty = off (send is confirm-only). If non-empty, `mail_send_email` recipients must match an entry (e.g. `"you@work.com"` or `"@work.com"`). Recipients can never be derived from email content. **Strongly recommended** if you enable real sending — see SECURITY.md.
---
## Usage examples
Three worked workflows (what you say → which tools run → what happens):
### 1. Morning triage
> **You:** "What needs my attention in my inbox today?"
The agent calls `mail_get_emails` (`filter: today`), groups senders, and surfaces the few human/actionable items above the newsletter noise. Any verification codes in the listing come back `[REDACTED]`. **Read-only — nothing changes.**
### 2. Find a thread and draft a reply
> **You:** "Find the contract-renewal thread with Dana and draft a reply saying I'll join the call Thursday."
The agent calls `mail_search` (`query: "contract renewal"`, full-body FTS5), `mail_get_email` to read the latest message, then `mail_reply_to_message` **with no `confirm`** → a properly threaded **draft** lands in your Drafts. Nothing is sent; you review and hit send in Mail.
### 3. Bulk organize
> **You:** "Archive everything from the K1 Speed newsletter and flag anything from my advisor."
The agent calls `mail_search` to collect ids, then `mail_batch_move_messages` (→ Archive) and `mail_flag_message`. All reversible; **delete is not available** by design.
### Sending (gated)
> **You:** "Email finance@acme.com the summary." → the agent shows you recipient/subject/body and calls `mail_send_email` **only after you say "send it"** (it sets `confirm: true`). Without your approval, the send is refused.
---
## Verify your install
The proxy **requires** the two upstream paths in its environment (same ones your client config uses), so export them first:
```bash
export EMAILSRBORING_IMDINU_CMD=/path/to/apple-mail-mcp
export EMAILSRBORING_SWEETRB_ENTRY=/path/to/sweetrb/build/index.js
node build/index.js # boots: "[emailsRboring] ready — 26 tools (8 read / 18 write)" then waits on stdio (Ctrl-C)
python3 verify.py # 22 checks (surface, redaction w/ a live code, send-gate, exfil) → "22/22 ALL GREEN"
```
Without those env vars the server exits with a clear message telling you to set `EMAILSRBORING_SWEETRB_ENTRY`.
---
## Credits & License
- Read/search upstream: **imdinu/apple-mail-mcp** — GPL-3.0. Installed separately; this proxy spawns it as a subprocess and does **not** include or modify its code.
- Write upstream: **sweetrb/apple-mail-mcp** — MIT.
- This proxy: **MIT** (see [LICENSE](./LICENSE)).
Huge thanks to both upstream authors — emailsRboring is just the safety layer on top of their work.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues