imap-mcp
by aviman1109
README.md
# imap-mcp
IMAP client MCP. Read mail from a Dovecot / Synology MailPlus mailbox, and
optionally fire webhooks when new matching messages arrive — replaces fragile
Gmail OAuth for automation triggers.
## Tools
| Tool | Description |
|---|---|
| `list_unread(mailbox, limit)` | Unread message summaries |
| `search(criteria, mailbox, limit)` | Raw IMAP SEARCH |
| `fetch(uid, mailbox)` | Full message (headers + text + html) |
| `mark_read(uid, mailbox)` | Set `\Seen` flag |
| `move(uid, source, dest)` | Move to another folder |
| `list_folders()` | All folders |
| `get_status()` | IMAP ping + watcher rules + fire count |
## Environment
| Variable | Required | Description |
|---|---|---|
| `IMAP_HOST` | ✓ | Server (e.g. `192.168.68.61`) |
| `IMAP_PORT` | | Default `993` |
| `IMAP_SSL` | | `true` (default) or `false` |
| `IMAP_USERNAME` | ✓ | Synology account name, not email |
| `IMAP_PASSWORD` | ✓ | |
| `IMAP_DEFAULT_MAILBOX` | | Default `INBOX` |
| `WATCHES_JSON` | | Inline JSON array of watch rules |
| `WATCHES_FILE` | | Path to JSON file (default `/data/watches.json`) |
| `POLL_INTERVAL_SECS` | | Default `30` |
| `PORT` | | MCP server port (default `38105`) |
## Watch rules
```json
[
{
"name": "garmin-livetrack",
"mailbox": "INBOX",
"criteria": "FROM \"noreply@garmin.com\" SUBJECT \"LiveTrack\" UNSEEN",
"webhook_url": "http://host.docker.internal:5678/webhook/livetrack-mail",
"mark_read": true,
"move_to": null
}
]
```
On startup the watcher "primes" each rule with existing matching UIDs, so
only *new* mail after boot fires. Every `POLL_INTERVAL_SECS` it re-runs
each rule's criteria and POSTs matching messages (full body) to `webhook_url`
as `{ "rule": "...", "mailbox": "...", "message": {...} }`. After a
successful POST it either moves the message to `move_to`, or marks it read
if `mark_read`.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues