mcp-email-server

Read, search, file and send mail on any IMAP and SMTP account from an MCP client

By Zhongsheng Ji (individual) Python Local · stdio Communication

67 popularity score ★ 378 ↓ 14k/mo

Connect your client

Local (PyPI)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs MCP_EMAIL_SERVER_EMAIL_ADDRESS, MCP_EMAIL_SERVER_PASSWORD, MCP_EMAIL_SERVER_IMAP_HOST. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add email -e MCP_EMAIL_SERVER_EMAIL_ADDRESS=<MCP_EMAIL_SERVER_EMAIL_ADDRESS> -e MCP_EMAIL_SERVER_PASSWORD=<MCP_EMAIL_SERVER_PASSWORD> -e MCP_EMAIL_SERVER_IMAP_HOST=<MCP_EMAIL_SERVER_IMAP_HOST> -- uvx mcp-email-server@latest stdio
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "email": {
      "command": "uvx",
      "args": [
        "mcp-email-server@latest",
        "stdio"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "email": {
      "command": "uvx",
      "args": [
        "mcp-email-server@latest",
        "stdio"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "email": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "mcp-email-server@latest",
        "stdio"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.email]
command = "uvx"
args = ["mcp-email-server@latest", "stdio"]

[mcp_servers.email.env]
MCP_EMAIL_SERVER_EMAIL_ADDRESS = "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>"
MCP_EMAIL_SERVER_PASSWORD = "<MCP_EMAIL_SERVER_PASSWORD>"
MCP_EMAIL_SERVER_IMAP_HOST = "<MCP_EMAIL_SERVER_IMAP_HOST>"
Gemini CLITerminal
gemini mcp add --scope user -e MCP_EMAIL_SERVER_EMAIL_ADDRESS=<MCP_EMAIL_SERVER_EMAIL_ADDRESS> -e MCP_EMAIL_SERVER_PASSWORD=<MCP_EMAIL_SERVER_PASSWORD> -e MCP_EMAIL_SERVER_IMAP_HOST=<MCP_EMAIL_SERVER_IMAP_HOST> email uvx -- mcp-email-server@latest stdio
Local (container)

Add in one click

Opens the app, which asks before it adds the server. Then replace each <NAME> in its settings with your value.

Or add it by command or config

It needs MCP_EMAIL_SERVER_EMAIL_ADDRESS, MCP_EMAIL_SERVER_PASSWORD, MCP_EMAIL_SERVER_IMAP_HOST. Replace each <NAME> with your value.

Claude CodeTerminal
claude mcp add email -e MCP_EMAIL_SERVER_EMAIL_ADDRESS=<MCP_EMAIL_SERVER_EMAIL_ADDRESS> -e MCP_EMAIL_SERVER_PASSWORD=<MCP_EMAIL_SERVER_PASSWORD> -e MCP_EMAIL_SERVER_IMAP_HOST=<MCP_EMAIL_SERVER_IMAP_HOST> -- docker run -i --rm -e MCP_EMAIL_SERVER_EMAIL_ADDRESS -e MCP_EMAIL_SERVER_PASSWORD -e MCP_EMAIL_SERVER_IMAP_HOST ghcr.io/wh1isper/mcp-email-server
Claude Desktopclaude_desktop_config.json
{
  "mcpServers": {
    "email": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS",
        "-e",
        "MCP_EMAIL_SERVER_PASSWORD",
        "-e",
        "MCP_EMAIL_SERVER_IMAP_HOST",
        "ghcr.io/wh1isper/mcp-email-server"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
Cursor~/.cursor/mcp.json
{
  "mcpServers": {
    "email": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS",
        "-e",
        "MCP_EMAIL_SERVER_PASSWORD",
        "-e",
        "MCP_EMAIL_SERVER_IMAP_HOST",
        "ghcr.io/wh1isper/mcp-email-server"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
VS Code.vscode/mcp.json
{
  "servers": {
    "email": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS",
        "-e",
        "MCP_EMAIL_SERVER_PASSWORD",
        "-e",
        "MCP_EMAIL_SERVER_IMAP_HOST",
        "ghcr.io/wh1isper/mcp-email-server"
      ],
      "env": {
        "MCP_EMAIL_SERVER_EMAIL_ADDRESS": "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>",
        "MCP_EMAIL_SERVER_PASSWORD": "<MCP_EMAIL_SERVER_PASSWORD>",
        "MCP_EMAIL_SERVER_IMAP_HOST": "<MCP_EMAIL_SERVER_IMAP_HOST>"
      }
    }
  }
}
Codex~/.codex/config.toml
[mcp_servers.email]
command = "docker"
args = ["run", "-i", "--rm", "-e", "MCP_EMAIL_SERVER_EMAIL_ADDRESS", "-e", "MCP_EMAIL_SERVER_PASSWORD", "-e", "MCP_EMAIL_SERVER_IMAP_HOST", "ghcr.io/wh1isper/mcp-email-server"]

[mcp_servers.email.env]
MCP_EMAIL_SERVER_EMAIL_ADDRESS = "<MCP_EMAIL_SERVER_EMAIL_ADDRESS>"
MCP_EMAIL_SERVER_PASSWORD = "<MCP_EMAIL_SERVER_PASSWORD>"
MCP_EMAIL_SERVER_IMAP_HOST = "<MCP_EMAIL_SERVER_IMAP_HOST>"
Gemini CLITerminal
gemini mcp add --scope user -e MCP_EMAIL_SERVER_EMAIL_ADDRESS=<MCP_EMAIL_SERVER_EMAIL_ADDRESS> -e MCP_EMAIL_SERVER_PASSWORD=<MCP_EMAIL_SERVER_PASSWORD> -e MCP_EMAIL_SERVER_IMAP_HOST=<MCP_EMAIL_SERVER_IMAP_HOST> email docker -- run -i --rm -e MCP_EMAIL_SERVER_EMAIL_ADDRESS -e MCP_EMAIL_SERVER_PASSWORD -e MCP_EMAIL_SERVER_IMAP_HOST ghcr.io/wh1isper/mcp-email-server

Settings 10

MCP_EMAIL_SERVER_EMAIL_ADDRESS Required: Email address of the account set by environment variables.
MCP_EMAIL_SERVER_PASSWORD Required: Password or app password for the account.
MCP_EMAIL_SERVER_IMAP_HOST Required: IMAP server host; port 993 with SSL by default.
MCP_EMAIL_SERVER_SMTP_HOST Optional: SMTP server host; needed to send (port 465 by default).
MCP_EMAIL_SERVER_ACCOUNT_NAME Optional: Name of the account; 'default' if unset.
MCP_EMAIL_SERVER_ALLOWED_RECIPIENTS Optional: Addresses mail may go to; empty blocks sending, * allows all.
MCP_EMAIL_SERVER_ALLOWED_MUTATIONS Optional: Kinds of change allowed (draft, organize, delete, send, append); all by default.
MCP_EMAIL_SERVER_ENABLE_ATTACHMENT_DOWNLOAD Optional: Allows saving attachments to disk; false by default.
MCP_EMAIL_SERVER_ENABLE_ATTACHMENT_CONTENT Optional: Allows returning attachment bytes to the client; false by default.
MCP_EMAIL_SERVER_CONFIG_PATH Optional: Path to the config file instead of ~/.config/mcp-email-server/config.toml.

In a container, a setting goes in with -e NAME=value after docker run.

What it does

mcp-email-server connects an MCP client to ordinary mailboxes over IMAP for reading and SMTP for sending. It is not tied to one provider, so it works with any account that allows password sign-in over those protocols. It runs on your own machine over stdio by default, and it can also serve SSE or Streamable HTTP. It can hold several accounts.

Version 1.13.1 registers 21 tools (counted in app.py at that tag). An assistant can list accounts and mailboxes, search a mailbox by its headers, and then fetch message bodies. It can send, forward, save drafts, add messages to a mailbox, and set flags and tags. It can also move, archive and delete messages, fetch attachments, and run raw IMAP or SMTP commands through email_command. Searches return 10 messages per page by default, up to 100 with page_size. Bodies are cut at 20,000 characters by default (max_body_length, up to 100,000), and body_offset fetches the rest.

Since 1.0.0 ("Local Email App V2"), you add accounts and passwords through a local web UI (`mcp-email-server ui`) or the CLI. As an alternative, you can configure a single account with environment variables. The MCP side has no tool to add accounts or change credentials: the add_email_account tool from 0.16.0 and earlier was removed. A local policy controls what tools may do: which kinds of change are allowed (draft, organize, delete, send, append), which recipients may be mailed, and which senders' mail is shown.

What it needs

RuntimePython 3.11+orDocker

Python 3.11 or later, run through uv (`uvx`), or Docker for the ghcr.io image (Linux amd64/arm64, from 1.6.2). You need an email account that allows IMAP sign-in with a password, plus SMTP details if you want to send. Configure the account before the client starts it: either run `uvx mcp-email-server@latest ui` once, or set MCP_EMAIL_SERVER_EMAIL_ADDRESS, MCP_EMAIL_SERVER_PASSWORD and MCP_EMAIL_SERVER_IMAP_HOST.

Limits

Sign-in is by password only: the docs describe no OAuth flow, so an account whose provider blocks plain password sign-in needs an app password. Nothing can be sent until you add allowed recipients: an empty allowed_recipients list blocks sending. Attachment download and attachment content are both off by default. email_command is off unless allow_protocol_commands is turned on for the account outside MCP. Deleting messages, and the fallback way of moving them, need a server with UIDPLUS. Environment variables configure one account only. Settings from 0.16.0 and earlier are not imported automatically; they keep running in legacy mode.

Who it suits

A good fit for anyone who wants an assistant to work on a personal or work mailbox from any provider that speaks IMAP/SMTP, with local control over what it may change or whom it may mail. Everything runs on your own machine, and passwords never pass through the assistant. If your mail account only allows OAuth sign-in, look for a server that supports it. If you want an assistant that only reads mail, set allowed_mutations to [] and leave allowed_recipients empty: by default every kind of change is allowed.

Tools 21

list_available_accounts
Lists the configured accounts and whether each can receive and send
list_allowed_recipients
Shows the recipient allowlist; empty means sending is off
list_allowed_senders
Shows the sender allowlist that filters which mail is shown
list_email_tags
Lists the semantic tags configured for messages
list_emails_metadata
Searches one mailbox and returns headers and IDs, page by page
get_emails_content
Fetches the bodies of chosen messages, optionally marking them read
list_mailboxes
Lists the folders on an account
send_email
Sends a new message over SMTP to allowed recipients
forward_email
Forwards a message, attachments included
save_draft
Saves a message to the Drafts folder
save_to_mailbox
Adds a composed message to a chosen folder
create_mailbox
Creates a new folder
set_email_flags
Adds or removes flags such as seen, flagged or answered
mark_emails_as_read
Marks messages as read
set_email_tags
Sets semantic tags on messages
move_emails
Moves messages to another folder, including Junk
archive_emails
Moves messages to the archive folder
delete_emails
Deletes messages permanently
get_attachment_content
Returns an attachment's bytes, when attachment content is enabled
download_attachment
Saves an attachment to the local disk, when downloads are enabled
email_command
Runs a sequence of raw IMAP or SMTP commands, when enabled per account

Similar servers