Skip to main content
Glama
nurked

imail-mcp

by nurked
README.md
# imail-mcp

> πŸ‡·πŸ‡Ί **ДокумСнтация Π½Π° русском:** [README.ru.md](README.ru.md)

An [MCP](https://modelcontextprotocol.io) server that connects Claude
(Cowork / Claude Code / Claude Desktop) to your email so it can
**read, search, send, and organize** your mail β€” directly from a conversation.

Runs as a **resident background service** (launchd) with a **web admin UI**,
serving all your Claude clients over one Streamable HTTP endpoint β€” or as a
classic per-client stdio server. **iCloud Mail** is the first supported
provider; the internals are written against a provider-agnostic interface, so
Gmail / Microsoft 365 adapters can be added later without touching a single
tool.

---

## Highlights

- πŸ–₯️ **Runs as a service** β€” one long-lived process (launchd LaunchAgent,
  auto-start at login, auto-restart) shared by every MCP client over
  Streamable HTTP; stdio mode still works for per-client setups.
- 🌐 **Web admin UI** β€” connect/disconnect Apple accounts, check live
  connection status, copy ready-made client configs, tail the service log β€”
  all at `http://127.0.0.1:4577`, localhost-only.
- πŸ‘₯ **Multiple accounts** β€” connect several iCloud accounts; every tool takes
  an optional `account` parameter.
- πŸ“₯ **Read & search** β€” folders, search with paging, full messages and whole
  threads, bulk fetch up to 20 full messages per call, attachments.
- βœ‰οΈ **Send & reply** β€” compose, reply, reply-all, forward with correct
  threading headers.
- πŸ—‚οΈ **Organize, in bulk** β€” move / archive / delete / flag up to 200 messages
  per call as a **single IMAP command**.
- πŸ”’ **Credentials stay local** β€” account passwords and the service's access
  token live in the **macOS Keychain**, never in a plaintext file or env var.
- πŸ›‘ **Never sends silently** β€” Claude must preview an email and get your
  approval first; on clients that support MCP **elicitation**, the server
  additionally asks *you* to confirm in-app before anything is sent.

---

## The Mac app

The nicest way to run imail-mcp is the **menu-bar app** in [`app/`](app/README.md):
a signed, notarizable `iMail MCP.app` that bundles the whole service as a
self-contained binary (no Node required), shows live status in the menu bar,
opens the control panel in its own window, and starts at login. Build it with
`cd app && npm install && npm run tauri build`, then drag the `.app` from
`app/src-tauri/target/release/bundle/macos/` into /Applications. On first
launch it takes over from the CLI-installed launchd service automatically.

Everything below β€” the CLI service, stdio mode, tools, security model β€” works
the same with or without the app; the app is just a shell that owns the
service process.

## Quick start (CLI, no app)

Requires **Node.js β‰₯ 18** and macOS.

```bash
git clone git@github.com:nurked/icloud-mail-mcp.git
cd icloud-mail-mcp
npm install
npm run build
node dist/index.js service install   # register + start the background service
node dist/index.js ui                # open the admin UI in your browser
```

In the admin UI:

1. **Accounts tab** β€” connect your iCloud account (see the app-specific
   password note below). The login is verified live over IMAP, then stored in
   your Keychain.
2. **Clients tab** β€” copy the ready-made one-liner for Claude Code, or the
   JSON block for Claude Desktop. Done.

> Installing globally (`npm link` or `npm i -g .`) gives you the `imail-mcp`
> command used in the examples below; otherwise use
> `node dist/index.js <command>`.

### CLI reference

```
imail-mcp                      stdio MCP server (for per-client mcpServers configs)
imail-mcp serve [--port N]     run the HTTP service in the foreground
imail-mcp ui                   open the admin UI (authenticated) in your browser
imail-mcp service install      install + start the launchd LaunchAgent
imail-mcp service status       show whether the service is installed/running
imail-mcp service uninstall    stop and remove the LaunchAgent
```

Default port: **4577**. Logs: `~/Library/Logs/imail-mcp/imail-mcp.log`.

### Generating the app-specific password

Apple does **not** offer OAuth for iCloud Mail β€” the only supported path is
IMAP/SMTP with an app-specific password (every iCloud account has 2FA):

1. Open [appleid.apple.com](https://appleid.apple.com/account/manage) β†’
   **Sign-In and Security β†’ App-Specific Passwords**.
2. Click **Generate an app-specific password**, name it `imail-mcp`.
3. Paste the 16-character password into the admin UI.

---

## Wire it into Claude

**Preferred β€” the shared service** (copy the exact command, with your token
filled in, from the admin UI's *Clients* tab):

```bash
claude mcp add --transport http imail http://127.0.0.1:4577/mcp \
  --header "Authorization: Bearer <token>"
```

Claude Desktop (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "imail": {
      "type": "http",
      "url": "http://127.0.0.1:4577/mcp",
      "headers": { "Authorization": "Bearer <token>" }
    }
  }
}
```

**Fallback β€” per-client stdio** (each client spawns its own process; no
service needed):

```json
{
  "mcpServers": {
    "imail": { "command": "node", "args": ["/absolute/path/to/dist/index.js"] }
  }
}
```

---

## Security model

- The HTTP service binds to **127.0.0.1 only** and validates the `Host`
  header (DNS-rebinding protection, plus the MCP SDK's own check).
- The `/mcp` endpoint requires a **bearer token**, generated on first run and
  stored in the Keychain β€” without it, other local processes can't read or
  send your mail through the service.
- The admin UI uses a one-time token URL (`imail-mcp ui`) exchanged for an
  HttpOnly, SameSite=Strict session cookie; mutating API calls additionally
  require a custom header (CSRF).
- Sending tools are gated three ways: prompt discipline (preview first), tool
  annotations (`destructiveHint` on sends/deletes), and **elicitation** β€” on
  supporting clients the server asks you to confirm each send in-app, and a
  declined confirmation returns `sent: false`.

---

## Tools

| Tool | What it does |
| --- | --- |
| `list_accounts` | Connected accounts and their live connection status |
| `list_mailboxes` | Folders with IMAP paths and special-use roles |
| `search_messages` | Search by from / to / subject / text / date / unread, with `limit` + `offset` paging |
| `get_message` | Full headers, text + HTML body, attachment metadata |
| `get_messages` | **Bulk fetch** up to 20 full messages in one call (missing UIDs reported, not fatal) |
| `get_thread` | The whole conversation, oldest β†’ newest |
| `download_attachment` | Save an attachment to a temp file; returns path + resource link |
| `compose_preview` | Build an email for review β€” **does not send** |
| `send_email` | Send now (after your approval; elicitation-confirmed where supported) |
| `save_draft` | Put it in Drafts for you to send yourself |
| `reply` | Reply / reply-all, threading headers set from the original |
| `forward` | Forward to new recipients with a quoted header |
| `move_message` / `bulk_move` | Move one / up to 200 messages |
| `set_flags` / `bulk_set_flags` | Read/unread, flag/unflag β€” one / up to 200 |
| `archive_message` / `bulk_archive` | Move to Archive β€” one / up to 200 |
| `delete_message` / `bulk_delete` | Move to Trash (expunge if already there) β€” one / up to 200 |

Every tool takes an optional `account` parameter (omit when only one account
is connected). Bulk operations execute as a **single IMAP command** (UID
set), not N round-trips. All tools declare MCP **tool annotations**
(read-only / destructive / idempotent hints) and **output schemas**
(structured content), per the 2025-06-18+ MCP spec.

---

## How it works

```
Claude Code ─┐
Claude Desktop ──  Streamable HTTP (127.0.0.1:4577/mcp, bearer token)
Cowork β”€β”˜        β”‚
                 β–Ό
      imail-mcp service (launchd)  ──IMAP (imap.mail.me.com:993)──▢  iCloud
        β”‚  admin UI at /           └─SMTP (smtp.mail.me.com:587)──▢  iCloud
        └─ credentials + token ◀── macOS Keychain
           account registry     ◀── ~/Library/Application Support/imail-mcp/
```

- **IMAP** ([imapflow](https://www.npmjs.com/package/imapflow)) reads and
  organizes; **SMTP** ([nodemailer](https://nodemailer.com)) sends; bodies are
  parsed with [mailparser](https://www.npmjs.com/package/mailparser).
- A shared **provider pool** keeps one live IMAP connection per account, with
  keepalive and transparent reconnect (dead sockets retry once).
- Connections are **lazy** β€” adding the server to Claude doesn't touch your
  mailbox until you actually use it.
- Built on MCP SDK 1.x (spec line 2025-06-18 / 2025-11-25). The transport
  layer is isolated in `src/http/`, so migrating to the stateless 2026-07-28
  spec / SDK v2 is a contained change.

### Project layout

```
src/
  index.ts              CLI: stdio server, serve, ui, service subcommands
  mcp.ts                MCP server factory: tools, schemas, annotations, elicitation
  bin/setup.ts          `imail-mcp-setup` β€” foreground service + admin UI (legacy entry)
  accounts/
    registry.ts         non-secret account registry (accounts.json)
    pool.ts             provider pool: lazy connect, keepalive, add/remove accounts
  auth/
    keychain.ts         Keychain storage: per-account credentials + HTTP token
  http/
    server.ts           HTTP service: /mcp (session map), /auth, /api, admin UI
    ui.ts               admin UI page (no framework, no build step)
  service/
    launchd.ts          LaunchAgent install/uninstall/status
  providers/
    types.ts            provider-agnostic MailProvider contract
    icloud.ts           iCloud IMAP/SMTP implementation (incl. bulk ops)
```

---

## Adding another provider

The tools only ever talk to the `MailProvider` interface, so a new backend is
one new file:

1. Implement `MailProvider` (see
   [`src/providers/types.ts`](src/providers/types.ts)) in a new file under
   `src/providers/`.
2. Wire it up in [`src/accounts/pool.ts`](src/accounts/pool.ts).

The tools stay unchanged.

---

## Troubleshooting

- **"No mail accounts are connected"** β€” open the admin UI (`imail-mcp ui`)
  and connect an account on the *Accounts* tab.
- **"Login failed"** when connecting β€” make sure you used an **app-specific
  password**, not your normal Apple ID password.
- **`imail-mcp ui` says the service isn't answering** β€” start it:
  `imail-mcp service install` (persistent) or `imail-mcp serve` (foreground).
- **Port already in use** β€” pass `--port N` to `serve` / `service install`,
  and update your client configs accordingly.
- **Upgrading from ≀0.1** β€” the old single-account Keychain entry is migrated
  automatically on first run; existing stdio client configs keep working.
- **Service logs** β€” `~/Library/Logs/imail-mcp/imail-mcp.log` (also shown in
  the admin UI's *Service* tab).

---

## License

**[PolyForm Noncommercial License 1.0.0](LICENSE.md)** β€” this is *source-available*,
not OSI open source.

- βœ… **Free** for any **noncommercial** purpose β€” personal use, study, research,
  hobby projects, and use by nonprofits, schools, and government bodies.
- βœ… You may read, modify, and redistribute it; the **copyright notice must stay
  intact**, so your work is always credited.
- πŸ’Ό **Commercial use requires a separate license.** If you want to use imail-mcp
  to make money β€” in a product, a paid service, or inside a for-profit company β€”
  contact Investment Fidelity Company at **ceo@investmentfidelity.company** to
  arrange a commercial license.

See [LICENSE.md](LICENSE.md) for the full terms.

TDQS

B3.4/5.0

Scored across 14 tools

Disambiguation5/5

Each tool targets a distinct email operation (e.g., archive vs delete vs move, compose vs send vs save draft, forward vs reply). No two tools have overlapping purposes.

Naming Consistency4/5

Most tools follow verb_noun pattern (e.g., archive_message, delete_message). 'forward' and 'reply' are just verbs, which is a minor inconsistency but still clear.

Tool Count5/5

14 tools cover essential email operations (send, receive, manage folders, flags, attachments, threads) without being excessive.

Completeness4/5

Covers major email lifecycle (send, receive, delete, move, flag, search, thread). Minor gaps: no direct edit draft or empty trash, but key workflows are supported.

Maintenance

ActivitySlowing
ResponsivenessNo issues