Content
# 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:
```bash
uvx git+https://github.com/ptbsare/email-mcp-server \
--email-user you@example.com \
--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
```bash
git clone https://github.com/ptbsare/email-mcp-server
cd email-mcp-server
uv pip install -e .
uv run main.py --email-user you@example.com --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:
```dotenv
EMAIL_USER=you@example.com
EMAIL_PASS=yourpassword
POP3_SERVER=pop.example.com
SMTP_SERVER=smtp.example.com
```
Then simply:
```bash
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
```bash
# CLI args only (no .env needed):
uv run main.py --email-user me@gmail.com --email-pass xxx \
--pop3-server pop.gmail.com --smtp-server smtp.gmail.com
# .env file for credentials, CLI for servers:
# .env: EMAIL_USER=me@gmail.com / EMAIL_PASS=xxx
uv run main.py --pop3-server pop.gmail.com --smtp-server smtp.gmail.com
# Env vars override .env:
EMAIL_USER=other@gmail.com 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.json`
**Windows:** `%APPDATA%/Claude/claude_desktop_config.json`
### With env vars (in config):
```json
{
"mcpServers": {
"email-mcp-server": {
"command": "uvx",
"args": ["git+https://github.com/ptbsare/email-mcp-server"],
"env": {
"EMAIL_USER": "your-email@example.com",
"EMAIL_PASS": "your-app-password",
"POP3_SERVER": "pop.example.com",
"SMTP_SERVER": "smtp.example.com"
}
}
}
}
```
### With CLI args (in config):
```json
{
"mcpServers": {
"email-mcp-server": {
"command": "uvx",
"args": [
"git+https://github.com/ptbsare/email-mcp-server",
"--email-user", "your-email@example.com",
"--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}]`
```python
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}]}]`
```python
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"}}`
```python
deleteEmailsById(ids=[1, 2, 3])
```
---
### `sendTextEmail(toAddresses, subject, body, attachments=None)`
Send a plain text email. Attachments: list of local file paths like `["/tmp/file.pdf"]`.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `toAddresses` | `list[str]` | ✅ | — | Recipients. Example: `["alice@example.com"]` |
| `subject` | `str` | ✅ | — | Subject line |
| `body` | `str` | ✅ | — | Plain text body |
| `attachments` | `list[str]` | | `None` | Local file paths. Example: `["/tmp/report.pdf"]` |
**Returns:** `{"status": "success"}`
```python
sendTextEmail(
toAddresses=["alice@example.com"],
subject="Hello",
body="Hi Alice!",
attachments=["/tmp/report.pdf"]
)
```
---
### `sendHtmlEmail(toAddresses, subject, body, attachments=None)`
Send an HTML email. Attachments: list of local file paths like `["/tmp/file.png"]`.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `toAddresses` | `list[str]` | ✅ | — | Recipients. Example: `["alice@example.com"]` |
| `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"}`
```python
sendHtmlEmail(
toAddresses=["alice@example.com"],
subject="Report",
body="<h1>Report</h1><p>Sales up <b>20%</b>.</p>",
attachments=["/tmp/chart.png"]
)
```
---
## Development Setup
### Prerequisites
- Python 3.12+
- [uv](https://github.com/astral-sh/uv)
### Steps
```bash
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
Connection Info
You Might Also Like
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
awesome-mcp-servers
A collection of MCP servers.
git
A Model Context Protocol server for Git automation and interaction.
OpenCrab
MetaOntology OS MCP Plugin? All agent environments evolve toward...
obsidian-hybrid-search
Hybrid search over your Obsidian vault – CLI and MCP server
perplexity-web-api-mcp
🔍 Perplexity AI MCP without API key