@agenticmail/mcp 0.7.4 → 0.7.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/dist/index.js +117 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -22395,6 +22395,12 @@ var TOOL_SETS = {
22395
22395
  // back. Essential enough that paying its tokens at every spawn beats
22396
22396
  // making the agent discover it via request_tools.
22397
22397
  "wait_for_email",
22398
+ // check_activity is the dispatcher visibility primitive: see which
22399
+ // agents the dispatcher has woken right now (or in the last 2 min)
22400
+ // and how long they have been running. The host uses it to answer
22401
+ // "did the agent I just emailed actually start working?" without
22402
+ // having to wait for a reply or send an acknowledgment.
22403
+ "check_activity",
22398
22404
  "check_tasks"
22399
22405
  ],
22400
22406
  /** Less-common mail operations. */
@@ -22609,7 +22615,7 @@ async function apiRequest(method, path, body, useMasterKey = false, timeoutMs =
22609
22615
  var toolDefinitions = [
22610
22616
  {
22611
22617
  name: "send_email",
22612
- description: "Send an email from the agent's mailbox. Supports multiple recipients on To and CC (comma-separated). This is the PRIMARY primitive for multi-agent coordination: kick off a thread with all participants on CC, and every local recipient is woken automatically. Each woken agent reads the thread, decides whose turn it is, and either reply-all's to contribute or stays silent. External emails are scanned for sensitive content; HIGH severity detections are BLOCKED for owner approval. You CANNOT bypass the outbound guard.",
22618
+ description: "Send an email from the agent's mailbox. Supports multiple recipients on To and CC (comma-separated). This is the PRIMARY primitive for multi-agent coordination: kick off a thread with all participants on CC, and every local recipient is woken automatically \u2014 UNLESS you set `wake` to limit the wake-up to specific agents. Use `wake` aggressively on large threads: 15 agents on CC \xD7 every reply burns 15 Claude turns per round if every recipient wakes. Naming the single next actor cuts that to one. External emails are scanned for sensitive content; HIGH severity detections are BLOCKED for owner approval. You CANNOT bypass the outbound guard.",
22613
22619
  inputSchema: {
22614
22620
  type: "object",
22615
22621
  properties: {
@@ -22617,7 +22623,12 @@ var toolDefinitions = [
22617
22623
  subject: { type: "string", description: "Email subject line" },
22618
22624
  text: { type: "string", description: "Plain text body" },
22619
22625
  html: { type: "string", description: "HTML body (optional)" },
22620
- cc: { type: "string", description: 'CC recipients \u2014 the team. Comma-separated, e.g. "vesper@localhost, orion@localhost". Every local @localhost recipient is auto-woken when this email lands.' },
22626
+ cc: { type: "string", description: 'CC recipients \u2014 the team. Comma-separated, e.g. "vesper@localhost, orion@localhost". Every local @localhost recipient is auto-woken when this email lands UNLESS you also pass `wake` to restrict.' },
22627
+ wake: {
22628
+ type: "array",
22629
+ items: { type: "string" },
22630
+ description: 'Optional. Names (or @localhost addresses) of the agents the dispatcher should give a Claude turn to when this mail lands. CC\'d agents NOT in this list still receive the email but get no Claude turn \u2014 they will see it the next time someone explicitly wakes them or they check their inbox. Use this to scope cost on large threads: send to 15 agents but wake only the 1 or 2 who need to act next. Pass an empty array `[]` for "deliver silently \u2014 wake nobody". Omit entirely to keep the default "wake everyone CC\'d" behaviour.'
22631
+ },
22621
22632
  inReplyTo: { type: "string", description: "Message-ID to reply to (optional)" },
22622
22633
  references: {
22623
22634
  type: "array",
@@ -22705,27 +22716,37 @@ var toolDefinitions = [
22705
22716
  },
22706
22717
  {
22707
22718
  name: "reply_email",
22708
- 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. Outbound guard applies \u2014 HIGH severity content is held for review.",
22719
+ 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.",
22709
22720
  inputSchema: {
22710
22721
  type: "object",
22711
22722
  properties: {
22712
22723
  uid: { type: "number", description: "UID of the email to reply to" },
22713
22724
  text: { type: "string", description: "Your reply text" },
22714
22725
  html: { type: "string", description: "HTML reply (optional)" },
22715
- replyAll: { type: "boolean", description: "Reply to all recipients (default: false)" }
22726
+ replyAll: { type: "boolean", description: "Reply to all recipients (default: false)" },
22727
+ wake: {
22728
+ type: "array",
22729
+ items: { type: "string" },
22730
+ description: "Optional. Names of the agents who should get a Claude turn from the dispatcher when this reply lands. CC'd agents NOT in this list still receive the email but stay asleep \u2014 saves significant tokens on large threads. Pass `[]` to deliver silently. Omit to wake everyone CC'd."
22731
+ }
22716
22732
  },
22717
22733
  required: ["uid", "text"]
22718
22734
  }
22719
22735
  },
22720
22736
  {
22721
22737
  name: "forward_email",
22722
- description: "Forward an email to another recipient. Outbound guard applies \u2014 HIGH severity content is held for review.",
22738
+ description: "Forward an email to another recipient. Outbound guard applies \u2014 HIGH severity content is held for review. Pass `wake` to limit which local recipients get a Claude turn from the dispatcher when this forward lands.",
22723
22739
  inputSchema: {
22724
22740
  type: "object",
22725
22741
  properties: {
22726
22742
  uid: { type: "number", description: "UID of the email to forward" },
22727
22743
  to: { type: "string", description: "Recipient to forward to" },
22728
- text: { type: "string", description: "Additional message (optional)" }
22744
+ text: { type: "string", description: "Additional message (optional)" },
22745
+ wake: {
22746
+ type: "array",
22747
+ items: { type: "string" },
22748
+ description: "Optional. Names of the agents who should get a Claude turn when the forward lands. Pass `[]` to deliver silently. Omit to wake everyone CC'd."
22749
+ }
22729
22750
  },
22730
22751
  required: ["uid", "to"]
22731
22752
  }
@@ -22826,7 +22847,7 @@ var toolDefinitions = [
22826
22847
  },
22827
22848
  {
22828
22849
  name: "manage_drafts",
22829
- description: "List, create, update, send, or delete drafts",
22850
+ description: "List, create, update, send, or delete drafts. On send, you can pass `wake` to limit which local recipients get a Claude turn \u2014 same semantics as send_email.",
22830
22851
  inputSchema: {
22831
22852
  type: "object",
22832
22853
  properties: {
@@ -22834,7 +22855,12 @@ var toolDefinitions = [
22834
22855
  id: { type: "string", description: "Draft ID (for update/send/delete)" },
22835
22856
  to: { type: "string", description: "Recipient (for create/update)" },
22836
22857
  subject: { type: "string", description: "Subject (for create/update)" },
22837
- text: { type: "string", description: "Body text (for create/update)" }
22858
+ text: { type: "string", description: "Body text (for create/update)" },
22859
+ wake: {
22860
+ type: "array",
22861
+ items: { type: "string" },
22862
+ description: "Optional, for action=send. Names of the agents who should get a Claude turn when the drafted mail lands. Pass `[]` to deliver silently. Omit to wake everyone CC'd."
22863
+ }
22838
22864
  },
22839
22865
  required: ["action"]
22840
22866
  }
@@ -23191,7 +23217,12 @@ var toolDefinitions = [
23191
23217
  to: { type: "string", description: "Recipient email" },
23192
23218
  variables: { type: "object", description: 'Variables to substitute: { name: "Alice" }' },
23193
23219
  cc: { type: "string", description: "CC recipients" },
23194
- bcc: { type: "string", description: "BCC recipients" }
23220
+ bcc: { type: "string", description: "BCC recipients" },
23221
+ wake: {
23222
+ type: "array",
23223
+ items: { type: "string" },
23224
+ description: "Optional. Names of the agents who should get a Claude turn when this template-rendered mail lands. Pass `[]` to deliver silently. Omit to wake everyone CC'd."
23225
+ }
23195
23226
  },
23196
23227
  required: ["id", "to"]
23197
23228
  }
@@ -23227,6 +23258,17 @@ var toolDefinitions = [
23227
23258
  required: ["action"]
23228
23259
  }
23229
23260
  },
23261
+ {
23262
+ name: "check_activity",
23263
+ description: "Check which agents are currently being woken by the dispatcher (right now or in the last 2 minutes). Use this when you sent mail to a teammate and want to know if they have actually started working, or to audit the live multi-agent state. Returns active workers with the agent name, what triggered the wake (mail UID + subject, or task id), how long they have been running, and a preview of the most recent finished work. Requires master key \u2014 the host session has it; subagents normally do not.",
23264
+ inputSchema: {
23265
+ type: "object",
23266
+ properties: {
23267
+ agent: { type: "string", description: "Filter to a specific agent by name (case-insensitive). Omit to see every active and recently-finished worker." },
23268
+ includeRecent: { type: "boolean", description: "Include workers that finished in the last ~2 minutes (default: true). Set false to see only currently-running workers." }
23269
+ }
23270
+ }
23271
+ },
23230
23272
  {
23231
23273
  name: "check_tasks",
23232
23274
  description: "Check for pending tasks assigned to you (or a specific agent) or tasks you assigned to others",
@@ -23568,6 +23610,9 @@ async function dispatchToolCall(name, args2, useMaster) {
23568
23610
  ...a.encoding ? { encoding: a.encoding } : {}
23569
23611
  }));
23570
23612
  }
23613
+ if (args2.wake !== void 0) {
23614
+ sendBody.wake = args2.wake;
23615
+ }
23571
23616
  const result = await apiRequest("POST", "/mail/send", sendBody);
23572
23617
  if (result?.blocked && result?.pendingId) {
23573
23618
  scheduleFollowUp(result.pendingId, String(args2.to), String(args2.subject || "(no subject)"), makePendingCheck(result.pendingId));
@@ -23701,6 +23746,9 @@ ${quotedBody}`;
23701
23746
  inReplyTo: original.messageId,
23702
23747
  references: refs
23703
23748
  };
23749
+ if (args2.wake !== void 0) {
23750
+ replySendBody.wake = args2.wake;
23751
+ }
23704
23752
  const sendResult = await apiRequest("POST", "/mail/send", replySendBody);
23705
23753
  if (sendResult?.blocked && sendResult?.pendingId) {
23706
23754
  scheduleFollowUp(sendResult.pendingId, to, String(replySendBody.subject || "(no subject)"), makePendingCheck(sendResult.pendingId));
@@ -23749,6 +23797,9 @@ ${orig.text || ""}`;
23749
23797
  encoding: "base64"
23750
23798
  }));
23751
23799
  }
23800
+ if (args2.wake !== void 0) {
23801
+ fwdSendBody.wake = args2.wake;
23802
+ }
23752
23803
  const fwdResult = await apiRequest("POST", "/mail/send", fwdSendBody);
23753
23804
  if (fwdResult?.blocked && fwdResult?.pendingId) {
23754
23805
  scheduleFollowUp(fwdResult.pendingId, String(args2.to), fwdSubject, makePendingCheck(fwdResult.pendingId));
@@ -23853,7 +23904,9 @@ ${lines.join("\n")}`;
23853
23904
  }
23854
23905
  if (args2.action === "send") {
23855
23906
  if (!args2.id) throw new Error("id is required");
23856
- const r = await apiRequest("POST", `/drafts/${args2.id}/send`);
23907
+ const draftSendBody = {};
23908
+ if (args2.wake !== void 0) draftSendBody.wake = args2.wake;
23909
+ const r = await apiRequest("POST", `/drafts/${args2.id}/send`, draftSendBody);
23857
23910
  return `Draft sent. Message ID: ${r?.messageId ?? "unknown"}`;
23858
23911
  }
23859
23912
  if (args2.action === "delete") {
@@ -24459,12 +24512,14 @@ ${lines.join("\n\n---\n\n")}`;
24459
24512
  ${lines.join("\n")}`;
24460
24513
  }
24461
24514
  case "template_send": {
24462
- const result = await apiRequest("POST", `/templates/${args2.id}/send`, {
24515
+ const templateBody = {
24463
24516
  to: args2.to,
24464
24517
  variables: args2.variables,
24465
24518
  cc: args2.cc,
24466
24519
  bcc: args2.bcc
24467
- });
24520
+ };
24521
+ if (args2.wake !== void 0) templateBody.wake = args2.wake;
24522
+ const result = await apiRequest("POST", `/templates/${args2.id}/send`, templateBody);
24468
24523
  return `Template email sent. Message ID: ${result?.messageId ?? "unknown"}`;
24469
24524
  }
24470
24525
  case "manage_rules": {
@@ -24519,6 +24574,38 @@ ${r.agents.map(
24519
24574
  }
24520
24575
  throw new Error("Invalid action. Use: list_inactive, cleanup, or set_persistent");
24521
24576
  }
24577
+ case "check_activity": {
24578
+ const r = await apiRequest("GET", "/dispatcher/activity", void 0, true);
24579
+ const filterAgent = typeof args2.agent === "string" ? args2.agent.toLowerCase() : "";
24580
+ const includeRecent = args2.includeRecent !== false;
24581
+ const matchesFilter = (w) => !filterAgent || (w.agentName ?? "").toLowerCase().includes(filterAgent);
24582
+ const activeList = Array.isArray(r?.active) ? r.active.filter(matchesFilter) : [];
24583
+ const recentList = includeRecent && Array.isArray(r?.recent) ? r.recent.filter(matchesFilter) : [];
24584
+ if (activeList.length === 0 && recentList.length === 0) {
24585
+ if (filterAgent) return `No dispatcher activity for "${args2.agent}" right now or in the last 2 minutes. Either the agent has not been woken on this thread yet, the dispatcher is not running, or mail to them is still in flight.`;
24586
+ return "No dispatcher activity right now or in the last 2 minutes. If you just sent mail and expected an agent to wake, give it a moment \u2014 the dispatcher subscribes to /system/events for sub-second wake. If nothing happens for 30s, check that the dispatcher process is running (`pm2 list`) and that the recipient is a real local agent (`list_agents`).";
24587
+ }
24588
+ const fmt = (w, prefix) => {
24589
+ const dur = w.durationMs ? `${(w.durationMs / 1e3).toFixed(1)}s` : "?";
24590
+ const trig = w.trigger?.subject ? ` \u2014 ${String(w.trigger.subject).slice(0, 60)}` : w.trigger?.taskId ? ` \u2014 task ${String(w.trigger.taskId).slice(0, 8)}` : "";
24591
+ const from = w.trigger?.from ? ` (from ${w.trigger.from})` : "";
24592
+ const preview = w.resultPreview ? `
24593
+ \u2192 ${String(w.resultPreview).slice(0, 140).replace(/\s+/g, " ").trim()}` : "";
24594
+ const status = w.endedAtMs ? w.ok === false ? "failed" : "finished" : "running";
24595
+ return ` ${prefix} ${w.agentName} [${w.kind}] ${status} ${dur}${trig}${from}${preview}`;
24596
+ };
24597
+ const lines = [];
24598
+ if (activeList.length > 0) {
24599
+ lines.push(`Active workers (${activeList.length}):`);
24600
+ for (const w of activeList) lines.push(fmt(w, "\u25CF"));
24601
+ }
24602
+ if (recentList.length > 0) {
24603
+ if (lines.length > 0) lines.push("");
24604
+ lines.push(`Recently finished (last 2 min, ${recentList.length}):`);
24605
+ for (const w of recentList) lines.push(fmt(w, "\u25CB"));
24606
+ }
24607
+ return lines.join("\n");
24608
+ }
24522
24609
  case "check_tasks": {
24523
24610
  let endpoint = args2.direction === "outgoing" ? "/tasks/assigned" : "/tasks/pending";
24524
24611
  if (args2.direction !== "outgoing" && args2.assignee) {
@@ -25069,6 +25156,7 @@ var SERVER_INSTRUCTIONS = [
25069
25156
  ' to: "vesper@localhost", // primary owner of step 1',
25070
25157
  ' cc: "orion@localhost, claudecode@localhost", // teammates + yourself',
25071
25158
  ' subject: "Build a small terminal game",',
25159
+ ' wake: ["vesper"], // only Vesper gets a Claude turn',
25072
25160
  " text: [",
25073
25161
  ' "Team \u2014",',
25074
25162
  ' "",',
@@ -25081,6 +25169,14 @@ var SERVER_INSTRUCTIONS = [
25081
25169
  ' ].join("\\n"),',
25082
25170
  " })",
25083
25171
  "",
25172
+ " The `wake` parameter is the SINGLE BIGGEST TOKEN SAVER on large threads.",
25173
+ " Without it, every CC'd recipient burns one Claude turn deciding whether",
25174
+ " it is their turn. With it, only the named agents get a turn \u2014 the rest",
25175
+ " receive the mail in their inbox but stay asleep until you (or another",
25176
+ " agent) explicitly names them in a later `wake` list. Pass `wake: []`",
25177
+ ' for "deliver silently \u2014 wake nobody". Omit `wake` entirely to keep the',
25178
+ ` old "wake every CC'd agent" behaviour (backwards compatible).`,
25179
+ "",
25084
25180
  " The mail server pushes a wake-up to every local recipient simultaneously.",
25085
25181
  " Each agent reads the thread, decides if it is THEIR turn, and either",
25086
25182
  " reply-all's to contribute or stays silent. Vesper goes first because she",
@@ -25100,7 +25196,15 @@ var SERVER_INSTRUCTIONS = [
25100
25196
  " To unblock a stuck agent or change direction, just reply-all into the",
25101
25197
  " same thread.",
25102
25198
  "",
25103
- '4. Done when the last hand-off (or an explicit "complete" message) lands',
25199
+ "4. **Close the thread when work is complete.** Send a wrap-up reply",
25200
+ " with one of these markers in the subject: `[FINAL]`, `[DONE]`,",
25201
+ " `[CLOSED]`, or `[WRAP]`. The dispatcher honours those markers and",
25202
+ " stops waking workers on any further replies to that thread. Without",
25203
+ " this, the cascade can keep firing as agents critique each other's",
25204
+ " work even after the deliverables are in. Add the marker once, the",
25205
+ " thread is sealed.",
25206
+ "",
25207
+ '5. Done when the last hand-off (or an explicit "complete" message) lands',
25104
25208
  " in your inbox. Show the result to the user.",
25105
25209
  "",
25106
25210
  "Why this is right:",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/mcp",
3
- "version": "0.7.4",
3
+ "version": "0.7.7",
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",