Add archive_email — combine move and mark-read in one atomic call#67
Merged
Conversation
Working through a Fastmail-rail port of an email-processing skill, I noticed every "archive into folder X" site needed two MCP calls: move_email + mark_email_read. The pair has awkward partial-failure semantics (the move succeeds but the mark-read doesn't, or vice versa), and the two-call pattern adds latency and complexity at every archive site in the calling code. archive_email folds both operations into a single Email/set patch: remove all current mailbox memberships, add the target mailbox, and set keywords/$seen=true. JMAP guarantees per-email patch atomicity, so either the whole archive lands or none of it does — no "moved but not marked read" middle state to handle. Scope is deliberately narrow: it's "archive into a folder + mark read", which is what most rule-based filing flows want. Trashing has a different convention (trashed mail often stays unread because Trash doesn't surface in folder lists or unread counts), so delete_email remains the right call there — archive_email intentionally doesn't cover that case. Smoke-tested against a real account: round-tripping a marketing email out to a supplier folder and back to Inbox worked cleanly on both legs, $seen stayed set as expected, no errors. All 176 existing unit tests still pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Working through a Fastmail-rail port of an email-processing skill, I noticed every "archive into folder X" site needed two MCP calls:
move_email+mark_email_read. The pair has awkward partial-failure semantics (the move succeeds but the mark-read doesn't, or vice versa), and the two-call pattern adds latency and complexity at every archive site in the calling code.archive_emailfolds both operations into a singleEmail/setpatch: remove all current mailbox memberships, add the target mailbox, and setkeywords/$seen=true. JMAP guarantees per-email patch atomicity, so either the whole archive lands or none of it does — no "moved but not marked read" middle state to handle.Scope is deliberately narrow: it's "archive into a folder + mark read", which is what most rule-based filing flows want. Trashing has a different convention (trashed mail often stays unread because Trash doesn't surface in folder lists or unread counts), so
delete_emailremains the right call there —archive_emailintentionally doesn't cover that case.Smoke-tested against a real account: round-tripping a marketing email out to a supplier folder and back to Inbox worked cleanly on both legs,
$seenstayed set as expected, no errors. All 176 existing unit tests still pass.This PR was drafted with Claude Opus 4.7; I reviewed and tested each commit before opening.