IMAP MCP Server
A read-only IMAP server for the Model Context Protocol that lets users list mailboxes, search messages, and retrieve messages and attachments through MCP. It exposes Streamable HTTP at /mcp with strict safety limits.
README
IMAP MCP Server
A production-minded, strictly read-only IMAP server for the Model Context Protocol
(MCP). It exposes Streamable HTTP at /mcp and supports exactly these tools:
health_checklist_mailboxessearch_messagesget_messageget_attachment
Messages are identified by mailbox plus IMAP UID. Mailboxes are always selected with
readonly=True; the server has no send, flag, move, delete, or raw-command tool.
Remote SSH development
Clone the repository on the Docker host and open that directory with VS Code Remote - SSH. Python 3.11 or newer is required for development. Docker and the Compose plugin are required for container verification.
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
pytest
ruff check .
mypy
Automated tests use fakes and generated MIME messages; they do not access a mailbox.
Configuration and secrets
Copy .env.example to the ignored .env file and set the host, port, username,
mailbox allowlist, and safety limits. TLS certificate verification cannot be disabled.
Supported TLS modes are implicit_tls and starttls.
Compose expects the password in an ignored file:
mkdir -p secrets
chmod 700 secrets
printf '%s' 'replace-with-the-real-password' > secrets/imap_password
sudo chown 10001:10001 secrets/imap_password
sudo chmod 600 secrets/imap_password
cp .env.example .env
The container runs as the non-root user and group 10001:10001. File-backed Compose
secrets are bind-mounted with their host ownership and permissions, so a secret owned
by root:root with mode 0600 cannot be read by the application. The commands above
make the password readable only by the container's application identity.
To keep root as the owner instead, grant read access to the application group:
sudo chown root:10001 secrets/imap_password
sudo chmod 640 secrets/imap_password
Do not use mode 0644 and do not run the container as root merely to access the
secret. After changing ownership or permissions, recreate the service and verify its
health:
docker compose up -d --force-recreate mcp-server
docker compose ps
docker compose logs --tail=30 mcp-server
Do not add the password directly to .env when using Compose: the service injects
IMAP_PASSWORD_FILE=/run/secrets/imap_password. For a non-Compose launch, set exactly
one of IMAP_PASSWORD or IMAP_PASSWORD_FILE in the protected process environment.
The limits for results, body bytes, attachment bytes, query length, and socket timeout
are server configuration. Tool callers can request a smaller search page but cannot
raise these limits. Attachments are restricted to PDF, JPEG, PNG, CSV, and plain text;
accepted attachment bytes are returned as content_base64.
Build and startup
docker compose build
docker compose up -d mcp-server
docker compose ps
docker compose logs --tail=100 mcp-server
The published endpoint is http://127.0.0.1:8700/mcp by default. Configure the
production and development ports centrally with MCP_PORT and MCP_DEV_PORT in
.env; Compose uses each value for the application listener, localhost publication,
and health check. The endpoint is not reachable from another host. The image runs as
UID 10001, uses a read-only filesystem, and keeps no persistent mailbox data.
The optional development profile mounts only src/ read-only and uses port 8701:
docker compose --profile dev up mcp-server-dev
Verification
Run the complete checks inside the image:
docker build --target test -t imap-mcp:test .
docker run --rm imap-mcp:test
Run the opt-in smoke test only against a disposable account configured through the same IMAP environment variables:
IMAP_INTEGRATION_TEST=1 pytest -q tests/test_real_imap_opt_in.py
That smoke test lists mailboxes only. Broader real-account validation should verify all tools using non-sensitive fixture mail while independently checking that no flags or mailbox state change.
To inspect the running Streamable HTTP endpoint, use MCP Inspector 2 from a machine that can reach the localhost-bound port. In web mode, pass the transport and server URL explicitly:
npx @modelcontextprotocol/inspector \
--web \
--transport http \
--server-url http://127.0.0.1:8700/mcp
Replace 8700 with the configured MCP_PORT. The Inspector web UI listens on remote
port 6274 by default. When working through VS Code Remote SSH, forward remote port
6274 to local port 6274. If local port 6274 is already occupied, VS Code may
silently choose 6275; the resulting browser origin is then rejected by Inspector's
DNS-rebinding protection.
Prefer stopping the stale local process or port forward and restoring the
6274 -> 6274 mapping. If a different local port is intentional, allow its exact
browser origin when starting Inspector. For example, for a browser URL beginning with
http://127.0.0.1:6275:
ALLOWED_ORIGINS=http://127.0.0.1:6275 \
npx @modelcontextprotocol/inspector \
--web \
--transport http \
--server-url http://127.0.0.1:8700/mcp
ALLOWED_ORIGINS must contain the browser origin (scheme://host:port), not the MCP
server URL or port. Do not include a path, query string, or token, and do not disable
Inspector authentication or DNS-rebinding protection. Inspector does not accept a
wildcard localhost port, so a dynamically remapped port must be allowed explicitly.
For a non-browser discovery check, use CLI mode:
npx @modelcontextprotocol/inspector \
--cli \
--transport http \
--server-url http://127.0.0.1:8700/mcp \
--method tools/list
Confirm discovery of exactly the five tools listed above and that every tool has the read-only annotation.
Troubleshooting
- Configuration errors name the invalid variable but never print secret values.
- A TLS error normally means the hostname, port, trust store, or server certificate is wrong. Certificate verification is intentionally mandatory.
- An authentication error is deliberately generic. Verify the username and secret file permissions without printing the password.
- A missing mailbox may mean its exact IMAP name differs from the configured allowlist.
- Missing UID errors can occur after mailbox retention or deletion by another client; sequence numbers are never used as identifiers.
- Oversized bodies and attachments are rejected rather than truncated. Unsupported attachment types are rejected by default.
- Inspector web errors containing
Invalid origincome from Inspector itself, not from this MCP endpoint. Check whether Remote SSH changed local port6274and setALLOWED_ORIGINSto the exact origin shown in the browser address bar if needed. - The Docker health check proves that the MCP TCP listener accepts connections; it does not authenticate to IMAP.
The Secure MCP Tunnel, ChatGPT Work configuration, and scheduled analysis are deferred until this local milestone has passed container, Inspector, and disposable-account verification.
MCP connection to chatgpt
- Open https://platform.openai.com/settings/organization/api-keys
- new API key is needed:
- create secrets/control_plane_api_key
- copy there a new key from the openai website
- restrict permissions to 600 and 65532:65532 not to be available to anyone
- Open https://platform.openai.com/settings/organization/tunnels
- it is needed to:
- create a new tunnel
- assign it to the personal organization
- assign it to workspace, where it will be used
- get tunnel ID, copy it to CONTROL_PLANE_TUNNEL_ID into .env file
- create runtime API for tunnel client
- do not share API key, do not put it to docker compose.yaml
- Open https://platform.openai.com/settings/organization/tunnels
- click on Download tunnel-client and select the version you need (e.g. v0.0.10 for linux-amd64)
- extract and store the file to tunnel-client folder
- build docker and check logs:
docker compose logs --tail=100 tunnel-client
- verify tunnel_id
- verify health and conenctions:
curl -i http://127.0.0.1:8702/healthz
curl -i http://127.0.0.1:8702/readyz
- you should get e.g.:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Wed, 05 Aug 2026 14:04:16 GMT
Content-Length: 4
live
- go to Chatgpt Settings->Securitty and login
- enable Developer mode
- open ChatGPT Plugins (or browse for plugins)
- klick to + and enter e.g.:
- change connection to Tunnel and select your tunnel
- Name: My IMAP
- Description: Read-only access to my IMAP mailbox
- choose no authentication (tunnel is used)
- agree with the risk
- create plugin
- and then connect
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。