ptbsare

MCP Email Server

Community ptbsare
Updated

This Python script implements an MCP (Model Context Protocol) server using the mcp library (FastMCP) that allows an LLM (like Claude) to interact with an email account using POP3 (for reading/deleting emails) and SMTP (for sending emails), both secured with TLS encryption.

MCP Email Server

A Model Context Protocol (MCP) server for email operations (POP3/SMTP with TLS). Allows an LLM like Claude to read, send, and manage emails.

Quick Start

Option 1: uvx (recommended)

No clone, no install — runs directly from GitHub:

uvx git+https://github.com/ptbsare/email-mcp-server \
  --email-user [email protected] \
  --email-pass yourpassword \
  --pop3-server pop.example.com \
  --smtp-server smtp.example.com

First run caches the package; subsequent launches are instant.

Option 2: Clone + run locally

git clone https://github.com/ptbsare/email-mcp-server
cd email-mcp-server
uv pip install -e .
uv run main.py --email-user [email protected] --email-pass yourpassword \
  --pop3-server pop.example.com --smtp-server smtp.example.com

Option 3: .env file

Create a .env file in the working directory:

[email protected]
EMAIL_PASS=yourpassword
POP3_SERVER=pop.example.com
SMTP_SERVER=smtp.example.com

Then simply:

uvx git+https://github.com/ptbsare/email-mcp-server
# or
uv run main.py

Configuration

Config Priority (highest → lowest)

  1. CLI arguments — override everything
  2. Environment variables — override .env file
  3. .env file — fallback defaults

All Config Options

CLI Argument Env Variable Required Default Description
--email-user EMAIL_USER Email address
--email-pass EMAIL_PASS Email password / app password
--pop3-server POP3_SERVER POP3 server hostname
--pop3-port POP3_PORT 995 POP3 SSL port
--smtp-server SMTP_SERVER SMTP server hostname
--smtp-port SMTP_PORT 587 SMTP port (auto 465 if --smtp-use-ssl)
--smtp-use-ssl SMTP_USE_SSL false Use SMTP_SSL (port 465) instead of STARTTLS
--log-level LOG_LEVEL INFO Logging: DEBUG / INFO / WARNING / ERROR

Examples: Mixing Config Sources

# CLI args only (no .env needed):
uv run main.py --email-user [email protected] --email-pass xxx \
  --pop3-server pop.gmail.com --smtp-server smtp.gmail.com

# .env file for credentials, CLI for servers:
# .env: [email protected] / EMAIL_PASS=xxx
uv run main.py --pop3-server pop.gmail.com --smtp-server smtp.gmail.com

# Env vars override .env:
[email protected] uv run main.py --pop3-server pop.gmail.com ...

Using with Claude Desktop

Add to your Claude Desktop config file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.jsonWindows: %APPDATA%/Claude/claude_desktop_config.json

With env vars (in config):

{
  "mcpServers": {
    "email-mcp-server": {
      "command": "uvx",
      "args": ["git+https://github.com/ptbsare/email-mcp-server"],
      "env": {
        "EMAIL_USER": "[email protected]",
        "EMAIL_PASS": "your-app-password",
        "POP3_SERVER": "pop.example.com",
        "SMTP_SERVER": "smtp.example.com"
      }
    }
  }
}

With CLI args (in config):

{
  "mcpServers": {
    "email-mcp-server": {
      "command": "uvx",
      "args": [
        "git+https://github.com/ptbsare/email-mcp-server",
        "--email-user", "[email protected]",
        "--email-pass", "your-app-password",
        "--pop3-server", "pop.example.com",
        "--smtp-server", "smtp.example.com"
      ]
    }
  }
}

Tip: The env section and CLI args can be used together. CLI args always take priority.

Features

  • Poll Emails: List inbox email headers with configurable limit (pollEmails)
  • Fetch Full Emails: Get complete email content by ID, with automatic attachment extraction (getEmailsById)
  • Delete Emails: Remove emails by ID (deleteEmailsById)
  • Send Emails: Send plain text (sendTextEmail) or HTML (sendHtmlEmail) emails with optional file attachments
  • Secure Connections: POP3 over SSL (port 995), SMTP with STARTTLS (port 587) or direct SSL (port 465)
  • Attachment Support: Send local files as attachments; received attachments are auto-saved to /tmp/email_mcp_attachments/<email_id>/

Tools

pollEmails(limit=50)

List recent email headers (no body). Returns newest first. Use this first to get IDs for getEmailsById/deleteEmailsById.

Parameter Type Default Description
limit int 50 Max emails to return, newest first

Returns: [{"id": int, "Subject": str, "From": str, "Date": str, "Message-ID": str}]

pollEmails(limit=10)   # 10 most recent
pollEmails()           # default 50

getEmailsById(ids)

Fetch full email content (headers + body) by IDs from pollEmails. Attachments auto-saved to /tmp/email_mcp_attachments/<id>/.

Parameter Type Required Description
ids list[int] Email IDs from pollEmails(). Example: [1, 3, 5]

Returns: [{"id": int, "headers": dict, "body": str, "attachments": [{"filename": str, "local_path": str, "size": int, "content_type": str}]}]

getEmailsById(ids=[1, 3, 5])

deleteEmailsById(ids)

Permanently delete emails by IDs. Irreversible. Call pollEmails first.

Parameter Type Required Description
ids list[int] Email IDs from pollEmails(). Example: [1, 2, 3]

Returns: {"deleted": [int], "failed": {"id": "error msg"}}

deleteEmailsById(ids=[1, 2, 3])

sendTextEmail(toAddresses, subject, body, attachments=None)

Send a plain text email. Sender auto-set to EMAIL_USER. Attachments: list of local file paths like ["/tmp/file.pdf"].

Parameter Type Required Default Description
toAddresses list[str] Recipients. Example: ["[email protected]"]
subject str Subject line
body str Plain text body
attachments list[str] None Local file paths. Example: ["/tmp/report.pdf"]

Returns: {"status": "success"}

sendTextEmail(
    toAddresses=["[email protected]"],
    subject="Hello",
    body="Hi Alice!",
    attachments=["/tmp/report.pdf"]
)

sendHtmlEmail(toAddresses, subject, body, attachments=None)

Send an HTML email. Sender auto-set to EMAIL_USER. Attachments: list of local file paths like ["/tmp/file.png"].

Parameter Type Required Default Description
toAddresses list[str] Recipients. Example: ["[email protected]"]
subject str Subject line
body str HTML content. Example: "<h1>Hi</h1><p>Hello!</p>"
attachments list[str] None Local file paths. Example: ["/tmp/chart.png"]

Returns: {"status": "success"}

sendHtmlEmail(
    toAddresses=["[email protected]"],
    subject="Report",
    body="<h1>Report</h1><p>Sales up <b>20%</b>.</p>",
    attachments=["/tmp/chart.png"]
)

Development Setup

Prerequisites

  • Python 3.12+
  • uv

Steps

git clone https://github.com/ptbsare/email-mcp-server
cd email-mcp-server
uv pip install -e .
uv run main.py --help

Important Notes

  • App Passwords: If your email provider uses 2FA, generate an App Password for EMAIL_PASS
  • Email IDs: POP3 IDs are session-specific. Call pollEmails() before getEmailsById() or deleteEmailsById()
  • Attachment Storage: Received attachments are saved to /tmp/email_mcp_attachments/<email_id>/
  • Security: Never commit your .env file — it's already in .gitignore
  • Config Priority: CLI args > environment variables > .env file

Project Structure

email-mcp-server/
├── main.py              # MCP server entry point (all logic)
├── pyproject.toml       # Package config & dependencies
├── uv.lock              # Dependency lock file
├── .env                 # Credentials (create your own)
├── .gitignore
└── README.md

License

MIT

MCP Server · Populars

MCP Server · New

    sjkim1127

    Reversecore_MCP

    A security-first MCP server empowering AI agents to orchestrate Ghidra, Radare2, and YARA for automated reverse engineering.

    Community sjkim1127
    sebringj

    Autonomo MCP

    Tired of 'it works' lies? Autonomo MCP makes your AI prove it—on real hardware, right in your editor.

    Community sebringj
    softerist

    Heuristic MCP Server

    Enhanced MCP server for semantic code search with call-graph proximity, recency ranking, and find-similar-code. Built for AI coding assistants.

    Community softerist
    arm

    Arm MCP Server

    Arm's MCP server

    Community arm
    bobmatnyc

    MCP Vector Search

    CLI-first semantic code search with MCP integration. Modern, fast, and intelligent code search powered by ChromaDB and AST parsing.

    Community bobmatnyc