Own your data. Squirrel is a local, sovereign personal-information hub that exposes your mailbox to Claude and other MCP clients — running entirely on your machine, talking straight to your mail provider over TLS. No mail content ever leaves for a third party.
Squirrel is the face; the providers underneath are swappable backends.
It speaks plain IMAP/SMTP for mail, CardDAV for contacts and CalDAV
for calendar — the three pillars, each behind its own provider protocol so
Gmail/Outlook can plug in later without a rewrite. Point it at any mailbox by
filling in your provider's host names; there are no built-in presets. A tool
family (mail_*, contacts_*, calendar_*) is present only when that pillar
is configured.
Little brother of
odoo-mcp-pro: same stack, same patterns, same open-core split.
- "Which unread mails came in this week from my accountant?"
- "Read message 4213 in INBOX and summarise the thread."
- "Draft a reply to Anna — I'll review before it goes out."
- "File these three newsletters into the Archive folder."
| Tool | What it does | Safe? |
|---|---|---|
mail_list_folders |
List mailboxes/folders | read-only |
mail_search |
Search a folder, paginated (large mailboxes OK) | read-only |
mail_read |
Read one message (large bodies are truncated) | read-only |
mail_read_chunk |
Fetch the next slice of a large body | read-only |
mail_get_attachment |
Download one attachment | read-only |
mail_draft / mail_edit_draft |
Create / update a draft in Drafts | writes to Drafts |
mail_send |
Send a message — requires confirm=true |
|
mail_move |
Move messages between folders — requires confirm=true |
Guardrails: sending and moving are flagged destructiveHint and refuse to run
without an explicit confirm=true, so Claude checks with you first. Big mailboxes
are handled with pagination (mail_search) and chunking (mail_read_chunk) —
never an all-in-one dump.
contacts_*: contacts_list_addressbooks · contacts_search (paginated) ·
contacts_read · contacts_create / contacts_update / contacts_delete.
calendar_*: calendar_list_calendars · calendar_search_events (ISO date
window) · calendar_read_event · calendar_create_event / calendar_update_event
/ calendar_delete_event.
All writes require confirm=true. Both pillars reuse the same account credentials
as mail (most providers let one password cover IMAP/SMTP, CardDAV and CalDAV) and
lean on the mature caldav + icalendar + vobject libraries.
git clone https://github.com/pantalytics/squirrel-mcp.git
cd squirrel-mcp
uv venv --python 3.10 && source .venv/bin/activate
uv pip install -e .cp .env.example .envFill in .env with your mailbox login and your provider's IMAP/SMTP hosts — look
those up in your provider's own docs; Squirrel never guesses them. The ports
default to implicit TLS (993 / 465), so usually the hosts are all you add:
SQUIRREL_MAIL_EMAIL=you@yourdomain.eu
SQUIRREL_MAIL_PASSWORD=your-account-password
SQUIRREL_IMAP_HOST=imap.yourprovider.eu
SQUIRREL_SMTP_HOST=smtp.yourprovider.eu
Optional: SQUIRREL_CARDDAV_URL / SQUIRREL_CALDAV_URL switch on the contacts
and calendar pillars, and SQUIRREL_MAIL_USERNAME covers the rare provider whose
login isn't the email address.
.env is gitignored and never leaves your machine.
Test it before wiring up Claude:
python -m squirrel_mcp --check# stdio (for Claude Desktop / Claude Code)
python -m squirrel_mcp
# streamable-http (for one trusted network; put auth in front of it)
python -m squirrel_mcp --transport streamable-http --host 0.0.0.0 --port 8000Claude Code:
claude mcp add squirrel -- python -m squirrel_mcpClaude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"squirrel": {
"command": "python",
"args": ["-m", "squirrel_mcp"],
"env": {
"SQUIRREL_MAIL_EMAIL": "you@yourdomain.eu",
"SQUIRREL_MAIL_PASSWORD": "your-account-password",
"SQUIRREL_IMAP_HOST": "imap.yourprovider.eu",
"SQUIRREL_SMTP_HOST": "smtp.yourprovider.eu"
}
}
}
}With .env filled in, verify the live connection without touching Claude:
python scripts/e2e_soverin.pyIt logs in, lists your folders, shows the newest few INBOX subjects, and reads the latest message — read-only, nothing is sent or moved.
cp .env.example .env # fill in your credentials
docker compose up --build # MCP endpoint at http://localhost:8000/mcpFour layers, all runnable with make (see make help):
| Layer | Command | What it does | Needs |
|---|---|---|---|
| Unit | make test |
Mocked handler/config/tool tests | nothing |
| Integration (real e2e) | make test-int |
Spins up GreenMail (a real IMAP/SMTP server) in Docker and exercises the actual provider: folders, search, read, attachment, draft, move, send | Docker |
| Docker smoke | make docker-smoke |
Builds the image, runs Squirrel-in-a-container wired to GreenMail, and drives a full MCP handshake + tool call over http | Docker |
| Browser (Playwright) | make playwright |
A browser client (web/console.html) connects to the containerised server, lists tools, and reads folders — proving the whole stack through a real browser |
Docker + Node |
make test-all runs everything and tears the stack down. No secrets are needed —
the e2e layers use a local GreenMail server, not your real mailbox. CI
(.github/workflows/ci.yml) runs all four on every push.
make install # venv + dev deps
make lint # ruff + ty
make test # fast unit tests
make test-all # unit + integration + docker + playwrightThe end-to-end tests point Squirrel at GreenMail over plaintext via the transport
knobs SQUIRREL_IMAP_SECURITY / SQUIRREL_SMTP_SECURITY (ssl | starttls |
plain) and SQUIRREL_TLS_VERIFY. Against a real provider these stay at their
secure defaults (ssl, verify on).
Tools talk only to the MailProvider protocol (providers/protocol.py); the
SoverinMailProvider (providers/soverin/) is the sole place that knows IMAP/SMTP,
and it leans on imap-tools + stdlib. Swapping to Gmail/Outlook later means adding
a provider that satisfies the same protocol — the tools don't change. Blocking
network calls run off the event loop via run_blocking. See CLAUDE.md for the
full map and the open-core seams the private admin package extends.
© Pantalytics B.V. Licensed under the Elastic License 2.0.