apple-mail-mcp 2.20.6 → 2.20.7

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 (2) hide show
  1. package/build/index.js +69 -12
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -82762,6 +82762,25 @@ function describeUnscopedMiss(id, raw) {
82762
82762
  );
82763
82763
  return parts.join(" ");
82764
82764
  }
82765
+ var STALLED_PROBE_SUFFIX = ` (size unknown (count probe exceeded ${BYID_PROBE_TIMEOUT_SECONDS}s))`;
82766
+ function extractFreshlyStalledMailboxes(raw) {
82767
+ const covIdx = raw.indexOf(BYID_COVERAGE_MARKER);
82768
+ if (covIdx === -1) return [];
82769
+ const [skippedRaw = ""] = raw.slice(covIdx + BYID_COVERAGE_MARKER.length).split(DIAG_FIELD_SEP);
82770
+ const out = [];
82771
+ for (const entry of skippedRaw.split(DIAG_ITEM_SEP)) {
82772
+ const trimmed = entry.trim();
82773
+ if (!trimmed.endsWith(STALLED_PROBE_SUFFIX)) continue;
82774
+ const withoutSuffix = trimmed.slice(0, -STALLED_PROBE_SUFFIX.length);
82775
+ const sepIdx = withoutSuffix.indexOf(" / ");
82776
+ if (sepIdx === -1) continue;
82777
+ const account = withoutSuffix.slice(0, sepIdx);
82778
+ const path3 = withoutSuffix.slice(sepIdx + 3);
82779
+ const leaf = path3.split("/").pop();
82780
+ if (account && leaf) out.push(`${account}${leaf}`);
82781
+ }
82782
+ return out;
82783
+ }
82765
82784
  var GROUP_SEP = "";
82766
82785
  var FIELD_SEP = "";
82767
82786
  var RECORD_SEP = "";
@@ -83272,6 +83291,24 @@ var AppleMailManager = class {
83272
83291
  * cross-mailbox scan — see `resolveScopedById` (#270).
83273
83292
  */
83274
83293
  idLocationIndex = /* @__PURE__ */ new Map();
83294
+ /**
83295
+ * "Account\x1fLeafMailboxName" pairs whose `count of messages` size-guard
83296
+ * probe has previously exceeded BYID_PROBE_TIMEOUT_SECONDS (#270 follow-up,
83297
+ * @j5pu). The 3s `with timeout of` wrapper only stops the SERVER's script
83298
+ * from waiting — Mail.app handles Apple events one at a time and keeps
83299
+ * running the abandoned count to completion regardless, so re-probing the
83300
+ * same mailbox on the next call doesn't just waste its own 3s, it queues
83301
+ * behind whatever is still draining inside Mail.app. Once a mailbox has
83302
+ * demonstrated this, the unscoped scan skips the probe for it entirely —
83303
+ * no `count of messages` call at all — straight to "size unknown,
83304
+ * previously timed out". Keyed on the leaf mailbox name (not the
83305
+ * container-walked path `mailboxPathFragment` builds for display) so
83306
+ * checking it costs nothing extra per mailbox visited. Remembered for the
83307
+ * life of the process: nothing ever evicts an entry, because there is no
83308
+ * signal that an abandoned Apple event has finished, and a mailbox that
83309
+ * stalled once on a store this large has no reason to get faster.
83310
+ */
83311
+ knownStalledMailboxes = /* @__PURE__ */ new Set();
83275
83312
  /** Error from the most recent numeric message read, if it was refused. */
83276
83313
  lastMessageLookupError;
83277
83314
  /** Cap on the id→location index so a long-lived process can't grow unbounded. */
@@ -84463,10 +84500,10 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
84463
84500
  return null;
84464
84501
  }
84465
84502
  if (result.output.startsWith(LOOKUP_ERROR_MARKER)) {
84466
- this.lastMessageLookupError = describeUnscopedMiss(
84467
- id,
84468
- result.output.slice(LOOKUP_ERROR_MARKER.length)
84469
- );
84503
+ const rawTail = result.output.slice(LOOKUP_ERROR_MARKER.length);
84504
+ for (const key of extractFreshlyStalledMailboxes(rawTail))
84505
+ this.knownStalledMailboxes.add(key);
84506
+ this.lastMessageLookupError = describeUnscopedMiss(id, rawTail);
84470
84507
  return null;
84471
84508
  }
84472
84509
  return result.output;
@@ -84537,22 +84574,42 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
84537
84574
  */
84538
84575
  unscopedByIdScript(id, innerAction, opts = {}) {
84539
84576
  const threshold = getByIdScanThreshold();
84540
- const sizeGuard = (mbVar, acctNameExpr) => threshold > 0 ? `set _mbCount to -1
84577
+ const stalledCheck = (mbVar, acctNameExpr) => {
84578
+ if (this.knownStalledMailboxes.size === 0) return void 0;
84579
+ const clauses = Array.from(this.knownStalledMailboxes).map((key) => {
84580
+ const [acct = "", leaf = ""] = key.split("");
84581
+ return `(${acctNameExpr} is "${escapeForAppleScript(acct)}" and (name of ${mbVar}) is "${escapeForAppleScript(leaf)}")`;
84582
+ });
84583
+ return clauses.join(" or ");
84584
+ };
84585
+ const sizeGuard = (mbVar, acctNameExpr) => {
84586
+ if (threshold <= 0) return "";
84587
+ const stalled = stalledCheck(mbVar, acctNameExpr);
84588
+ const skipEntry = (sizeLabelExpr) => `
84589
+ set _skipPath to ""
84590
+ try
84591
+ ${mailboxPathFragment(mbVar, "_skipPath")}
84592
+ end try
84593
+ set _skipped to _skipped & ${acctNameExpr} & " / " & _skipPath & " (" & ${sizeLabelExpr} & ")${DIAG_ITEM_SEP}"
84594
+ set _probe to false`;
84595
+ const probeBlock = `set _mbCount to -1
84541
84596
  try
84542
84597
  with timeout of ${BYID_PROBE_TIMEOUT_SECONDS} seconds
84543
84598
  set _mbCount to count of messages of ${mbVar}
84544
84599
  end timeout
84545
84600
  end try
84546
84601
  if _mbCount < 0 or _mbCount > ${threshold} then
84547
- set _skipPath to ""
84548
- try
84549
- ${mailboxPathFragment(mbVar, "_skipPath")}
84550
- end try
84551
84602
  set _sizeLabel to "size unknown (count probe exceeded ${BYID_PROBE_TIMEOUT_SECONDS}s)"
84552
84603
  if _mbCount > -1 then set _sizeLabel to (_mbCount as string)
84553
- set _skipped to _skipped & ${acctNameExpr} & " / " & _skipPath & " (" & _sizeLabel & ")${DIAG_ITEM_SEP}"
84554
- set _probe to false
84555
- end if` : "";
84604
+ ${skipEntry("_sizeLabel")}
84605
+ end if`;
84606
+ if (!stalled) return probeBlock;
84607
+ return `if ${stalled} then
84608
+ ${skipEntry('"size unknown (previously timed out)"')}
84609
+ else
84610
+ ${probeBlock}
84611
+ end if`;
84612
+ };
84556
84613
  const budgetCheck = `if ((current date) - _startedAt) > ${BYID_SCAN_BUDGET_SECONDS} then
84557
84614
  set _budgetHit to true
84558
84615
  exit repeat
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.20.6",
3
+ "version": "2.20.7",
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",