apple-mail-mcp 2.11.1 → 2.11.2

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 +68 -30
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -80955,20 +80955,15 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
80955
80955
  replyToMessage(id, body, replyAll = false, send = true) {
80956
80956
  const safeBody = escapeForAppleScriptBody(body);
80957
80957
  const replyAllClause = replyAll ? " with reply to all" : "";
80958
- const sendAction = send ? "send theReply" : "";
80958
+ const finalAction = send ? "send theReply" : "save theReply";
80959
80959
  const script = this.findMessageScript(
80960
80960
  id,
80961
80961
  `
80962
80962
  set theReply to reply msg without opening window${replyAllClause}
80963
80963
  set content of theReply to "${safeBody}"
80964
- ${sendAction}`
80964
+ ${finalAction}`
80965
80965
  );
80966
- const result = executeAppleScript(script, { timeoutMs: 6e4 });
80967
- if (!result.success || result.output.startsWith("error:")) {
80968
- console.error(`Failed to reply to message: ${result.error || result.output}`);
80969
- return false;
80970
- }
80971
- return true;
80966
+ return this.runComposeScript(script, "reply to");
80972
80967
  }
80973
80968
  /**
80974
80969
  * Forward a message.
@@ -80981,7 +80976,7 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
80981
80976
  */
80982
80977
  forwardMessage(id, to, body, send = true) {
80983
80978
  const safeBody = body ? escapeForAppleScriptBody(body) : "";
80984
- const sendAction = send ? "send theForward" : "";
80979
+ const finalAction = send ? "send theForward" : "save theForward";
80985
80980
  let recipientCommands = "";
80986
80981
  for (const addr of to) {
80987
80982
  recipientCommands += `make new to recipient at end of to recipients of theForward with properties {address:"${escapeForAppleScript(addr)}"}
@@ -80993,14 +80988,9 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
80993
80988
  set theForward to forward msg without opening window
80994
80989
  ${recipientCommands}
80995
80990
  ${safeBody ? `set content of theForward to "${safeBody}"` : ""}
80996
- ${sendAction}`
80991
+ ${finalAction}`
80997
80992
  );
80998
- const result = executeAppleScript(script, { timeoutMs: 6e4 });
80999
- if (!result.success || result.output.startsWith("error:")) {
81000
- console.error(`Failed to forward message: ${result.error || result.output}`);
81001
- return false;
81002
- }
81003
- return true;
80993
+ return this.runComposeScript(script, "forward");
81004
80994
  }
81005
80995
  /**
81006
80996
  * Helper to find and operate on a message by ID, scoped to the mailbox the id
@@ -81025,6 +81015,25 @@ ${indent}end try${this.sanitizeFragment("_uacct", indent)}${this.sanitizeFragmen
81025
81015
  * it immediately, so this is also where the previous operation's forensic
81026
81016
  * report is invalidated — see `beginMutation()`.
81027
81017
  */
81018
+ /**
81019
+ * Run a reply/forward compose script and surface Mail's OWN error text.
81020
+ *
81021
+ * These used to return a bare boolean and log the reason to stderr, so the
81022
+ * tool layer could only say "Failed to reply to message X". That hid the two
81023
+ * failures a caller can actually act on — an id present in several mailboxes
81024
+ * (which names the candidates and tells you to re-list) and a missing id —
81025
+ * behind one indistinguishable message.
81026
+ */
81027
+ runComposeScript(script, verb) {
81028
+ const result = executeAppleScript(script, { timeoutMs: 6e4 });
81029
+ if (!result.success || result.output.startsWith("error:")) {
81030
+ const raw = result.error || result.output;
81031
+ const error2 = raw.startsWith("error:") ? raw.slice("error:".length) : raw;
81032
+ console.error(`Failed to ${verb} message: ${error2}`);
81033
+ return { success: false, error: error2 };
81034
+ }
81035
+ return { success: true };
81036
+ }
81028
81037
  findMessageScript(id, operation, instrument = false) {
81029
81038
  this.beginMutation();
81030
81039
  const loc = this.locationFor(id);
@@ -85940,6 +85949,23 @@ function resolveSmtpOrFallback() {
85940
85949
  return null;
85941
85950
  }
85942
85951
  }
85952
+ async function toNumericMailId(id) {
85953
+ const ref = decodeImapId(id);
85954
+ if (!ref) return { numericId: id };
85955
+ const messageId = await imapFetchMessageId(id);
85956
+ if (!messageId) {
85957
+ return {
85958
+ error: `could not read the RFC Message-ID for "${id}" over IMAP, which is what maps it to a Mail.app id. Pass the numeric id instead (see the resolve-message-id tool).`
85959
+ };
85960
+ }
85961
+ const numericId = mailManager.findNumericIdByMessageId(messageId, ref.account);
85962
+ if (!numericId) {
85963
+ return {
85964
+ error: `Mail.app has no message with Message-ID <${messageId}> in account "${ref.account}", so this IMAP message has no numeric id to reply to or forward. It may not have synced to Mail.app yet.`
85965
+ };
85966
+ }
85967
+ return { numericId };
85968
+ }
85943
85969
  async function sendReplyViaSmtp(id, body, replyAll) {
85944
85970
  const cfg = resolveSmtpOrFallback();
85945
85971
  if (!cfg) return { sent: false, fallback: true };
@@ -85998,17 +86024,23 @@ registerTool(
85998
86024
  },
85999
86025
  withErrorHandling(async ({ id, body, replyAll, send }) => {
86000
86026
  if (send && isSmtpConfigured()) {
86001
- const outcome = await sendReplyViaSmtp(id, body, replyAll);
86002
- if (outcome.sent) {
86027
+ const outcome2 = await sendReplyViaSmtp(id, body, replyAll);
86028
+ if (outcome2.sent) {
86003
86029
  return successResponse("Reply sent", { ok: true, sent: true, id });
86004
86030
  }
86005
- if (!outcome.fallback) {
86006
- return errorResponse(`Failed to reply to message "${id}" via SMTP: ${outcome.error}`);
86031
+ if (!outcome2.fallback) {
86032
+ return errorResponse(`Failed to reply to message "${id}" via SMTP: ${outcome2.error}`);
86007
86033
  }
86008
86034
  }
86009
- const success = mailManager.replyToMessage(id, body, replyAll, send);
86010
- if (!success) {
86011
- return errorResponse(`Failed to reply to message "${id}"`);
86035
+ const resolvedReply = await toNumericMailId(id);
86036
+ if (!resolvedReply.numericId) {
86037
+ return errorResponse(`Failed to reply to message "${id}": ${resolvedReply.error}`);
86038
+ }
86039
+ const outcome = mailManager.replyToMessage(resolvedReply.numericId, body, replyAll, send);
86040
+ if (!outcome.success) {
86041
+ return errorResponse(
86042
+ outcome.error ? `Failed to reply to message "${id}": ${outcome.error}` : `Failed to reply to message "${id}"`
86043
+ );
86012
86044
  }
86013
86045
  return successResponse(send ? "Reply sent" : "Reply saved as draft", {
86014
86046
  ok: true,
@@ -86036,8 +86068,8 @@ registerTool(
86036
86068
  },
86037
86069
  withErrorHandling(async ({ id, to, body, send }) => {
86038
86070
  if (send && isSmtpConfigured()) {
86039
- const outcome = await sendForwardViaSmtp(id, to, body);
86040
- if (outcome.sent) {
86071
+ const outcome2 = await sendForwardViaSmtp(id, to, body);
86072
+ if (outcome2.sent) {
86041
86073
  return successResponse(`Message forwarded to ${to.join(", ")}`, {
86042
86074
  ok: true,
86043
86075
  sent: true,
@@ -86045,13 +86077,19 @@ registerTool(
86045
86077
  id
86046
86078
  });
86047
86079
  }
86048
- if (!outcome.fallback) {
86049
- return errorResponse(`Failed to forward message "${id}" via SMTP: ${outcome.error}`);
86080
+ if (!outcome2.fallback) {
86081
+ return errorResponse(`Failed to forward message "${id}" via SMTP: ${outcome2.error}`);
86050
86082
  }
86051
86083
  }
86052
- const success = mailManager.forwardMessage(id, to, body, send);
86053
- if (!success) {
86054
- return errorResponse(`Failed to forward message "${id}"`);
86084
+ const resolvedFwd = await toNumericMailId(id);
86085
+ if (!resolvedFwd.numericId) {
86086
+ return errorResponse(`Failed to forward message "${id}": ${resolvedFwd.error}`);
86087
+ }
86088
+ const outcome = mailManager.forwardMessage(resolvedFwd.numericId, to, body, send);
86089
+ if (!outcome.success) {
86090
+ return errorResponse(
86091
+ outcome.error ? `Failed to forward message "${id}": ${outcome.error}` : `Failed to forward message "${id}"`
86092
+ );
86055
86093
  }
86056
86094
  return successResponse(
86057
86095
  send ? `Message forwarded to ${to.join(", ")}` : "Forward saved as draft",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apple-mail-mcp",
3
- "version": "2.11.1",
3
+ "version": "2.11.2",
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",