apple-mail-mcp 1.6.5 → 1.6.6

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.
@@ -335,35 +335,48 @@ export declare class AppleMailManager {
335
335
  private moveMessageInternal;
336
336
  moveMessage(id: string, mailbox: string, account?: string): boolean;
337
337
  /**
338
- * Delete multiple messages at once.
338
+ * Run one operation over many message IDs in a SINGLE osascript invocation.
339
339
  *
340
- * @param ids - Array of message IDs to delete
341
- * @returns Array of results for each message
340
+ * Previously each batch method looped and called the per-id method, so a
341
+ * 100-id batch spawned 100 osascript processes — each one re-resolving
342
+ * accounts and walking the whole account→mailbox tree — all serialized
343
+ * through the gate (issue #31). This walks the tree exactly once: for each
344
+ * mailbox it probes the still-pending IDs with `whose id is` (indexed, so
345
+ * effectively free) and applies `operation` to any match, tracking found IDs
346
+ * so it can stop early once all are accounted for. Per-id outcomes come back
347
+ * as control-char-delimited `id<FS>status` records (status: `ok`,
348
+ * `notfound`, or `error:<msg>`), and results are returned in input order.
349
+ *
350
+ * `setup` runs once before the walk (used by move to resolve the destination);
351
+ * it may bail the whole batch by returning a `BATCH_FATAL`-prefixed string.
352
+ */
353
+ private runBatchOperation;
354
+ /**
355
+ * Delete multiple messages at once (single tree walk — see runBatchOperation).
342
356
  */
343
357
  batchDeleteMessages(ids: string[]): BatchOperationResult[];
344
358
  /**
345
- * Move multiple messages to a mailbox at once.
359
+ * Move multiple messages to a mailbox at once (single tree walk).
346
360
  *
347
- * @param ids - Array of message IDs to move
348
- * @param mailbox - Destination mailbox name
349
- * @param account - Account containing the destination mailbox
350
- * @returns Array of results for each message
361
+ * The destination is resolved once (account-scoped, ambiguity-aware a name
362
+ * matching more than one mailbox fails the whole batch rather than guessing),
363
+ * then every matched message is moved in the same walk.
351
364
  */
352
365
  batchMoveMessages(ids: string[], mailbox: string, account?: string): BatchOperationResult[];
353
366
  /**
354
- * Mark multiple messages as read at once.
367
+ * Mark multiple messages as read at once (single tree walk).
355
368
  */
356
369
  batchMarkAsRead(ids: string[]): BatchOperationResult[];
357
370
  /**
358
- * Mark multiple messages as unread at once.
371
+ * Mark multiple messages as unread at once (single tree walk).
359
372
  */
360
373
  batchMarkAsUnread(ids: string[]): BatchOperationResult[];
361
374
  /**
362
- * Flag multiple messages at once.
375
+ * Flag multiple messages at once (single tree walk).
363
376
  */
364
377
  batchFlagMessages(ids: string[]): BatchOperationResult[];
365
378
  /**
366
- * Unflag multiple messages at once.
379
+ * Unflag multiple messages at once (single tree walk).
367
380
  */
368
381
  batchUnflagMessages(ids: string[]): BatchOperationResult[];
369
382
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"appleMailManager.d.ts","sourceRoot":"","sources":["../../src/services/appleMailManager.ts"],"names":[],"mappings":"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"}
@@ -70,6 +70,7 @@ const DIAG_FIELD_SEP = "\x1dF\x1d"; // between diagnostics fields
70
70
  const DIAG_ITEM_SEP = "\x1dM\x1d"; // between diagnostics list items
71
71
  const CONTENT_MARKER = "\x1dCONTENT\x1d"; // subject/plain-text boundary
72
72
  const HTML_MARKER = "\x1dHTML\x1d"; // plain-text/source boundary
73
+ const BATCH_FATAL = "\x1dFATAL\x1d"; // prefix for a whole-batch failure (e.g. bad destination)
73
74
  /**
74
75
  * Merge a per-account SearchDiagnostics into an aggregate (all-accounts) one.
75
76
  *
@@ -1466,90 +1467,174 @@ export class AppleMailManager {
1466
1467
  // Batch Operations
1467
1468
  // ===========================================================================
1468
1469
  /**
1469
- * Delete multiple messages at once.
1470
+ * Run one operation over many message IDs in a SINGLE osascript invocation.
1470
1471
  *
1471
- * @param ids - Array of message IDs to delete
1472
- * @returns Array of results for each message
1472
+ * Previously each batch method looped and called the per-id method, so a
1473
+ * 100-id batch spawned 100 osascript processes — each one re-resolving
1474
+ * accounts and walking the whole account→mailbox tree — all serialized
1475
+ * through the gate (issue #31). This walks the tree exactly once: for each
1476
+ * mailbox it probes the still-pending IDs with `whose id is` (indexed, so
1477
+ * effectively free) and applies `operation` to any match, tracking found IDs
1478
+ * so it can stop early once all are accounted for. Per-id outcomes come back
1479
+ * as control-char-delimited `id<FS>status` records (status: `ok`,
1480
+ * `notfound`, or `error:<msg>`), and results are returned in input order.
1481
+ *
1482
+ * `setup` runs once before the walk (used by move to resolve the destination);
1483
+ * it may bail the whole batch by returning a `BATCH_FATAL`-prefixed string.
1473
1484
  */
1474
- batchDeleteMessages(ids) {
1475
- const results = [];
1485
+ runBatchOperation(ids, operation, setup = "") {
1486
+ // Keep the numeric IDs paired with their original string form and 1-based
1487
+ // position. The AppleScript reports outcomes by POSITION, not by id: a Mail
1488
+ // id large enough to exceed AppleScript's 2^29 integer range coerces to
1489
+ // scientific notation under `as string` (999999999 -> "9.99999999E+8"), so
1490
+ // echoing the id back can't be matched to the input. Positions are always
1491
+ // small integers, so they round-trip cleanly.
1492
+ const valid = [];
1476
1493
  for (const id of ids) {
1477
- const success = this.deleteMessage(id);
1478
- results.push({
1479
- id,
1480
- success,
1481
- error: success ? undefined : "Failed to delete message",
1482
- });
1494
+ const num = Number(id);
1495
+ if (Number.isFinite(num))
1496
+ valid.push({ id, num });
1483
1497
  }
1484
- return results;
1498
+ if (valid.length === 0) {
1499
+ return ids.map((id) => ({ id, success: false, error: "Invalid message ID" }));
1500
+ }
1501
+ const script = buildAppLevelScript(`
1502
+ try
1503
+ ${setup}
1504
+ set _out to ""
1505
+ set _done to {}
1506
+ set _ids to {${valid.map((v) => v.num).join(", ")}}
1507
+ set _total to count of _ids
1508
+ repeat with acct in accounts
1509
+ if (count of _done) is _total then exit repeat
1510
+ repeat with mb in (mailboxes of acct)
1511
+ if (count of _done) is _total then exit repeat
1512
+ repeat with _idx from 1 to _total
1513
+ if _idx is not in _done then
1514
+ set _theId to item _idx of _ids
1515
+ try
1516
+ set _m to (messages of mb whose id is _theId)
1517
+ if (count of _m) > 0 then
1518
+ set _msg to item 1 of _m
1519
+ ${operation}
1520
+ set end of _done to _idx
1521
+ set _out to _out & (_idx as string) & "${FIELD_SEP}ok${RECORD_SEP}"
1522
+ end if
1523
+ on error _e
1524
+ set end of _done to _idx
1525
+ set _out to _out & (_idx as string) & "${FIELD_SEP}error:" & _e & "${RECORD_SEP}"
1526
+ end try
1527
+ end if
1528
+ end repeat
1529
+ end repeat
1530
+ end repeat
1531
+ repeat with _idx from 1 to _total
1532
+ if _idx is not in _done then set _out to _out & (_idx as string) & "${FIELD_SEP}notfound${RECORD_SEP}"
1533
+ end repeat
1534
+ return _out
1535
+ on error errMsg
1536
+ return "${BATCH_FATAL}" & errMsg
1537
+ end try
1538
+ `);
1539
+ // Generous timeout: one walk over the tree with indexed id probes. Scale a
1540
+ // little with batch size, capped.
1541
+ const timeoutMs = Math.min(180000, 60000 + valid.length * 500);
1542
+ const result = executeAppleScript(script, { timeoutMs });
1543
+ if (!result.success) {
1544
+ const err = result.error || "Batch operation failed";
1545
+ return ids.map((id) => ({ id, success: false, error: err }));
1546
+ }
1547
+ if (result.output.startsWith(BATCH_FATAL)) {
1548
+ const err = result.output.slice(BATCH_FATAL.length);
1549
+ return ids.map((id) => ({ id, success: false, error: err }));
1550
+ }
1551
+ // Map by-position outcomes back to the original id strings.
1552
+ const byId = new Map();
1553
+ for (const rec of result.output.split(RECORD_SEP)) {
1554
+ if (!rec)
1555
+ continue;
1556
+ const sep = rec.indexOf(FIELD_SEP);
1557
+ if (sep < 0)
1558
+ continue;
1559
+ const pos = Number(rec.slice(0, sep));
1560
+ const status = rec.slice(sep + FIELD_SEP.length);
1561
+ const entry = valid[pos - 1];
1562
+ if (!entry)
1563
+ continue;
1564
+ const id = entry.id;
1565
+ if (status === "ok") {
1566
+ byId.set(id, { id, success: true });
1567
+ }
1568
+ else if (status === "notfound") {
1569
+ byId.set(id, { id, success: false, error: "Message not found" });
1570
+ }
1571
+ else if (status.startsWith("error:")) {
1572
+ byId.set(id, { id, success: false, error: status.slice("error:".length) });
1573
+ }
1574
+ else {
1575
+ byId.set(id, { id, success: false, error: status || "Unknown error" });
1576
+ }
1577
+ }
1578
+ return ids.map((id) => byId.get(id) ??
1579
+ (Number.isFinite(Number(id))
1580
+ ? { id, success: false, error: "No result returned" }
1581
+ : { id, success: false, error: "Invalid message ID" }));
1485
1582
  }
1486
1583
  /**
1487
- * Move multiple messages to a mailbox at once.
1584
+ * Delete multiple messages at once (single tree walk — see runBatchOperation).
1585
+ */
1586
+ batchDeleteMessages(ids) {
1587
+ return this.runBatchOperation(ids, "delete _msg");
1588
+ }
1589
+ /**
1590
+ * Move multiple messages to a mailbox at once (single tree walk).
1488
1591
  *
1489
- * @param ids - Array of message IDs to move
1490
- * @param mailbox - Destination mailbox name
1491
- * @param account - Account containing the destination mailbox
1492
- * @returns Array of results for each message
1592
+ * The destination is resolved once (account-scoped, ambiguity-aware a name
1593
+ * matching more than one mailbox fails the whole batch rather than guessing),
1594
+ * then every matched message is moved in the same walk.
1493
1595
  */
1494
1596
  batchMoveMessages(ids, mailbox, account) {
1495
- const results = [];
1496
- for (const id of ids) {
1497
- const { success, error } = this.moveMessageInternal(id, mailbox, account);
1498
- results.push({
1499
- id,
1500
- success,
1501
- error: success ? undefined : error || "Failed to move message",
1502
- });
1503
- }
1504
- return results;
1597
+ const targetAccount = this.resolveAccount(account);
1598
+ const targetMailbox = this.resolveMailbox(mailbox, targetAccount);
1599
+ const safeMailbox = escapeForAppleScript(targetMailbox);
1600
+ const safeAccount = escapeForAppleScript(targetAccount);
1601
+ // Resolved once, before the walk. `mailboxes of account` is already flat
1602
+ // (includes nested mailboxes by path), so we match by exact name and use the
1603
+ // reference directly. A bad/ambiguous destination fails the whole batch.
1604
+ const setup = `
1605
+ set destName to "${safeMailbox}"
1606
+ set destMatches to {}
1607
+ repeat with _dmb in (mailboxes of account "${safeAccount}")
1608
+ if (name of _dmb) is destName then set end of destMatches to _dmb
1609
+ end repeat
1610
+ if (count of destMatches) is 0 then return "${BATCH_FATAL}Destination mailbox \\"" & destName & "\\" not found in account \\"${safeAccount}\\""
1611
+ if (count of destMatches) > 1 then return "${BATCH_FATAL}Destination mailbox \\"" & destName & "\\" is ambiguous (" & (count of destMatches) & " matches) in account \\"${safeAccount}\\"; move by full path"
1612
+ set destMailbox to item 1 of destMatches`;
1613
+ return this.runBatchOperation(ids, "move _msg to destMailbox", setup);
1505
1614
  }
1506
1615
  /**
1507
- * Mark multiple messages as read at once.
1616
+ * Mark multiple messages as read at once (single tree walk).
1508
1617
  */
1509
1618
  batchMarkAsRead(ids) {
1510
- const results = [];
1511
- for (const id of ids) {
1512
- const success = this.markAsRead(id);
1513
- results.push({ id, success, error: success ? undefined : "Failed to mark message as read" });
1514
- }
1515
- return results;
1619
+ return this.runBatchOperation(ids, "set read status of _msg to true");
1516
1620
  }
1517
1621
  /**
1518
- * Mark multiple messages as unread at once.
1622
+ * Mark multiple messages as unread at once (single tree walk).
1519
1623
  */
1520
1624
  batchMarkAsUnread(ids) {
1521
- const results = [];
1522
- for (const id of ids) {
1523
- const success = this.markAsUnread(id);
1524
- results.push({
1525
- id,
1526
- success,
1527
- error: success ? undefined : "Failed to mark message as unread",
1528
- });
1529
- }
1530
- return results;
1625
+ return this.runBatchOperation(ids, "set read status of _msg to false");
1531
1626
  }
1532
1627
  /**
1533
- * Flag multiple messages at once.
1628
+ * Flag multiple messages at once (single tree walk).
1534
1629
  */
1535
1630
  batchFlagMessages(ids) {
1536
- const results = [];
1537
- for (const id of ids) {
1538
- const success = this.flagMessage(id);
1539
- results.push({ id, success, error: success ? undefined : "Failed to flag message" });
1540
- }
1541
- return results;
1631
+ return this.runBatchOperation(ids, "set flagged status of _msg to true");
1542
1632
  }
1543
1633
  /**
1544
- * Unflag multiple messages at once.
1634
+ * Unflag multiple messages at once (single tree walk).
1545
1635
  */
1546
1636
  batchUnflagMessages(ids) {
1547
- const results = [];
1548
- for (const id of ids) {
1549
- const success = this.unflagMessage(id);
1550
- results.push({ id, success, error: success ? undefined : "Failed to unflag message" });
1551
- }
1552
- return results;
1637
+ return this.runBatchOperation(ids, "set flagged status of _msg to false");
1553
1638
  }
1554
1639
  /**
1555
1640
  * List attachments for a message.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "1.6.5",
3
+ "version": "1.6.6",
4
4
  "description": "MCP server for Apple Mail - read, search, send, and manage emails via Claude",
5
5
  "type": "module",
6
6
  "main": "build/index.js",