email-mcp
Small personal MCP server for a single mailbox over IMAP + SMTP.
It is aimed at a private setup first:
- one mailbox
- credentials supplied through environment variables
- read mail over IMAP
- send mail over SMTP
- works well with Yandex Mail defaults, but can be pointed at any IMAP/SMTP provider
What I changed
This repo originally worked only in stdio mode. That is fine for local MCP clients, but ChatGPT web integration needs an HTTP MCP endpoint. The server now supports:
stdiofor local/dev usestreamable-httpfor ChatGPT web app usessefor compatibility
I also fixed a mail-threading issue:
- the old
reply_toparameter only set theReply-Toheader - real replies should usually use
In-Reply-ToandReferences read_emailnow returns those headers so they can be passed back intosend_email
And I improved read_email output by returning:
- decoded headers
- attachment metadata
- message threading headers
Attachment support
This version supports both reading and sending attachments.
Download an attachment from a received email
- Call
read_email(uid=..., folder="INBOX") - Inspect the
attachmentslist - Use
attachment_indexwithget_attachment(...)
get_attachment(...) returns:
filenamecontent_typesize_bytescontent_base64
Send attachments in outgoing email
send_email(...) accepts an attachments list.
Each item can be one of:
{"path": "/path/to/file.pdf"}
{"filename": "note.txt", "content_text": "hello from MCP"}
{"filename": "report.pdf", "content_base64": "JVBERi0x...", "content_type": "application/pdf"}
Sent folder behavior
After SMTP send succeeds, the same MIME message is appended to your IMAP sent folder.
By default that folder name is:
Sent
You can override it if your mailbox uses a different IMAP folder name:
export SENT_FOLDER="Sent"
# or
export MAILBOX_SENT_FOLDER="Sent"
If sent mail does not show up, first run list_folders() and use the exact folder name returned by your mailbox.
Files
server.py— MCP tool definitions and transport startupmail_ops.py— IMAP/SMTP implementationrequirements.txt— Python dependencies
Environment
Required:
export MAILBOX_EMAIL="you@example.com"
export MAILBOX_PASSWORD="your-app-password"
Optional provider settings:
export IMAP_HOST="imap.yandex.com"
export IMAP_PORT="993"
export SMTP_HOST="smtp.yandex.com"
export SMTP_PORT="465"
Optional sent-folder setting:
export SENT_FOLDER="Sent"
Optional MCP server settings:
export MCP_TRANSPORT="stdio"
export MCP_HOST="0.0.0.0"
export MCP_PORT="8000"
Aliases also supported for convenience:
export YANDEX_EMAIL="you@yandex.ru"
export YANDEX_APP_PASSWORD="..."
Install
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Run locally with stdio
python server.py
This is the right mode for local MCP clients that spawn the process directly.
Run for ChatGPT web app
ChatGPT web needs a public HTTPS MCP endpoint. Start the server in HTTP mode:
python server.py --transport streamable-http --host 0.0.0.0 --port 8000
Then expose that port through a public HTTPS tunnel or reverse proxy, and register the resulting MCP URL in ChatGPT.
Tools exposed
list_folders()
Lists available IMAP folders.
search_emails(folder="INBOX", text=None, unseen_only=False, since_date=None, limit=30)
Searches messages by IMAP criteria.
Returns items like:
uidsubjectfromtodateflagssize_bytes
read_email(uid, folder="INBOX")
Fetches a full message without marking it read.
Returns:
- decoded headers
message_idin_reply_toreferencesattachmentsbody_plainbody_html
get_attachment(uid, folder="INBOX", attachment_index=None, filename=None)
Fetches a single attachment and returns it as base64.
send_email(...)
Sends a message through SMTP.
Important parameters:
reply_to_header— sets the Reply-To headerin_reply_to— threading headerreferences— threading headerattachments— optional list of attachment specs
For a real reply, use in_reply_to and usually also references.
Yandex notes
Typical Yandex defaults are:
- IMAP:
imap.yandex.com:993over SSL/TLS - SMTP:
smtp.yandex.com:465over SSL/TLS
Use an app password, not your main account password.
Next sensible upgrades
- inline/embedded image attachments
- attachment size limits and streaming
- move/archive/delete tools with confirmation
- OAuth instead of env-based credentials
- tests with mocked IMAP/SMTP backends