list_accounts_and_foldersLABSCO SUMMARY
The agent never holds IMAP credentials — those belong to the sync engine alone.
Nothing an MCP tool returns includes them, and even a delete is a move to a folder you named, with the trash folder excluded from every query afterwards. The shadow copy also buys things raw IMAP cannot do: instant full-text search across every folder and account at once, filtered by read status, attachments, date and sender.
What it is
A sync engine plus MCP server: it mirrors your IMAP mailboxes into a local SQLite database with full-text search, and the AI agent only ever queries that copy.
What you get
- list_accounts_and_folders — every synced account and its folders
- get_recent_activity — the most recent emails, filterable by read status and attachments
- get_email_content — full body text, read and replied status, and the attachment list for one email
- search_emails — FTS5 full-text search with subject, sender, date, folder and read-status filters
- get_thread — every email in a thread, sorted by date
- download_attachments and get_download_link
- delete_mail — a soft delete that moves the email to a folder you designate; nothing is permanently deleted
- Several mailboxes at once, with optional IMAP IDLE for near-instant new-mail sync
Requirements
Docker is the recommended path — the ghcr.io/dryas/mail-shadow-mcp:latest container writes an annotated config.yaml on first run. Fill in each account's host, port and credentials, set trash_folder for soft deletes, and set http_bearer_token to protect the HTTP endpoint. A prebuilt binary with stdio transport is on the releases page.
Setup effort
Run a container — pull the image, run it, then point your client at its URL
USE CASES
Checking whether an invoice arrived
Search across accounts by sender and date, then open the one that matches.
Summarizing a thread you have lost track of
Pull every message in it, in order, instead of scrolling the client.
Catching up on unread mail in one folder
Ask for recent activity filtered to unread, with attachments flagged.
Clearing something out without risking the mailbox
The soft delete moves it to your designated folder, where you can still restore it.
8 tools
Listed in project docs. Your client may show a different list.
get_recent_activityget_email_contentsearch_emailsget_threaddownload_attachmentsget_download_linkdelete_mailBEFORE YOU INSTALL
What to know first
Tools you get
8 tools named in the project's documentation.
INSTALLATION
Connect your client
Pull the image, run it, then point your client at its URL.
Server setup
Setup
mkdir -p ./config ./dataFirst run generates the config, and it must happen BEFORE you can edit anything. The container detects that no config.yaml exists, copies an annotated example into ./config/, prints a message, and exits:
docker run --rm -v ./config:/config -v ./data:/data ghcr.io/dryas/mail-shadow-mcp:latestEdit ./config/config.yaml: enter your IMAP account (host, port, username), set password to a $ENV_VAR placeholder such as "$WORK_IMAP_PASS", choose folders / idle_folders / trash_folder, and set http_bearer_token (generate with: openssl rand -hex 32)
Start it for real. The MCP server is then reachable at http://localhost:8080/mcp:
docker run -d --name mail-shadow-mcp --restart unless-stopped -v ./config:/config:ro -v ./data:/data -e WORK_IMAP_PASS=<YOUR_WORK_IMAP_PASS> -p 8080:8080 ghcr.io/dryas/mail-shadow-mcp:latestConnect your agent with one of the client tabs (Hermes Agent, OpenClaw), using the SAME bearer token you put in config.yaml
docker
docker pull ghcr.io/dryas/mail-shadow-mcp:latestMCP Clients
Hermes Agent
mcp_servers:
mail-shadow:
url: http://localhost:8080/mcp
headers:
Authorization: Bearer <YOUR_SECRET_TOKEN>OpenClaw
{
"mcp": {
"servers": {
"mail_shadow": {
"url": "http://localhost:8080/mcp",
"transport": "streamable-http",
"headers": {
"Authorization": "Bearer <YOUR_SECRET_TOKEN>"
}
}
}
}
}Any MCP client — local binary
Download a pre-compiled binary from the Releases page (https://github.com/dryas/mail-shadow-mcp/releases) and use the stdio command form. The README warns that this shares the agent's user context and reduces the isolation benefit:
{
"mcpServers": {
"mail_shadow": {
"command": "<YOUR_PATH_TO_MAIL_SHADOW_MCP>",
"args": [
"serve",
"--config",
"<YOUR_PATH_TO_CONFIG>"
]
}
}
}Docker Compose server
services:
mail-shadow-mcp:
image: ghcr.io/dryas/mail-shadow-mcp:latest
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config/config.yaml:/config/config.yaml:ro
- ./data:/data
environment:
- WORK_IMAP_PASS=<YOUR_WORK_IMAP_PASS>