apple-mail-mcp 2.10.22 → 2.10.24

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 +11 -10
  2. package/build/index.js +25 -20
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -74,7 +74,7 @@ codex plugin marketplace add sweetrb/apple-mail-mcp
74
74
  codex plugin add apple-mail@apple-mail-mcp
75
75
  ```
76
76
 
77
- The Codex package registers the same `apple-mail` MCP server through `npx -y apple-mail-mcp` and includes the Apple Mail skill guidance.
77
+ The Codex package registers the same `apple-mail` MCP server through an exactly pinned runtime — `npx -y apple-mail-mcp@<plugin version>` — and includes the Apple Mail skill guidance. The pin in `codex/.mcp.json` is rewritten to match `package.json` by `scripts/sync-plugin-version.mjs` on every version bump, so the plugin manifest and the server it launches are always the same release; CI fails the PR if they drift.
78
78
 
79
79
  ### Other Hosts (Hermes, Antigravity)
80
80
 
@@ -852,11 +852,12 @@ likely to be refused as ambiguous. Passing the source mailbox explicitly is the
852
852
  stay scoped, and it overrides the remembered location. These parameters name where the ids **came
853
853
  from**; for `batch-move-messages` that is distinct from `mailbox`, the destination.
854
854
 
855
- `sourceMailbox` is the one that scopes, and it works on its own: omitting `sourceAccount` means
856
- that mailbox **in the default account**, exactly as an omitted `account` does elsewhere. If the
857
- default account cannot be determined, the ids fail with an error asking for an explicit
858
- `sourceAccount` a scope the server can't honor is never quietly downgraded to the guess-the-copy
859
- walk. `sourceAccount` by itself pins nothing, since the mailbox is what an id is scoped to.
855
+ `sourceMailbox` and `sourceAccount` are an atomic scope pair: provide **both** for numeric ids.
856
+ The server never fills in a missing account from mutable default-send state, because the same
857
+ mailbox name can exist in more than one account and numeric ids are only unique within an account
858
+ and mailbox. A whitespace-only source field is rejected. `sourceAccount` by itself pins nothing,
859
+ since the mailbox is what an id is scoped to; `imap:…` ids ignore both fields because they carry
860
+ their own account, mailbox, and UID identity.
860
861
 
861
862
  **A repeated id is one message.** `ids` is treated as a set: a duplicate names the same message,
862
863
  so it is operated on once, and the batch returns **one result per distinct id**. `success` is
@@ -868,7 +869,7 @@ therefore a count of messages, not of list positions.
868
869
  |-----------|------|----------|-------------|
869
870
  | `ids` | string[] | Yes | Message IDs to delete (max 100) |
870
871
  | `sourceMailbox` | string | No | Mailbox the **numeric** ids were listed from — pins them to it. Ignored for `imap:` ids. |
871
- | `sourceAccount` | string | No | Account the numeric ids were listed from. Defaults to the default account; on its own it pins nothing — pair it with `sourceMailbox`. |
872
+ | `sourceAccount` | string | No | Account the numeric ids were listed from. Required when `sourceMailbox` is supplied; on its own it pins nothing. |
872
873
 
873
874
  `structuredContent` carries `countDelta` — what the batch actually did to each
874
875
  source mailbox. See [Auditing destructive operations](#auditing-destructive-operations).
@@ -883,7 +884,7 @@ source mailbox. See [Auditing destructive operations](#auditing-destructive-oper
883
884
  | `mailbox` | string | Yes | Destination mailbox |
884
885
  | `account` | string | No | Account containing mailbox |
885
886
  | `sourceMailbox` | string | No | Mailbox the **numeric** ids were listed from — pins them to it. Ignored for `imap:` ids. |
886
- | `sourceAccount` | string | No | Account the numeric ids were listed from. Defaults to the default account; on its own it pins nothing — pair it with `sourceMailbox`. |
887
+ | `sourceAccount` | string | No | Account the numeric ids were listed from. Required when `sourceMailbox` is supplied; on its own it pins nothing. |
887
888
 
888
889
  `structuredContent` carries `countDelta` — what the batch actually did to each
889
890
  **source** mailbox. See [Auditing destructive operations](#auditing-destructive-operations).
@@ -894,7 +895,7 @@ source mailbox. See [Auditing destructive operations](#auditing-destructive-oper
894
895
  |-----------|------|----------|-------------|
895
896
  | `ids` | string[] | Yes | Message IDs (max 100) |
896
897
  | `sourceMailbox` | string | No | Mailbox the **numeric** ids were listed from — pins them to it. Ignored for `imap:` ids. |
897
- | `sourceAccount` | string | No | Account the numeric ids were listed from. Defaults to the default account; on its own it pins nothing — pair it with `sourceMailbox`. |
898
+ | `sourceAccount` | string | No | Account the numeric ids were listed from. Required when `sourceMailbox` is supplied; on its own it pins nothing. |
898
899
 
899
900
  #### `batch-flag-messages` / `batch-unflag-messages`
900
901
 
@@ -903,7 +904,7 @@ source mailbox. See [Auditing destructive operations](#auditing-destructive-oper
903
904
  | `ids` | string[] | Yes | Message IDs (max 100) |
904
905
  | `color` | string | No | (`batch-flag-messages` only) Flag color — see [`flag-message`](#flag-message--unflag-message). Applied on both routes, so a mixed batch of numeric and `imap:` ids all end up colored. |
905
906
  | `sourceMailbox` | string | No | Mailbox the **numeric** ids were listed from — pins them to it. Ignored for `imap:` ids. |
906
- | `sourceAccount` | string | No | Account the numeric ids were listed from. Defaults to the default account; on its own it pins nothing — pair it with `sourceMailbox`. |
907
+ | `sourceAccount` | string | No | Account the numeric ids were listed from. Required when `sourceMailbox` is supplied; on its own it pins nothing. |
907
908
 
908
909
  ---
909
910
 
package/build/index.js CHANGED
@@ -80734,39 +80734,44 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
80734
80734
  /**
80735
80735
  * Turn a caller-supplied batch source scope into an account+mailbox pair.
80736
80736
  *
80737
- * `mailbox` is what does the scoping, and it works ON ITS OWN: an omitted
80738
- * `account` means "the default account" here exactly as it does for every
80739
- * other tool in this server (see resolveAccount), never "ignore the argument
80740
- * you were given". Requiring both used to make a lone `sourceMailbox` a silent
80741
- * no-op the ids fell back to the whole-tree path and were then refused as
80742
- * ambiguous, which is the very failure the parameter exists to prevent.
80737
+ * A numeric source scope is an account+mailbox pair. A mailbox name alone is
80738
+ * not an identity: the same mailbox can exist in several accounts, and a
80739
+ * numeric Mail id is not globally unique. Resolving a missing account from
80740
+ * mutable default-send state can therefore target the wrong account. Require
80741
+ * both fields so a caller cannot silently cross that account boundary.
80743
80742
  *
80744
80743
  * The safety property is absolute: when the account cannot be determined there
80745
80744
  * is NO fallback to the scan-and-guess walk. The caller gets an error naming
80746
80745
  * the mailbox it asked for, so it can retry with an explicit `sourceAccount`.
80747
80746
  * (An `account` with no `mailbox` cannot pin anything, so it scopes nothing —
80748
- * those ids still go through the index / ambiguity-checked path.)
80747
+ * those ids still go through the index / ambiguity-checked path. A supplied
80748
+ * whitespace-only field is rejected rather than silently discarded.)
80749
80749
  */
80750
80750
  resolveBatchScope(scope) {
80751
- const mailbox = scope?.mailbox?.trim();
80752
- if (!mailbox) return { kind: "none" };
80753
- const account = scope?.account?.trim();
80754
- if (account) return { kind: "scoped", account, mailbox };
80755
- const known = this.getCachedAccounts();
80756
- if (known.length === 0) {
80751
+ const rawMailbox = scope?.mailbox;
80752
+ const rawAccount = scope?.account;
80753
+ const mailbox = rawMailbox?.trim();
80754
+ const account = rawAccount?.trim();
80755
+ if (rawMailbox !== void 0 && !mailbox) {
80757
80756
  return {
80758
80757
  kind: "unresolvable",
80759
- error: `Cannot scope to source mailbox "${mailbox}": no sourceAccount was given and no Mail account could be read (Mail returned none, or the AppleScript transport failed). Retry with an explicit sourceAccount.`
80758
+ error: "sourceMailbox must contain a mailbox name; whitespace-only scope is not allowed."
80760
80759
  };
80761
80760
  }
80762
- const chosen = this.resolveAccount();
80763
- if (!known.some((a) => a.name === chosen)) {
80761
+ if (rawAccount !== void 0 && !account) {
80762
+ return {
80763
+ kind: "unresolvable",
80764
+ error: "sourceAccount must contain an account name; whitespace-only scope is not allowed."
80765
+ };
80766
+ }
80767
+ if (!mailbox) return { kind: "none" };
80768
+ if (!account) {
80764
80769
  return {
80765
80770
  kind: "unresolvable",
80766
- error: `Cannot scope to source mailbox "${mailbox}": no sourceAccount was given and the default account could not be determined. Retry with an explicit sourceAccount (available: ${known.map((a) => a.name).join(", ")}).`
80771
+ error: `Cannot scope to source mailbox "${mailbox}" without sourceAccount: numeric Mail ids are only unique within an account and mailbox. Retry with both sourceAccount and sourceMailbox explicitly set.`
80767
80772
  };
80768
80773
  }
80769
- return { kind: "scoped", account: chosen, mailbox };
80774
+ return { kind: "scoped", account, mailbox };
80770
80775
  }
80771
80776
  /**
80772
80777
  * Run one operation over many message IDs in a SINGLE osascript invocation.
@@ -84420,10 +84425,10 @@ function withJsonSchema2020_12(transport2) {
84420
84425
  // src/index.ts
84421
84426
  loadFileConfig();
84422
84427
  var BATCH_SOURCE_MAILBOX_SCHEMA = external_exports.string().optional().describe(
84423
- "Mailbox the numeric ids were listed from (e.g. 'INBOX'). Pins each id to that mailbox \u2014 strongly recommended, since one numeric id can match in several mailboxes. Works on its own: without sourceAccount it means that mailbox in the default account. Ignored for imap: ids."
84428
+ "Mailbox the numeric ids were listed from (e.g. 'INBOX'). Must be paired with sourceAccount to form an unambiguous scope. Ignored for imap: ids."
84424
84429
  );
84425
84430
  var BATCH_SOURCE_ACCOUNT_SCHEMA = external_exports.string().optional().describe(
84426
- "Account the numeric ids were listed from. Defaults to the default account. On its own it pins nothing \u2014 pair it with sourceMailbox."
84431
+ "Account the numeric ids were listed from. Required when sourceMailbox is supplied; on its own it pins nothing."
84427
84432
  );
84428
84433
  var FLAG_COLOR_INDEX = {
84429
84434
  red: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.10.22",
3
+ "version": "2.10.24",
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",