Mail drafts can be edited after their window closes.
Version 1.32.0 ·
A closed reply is rebuilt as a reply, edits change only the words you name, everyday Mail reads answer from its index, and Mail and Messages can tell a session when something arrives.
Share this release
Mail drafts can be edited after their window closes. A closed reply is rebuilt as a reply, edits change only the words you name, everyday Mail reads answer from its index, and Mail and Messages can tell a session when something arrives. https://cupertino.mgcrea.io/changelog/1.32.0/
Added
The npm servers also speak the 2026-07-28 MCP protocol. Mail, Notes, Reminders, Calendar, Contacts, Messages, Safari and Maps answer
server/discoverand serve a client that opens with the new per-request handshake, alongside the 2025initializeone. Clients on the older protocol see no change.Mail and Messages can tell a session when something arrives.
apple_mail_watchandapple_messages_watchtake a sender filter,fromordomains, and hand back a resource the host can subscribe to; when a matching message lands, the server pushesnotifications/resources/updated, and a read of the resource returns what came in. Off by default behindAPPLE_MAIL_ALLOW_WATCHESandAPPLE_MESSAGES_ALLOW_WATCHES, and a sender is required, since there is no watch on everything. A watch carries envelope metadata only, never a body or message text. It works with both the 2025 and the 2026-07-28 protocol, and lives as long as the connection that made it. Claude Code does not subscribe yet, in either protocol, so an agent there checks a watch by reading it. The Activity log shows each subscription, and the Activity log and the audit file record each push, so what Cupertino sent into a session reads the same as what it was asked.Correction, added after release: Claude Code does subscribe, just never to a watch. On the 2026-07-28 protocol it opens one
subscriptions/listenwhen it connects, for the list-changed notifications only, and never one naming a watch's URI. On the 2025 protocol it never sendsresources/subscribe. Measured on Claude Code 2.1.311 to 2.1.316. The conclusion stands: nothing is pushed into a Claude Code session, and an agent there reads the watch.A draft whose window was closed can still be edited.
apple_mail_update_draftused to refuse once the window was gone. A reply is now rebuilt as a reply to its original, so it stays in the thread and keeps its files and formatting, and the old draft is deleted only after the new one is confirmed in Drafts. It still refuses, leaving the draft as it was, for a forward and for an original Mail can't find. When the quote Mail writes into the new reply is not the one the draft had, the draft is left as it was too, but that new reply window stays open, unfilled and unsaved, for you to close without saving.Edits can be find and replace.
update_drafttakesedits, pairs of text to find and what replaces it, applied to what you wrote and never to the quoted message. Eachfindmust match exactly once, and only the matched words change, so the rest of the draft, its formatting and its files are left alone.A draft can be named by its window, or not at all.
update_drafttakes acomposerhandle fromapple_mail_list_open_drafts, and with neither arefnor a handle it edits the one compose window that is open. With none or several open it refuses and lists them.Drafts open as tabs of one window are handled. With macOS set to prefer tabs, Mail opens every compose window as a tab, and only the tab it shows can be read.
apple_mail_list_open_draftsnow lists each tab with its own handle, a hidden one by subject only.update_draftselects a hidden tab, checks it is the draft, edits and saves it, and then leaves that tab shown, because Mail does not say when a save has landed and switching back early could save the other draft. A handle can come back markedreboundafter Mail rebuilds its tab bar; it then edits only byref, which checks the text, until that text is proved.The Mail pane says when drafts need Accessibility. Writing into a compose window requires it, and the rest of Mail doesn't, so the pane now shows a row with an Allow button when Mail writes are on and the grant is missing.
Changed
Mail's everyday reads no longer wait on Mail. With Full Disk Access,
list_messages,count_messages,list_mailboxeswith counts,get_messageandlist_attachmentsanswer from Mail's search index and the message files, and send Mail no Apple Event at all. On a 210,000-message store, listing twenty messages took 8.4 s and now takes milliseconds;list_mailboxestook 1.2 s,count_messages0.77 s andget_message0.45 s, nearly all of it Apple Events for columns the index already holds.list_messagesis no longer capped at 50 when the index answers, and itssourcesays which lane did.count_messagesreportsunread.indexalone when the index answers, and Mail's cached badge figure only when it cannot; counts fromlist_mailboxesnow agree with it, Gmail labels included, and are null for a mailbox the index does not hold rather than zero. Without Full Disk Access, or for a mailbox the index has no row for, each still asks Mail.A sender's display name is quoted the way Mail writes it. Results built from the index,
search_messagesandget_threadincluded, gaveDoe, Jane <jane@example.com>, which reads as two recipients. They now give"Doe, Jane" <jane@example.com>, matching Mail's ownsender— which differed on 18 of 20 messages of an Exchange account.The account list stops costing a second a minute. It was cached for 60 s, so the first call after every pause waited about a second for Mail to list its accounts again. An expired list is now served at once and refreshed behind the call, and an account name it does not know is read afresh before it is refused.
A new message, reply or forward keeps your signature. The text you give goes in above the signature Mail adds, as it always did, and the signature stays below it, an image in it included; the check that the text landed reads back your text followed by the signature. Changing a draft that already exists with
update_draftand abodystill replaces everything you wrote in it, signature included.Editing a draft is faster and interrupts less. The text is selected without moving the caret line by line and without a copy for every step, so Mail comes to the front once, to paste, and your clipboard and the app you were in are put back afterwards.
apple_mail_list_open_draftsreturns a handle for each window. It also reports From, To, Cc and Bcc, and the start of the quoted message, so a draft can be reviewed and then edited without searching for it first.Reminders'
list_liststakes seconds, not half a minute. It sent five Apple Events per list and took 17–29 s for twelve lists. It now reads the list tree in bulk, and takes each list's counts from the Reminders store with Full Disk Access (1 ms, agreeing with Reminders on every list measured) or from one chained Apple Event without it. A list whose counts could not be read reports null rather than zero.list_accountsreports an account'sreminderCountas null when Reminders will not count it, which it never does on macOS 27, instead of 0.
Fixed
Two drafts with the same subject are no longer refused. Two replies in one thread share a title, and the old edit gave up rather than guess which window was meant. Each window now has its own handle, so the right one is edited and the other is left as it was.
A missing Accessibility grant is explained once, in plain words. Each draft tool said so in its own way, and some only said it could not read the window. They now say what the missing grant stopped and where to turn it on.
apple_reminders_get_reminderanswers instead of timing out. It read sixteen properties as separate Apple Events, each costing about a second while Reminders resolved the reminder again, and ran past the 30 s timeout on every call. It now reads them in one event of about a second, and names the reminder's list from the store when it can. A reminder Reminders no longer has is reported as not found rather than as a row of empty fields.