UC

u-c4n/thunderbird-mcp

开发工具
50 stars 0 forks 质量 35 趋势 35

Thunderbird MCP gives an AI agent real control of the Thunderbird already running on your machine — your mail, your folders, your contacts, your calendar, your filters, and your actual settings.

概览

Thunderbird MCP gives an AI agent real control of the Thunderbird already running on your machine — your mail, your folders, your contacts, your calendar, your filters, and your actual settings.

README

Thunderbird MCP

Thunderbird MCP gives an AI agent real control of the Thunderbird already running on your machine — your mail, your folders, your contacts, your calendar, your filters, and your actual settings. Not a copy, not an IMAP re-implementation: the same Thunderbird you have open, driven through its own internals.

Written in Python, built for Claude Code and Codex CLI, and able to drive one Thunderbird from both at the same time.

What you can ask for

  • Find things you half-remember. “What did the accountant say about VAT in June?” runs a ranked search over the whole indexed corpus and can reconstruct a thread that spans Inbox, Sent and an archive folder in one call.
  • Triage a mailbox. Mark, tag, move, archive and file in bulk — with the source folders reported back so a wrong move is reversible.
  • Write mail you get to read first. mail_send produces a reviewable draft by default; sending is a separate, confirmed step, and needs no compose window.
  • Change settings, properly. Server ports and connection security, identities and signatures, SMTP servers, junk handling, archive layout, message-pane layout, ~5,700 preferences — read the current value, write the new one, and get the old one back so you can undo it.
  • Automate the boring rules. Create and reorder message filters, then run them over an existing folder to check they do what you meant.
  • Keep a calendar honest. Events and tasks, with recurring items addressed as a series unless you name one occurrence.

[!NOTE] Everything documented here was verified against a live Thunderbird 153 on Windows 11, not inferred from documentation. The measurements, and the traps found the hard way, are in docs/VERIFIED-FINDINGS.md.


Quick start

There is no PyPI package to install from yet — clone the repo and let it build its own environment:

git clone https://github.com/U-C4N/Thunderbird-MCP
cd Thunderbird-MCP
python bootstrap.py

One command: it picks an interpreter that works, builds the environment, installs the add-on, and verifies the whole chain before it returns. Re-running it is safe — healthy steps are no-ops. Add --clients claude-code,codex to also register those clients in the same run, or do it afterward from “Install into a client” below.

Installing the add-on closes Thunderbird, installs through Thunderbird’s own automation channel, and starts it again — no clicking through the Add-ons UI; bootstrap does this for you as its addon step. Prefer to do it by hand, or on its own? tbmcp install-addon --manual builds the package and prints the three clicks.

Already installed? tbmcp bootstrap does the same thing.

For AI agents

python bootstrap.py --json

Emits one object: ok, version, launcher, steps[] (each with name, status, seconds, detail), and next_command — null on success, otherwise the single command that addresses the failure. status is one of ok, repaired, skipped, failed. Parse this instead of the human output; the columns are not a stable interface and the JSON is.

A healthy doctor looks like this:

thunderbird-mcp doctor

Python
  version                    3.14.6
  interpreter                C:\Users\VECTOR\Documents\GitHub\Thunderbird-MCP\.venv\Scripts\python.exe

Thunderbird
  executable                 C:\Program Files\Mozilla Thunderbird\thunderbird.exe
  running                    True
  add-on version (source)    1.2.0
  profile                    C:\Users\VECTOR\AppData\Roaming\Thunderbird\Profiles\81l4u5ba.default-release
  accounts (from prefs.js)   2
  outgoing servers           1
  global index db            True
  add-on startup report      2026-08-11T06:41:40.527Z
  privileged modules         12 loaded
  bridge methods             128

Bridge
  daemon                     pid 31120
  connected                  True
  add-on version (live)      1.2.0
  privileged half            True
  app                        Thunderbird 153.0.2
  tb_status tool call        connected

Tools
  toolsets                   mail,folders,compose,search,admin
  read-only                  False
  send mode                  draft

Install into a client


Toolsets

Tools are grouped so you only pay context for what you use. The default set is lean; add the rest with --toolsets.

tbmcp serve --toolsets all              # everything
tbmcp serve --toolsets mail,settings    # exactly these
tbmcp serve --toolsets +calendar        # the default set plus one
tbmcp tools --toolsets all              # list what would be registered

112 tools across 10 toolsets; 48 of them read-only. Full signatures in docs/TOOL-REFERENCE.md.


Safety

Reads are unrestricted. Anything that sends, deletes, or changes configuration is gated four ways, because no single mechanism exists on every client:

Layer Effect Present on
readOnlyHint / destructiveHint annotations lets the host decide when to ask hosts that read annotations
anthropic/requiresUserInteraction prompts even under bypassPermissions Claude Code
an explicit confirm=true argument the call is refused without it everything, including Codex
an approval prompt via elicitation a real question, and invisible in the tool schema so a model cannot fabricate the answer clients with elicitation

Beyond the gate:

  • mail_send drafts by default. --send or mode="send" changes that.
  • dry_run_only=true previews a write — including what it would replace — without asking for approval and without touching anything.
  • Every write reports the previous value, which is what makes an undo possible without a transaction log.
  • Preference writes are allowlisted. --unsafe-prefs widens the allowlist, but credentials, network.proxy.*, security.* and the add-on trust model are refused outright — at the Python layer and again in the privileged module, which is the only layer with real privilege.
  • Private keys never move. OpenPGP keys can be listed and public keys exported; asking for secret key material is refused by design.
  • --read-only registers no mutating tools at all, which makes a safe second registration easy.
  • --yolo removes every gate. It exists for scripted use. Do not leave it on.

How it works

Thunderbird has no external API, so anything that drives it has to run inside it. The official MailExtension API is large — 250 functions on 153 — but it cannot touch preferences, account or server configuration, message filters, junk training, virtual folders, or the calendar. So the add-on pairs that API with a WebExtension Experiment API, which runs with the system principal and therefore has full XPCOM access. Release Thunderbird builds ship MOZ_REQUIRE_SIGNING=false and default extensions.experiments.enabled=true, so the unsigned bridge installs and gets those privileges on a stock install.

Python listens and the add-on dials out, rather than embedding an HTTP server in Thunderbird. That needs no port bound inside Thunderbird and no firewall exception, survives Thunderbird restarts, works unchanged under Snap and Flatpak, and vendors no MPL-licensed Mozilla code. A small broker daemon owns the single connection, which is what lets two clients share one Thunderbird.

  Claude Code ──stdio──▶ tbmcp serve ─┐
                                      ├─local RPC─▶ tbmcp daemon ◀══WebSocket══ add-on
  Codex CLI  ──stdio──▶ tbmcp serve ─┘              owns the socket,            inside
                                                    multiplexes clients      Thunderbird

The daemon picks a free port and writes /tbmcp-bridge.json with a token; the add-on reads it with privileged file I/O and authenticates on connect. Nothing is ever bound to a non-loopback interface.

Full detail in docs/ARCHITECTURE.md and docs/PROTOCOL.md.


Requirements

  • Thunderbird 128 or newer — developed and verified against 153
  • Python 3.11+
  • Windows, macOS or Linux, including Snap and Flatpak Thunderbird

Troubleshooting

tbmcp doctor checks each link in the chain and names the one that is broken. The add-on also writes /tbmcp-addon-status.json at startup — which privileged modules loaded, how many bridge methods exist, which capabilities Thunderbird actually granted — and doctor reads it. Its absence, on an add-on that is installed and active, is itself the diagnosis.

Symptom Cause
“Thunderbird is not connected” Thunderbird is closed, or the add-on is not installed
“the add-on never wrote its startup report” the privileged half did not load → tbmcp install-addon again
settings tools fail but mail tools work same cause; check privileged modules in doctor
full-text search finds nothing Thunderbird’s global indexer is off (Settings → General)
raw message source unavailable on IMAP the message is not stored offline → folder_sync_offline
the first tool call after a killed daemon fails the add-on takes ~40-60 s to reattach after an abnormal daemon exit; retry, or tbmcp doctor --wait 60. A clean exit reattaches in about a second. Details
Codex reports a startup timeout raise startup_timeout_sec; Codex defaults to 10 s
Claude Code truncates a large result raise MAX_MCP_OUTPUT_TOKENS (default 25,000)
A dependency fails with “DLL load failed” or “cannot open shared object file” A binary your OS will not load — Windows Application Control blocks unsigned, low-reputation wheels. bootstrap detects this and downgrades the offending package automatically; run python bootstrap.py and read the binaries step.

TBMCP_DEBUG=1 turns on verbose logging to stderr. The add-on logs to Thunderbird’s error console with a [tbmcp] prefix, and tb_console returns those lines as a tool.


Development

uv venv && uv pip install -e ".[dev]"

pytest                                  # 181 tests, no Thunderbird needed
ruff check . && ruff format --check .
python tools/check_consistency.py       # do all three layers still agree?
python tools/build_xpi.py build         # build the add-on package
python tools/gen_tool_reference.py      # regenerate the tool docs from the code
python tools/smoke_live.py              # read-only checks against a live Thunderbird
python tools/smoke_write.py             # gated-write checks; leaves the profile unchanged

Three layers have to agree on method names — the Python tools, the add-on handlers, and the privileged forwarding list — and nothing notices when they stop agreeing until runtime. check_consistency.py compares them, validates every JavaScript file, and checks the manifest lists exactly the scripts that exist. Run it before you commit.

Document
ARCHITECTURE.md why it is built this way, and what was rejected
PROTOCOL.md the wire protocol between Python and the add-on
TOOLS.md the contract: tool → bridge method → implementation
TOOL-REFERENCE.md every tool and parameter, generated from the code
VERIFIED-FINDINGS.md measurements against a live Thunderbird, and the traps

Author

GitHub @U-C4N · X @UEdizaslan

Built from actually living in Thunderbird all day, then made model-agnostic through MCP. Every capability was measured against a real install before it was documented — see VERIFIED-FINDINGS.md for what that turned up.

Related work: Autocad-MCP · U-Pool · Deuz-SDK

Contributing

Issues and pull requests are welcome. Before opening one:

pytest && ruff check . && python tools/check_consistency.py

check_consistency.py is the important one — it catches the mismatches between the three layers that nothing else notices until runtime. If you add a tool, run python tools/gen_tool_reference.py so the docs follow the code.

Report a security problem through GitHub rather than a public issue.

Licence

MIT — see LICENSE. The add-on contains no Mozilla-licensed code: the reverse-WebSocket design was chosen partly so that no MPL-2.0 HTTP server needed to be vendored.

View this README on GitHub

安装

This server does not publish a one-line install command.

Open the repository installation guide