apple-mail-mcp 2.13.2 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +17 -3
  2. package/build/index.js +51 -12
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -935,9 +935,23 @@ List all mailboxes for an account.
935
935
 
936
936
  | Parameter | Type | Required | Description |
937
937
  |-----------|------|----------|-------------|
938
- | `account` | string | No | Account to list from |
939
-
940
- **Returns:** List of mailbox names with message and unread counts.
938
+ | `account` | string | No | Account to list from, or `"On My Mac"` for the local store |
939
+
940
+ **Returns:** List of mailbox names with message and unread counts. A source that
941
+ could not be read is **named** (`partial: true` + `failedAccounts`) rather than
942
+ dropped, and a listing Mail refused outright returns an error naming the accounts
943
+ that do exist — never an empty list.
944
+
945
+ **Mail's local "On My Mac" mailboxes** are not children of any account — they
946
+ hang off the application — so they are reported under the synthetic account label
947
+ **`On My Mac`**. An unscoped call includes them (listed last); `account="On My
948
+ Mac"` lists only them. `on my computer`, `local` and `local folders` are accepted
949
+ as aliases.
950
+
951
+ They deliberately do **not** appear in `list-accounts`, which reports real
952
+ accounts only: the local store is a store, not an account. Nothing selects it
953
+ implicitly — omitting `account` still resolves to a real account for every other
954
+ tool.
941
955
 
942
956
  ---
943
957
 
package/build/index.js CHANGED
@@ -79129,6 +79129,24 @@ function buildAccountScopedScript(account, command) {
79129
79129
  end tell
79130
79130
  `;
79131
79131
  }
79132
+ var LOCAL_STORE_LABEL = "On My Mac";
79133
+ var LOCAL_STORE_ALIASES = ["on my mac", "on my computer", "local", "local folders"];
79134
+ function isLocalStoreLabel(name) {
79135
+ return name !== void 0 && LOCAL_STORE_ALIASES.includes(name.trim().toLowerCase());
79136
+ }
79137
+ function localMailboxBindingFragment() {
79138
+ return `
79139
+ set _mbs to {}
79140
+ repeat with _m in mailboxes
79141
+ set _isLoc to false
79142
+ try
79143
+ if (account of _m) is missing value then set _isLoc to true
79144
+ on error
79145
+ set _isLoc to true
79146
+ end try
79147
+ if _isLoc then set end of _mbs to (contents of _m)
79148
+ end repeat`;
79149
+ }
79132
79150
  function groupKey(account, mailbox) {
79133
79151
  return `${account}\0${mailbox}`;
79134
79152
  }
@@ -81983,10 +82001,11 @@ ${this.errorEmit(" ")}
81983
82001
  * List all mailboxes for an account.
81984
82002
  */
81985
82003
  listMailboxes(account, options = {}) {
81986
- const targetAccount = this.resolveAccount(account);
81987
- const listCommand = `
82004
+ const local = isLocalStoreLabel(account);
82005
+ const targetAccount = local ? LOCAL_STORE_LABEL : this.resolveAccount(account);
82006
+ const listCommand = (iterExpr) => `
81988
82007
  set mailboxList to {}
81989
- repeat with mb in mailboxes
82008
+ repeat with mb in ${iterExpr}
81990
82009
  set mbName to name of mb
81991
82010
  set mbUnread to unread count of mb
81992
82011
  set mbCount to count of messages of mb
@@ -81995,7 +82014,8 @@ ${this.errorEmit(" ")}
81995
82014
  set AppleScript's text item delimiters to "${RECORD_SEP}"
81996
82015
  return mailboxList as text
81997
82016
  `;
81998
- const script = buildAccountScopedScript(targetAccount, listCommand);
82017
+ const script = local ? buildAppLevelScript(`${localMailboxBindingFragment()}
82018
+ ${listCommand("_mbs")}`) : buildAccountScopedScript(targetAccount, listCommand("mailboxes"));
81999
82019
  const result = executeAppleScript(script, { timeoutMs: options.timeoutMs ?? 6e4 });
82000
82020
  if (!result.success) {
82001
82021
  console.error(`Failed to list mailboxes: ${result.error}`);
@@ -84653,19 +84673,15 @@ function withErrorHandling(handler, errorPrefix) {
84653
84673
  }
84654
84674
 
84655
84675
  // src/tools/mailboxListing.ts
84656
- var LOCAL_STORE_NAMES = ["on my mac", "on my computer", "local", "local folders"];
84657
- function isLocalStoreName(name) {
84658
- return LOCAL_STORE_NAMES.includes(name.trim().toLowerCase());
84659
- }
84660
84676
  function unlistableStoreError(account, error2, knownAccounts) {
84661
84677
  const scope = account ? ` for "${account}"` : "";
84662
84678
  const parts = [`Could not list mailboxes${scope}: ${error2 ?? "Mail declined the request"}`];
84663
84679
  if (knownAccounts.length > 0) {
84664
84680
  parts.push(`Accounts on this Mac: ${knownAccounts.join(", ")}.`);
84665
84681
  }
84666
- if (account && isLocalStoreName(account)) {
84682
+ if (account && isLocalStoreLabel(account)) {
84667
84683
  parts.push(
84668
- `"${account}" is Mail's LOCAL store, not an account \u2014 its mailboxes are not children of any account, so they cannot be reached with an \`account\` argument. Enumerating them is not yet supported.`
84684
+ `"${account}" addresses Mail's LOCAL store, which IS listable \u2014 it is read at the application level rather than through an account, so this failure is not "no such account". Something went wrong reading the local store itself.`
84669
84685
  );
84670
84686
  }
84671
84687
  return parts.join("\n\n");
@@ -86709,10 +86725,26 @@ ${r.base64}`,
86709
86725
  );
86710
86726
  }, "Error fetching attachment")
86711
86727
  );
86728
+ function appendLocalStoreRows(rows, failedAccounts) {
86729
+ const checked = mailManager.listMailboxesChecked(LOCAL_STORE_LABEL);
86730
+ if (checked.failed) {
86731
+ console.error(`list-mailboxes failed for "${LOCAL_STORE_LABEL}": ${checked.error}`);
86732
+ failedAccounts.push(LOCAL_STORE_LABEL);
86733
+ return;
86734
+ }
86735
+ for (const mb of checked.mailboxes) {
86736
+ rows.push({
86737
+ name: `${LOCAL_STORE_LABEL}/${mb.name}`,
86738
+ account: LOCAL_STORE_LABEL,
86739
+ unreadCount: mb.unreadCount,
86740
+ messageCount: mb.messageCount
86741
+ });
86742
+ }
86743
+ }
86712
86744
  registerTool(
86713
86745
  "list-mailboxes",
86714
86746
  {
86715
- description: "Use when: discovering the mailbox/folder names (and unread/message counts) available in an account, e.g. before moving messages or searching a specific mailbox.\nReturns: each mailbox's name with its unread (and, for IMAP, total message) count, plus a count. A source that could not be read is NAMED \u2014 the result carries `partial: true` + `failedAccounts` and the list is a floor, not the complete set \u2014 and a listing Mail refused outright (e.g. an account that does not exist) returns an ERROR naming the accounts that do exist, never an empty list.\nDo not use when: you want the messages inside a mailbox (use list-messages or search-messages) or the list of accounts (use list-accounts).\nNote: Mail's local \"On My Mac\" mailboxes are not part of any account and are not currently enumerated by this tool.",
86747
+ description: 'Use when: discovering the mailbox/folder names (and unread/message counts) available in an account, e.g. before moving messages or searching a specific mailbox.\nReturns: each mailbox\'s name with its unread (and, for IMAP, total message) count, plus a count. A source that could not be read is NAMED \u2014 the result carries `partial: true` + `failedAccounts` and the list is a floor, not the complete set \u2014 and a listing Mail refused outright (e.g. an account that does not exist) returns an ERROR naming the accounts that do exist, never an empty list.\nDo not use when: you want the messages inside a mailbox (use list-messages or search-messages) or the list of accounts (use list-accounts).\nNote: Mail\'s local "On My Mac" mailboxes are not part of any account, so they are reported under the synthetic account label "On My Mac" \u2014 an unscoped call includes them, and `account: "On My Mac"` lists only them. They will not appear in list-accounts, which reports real accounts only.',
86716
86748
  inputSchema: {
86717
86749
  account: external_exports.string().optional().describe("Account to list mailboxes from")
86718
86750
  },
@@ -86778,6 +86810,7 @@ ${list2}`, structured3);
86778
86810
  });
86779
86811
  }
86780
86812
  }
86813
+ appendLocalStoreRows(rows, failedAccounts);
86781
86814
  const partial2 = failedAccounts.length > 0;
86782
86815
  const structured2 = {
86783
86816
  mailboxes: rows,
@@ -86806,7 +86839,13 @@ ${list}${caveat}`, structured2);
86806
86839
  )
86807
86840
  );
86808
86841
  }
86809
- const structured = { mailboxes, count: mailboxes.length };
86842
+ const localFailures = [];
86843
+ if (account === void 0) appendLocalStoreRows(mailboxes, localFailures);
86844
+ const structured = {
86845
+ mailboxes,
86846
+ count: mailboxes.length,
86847
+ ...localFailures.length ? { partial: true, failedAccounts: localFailures } : {}
86848
+ };
86810
86849
  if (mailboxes.length === 0) {
86811
86850
  return successResponse("No mailboxes found", structured);
86812
86851
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.13.2",
3
+ "version": "2.14.0",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude and other AI assistants",
5
5
  "type": "module",
6
6
  "main": "build/index.js",