@agenticmail/mcp 0.9.1 → 0.9.4

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/dist/index.js +22 -12
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -22627,11 +22627,11 @@ async function apiRequest(method, path, body, useMasterKey = false, timeoutMs =
22627
22627
  var toolDefinitions = [
22628
22628
  {
22629
22629
  name: "send_email",
22630
- description: 'Send an email from the agent\'s mailbox. Supports multiple recipients on To and CC (comma-separated). The PRIMARY primitive for multi-agent coordination. WAKE SEMANTICS (changed in 0.9.0): by default only local @localhost recipients on `To:` get a Claude wake; CC\'d local agents receive the mail but don\'t wake \u2014 they see it on their next natural wake (replies addressed to them, or a future inbox check). This mirrors the email convention "To is for action, CC is for awareness" and prevents wake-thrash on multi-CC threads. To override: pass `wake: ["alice","bob"]` to wake specific agents regardless of To/CC position, or `wake: "all"` to opt back into the pre-0.9.0 "wake every CC\'d recipient" behaviour. Pass `wake: []` to deliver silently with no wakes at all. External emails are scanned for sensitive content; HIGH severity detections are BLOCKED for owner approval.',
22630
+ description: 'Send an email from the agent\'s mailbox. The PRIMARY primitive for multi-agent coordination. **Use `to` and `cc` as the email standard intends** \u2014 `to` is the actor(s) the message is addressed to (one or two recipients in most cases); `cc` is everyone else on the thread for awareness. Lumping every participant on `to` is wrong and defeats the wake gating. WAKE SEMANTICS (0.9.0+): by default only local @localhost recipients on `to:` get a Claude wake; CC\'d local agents receive the mail but don\'t wake \u2014 they see it on their next natural wake. To override: pass `wake: ["alice","bob"]` for specific agents regardless of To/CC, or `wake: "all"` for the pre-0.9.0 "wake every recipient" behaviour, or `wake: []` to deliver silently. External emails are scanned for sensitive content; HIGH severity detections are BLOCKED for owner approval.',
22631
22631
  inputSchema: {
22632
22632
  type: "object",
22633
22633
  properties: {
22634
- to: { type: "string", description: "Recipient email address(es). For multi-agent threads, put the primary actor here and CC the rest. Comma-separated supported." },
22634
+ to: { type: "string", description: "Primary actor \u2014 the agent(s) you want to act on this message. Usually one address; rarely two. **Everyone else on the thread goes on `cc`, NOT here.** Lumping all participants on `to` defeats the wake gating: every local @localhost recipient on `to` gets a Claude turn, so a 5-agent thread = 5 Claude turns per round. Comma-separated supported but use sparingly." },
22635
22635
  subject: { type: "string", description: "Email subject line" },
22636
22636
  text: { type: "string", description: "Plain text body" },
22637
22637
  html: { type: "string", description: "HTML body (optional)" },
@@ -22726,7 +22726,7 @@ var toolDefinitions = [
22726
22726
  },
22727
22727
  {
22728
22728
  name: "reply_email",
22729
- description: "Reply to an email. Fetches the original message, auto-fills To, Subject (Re:), In-Reply-To, and References, then sends with quoted body. **For multi-agent thread coordination, pass `replyAll: true`** so every CC'd participant sees your contribution and stays in context \u2014 that is how the thread-as-workspace pattern works. **Pass `wake` to name only the next actor(s)** so the dispatcher gives a Claude turn only to them; everyone else still receives the mail but stays asleep. Outbound guard applies \u2014 HIGH severity content is held for review.",
22729
+ description: "Reply to an email. Fetches the original message, auto-fills To, Subject (Re:), In-Reply-To, and References, then sends with quoted body. **For multi-agent thread coordination, pass `replyAll: true`** \u2014 the original sender lands on To: (so they wake, by default), every other thread participant lands on Cc: (so they see it without waking). This is the correct shape; the tool builds it for you. **Pass `wake` to override** the default wake target (e.g. you want to wake a specific CC'd participant). Outbound guard applies \u2014 HIGH severity content is held for review.",
22730
22730
  inputSchema: {
22731
22731
  type: "object",
22732
22732
  properties: {
@@ -23785,9 +23785,13 @@ Connected account (${result.relayResults[0].account}): ${result.relayResults.len
23785
23785
  On ${original.date}, ${replyTo} wrote:
23786
23786
  ${quotedBody}`;
23787
23787
  let to = replyTo;
23788
+ let cc;
23788
23789
  if (args2.replyAll) {
23789
- const allTo = [...original.to || [], ...original.cc || []].map((a) => a.address).filter(Boolean);
23790
- to = [replyTo, ...allTo].filter((v, i, a) => v && a.indexOf(v) === i).join(", ");
23790
+ const norm = (a) => (typeof a === "string" ? a : a?.address ?? "").trim().toLowerCase();
23791
+ const replyToLower = norm(replyTo);
23792
+ const others = [...original.to || [], ...original.cc || []].map((a) => a?.address).filter((v) => !!v).filter((v) => norm(v) !== replyToLower).filter((v, i, a) => a.findIndex((x) => norm(x) === norm(v)) === i);
23793
+ to = replyTo;
23794
+ cc = others.length > 0 ? others.join(", ") : void 0;
23791
23795
  }
23792
23796
  const replySendBody = {
23793
23797
  to,
@@ -23795,7 +23799,8 @@ ${quotedBody}`;
23795
23799
  text: fullText,
23796
23800
  html: args2.html,
23797
23801
  inReplyTo: original.messageId,
23798
- references: refs
23802
+ references: refs,
23803
+ ...cc !== void 0 ? { cc } : {}
23799
23804
  };
23800
23805
  if (args2.wake !== void 0) {
23801
23806
  replySendBody.wake = args2.wake;
@@ -24019,7 +24024,7 @@ ${lines.join("\n")}`;
24019
24024
  if (action === "untag_message") {
24020
24025
  if (!args2.id || !args2.uid) throw new Error("id and uid are required");
24021
24026
  const folder = args2.folder || "INBOX";
24022
- await apiRequest("DELETE", `/tags/${args2.id}/messages/${args2.uid}?folder=${encodeURIComponent(folder)}`);
24027
+ await apiRequest("DELETE", `/tags/${args2.id}/messages/${args2.uid}?folder=${encodeURIComponent(String(folder))}`);
24023
24028
  return `Removed tag from message UID ${args2.uid} in ${folder}`;
24024
24029
  }
24025
24030
  if (action === "get_messages") {
@@ -24038,10 +24043,14 @@ ${r.messages.map((m) => ` UID ${m.uid} (${m.folder})`).join("\n")}`;
24038
24043
  throw new Error("Invalid action");
24039
24044
  }
24040
24045
  case "create_account": {
24046
+ const hostTag = process.env.AGENTICMAIL_MCP_HOST?.trim();
24047
+ const userMetadata = args2.metadata && typeof args2.metadata === "object" && !Array.isArray(args2.metadata) ? args2.metadata : void 0;
24048
+ const metadata = hostTag ? { ...userMetadata ?? {}, host: hostTag } : userMetadata;
24041
24049
  const result = await apiRequest("POST", "/accounts", {
24042
24050
  name: args2.name,
24043
24051
  domain: args2.domain,
24044
- role: args2.role
24052
+ role: args2.role,
24053
+ ...metadata ? { metadata } : {}
24045
24054
  }, useMaster);
24046
24055
  if (!result) throw new Error("No response from account creation");
24047
24056
  return [
@@ -24050,8 +24059,9 @@ ${r.messages.map((m) => ` UID ${m.uid} (${m.folder})`).join("\n")}`;
24050
24059
  ` Email: ${result.email}`,
24051
24060
  ` Role: ${result.role}`,
24052
24061
  ` API Key: ${result.apiKey}`,
24053
- ` ID: ${result.id}`
24054
- ].join("\n");
24062
+ ` ID: ${result.id}`,
24063
+ hostTag ? ` Host: ${hostTag} (this account is owned by the ${hostTag} dispatcher)` : ""
24064
+ ].filter(Boolean).join("\n");
24055
24065
  }
24056
24066
  case "setup_email_relay": {
24057
24067
  const result = await apiRequest("POST", "/gateway/relay", {
@@ -24699,7 +24709,7 @@ ${r.tail.join("\n")}`;
24699
24709
  case "check_tasks": {
24700
24710
  let endpoint = args2.direction === "outgoing" ? "/tasks/assigned" : "/tasks/pending";
24701
24711
  if (args2.direction !== "outgoing" && args2.assignee) {
24702
- endpoint += `?assignee=${encodeURIComponent(args2.assignee)}`;
24712
+ endpoint += `?assignee=${encodeURIComponent(String(args2.assignee))}`;
24703
24713
  }
24704
24714
  const r = await apiRequest("GET", endpoint);
24705
24715
  if (!r?.tasks?.length) return args2.direction === "outgoing" ? "No tasks assigned by you." : "No pending tasks.";
@@ -24770,7 +24780,7 @@ ${lines.join("\n")}`;
24770
24780
  const uid = Number(args2.uid);
24771
24781
  if (!uid || uid < 1) throw new Error("uid is required");
24772
24782
  const folder = args2.folder || "INBOX";
24773
- const result = await apiRequest("GET", `/mail/messages/${uid}/spam-score?folder=${encodeURIComponent(folder)}`);
24783
+ const result = await apiRequest("GET", `/mail/messages/${uid}/spam-score?folder=${encodeURIComponent(String(folder))}`);
24774
24784
  const lines = [
24775
24785
  `Spam Score: ${result.score}/100 (${result.isSpam ? "SPAM" : result.isWarning ? "WARNING" : "CLEAN"})`,
24776
24786
  result.topCategory ? `Top Category: ${result.topCategory}` : null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/mcp",
3
- "version": "0.9.1",
3
+ "version": "0.9.4",
4
4
  "mcpName": "io.github.agenticmail/mcp",
5
5
  "description": "MCP server for AgenticMail — give any AI client real email and SMS capabilities",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/sdk": "^1.12.0",
32
32
  "zod": "^3.24.0",
33
- "@agenticmail/core": "^0.9.1"
33
+ "@agenticmail/core": "^0.9.3"
34
34
  },
35
35
  "devDependencies": {
36
36
  "tsup": "^8.4.0",