Skip to main content
Glama
MinKyawNyunt

IMAP MCP Connector

by MinKyawNyunt

IMAP MCP Connector

Use your own mailbox from Claude or ChatGPT. This is a small self-hosted server: people sign in with their email address and (app) password, choose what the AI may do, and paste one connector URL into their AI app.

  • Works with any IMAP mailbox that accepts a password or app password: Gmail, iCloud, Yahoo, Fastmail, Zoho, most hosting providers and self-run servers.

  • One deployment serves many users, for example a company or a family.

  • Per-user permission levels: Read only, Read and draft (default), Full access (send and delete-to-Trash).

  • Remote MCP server with OAuth 2.1 (dynamic client registration, PKCE), so it works as a custom connector in Claude and ChatGPT.

Not supported yet: Outlook.com and Microsoft 365, which no longer allow password sign-in over IMAP.

Quickstart (Docker Compose, ~5 minutes)

  1. Point a DNS name (e.g. mail.example.com) at your server, with ports 80 and 443 open.

  2. Clone this repository and create your config:

    cp .env.example .env
    # fill in DOMAIN, PUBLIC_URL, ENCRYPTION_KEY (openssl rand -base64 32),
    # SESSION_SECRET (openssl rand -hex 32), ALLOWED_EMAIL_DOMAINS or ALLOWED_IMAP_HOSTS
  3. Start it:

    docker compose up -d
  4. Open https://mail.example.com, sign in with your email and app password, and follow the connect instructions shown on the settings page.

Caddy obtains HTTPS certificates automatically.

Related MCP server: IMAP MCP Server

Connect to Claude

Settings → Connectors → Add custom connector → paste https://<your-domain>/mcp → Connect. Sign in and approve access when prompted.

Connect to ChatGPT

Settings → Connectors (turn on developer mode if your plan requires it) → Create → paste https://<your-domain>/mcp → authentication OAuth. Sign in and approve access when prompted.

App passwords

Most big providers refuse your normal password over IMAP once two-factor sign-in is on. Create an app password and use it to sign in:

Lost it? Create a new one and sign in again. The stored password is replaced.

Configuration

Variable

Required

Meaning

PUBLIC_URL

yes

External origin, https:// only (no path).

ENCRYPTION_KEY

yes

32 random bytes, base64. Encrypts stored mail passwords. Back it up: if it is lost, users must sign in again.

SESSION_SECRET

yes

≥ 32 characters, signs session cookies.

ALLOWED_EMAIL_DOMAINS

at least one of these

Comma-separated email domains allowed to sign in.

ALLOWED_IMAP_HOSTS

at least one of these

Comma-separated IMAP hosts allowed; * allows any public server that auto-discovery finds. Hand-entered servers must be listed by name.

ALLOW_PRIVATE_HOSTS

no (false)

Allow mail servers on private networks and unencrypted connections.

DEFAULT_SEND_LIMIT_PER_HOUR

no (20)

Emails each user's AI may send per hour.

DATA_DIR

no (/data)

Where the SQLite database lives.

PORT

no (3000)

Listen port.

When both allowlists are set, a sign-in must pass both: the email domain must be in ALLOWED_EMAIL_DOMAINS and the IMAP host must be in ALLOWED_IMAP_HOSTS (unless it is *). A list that is not set does not restrict, so ALLOWED_EMAIL_DOMAINS alone allows any public mail server for those domains. The check runs at sign-in, when SMTP settings change, and again before each new mail connection.

Server settings are auto-discovered on first sign-in (built-in presets, the Thunderbird ISPDB, then DNS SRV records), and the first successful sign-in pins the server for that address. Settings typed into the sign-in form are accepted only when discovery definitively finds nothing and the IMAP host is listed by name in ALLOWED_IMAP_HOSTS (* does not count). Otherwise, whoever signed in first with an address could point it at a server they control and capture the real owner's password at the owner's first sign-in. If the automatic lookup fails temporarily (for example the ISPDB or DNS is unreachable), sign-in is refused with a request to try again. Most company domains publish no discoverable settings, including Google Workspace and Microsoft-hosted ones, so for those domains list their IMAP server, e.g. ALLOWED_IMAP_HOSTS=imap.gmail.com or ALLOWED_IMAP_HOSTS=mail.example.com.

Upgrading from an earlier version: accounts created before this rule are re-confirmed at their next sign-in. They keep working if their IMAP host matches a built-in preset, is listed in ALLOWED_IMAP_HOSTS, or matches what discovery finds now. Otherwise sign-in and AI access are refused until you list the host. Before listing a host, check that it is your users' real server:

docker compose exec app node -e "const db=require('better-sqlite3')('/data/imap-connector.db'); console.table(db.prepare(\"SELECT email, imap_host, smtp_host FROM users WHERE settings_source = 'legacy'\").all())"

Delete any account whose server is not its owner's real mail server (DELETE FROM users WHERE email = ?); the owner can then sign in normally.

To change one user's send limit (run in the deployment directory):

docker compose exec app node -e "const db=require('better-sqlite3')('/data/imap-connector.db'); db.prepare('UPDATE users SET send_limit_per_hour = ? WHERE email = ?').run(50, 'someone@example.com')"

Tools the AI gets

Level

Tools

Read only

list_folders, search_messages, get_message, get_thread, get_attachment

Read and draft

+ set_flags, move_messages, create_draft

Full access

+ send_email, delete_messages (moves to Trash, never permanent)

Security model

  • What is stored: each user's email address, server settings, and mail password encrypted with AES-256-GCM using ENCRYPTION_KEY. OAuth codes and tokens are stored only as SHA-256 hashes.

  • What is never logged: passwords, tokens, or message content.

  • Who can sign in: only addresses or servers on your allowlist. Mail hosts resolving to private addresses are rejected unless ALLOW_PRIVATE_HOSTS=true. Connections go to the exact address that passed this check (TLS still verifies the hostname), so a second DNS answer cannot redirect them to an internal address.

  • Prompt injection: an email can contain text written to manipulate an AI. Email content is marked as untrusted for the model (between tags carrying a random per-response id, so an email cannot fake the end of its block), tools carry read-only/destructive hints so AI apps ask before sending, sending is rate-limited, and sending is off by default. These measures reduce the risk but cannot eliminate it. Only enable Full access if you accept that risk.

  • Users can revoke any connected AI app, or delete their account, from the settings page.

Deployment notes and known limitations

  • Plain-http PUBLIC_URL: it works only for localhost / 127.0.0.1, even with NODE_ENV=development. The MCP SDK rejects any other non-https issuer URL.

  • Run behind exactly one reverse proxy: the app sets Express trust proxy to 1, as in the provided compose file with Caddy. If you expose the app directly without a proxy, clients can spoof X-Forwarded-For and weaken the per-IP sign-in rate limit.

  • Folder roles on servers without SPECIAL-USE: roles such as sent or trash are resolved from the server's SPECIAL-USE flags, then from common English top-level folder names, then from localized top-level names (for example "Gesendet" or "Papierkorb"). If a role still does not resolve, tools that take a folder accept the exact folder path returned by list_folders; create_draft, saving to Sent after send_email, and delete_messages need the Drafts, Sent and Trash roles to resolve.

Development

npm install
npm test                 # unit tests
npm run test:integration # needs Docker (GreenMail test server)
npm run dev              # needs the env vars above; NODE_ENV=development allows http://localhost

Gmail's native thread search (X-GM-EXT-1) is not covered by the automated tests. Check it manually against a Gmail account before releases.

License

MIT. Mail provider presets are adapted from nikolausm/imap-mcp-server (MIT); see THIRD_PARTY_NOTICES.md.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Enables Claude to interact with email accounts via IMAP and SMTP, providing tools for searching, reading, sending, and managing emails across multiple providers.
    40
    800 npm
    111
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude to read, search, send, and manage emails across multiple IMAP/SMTP accounts via a single deployment.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Connects Claude to Microsoft 365 Outlook and Google Gmail APIs for email search, invoice detection, attachment handling, folder/label management, and draft creation. Uses Anthropic OAuth for secure authentication.
    17 npm
    ISC