Skip to main content
Glama
jonathanhowell

imap-mcp

imap-mcp

An MCP server that gives AI agents access to email over IMAP, designed for agents that need to read and reason about email without making changes to it.

Philosophy

Read-first, intentionally constrained. imap-mcp is built for agentic workflows where the agent needs to understand a user's email — triage, summarise, search, monitor — but should not be able to send, delete, or move messages. The server is currently read-only, with one deliberate exception: agents can set and clear custom IMAP keywords (flags) on messages. This lets an agent mark messages it has processed, acted on, or flagged for follow-up, without touching the messages themselves.

Standard IMAP first. The server targets standard IMAP servers. Gmail is well-supported for reading, but keyword flagging does not yet work on Gmail — Gmail maps IMAP keywords to labels, which requires special handling. Gmail flagging support is next on the roadmap. Outlook/Microsoft 365 requires OAuth2, which is not currently implemented, so Microsoft accounts are not supported.

Multi-inbox, unified view. Connect as many accounts as you need. All tools accept an optional account parameter — omit it to query across all configured accounts and get a combined, sorted result.

Connect one or more email accounts and agents can read mailboxes, search messages by sender, subject, date, or body text, download attachments, and monitor for new mail — all via the Model Context Protocol. Designed to work with Claude Desktop and any MCP-compatible client.

Related MCP server: IMAP Mini MCP

Quick Start

  1. Clone and install:

    git clone https://github.com/jonathanhowell/imap-mcp.git
    cd imap-mcp
    npm install && npm run build
  2. Copy the example config:

    mkdir -p ~/.config/imap-mcp
    cp config.example.yaml ~/.config/imap-mcp/config.yaml
  3. Edit the config — fill in your account details and set environment variables for passwords:

    accounts:
      - name: personal
        host: imap.gmail.com
        port: 993
        username: you@gmail.com
        password: $GMAIL_PASSWORD

    Then export the variable:

    export GMAIL_PASSWORD="your-app-password"
  4. Run the server:

    node build/index.js

The server reads the config from ~/.config/imap-mcp/config.yaml by default. Override with IMAP_MCP_CONFIG=/path/to/config.yaml.

Configuration Reference

The config file is YAML. Default location: ~/.config/imap-mcp/config.yaml. Override with the IMAP_MCP_CONFIG environment variable.

accounts[]

Field

Type

Required

Default

Description

name

string

yes

Short identifier used by tools (e.g. personal, work)

host

string

yes

IMAP hostname (e.g. imap.gmail.com)

port

number

yes

Must be 993. TLS is enforced; port 143 and 587 are rejected

username

string

yes

IMAP login username (usually your email address)

password

string

yes

Use $ENV_VAR_NAME to read from environment variable

display_name

string

no

Human-readable label shown in list_accounts responses

polling (optional)

Field

Type

Required

Default

Description

interval_seconds

number

no

300

How often to poll for new mail (minimum: 60s)

Setting environment variables for passwords:

export GMAIL_PASSWORD="your-app-password"
export WORK_PASSWORD="your-work-password"

In config.yaml, reference them as $GMAIL_PASSWORD and $WORK_PASSWORD.

Performance note: To verify performance on large mailboxes, connect to a mailbox with 10,000+ messages, run list_messages with default parameters, and confirm the response arrives within 5 seconds and contains only message headers (no bodies). The 200-result cap ensures response size is bounded.

Claude Desktop Setup

Add this entry to your claude_desktop_config.json (usually at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "imap-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/imap-mcp/build/index.js"],
      "env": {
        "IMAP_MCP_CONFIG": "/absolute/path/to/config.yaml",
        "GMAIL_PASSWORD": "your-app-password"
      }
    }
  }
}

Replace /absolute/path/to/imap-mcp with the directory where you cloned the repo. The IMAP_MCP_CONFIG key is optional — omit it to use the default ~/.config/imap-mcp/config.yaml. Any env vars referenced in your config file (e.g. $GMAIL_PASSWORD) must appear in the env block so Claude Desktop passes them to the server process.

Provider Compatibility

Gmail

Gmail requires an App Password — your regular Google account password will not work with IMAP.

  1. Enable IMAP in Gmail settings: Settings → See all settings → Forwarding and POP/IMAP → Enable IMAP

  2. Generate an App Password: myaccount.google.com/apppasswords

  3. Use the generated 16-character password as $GMAIL_PASSWORD in your config

Host: imap.gmail.com, Port: 993

Generic IMAP

Any IMAP server that supports TLS on port 993 and Basic Auth should work. Check your provider's documentation for the correct hostname.

Outlook / Hotmail / Microsoft 365

Outlook/Hotmail/Microsoft 365: Microsoft deprecated Basic Auth for IMAP in October 2022. Modern Microsoft accounts require OAuth2, which this server does not currently support. If you are using an Outlook, Hotmail, or Microsoft 365 account, it will not work with this server.

Tool Reference

All tools are available via MCP. account parameters accept the name field from your config. Results are capped at 200 items for list_messages and search_messages.

list_accounts

Returns all configured accounts. No parameters.

Response: Array of { account, email, display_name? } objects.


list_folders

Parameter

Type

Required

Description

account

string

no

Account name. Omit to list folders for all accounts.

Response (single account): Array of { name, delimiter, flags, messages, unseen }.

Response (all accounts): Same array, sorted alphabetically by folder name.


list_messages

Parameter

Type

Required

Description

account

string

no

Account name. Omit to query all accounts.

folder

string

no

Folder name (default: INBOX)

limit

number

no

Max messages to return (server cap: 200)

offset

number

no

Pagination offset

sort

newest|oldest

no

Sort order (default: newest)

unread_only

boolean

no

Return only unread messages

Response (single account): Flat array of MessageHeader[] — each item includes uid, from, to[], cc[], subject, date, flags, and folder.

Response (all accounts): { results: MultiAccountMessageHeader[], errors?: Record<string, string> }. The errors key is present only when one or more accounts failed.


read_message

Parameter

Type

Required

Description

account

string

yes

Account name

uid

number

yes

Message UID

format

clean|full

no

clean strips reply chains (default). full returns raw body.

Response: Full message with headers, body, and attachments[] metadata. Inline text/calendar parts (calendar invites) are automatically surfaced as attachments with a default filename of invite.ics, even when they lack an explicit attachment disposition.


read_messages

Fetch multiple messages in a single call. All UIDs must belong to the same account and folder.

Parameter

Type

Required

Description

account

string

yes

Account name

uids

number[]

yes

List of message UIDs to fetch (max 50)

folder

string

no

Folder containing the messages (default: INBOX)

format

clean|full|truncated

no

Body format (default: clean)

max_chars

number

no

Max body characters when format is truncated (default: 2000)

Response: Array of message objects in the same order as uids. Each item includes headers, body, attachments[] metadata, and a uid field.


search_messages

Parameter

Type

Required

Description

account

string

no

Account name. Omit to search all accounts.

from

string

no

Filter by sender address or name

subject

string

no

Filter by subject text

body

string

no

Filter by body text content (case-insensitive, server-side IMAP SEARCH BODY)

since

string

no

ISO date string — messages on or after this date

before

string

no

ISO date string — messages before this date

unread

boolean

no

true = unread only, false = read only

folder

string

no

Folder to search (default: INBOX). Use all to search every folder sequentially.

max_results

number

no

Max results to return (server cap: 200)

exclude_keywords

string[]

no

Exclude messages that have any of these custom IMAP keywords set (e.g. ["ClaudeProcessed", "ClaudeReplied"]). First keyword filtered server-side; additional keywords filtered in memory.

include_keywords

string[]

no

Return only messages that have at least one of these custom IMAP keywords set (OR semantics). Single keyword uses server-side KEYWORD filter; multiple uses IMAP OR.

Response (single account): Flat array of SearchResultItem[] — each item includes uid, from, to[], cc[], subject, date, unread, folder, and keywords[].

Response (all accounts): { results: MultiAccountSearchResultItem[], errors?: Record<string, string> }.

Note: folder='all' searches every folder sequentially and can be slow on large mailboxes.


download_attachment

Parameter

Type

Required

Description

account

string

yes

Account name

uid

number

yes

Message UID

part_id

string

no

MIME part identifier (e.g. 2, 2.1). Faster when known.

filename

string

no

Attachment filename. Used to look up the part ID when part_id is not known.

folder

string

no

Folder containing the message (default: INBOX)

At least one of part_id or filename must be provided. When both are given, part_id takes precedence. Filename matching is case-insensitive.

Response: { filename, mimeType, size, data } where data is base64-encoded.

Calendar invites: Inline text/calendar parts are surfaced as attachments (typically named invite.ics). Use download_attachment with the part_id from the message's attachments[] to retrieve the ICS data.


get_new_mail

Parameter

Type

Required

Description

since

string

yes

ISO 8601 timestamp — return messages with internalDate after this time

account

string

no

Account name. Omit to query all accounts.

exclude_keywords

string[]

no

Exclude messages that have any of these custom IMAP keywords set (e.g. ["ClaudeProcessed"]). Filters cached results in memory.

Response: { results: MultiAccountMessageHeader[], errors?: Record<string, string> }. The server polls in the background at the configured interval; this tool reads from the cache, not live IMAP. Each result includes uid, from, subject, date, unread, folder, account, and keywords[].

Example Agent Prompts

Once connected to Claude Desktop, you can ask things like:

  • "Show me all unread emails from the last 24 hours across all my accounts"

  • "Search for emails from GitHub about pull requests in my work account from this week"

  • "Find any emails mentioning the invoice number INV-2024-042"

  • "Read the most recent email from alice@example.com and summarize it"

  • "Read all three emails in that thread and give me a summary"

  • "Download the PDF attachment from that email"

  • "Check if that email has a calendar invite and tell me the event details"

Troubleshooting

Connection refused / timeout

Check that port in your config is 993. This server enforces TLS — port 143 (plaintext) and port 587 (SMTP submission) will not work.

Authentication failed (Gmail)

Use an App Password, not your regular Google account password. Generate one at myaccount.google.com/apppasswords. Also verify IMAP is enabled in Gmail: Settings → See all settings → Forwarding and POP/IMAP → Enable IMAP.

Authentication failed (generic IMAP)

Verify the username and password are correct. Some providers require app-specific passwords even when not using Gmail — check your provider's security settings.

Outlook / Microsoft accounts not working

Microsoft deprecated Basic Auth for IMAP in October 2022. Microsoft 365, Outlook.com, and Hotmail accounts require OAuth2, which this server does not support. This is a Microsoft platform limitation that cannot be worked around with configuration changes.

Server crashes on startup

Check that the config file exists at the expected path (~/.config/imap-mcp/config.yaml by default, or the path in IMAP_MCP_CONFIG). Verify that all environment variables referenced in the config (e.g. $GMAIL_PASSWORD) are set before launching the server.

Performance: slow on large mailboxes

Using folder='all' in search_messages triggers a sequential search across every folder. On accounts with many folders or large mailboxes this can take several seconds. For faster results, specify a folder (e.g. folder='INBOX').

Contributing

Dev setup

npm install
npm run build
npm test

Guidelines

  • TypeScript strict mode throughout — no any types without explicit justification

  • All log output goes to stderr via logger.ts — never use console.log (enforced by ESLint)

  • Pre-commit hooks run lint + tests automatically via Husky

  • Install gitleaks for secret scanning (required for pre-commit hook): brew install gitleaks

PR flow

Branch from main, open a PR, CI must pass before merging.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jonathanhowell/imap-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server