An MCP server that lets AI agents read, search, send and organize email over IMAP and SMTP. It runs locally over stdio, works with any MCP client (Claude Desktop, OpenBot, Cursor, …), and needs only an email address and an app password.
- Reads and receives: list, read, search, threads, statistics, attachments, new-mail push
- Sends: new mail, reply / reply-all, forward with attachments, drafts, templates, scheduled send
- Organizes: read/unread/flag, move, archive, delete (to Trash), bulk actions, folders
- Safe: passwords never logged, tools annotated so clients ask before sending or deleting, nothing is ever expunged, optional read-only mode
{
"mcpServers": {
"email": {
"command": "npx",
"args": ["-y", "@sarequl/email-mcp"],
"env": {
"EMAIL_ADDRESS": "you@gmail.com",
"EMAIL_PASSWORD": "your-app-password"
}
}
}
}The domain of EMAIL_ADDRESS picks the IMAP and SMTP servers automatically for Gmail,
Google Workspace, Yahoo, iCloud, Zoho, Fastmail, GMX and AOL. Other domains are detected through
DNS SRV records and common host names; see Custom domains if that fails.
Requires Node.js 20 or newer.
Gmail does not accept your normal password over IMAP. Create an app password:
- Turn on 2-Step Verification: https://myaccount.google.com/signinoptions/two-step-verification
- Open https://myaccount.google.com/apppasswords, enter a name such as
email-mcp, click Create. - Copy the 16-character password (spaces do not matter) into
EMAIL_PASSWORD. - IMAP is enabled by default on current Gmail accounts. If
check_healthreports an IMAP login failure, open Gmail → Settings → See all settings → Forwarding and POP/IMAP → Enable IMAP.
Google Workspace accounts work the same way, but the administrator must allow app passwords and IMAP access for the organization.
Account Security → Generate app password → use it as EMAIL_PASSWORD.
Sign in at https://appleid.apple.com → Sign-In and Security → App-Specific Passwords →
Generate. Use your full iCloud address as EMAIL_ADDRESS.
Each provider offers app passwords in its security settings; use one as EMAIL_PASSWORD.
Zoho and GMX also need IMAP access switched on in the mail settings.
The built-in table knows Outlook's servers, but Microsoft is retiring password sign-in for IMAP.
OAuth sign-in is on the roadmap (see PLAN.md); until then basic authentication may be rejected.
If auto-detection fails, set the hosts explicitly:
| Variable | Meaning |
|---|---|
EMAIL_ADDRESS |
The mailbox address (required) |
EMAIL_PASSWORD |
App password or mailbox password (required) |
EMAIL_USERNAME |
Login name when it differs from the address |
EMAIL_IMAP_HOST, EMAIL_IMAP_PORT |
IMAP server (port defaults to 993) |
EMAIL_IMAP_SECURE |
true for implicit TLS (default for 993), false for plain/STARTTLS |
EMAIL_SMTP_HOST, EMAIL_SMTP_PORT |
SMTP server (port defaults to 587) |
EMAIL_SMTP_SECURE |
true for implicit TLS (default for 465), false for STARTTLS |
EMAIL_READ_ONLY |
true hides every tool that sends or changes mail |
EMAIL_CONFIG |
Path to the config file (default ~/.config/email-mcp/config.toml) |
EMAIL_DOWNLOAD_DIR |
Where download_attachment saves files (default: a folder under the OS temp dir) |
EMAIL_LOG_LEVEL |
debug for verbose logs on stderr |
Run the check_health tool after setup: it logs in to both servers and tells you what failed.
The environment variables define the default account. More accounts go in the config file
(~/.config/email-mcp/config.toml or the path in EMAIL_CONFIG):
[[accounts]]
name = "work"
email = "me@company.example"
password = "app-password"
# optional overrides, otherwise detected from the domain:
# username = "me"
# imap_host = "imap.company.example"
# imap_port = 993
# smtp_host = "smtp.company.example"
# smtp_port = 587
# appends_sent = false # true if the provider stores sent mail itself
[[accounts]]
name = "personal"
email = "me@yahoo.com"
password = "another-app-password"Every tool accepts an optional account argument (the name); the first account is the default.
list_accounts shows what is configured.
| Area | Tools |
|---|---|
| Connection | check_health, list_accounts |
| Reading | list_mailboxes, list_emails, get_email, search_emails, get_thread, get_email_stats, download_attachment |
| Sending | send_email, reply_email, forward_email, save_draft, send_draft |
| Organizing | mark_email, move_email, archive_email, delete_email, bulk_action, create_mailbox, rename_mailbox, delete_mailbox |
| Smart | extract_contacts, extract_calendar, list_templates, apply_template, schedule_email, list_scheduled, cancel_scheduled |
Messages are addressed by mailbox path and UID, both returned by list_emails and
search_emails. Mailbox names inbox, sent, drafts, trash, junk and archive are
resolved to the provider's real folders (for example [Gmail]/Sent Mail).
The server keeps an IMAP IDLE connection to each INBOX. When mail arrives it sends an MCP
notifications/resources/updated for the resource email://inbox/latest (and
email://<account>/inbox/latest) and a logging notification with the new message summaries.
Reading the resource returns the newest inbox messages.
Put Markdown files in <config dir>/templates/, e.g. ~/.config/email-mcp/templates/welcome.md:
---
subject: Welcome {{name}}
---
Hello {{name}},
Welcome aboard!list_templates lists them; apply_template fills the placeholders and previews, saves a draft
or sends.
schedule_email stores the message in <config dir>/scheduled.json and sends it when the time
comes, as long as the server is running. If the time passes while the server is off, the message is
sent at the next start. list_scheduled and cancel_scheduled manage the queue.
- Passwords are never written to logs, and error messages have them redacted.
- Tools carry MCP annotations: reading tools are
readOnlyHint, sending and deleting tools aredestructiveHint, so well-behaved clients ask the user before running them. delete_emailandbulk_action deletemove messages to Trash. Nothing is ever expunged.delete_mailboxrefuses special folders and non-empty folders unlessforceis set.- Attachments are only read from local paths you pass and written to paths returned in the result.
EMAIL_READ_ONLY=trueremoves every tool that sends or changes mail.
npm install
npm test # automated tests against local fake IMAP and SMTP servers
npm run build # compile to dist/
npm run dev # run from source with tsxnpm run live-check logs in to a real account, lists folders, appends a test message to the
INBOX, reads it back, moves it to Trash, and sends a test email to the account itself. Use a test
mailbox, not your main one:
EMAIL_ADDRESS=test@gmail.com EMAIL_PASSWORD=app-password npm run live-checkPublishing is automated by .github/workflows/publish.yml. Once, add an npm granular access
token with publish rights as the NPM_TOKEN repository secret. Then for each release bump the
version in package.json and push to main:
npm version patch # or minor / major
git push --follow-tagsEvery push to main checks whether that version is on npm and, if not, runs the tests and
publishes @sarequl/email-mcp with provenance. A v* tag or GitHub release triggers the same
job.
MIT