使用说明
MCP Email Server
A Model Context Protocol (MCP) server for handling SMTP/IMAP email operations. This server allows you to search past emails, send new emails, manage multiple email accounts, and work with drafts directly in your email client.
Features
- Search Emails: Flexible search across all email fields (sender, recipient, subject, body, date range)
- Send Emails: Send emails with support for text, HTML, attachments, CC, and BCC
- Draft Support: Create, read, send, and delete drafts that appear in your email client's Drafts folder
- Multi-Account Support: Manage multiple email accounts simultaneously
- Local Caching: SQLite-based cache for fast email searches
- Full-Text Search: Fast full-text search using SQLite FTS5
- Generic IMAP/SMTP: Works with any email provider that supports IMAP/SMTP
Requirements
- Go 1.23 or higher
- Docker (for containerized deployment)
- Email account with IMAP/SMTP access (app passwords recommended)
Configuration
Configuration is done via environment variables. You can configure either a single account or multiple accounts.
See .env.example for a complete example configuration file.
Single Account Configuration
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USERNAME=user@example.com
IMAP_PASSWORD=your_app_password
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=user@example.com
SMTP_PASSWORD=your_app_password
ACCOUNT_NAME=default
Multiple Accounts Configuration
# Account 1
ACCOUNT_1_NAME=work
ACCOUNT_1_IMAP_HOST=imap.work.com
ACCOUNT_1_IMAP_PORT=993
ACCOUNT_1_IMAP_USERNAME=user@work.com
ACCOUNT_1_IMAP_PASSWORD=your_app_password
ACCOUNT_1_SMTP_HOST=smtp.work.com
ACCOUNT_1_SMTP_PORT=587
ACCOUNT_1_SMTP_USERNAME=user@work.com
ACCOUNT_1_SMTP_PASSWORD=your_app_password
# Account 2
ACCOUNT_2_NAME=personal
ACCOUNT_2_IMAP_HOST=imap.gmail.com
ACCOUNT_2_IMAP_PORT=993
ACCOUNT_2_IMAP_USERNAME=user@gmail.com
ACCOUNT_2_IMAP_PASSWORD=your_app_password
ACCOUNT_2_SMTP_HOST=smtp.gmail.com
ACCOUNT_2_SMTP_PORT=587
ACCOUNT_2_SMTP_USERNAME=user@gmail.com
ACCOUNT_2_SMTP_PASSWORD=your_app_password
Optional Configuration
CACHE_PATH=/data/email_cache.db
SEARCH_RESULT_LIMIT=100
LOG_LEVEL=info
Common Email Provider Settings
Gmail
- IMAP:
imap.gmail.com:993 - SMTP:
smtp.gmail.com:587 - Note: Requires App Password (not regular password)
Outlook/Office365
- IMAP:
outlook.office365.com:993 - SMTP:
smtp.office365.com:587
Yahoo
- IMAP:
imap.mail.yahoo.com:993 - SMTP:
smtp.mail.yahoo.com:587
MCP Tools
list_folders
List available mailboxes/folders for configured email accounts.
Parameters:
account_name(optional): Specific account name, or all accounts if omitted
search_emails
Search cached emails with flexible filters.
Parameters:
account_name(optional): Filter by specific accountfolder(optional): Filter by folder/mailboxsender(optional): Filter by sender email/namerecipient(optional): Filter by recipient emailsubject(optional): Filter by subject (substring match)body(optional): Filter by body content (full-text search)date_from(optional): Start date (ISO 8601 format)date_to(optional): End date (ISO 8601 format)limit(optional): Result limit (default: 100, max: 1000)
get_email
Retrieve full email by ID from cache or IMAP.
Parameters:
email_id(required): Email ID (from search results)account_name(optional): Account name if needed
send_email
Send a new email with support for text, HTML, attachments, CC, BCC.
Parameters:
account_name(required): Account to send fromto(required): Recipient email address(es) (comma-separated)cc(optional): CC recipients (comma-separated)bcc(optional): BCC recipients (comma-separated)subject(required): Email subjectbody_text(optional): Plain text bodybody_html(optional): HTML bodyattachments(optional): Array of attachment paths/URLsreply_to(optional): Reply-To headerin_reply_to(optional): In-Reply-To header (for replies)
Attachments accept local file paths (read from the machine running the server) and http(s) URLs (fetched with a 15s timeout). Limits: max 10 files, 10MB per file, 25MB total. MIME types are detected from the extension/content. Previously the attachments parameter was accepted but silently ignored — files are now actually attached.
create_draft
Create a draft email and store it in the email client's Drafts folder. The draft appears in your email client (Gmail, Outlook, etc.) exactly as if you had composed it there — it is not sent.
Parameters:
account_name(required): Account to create the draft infolder(optional): Drafts folder name (default:Drafts; Gmail uses[Gmail]/Drafts)to(optional): Recipient email address(es) (comma-separated)cc(optional): CC recipients (comma-separated)bcc(optional): BCC recipients (comma-separated)subject(optional): Email subjectbody_text(optional): Plain text bodybody_html(optional): HTML bodyreply_to(optional): Reply-To headerin_reply_to(optional): In-Reply-To header (for replies)attachments(optional): Files to attach — local paths or http(s) URLs (max 10MB each, 10 files / 25MB total)
Requires at least one of subject, body_text, body_html, or attachments.
list_drafts
List drafts stored in the email client's Drafts folder. Returns each draft's UID (used to send/delete it), subject, recipients, a body snippet, plus attachment_count and an attachments array (filename, mime_type, size).
Parameters:
account_name(required): Account to list drafts fromfolder(optional): Drafts folder name (default:Drafts; Gmail uses[Gmail]/Drafts)
get_draft
Retrieve the full contents of a single draft by UID (from list_drafts), including the full plain-text and HTML body plus an attachments array (filename, mime_type, size).
Parameters:
account_name(required): Account the draft belongs touid(required): Draft UID (fromlist_drafts)folder(optional): Drafts folder name (default:Drafts)
send_draft
Send an existing draft by UID and, by default, delete it from the Drafts folder afterward. This is how a user asks an agent to "send that draft I saved". The stored message bytes are sent as-is, so attachments survive the round trip.
Parameters:
account_name(required): Account to send the draft fromuid(required): Draft UID (fromlist_drafts)folder(optional): Drafts folder name (default:Drafts)delete_after_send(optional): Delete the draft from the Drafts folder after sending (default:true)
delete_draft
Permanently delete a draft by UID from the email client's Drafts folder.
Parameters:
account_name(required): Account the draft belongs touid(required): Draft UID (fromlist_drafts)folder(optional): Drafts folder name (default:Drafts)
Note: The default drafts folder is
Drafts. Gmail stores drafts in[Gmail]/Drafts— passfolderaccordingly, or runlist_foldersto discover the correct folder name for your provider.
Building
Prerequisites
- Go 1.23 or higher — required to compile the server from source. Install with your package manager (
apt install golang-go,brew install go, etc.), or from https://go.dev/dl. - An email account with IMAP/SMTP access (app passwords recommended).
Build from Source
# Clone the repository
git clone https://github.com/Tillman32/mcp-email.git
cd mcp-email
# Download dependencies
go mod download
# Build the server binary
go build -o mcp-email-server ./cmd/server
# Verify it built
./mcp-email-server --version
The resulting mcp-email-server binary is self-contained — you can copy it to /usr/local/bin/ and reference it from your MCP config:
sudo cp mcp-email-server /usr/local/bin/
Docker Build
docker build -t mcp-email-server .
Running
Local Run
./mcp-email-server
Docker Run
docker run -it --name mcp-email-container \
-e IMAP_HOST=imap.example.com \
-e IMAP_PORT=993 \
-e IMAP_USERNAME=user@example.com \
-e IMAP_PASSWORD=your_app_password \
-e SMTP_HOST=smtp.example.com \
-e SMTP_PORT=587 \
-e SMTP_USERNAME=user@example.com \
-e SMTP_PASSWORD=your_app_password \
-v $(pwd)/data:/data \
mcp-email-server
Alternatively, you can use an environment file:
# Copy the example file
cp .env.example .env
# Edit .env with your credentials
# Then run:
docker run -it --name mcp-email-container --env-file .env -v $(pwd)/data:/data mcp-email-server
Note: The --name flag creates a persistent container that maintains your email cache between VS Code sessions. If you need to restart the container, use docker restart mcp-email-container. To completely reset the cache, stop and remove the container with docker rm -f mcp-email-container.
MCP Configuration
To use this server with Claude Desktop or VS Code, you need to configure it in your mcp.json file.
Claude Desktop Configuration
Location:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
VS Code Configuration
Location: .vscode/mcp.json in your project directory
Configuration Examples
1. Local Execution (Single Account)
Use this if you've built the server locally:
{
"mcpServers": {
"mcp-email": {
"command": "/absolute/path/to/mcp-email-server",
"env": {
"IMAP_HOST": "imap.gmail.com",
"IMAP_PORT": "993",
"IMAP_USERNAME": "your-email@gmail.com",
"IMAP_PASSWORD": "your-app-password",
"SMTP_HOST": "smtp.gmail.com",
"SMTP_PORT": "587",
"SMTP_USERNAME": "your-email@gmail.com",
"SMTP_PASSWORD": "your-app-password",
"CACHE_PATH": "/tmp/email_cache.db",
"SEARCH_RESULT_LIMIT": "100",
"LOG_LEVEL": "info"
}
}
}
}
See mcp.json.example.local for a complete example.
2. Docker Execution (Single Account)
Use this to run the server in a Docker container:
{
"mcpServers": {
"mcp-email": {
"command": "docker",
"args": [
"run",
"-i",
"--name", "mcp-email-container",
"-v", "/tmp:/data",
"-e", "IMAP_HOST=imap.gmail.com",
"-e", "IMAP_PORT=993",
"-e", "IMAP_USERNAME=your-email@gmail.com",
"-e", "IMAP_PASSWORD=your-app-password",
"-e", "SMTP_HOST=smtp.gmail.com",
"-e", "SMTP_PORT=587",
"-e", "SMTP_USERNAME=your-email@gmail.com",
"-e", "SMTP_PASSWORD=your-app-password",
"-e", "CACHE_PATH=/data/email_cache.db",
"-e", "SEARCH_RESULT_LIMIT=100",
"-e", "LOG_LEVEL=info",
"mcp-email-server:latest"
]
}
}
}
See mcp.json.example.docker for a complete example.
Note: Make sure you've built the Docker image first:
docker build -t mcp-email-server:latest .
3. Multi-Account Configuration
For multiple email accounts, use the ACCOUNT_N_* environment variables:
{
"mcpServers": {
"mcp-email": {
"command": "/absolute/path/to/mcp-email-server",
"env": {
"ACCOUNT_1_NAME": "work",
"ACCOUNT_1_IMAP_HOST": "imap.work.com",
"ACCOUNT_1_IMAP_PORT": "993",
"ACCOUNT_1_IMAP_USERNAME": "user@work.com",
"ACCOUNT_1_IMAP_PASSWORD": "your-app-password",
"ACCOUNT_1_SMTP_HOST": "smtp.work.com",
"ACCOUNT_1_SMTP_PORT": "587",
"ACCOUNT_1_SMTP_USERNAME": "user@work.com",
"ACCOUNT_1_SMTP_PASSWORD": "your-app-password",
"ACCOUNT_2_NAME": "personal",
"ACCOUNT_2_IMAP_HOST": "imap.gmail.com",
"ACCOUNT_2_IMAP_PORT": "993",
"ACCOUNT_2_IMAP_USERNAME": "user@gmail.com",
"ACCOUNT_2_IMAP_PASSWORD": "your-app-password",
"ACCOUNT_2_SMTP_HOST": "smtp.gmail.com",
"ACCOUNT_2_SMTP_PORT": "587",
"ACCOUNT_2_SMTP_USERNAME": "user@gmail.com",
"ACCOUNT_2_SMTP_PASSWORD": "your-app-password",
"CACHE_PATH": "/tmp/email_cache.db",
"SEARCH_RESULT_LIMIT": "100",
"LOG_LEVEL": "info"
}
}
}
}
See mcp.json.example.multi-account for a complete example.
Example Files
mcp.json.example.local- Local execution with single accountmcp.json.example.docker- Docker execution with single account (env vars in args)mcp.json.example.docker-envfile- Docker execution using an env filemcp.json.example.multi-account- Local execution with multiple accounts
Using Docker with Environment File
For a cleaner Docker configuration, you can use an environment file:
{
"mcpServers": {
"mcp-email": {
"command": "docker",
"args": [
"run",
"-i",
"--name", "mcp-email-container",
"--env-file", "/absolute/path/to/.env",
"-v", "/tmp:/data",
"mcp-email-server:latest"
]
}
}
}
See mcp.json.example.docker-envfile for a complete example.
This approach keeps your credentials in a separate .env file (which should not be committed to version control).
Setup Instructions
- Choose your configuration (local or Docker)
- Copy the appropriate example file to your MCP config location
- Update the paths and credentials with your actual values
- Restart Claude Desktop or VS Code to load the configuration
Security Notes
- Never commit your actual
mcp.jsonwith real passwords to version control - Use app passwords instead of your regular email password
- Consider using environment variables or secrets management for production
Using with Hermes Agent
Hermes Agent has a built-in MCP client that discovers a server's tools at startup and exposes them as first-class tools (prefixed mcp_email_*) the agent can call in any conversation.
1. Install Go and build the binary
Hermes host machines need Go 1.23+ to compile the server. Build and install the binary:
# Build (see "Building" above for details)
git clone https://github.com/Tillman32/mcp-email.git
cd mcp-email
go mod download
go build -o mcp-email-server ./cmd/server
# Install somewhere on PATH
sudo cp mcp-email-server /usr/local/bin/
2. Add the server to Hermes config
Edit ~/.hermes/config.yaml and add an entry under mcp_servers. Point command at the installed binary and provide your account credentials via env (use app passwords, not your real email password):
mcp_servers:
email:
command: "/usr/local/bin/mcp-email-server"
env:
IMAP_HOST: "imap.gmail.com"
IMAP_PORT: "993"
IMAP_USERNAME: "you@gmail.com"
IMAP_PASSWORD: "your-app-password"
SMTP_HOST: "smtp.gmail.com"
SMTP_PORT: "587"
SMTP_USERNAME: "you@gmail.com"
SMTP_PASSWORD: "your-app-password"
CACHE_PATH: "/var/lib/mcp-email/email_cache.db"
SEARCH_RESULT_LIMIT: "100"
LOG_LEVEL: "info"
Security: Hermes only passes environment variables you explicitly list under env to the subprocess — it does not leak your shell environment. Store secrets as normal YAML values here, or reference your secret manager. Never commit your real config.yaml.
3. Restart Hermes and verify
hermes mcp list # should list the email server
hermes mcp test email # test the connection
Then start a new session (/new or relaunch). On startup Hermes connects to the server and registers its tools with the mcp_email_ prefix. Verify with:
hermes tools list | grep mcp_email
You should see: mcp_email_create_draft, mcp_email_list_drafts, mcp_email_get_draft, mcp_email_send_draft, mcp_email_delete_draft, mcp_email_search_emails, mcp_email_send_email, mcp_email_list_folders, and mcp_email_get_email.
4. Use it in conversation
Once connected, you can just ask Hermes to work with your email:
- "Create a draft to Sarah about the project update, subject 'Status update', saying the build passed."
- "What drafts do I have saved?"
- "Send the draft about the project update."
- "Delete the draft titled 'meeting notes'."
- "Search my inbox for invoices from last month."
Multi-account configuration
For multiple accounts, use the ACCOUNT_N_* environment variables in the same env block (see Multiple Accounts Configuration) and pass the relevant account_name to each tool call.
Development
Project Structure
mcp-email/
├── cmd/server/ # Main application entry point
├── internal/
│ ├── config/ # Configuration management
│ ├── email/ # IMAP/SMTP client implementations
│ ├── cache/ # SQLite cache layer
│ ├── mcp/ # MCP server implementation
│ └── tools/ # MCP tool implementations
├── pkg/types/ # Shared data types
└── Dockerfile # Docker container definition
Testing
go test ./...
Linting
golangci-lint run --timeout=5m
CI/CD
This project uses GitHub Actions for continuous integration and releases.
CI Workflow
- Runs on every push and pull request
- Tests on multiple Go versions (1.21, 1.22, 1.23)
- Runs linters and code quality checks
- Builds and validates on multiple platforms
- Builds and tests Docker image
Release Workflow
- Automatically triggered on version tags (e.g.,
v1.0.0) - Validates semantic versioning (must be greater than previous tag)
- Builds binaries for all platforms (Linux, macOS, Windows - amd64, arm64)
- Publishes Docker images to GitHub Container Registry (and optionally Docker Hub)
- Creates GitHub releases with all artifacts
Creating a Release
-
Create and push a version tag:
git tag -a v1.0.0 -m "Release v1.0.0" git push origin v1.0.0 -
The release workflow will automatically:
- Validate the version
- Build all binaries
- Create Docker images
- Publish to registries
- Create GitHub release
See RELEASE.md and .github/SETUP.md for detailed information.
License
MIT
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
