Repository navigation
v0.12.0
·
56 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Breaking
replyToMessagewithskipReviewnow needs explicittoandfrom, andforwardMessagewithskipReviewan
explicitfrom. A direct send no longer takes any address from the original message, which anyone can write: it
goes only to the caller'sto/cc/bccplus the sending identity's own automatic Cc / Bcc, with that
identity's Reply-To (a direct reply-all no longer adds the original's To / Cc). The result of a direct send lists
thefrom,to,cc,bccandreplyToit went out with. By @mazixs in #26.- The error that
replyToMessageandforwardMessagereturn when direct sending is blocked has new text, and it now
coversmode: "send"as well asskipReview: it was "User preference blocks skipReview. Retry with skipReview:
false (or omitted) to open the review window instead.", it is now "User preference blocks direct sending (mode
"send" or skipReview). Use mode "draft" to save a draft, or "window" (the default) to open a review
window." A client that matches the old string exactly must be updated (sendMail,createEventandcreateTask
keep theirs). By @mazixs in #27.
Added
replyToMessageandforwardMessagetakemode:window(the default, the review window as before),draftor
send.mode: "send"is a direct send, the same asskipReview: true, with the same rules: explicittoand
from, subject to BlockskipReview, and the bridge waits up to 150 s for it.mode: "draft"saves the
reply or forward to the identity's Drafts folder without opening a window and returns itsmessageIdand
folderPath. It sends nothing, so BlockskipReviewdoes not block it. By @mazixs in #27.
mode: "draft"needs thesaveDrafttool to be enabled: a tool the user disabled is not reachable through
another tool, and the call returns an error saying so.- A reply draft gets the recipients Thunderbird's Reply / Reply All computes (
nsMsgCompose.cpp, ported to a
pure function): Reply-To and Mail-Reply-To, Mail-Followup-To for Reply All, the author instead of a mailing list
that rewrites Reply-To, the recipients of your own message from the identity that sent it, your own addresses
dropped, and the identity's automatic Cc / Bcc and Reply-To. Atoorccfrom the caller replaces the
computed one. - The draft stores the state Thunderbird's own reply or forward draft stores (
origURIs,queuedDisposition), so
the original is marked as replied or forwarded when the draft is sent, not when it is saved. - The body is quoted by the tool, as for a direct send.
- A reply draft gets the recipients Thunderbird's Reply / Reply All computes (
- The bridge tells the user, once per connection, when the add-on is older than the version it needs
(MIN_EXTENSION_VERSION, 0.12.0). After the firsttools/listortools/callthat Thunderbird answers, it sends
the add-on aninitializeon the same validated connection (1.5 s at most, answer capped at 64 KB) and, if the
add-on is older, appends one text item to the result of the nexttools/call(Check for Updates, then restart
Thunderbird; the release page) and writes one line to stderr. Never for a direct send (skipReviewor
mode: "send"); silent when a version is missing,0.0.0or malformed, or when the server is notcommonpost-mcp; only
digits from the add-on reach the text. When the add-on is newer, the add-on judges the bridge (below). - A
.mcpbbundle for Claude Desktop (macOS and Windows), attached to each release from the next one on:commonpost-mcp-v<version>.mcpb, with a provenance attestation. It contains only the stdio bridge (mcp-bridge.cjs,LICENSE,THIRD-PARTY.md, an icon and amanifest.jsoninmcpb/, manifest_version 0.3), needs Node.js 22 or later and the add-on of the same release or newer, has no settings and is not signed. It is built byscripts/build-mcpb-reproducible.cjslike the XPI (committed files only, sorted stored entries, fixed date: the same bytes on any Node version), and the release job rebuilds it from the tag and refuses any difference. The zip writer moved toscripts/zip-stored.cjs(the XPI is byte for byte unchanged). The Version sync check and the tag check now covermcpb/manifest.jsontoo. - The bridge ignores
COMMONPOST_MCP_CONNECTION_FILEwhen its value is exactly an unexpanded${user_config.…}placeholder (a client passing an empty optional field through as text) and runs the automatic discovery, instead of pinning itself to a path that cannot exist. - The bridge answers
server/discoveritself, at once, with the JSON-RPC error -32601 "Method not found", without
contacting Thunderbird. Clients that speak both protocol eras (MCP 2026-07-28 and earlier, such as Claude Desktop)
probe with it first and fall back toinitialize; the probe used to reach Thunderbird and, with Thunderbird closed,
came back after about 5 s with a discovery error that named local paths. - The bridge announces itself on every request to the add-on, in the
X-Commonpost-Bridgeheader: its version, how it
was installed (packaging=mcpbwhen the.mcpbbundle setsCOMMONPOST_MCP_PACKAGING=mcpb, otherwisefile) and,
whenCOMMONPOST_MCP_PROFILEholds a valid name (a-z, 0-9 and -, 32 at most),profile=<name>, reserved for
per-client tool sets (nothing uses it yet). The header is self-declared: it is not a security boundary, the token
is. - The add-on judges bridges older than itself: once per client session (at most every 10 minutes) it adds a notice to
a tool result when the bridge is older than 0.12.0 or reports no version (0.11 or older), with the release page and
what to do (.mcpbor file); never on a direct send. It refusesreplyToMessage/forwardMessagewith
mode: "send"or"draft"(withoutskipReview) from such a bridge before doing anything, because an old bridge stops
waiting after 30 s and can report a failure for a message that is still being sent;mode: "window"and every other
call keep working. A program that calls the HTTP API directly can declare itself with the header (README,
Development). - A local security floor in the add-on (
BRIDGE_SECURITY_FLOOR), shipped disarmed (0.0.0): if a future release arms
it, every tool call from an older bridge, or from a client without the header, is refused before anything acts, with
the reason and the release page;tools/listkeeps answering. No remote switch, no setting to bypass it. - Options page, section "Bridge": the bridges that connected since Thunderbird started (version, installation,
profile, last seen, status) and the release page to update one. Kept in memory only.
Changed
- Without
from,replyToMessageandforwardMessageuse the identity Thunderbird's own Reply / Forward picks
(MailUtils.getIdentityForHeader, asComposeMessageinmailCommands.jscalls it) instead of the account's
default identity: the identity the message was addressed to (To / Cc, then Delivered-To), the identity that sent
it for a reply to your own message, and for a catch-all identity the address the message was sent to. Identities
of accounts the MCP may not access are never picked. By @mazixs in #26.
An identity shared by an accessible and a restricted account counts as accessible, whatever the order of the
accounts, asfindIdentityalready did. Fetching the original message for that choice gives up after 20 s: a
compose window or a draft then opens without it, and a direct send returns an error instead of hanging. Encrypted
messages stay withheld from a direct reply or forward while the "read encrypted messages" option is off. saveDraftsaves throughnsIMsgCompose, as Thunderbird's compose window does, and returns the new draft's
messageIdandfolderPath. IfnsIMsgComposecannot be used, it falls back to the previousnsIMsgSendpath.
By @mazixs in #27.forwardMessageno longer requiresto, except withmode: "send"(orskipReview). By @mazixs in #27.- A reply's References header is the original's References plus its Message-ID, as Thunderbird's reply builds it
(it used to be the original's Message-ID only); Thunderbird trims a chain longer than the header limit when it
writes the message, as for its own reply. A reply to a message without Message-ID gets no References. In-Reply-To
is no longer set by the tool: Thunderbird derives it from the last References entry. By @mazixs in #27. mcp-bridge.cjs: areplyToMessageorforwardMessagecall withmode: "send"is a direct send like
skipReview: true, so it waits up to 150 s and gets the same "outcome unknown" error on a timeout. By @mazixs in
#27. On top, from the maintainers: the mode is compared trimmed and lower-cased to decide that (so"SEND", which
the extension refuses, still counts as a send: no version notice, the long wait), without changing what is sent to
the extension; andmode: "draft"waits 150 s too, since Thunderbird can take up to 120 s to save a draft and a
client that retries after 30 s would create two. After that wait the error says the draft may still appear in the
Drafts folder later.- README: a "Quick install" section at the top, in five steps, with the Claude Code command (Windows example included) and a bold reminder that the bridge is not updated with the extension. It also corrects the old advice to replace the bridge's
package.jsontoo: the release ships onlymcp-bridge.cjs, which needs nothing else. - README: a new "Other MCP clients" section with the configuration file, location and format of Claude Desktop, VS Code, Cursor, OpenAI Codex CLI and Gemini CLI, checked against each client's documentation, and when and how to set
COMMONPOST_MCP_CONNECTION_FILE(only if the bridge cannot find the connection file). The bridge is not tied to any client, andmcpServersis not the key every client uses. - RELEASING: the verification step now says that a rebase merge rewrites the commit date, so the reproducible hash built from the pull request branch cannot match the release; compare with a rebuild from a checkout of the tag.
BRIDGE_VERSIONis now the release in which the bridge (or anything in its.mcpbbundle) last changed, not the
product version: a release that changes only the add-on ships the samemcp-bridge.cjsand the same
commonpost-mcp-v<bridge version>.mcpb, byte for byte.scripts/check-versions.cjsreplaces the shell check of the
Version sync job and the version part of the release tag check: product version inpackage.json,
package-lock.jsonand the add-on manifest;BRIDGE_VERSION=.mcpbmanifest, never newer than the product;
bridge bundle compared with the previous release tag; thresholds at or belowBRIDGE_VERSION; an armed floor must
be announced here..mcpbmanifest:homepagepoints to the latest release,documentationto the README section of the bundle, and
it setsCOMMONPOST_MCP_PACKAGING=mcpb.- Known effect: after a downgrade of the add-on below what the bridge needs, the bridge's notice comes back after each
restart of Thunderbird.
Fixed
- The bridge did not start under Claude Desktop's built-in Node.js, which loads the entry point of a .mcpb bundle through a host script with import(): it now also starts when process.argv[1] is this file. Found while testing the bundle of #44 in Claude Desktop 2.16120 (Windows).
- The bridge of a release announced version
0.0.0inserverInfo: it readpackage.json, which the release does not ship (onlymcp-bridge.cjs), and next to another project'spackage.jsonit announced that project's version. Its version is now written inmcp-bridge.cjs(BRIDGE_VERSION), checked byscripts/check-versions.cjs(see Changed).