@agenticmail/mcp 0.7.7 → 0.7.8

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.
package/README.md CHANGED
@@ -8,6 +8,15 @@ The MCP (Model Context Protocol) server for [AgenticMail](https://github.com/age
8
8
 
9
9
  When connected, your AI agent can send emails and texts, check inboxes, reply to messages, receive verification codes, manage contacts, schedule emails, assign tasks to other agents, and more — all through natural language. The server provides 62 tools that cover every email, SMS, and agent management operation.
10
10
 
11
+ ## ✨ What's new in 0.7.7
12
+
13
+ - **`wake` parameter on every send tool** — `send_email`, `reply_email`, `forward_email`, `template_send`, `manage_drafts(send)` all accept `wake: ["alice", "bob"]` (or comma-separated string). The dispatcher gives a Claude turn only to listed agents; the rest still receive the mail but stay asleep. Single biggest token saver on multi-agent threads.
14
+ - **`check_activity` tool** (in the `essential` set) — see which agents the dispatcher has woken right now, what they're working on, how long they've been running, plus a preview of recently-finished work. Answers "did the agent I just emailed actually start working?" without waiting for a reply.
15
+ - **Thread-close markers** — put `[FINAL]`, `[DONE]`, `[CLOSED]`, or `[WRAP]` in a subject to tell the dispatcher this thread is sealed; no more wakes on any reply to it. The wake prompt teaches agents to add these markers when they sign off the work.
16
+ - **LLM-tolerant input coercion** — `batch_mark_read({ uids: "[1,2,3,4]" })`, `wait_for_email({ timeout: "120" })`, `manage_drafts({ where: '{"id":"abc"}' })`, `manage_pending({ allowSensitive: "true" })` all now just work. Strings get parsed before zod validates. No more "expected array, received string" retries.
17
+ - **Server `instructions` field** sent on `initialize` — every connecting MCP client (Claude Code, ChatGPT, Cursor, Grok…) gets the coordination protocol in context before they touch any tool. Provider-agnostic.
18
+ - **`wait_for_email` filters** — block on a specific reply, not just "any new event". Supports `from`, `subject`, `inReplyTo`, `participants`, `includeTasks`.
19
+
11
20
  ## Install
12
21
 
13
22
  ```bash
package/dist/index.js CHANGED
@@ -22401,6 +22401,11 @@ var TOOL_SETS = {
22401
22401
  // "did the agent I just emailed actually start working?" without
22402
22402
  // having to wait for a reply or send an acknowledgment.
22403
22403
  "check_activity",
22404
+ // tail_worker complements check_activity: when a worker has been
22405
+ // running a long time or shows up as stale, tail_worker gives you
22406
+ // the running log of what it actually did — every tool call, every
22407
+ // result. Paired with check_activity so they ship in the same tier.
22408
+ "tail_worker",
22404
22409
  "check_tasks"
22405
22410
  ],
22406
22411
  /** Less-common mail operations. */
@@ -23258,9 +23263,21 @@ var toolDefinitions = [
23258
23263
  required: ["action"]
23259
23264
  }
23260
23265
  },
23266
+ {
23267
+ name: "tail_worker",
23268
+ description: "Tail the log of a running (or recently-finished) dispatcher worker. Use this when check_activity shows a worker has been running a long time or is marked stale, and you want to see what it is actually doing \u2014 every tool call, tool result, and assistant chunk is logged as a one-liner. Returns the last N lines (default 80). The workerId comes from check_activity output. Requires master key.",
23269
+ inputSchema: {
23270
+ type: "object",
23271
+ properties: {
23272
+ workerId: { type: "string", description: "Worker id from check_activity output." },
23273
+ lines: { type: "number", description: "How many trailing log lines to return. Default 80, max 1000." }
23274
+ },
23275
+ required: ["workerId"]
23276
+ }
23277
+ },
23261
23278
  {
23262
23279
  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.",
23280
+ description: "Check which agents are currently being woken by the dispatcher. 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, the most recent tool they invoked, how many tool calls they have made, a `stale` flag (true if the dispatcher has not heartbeated in 90s+), and a preview of recently-finished work. Workers may run for hours \u2014 there is no auto-eviction; staleness is just a hint. Requires master key.",
23264
23281
  inputSchema: {
23265
23282
  type: "object",
23266
23283
  properties: {
@@ -24574,6 +24591,15 @@ ${r.agents.map(
24574
24591
  }
24575
24592
  throw new Error("Invalid action. Use: list_inactive, cleanup, or set_persistent");
24576
24593
  }
24594
+ case "tail_worker": {
24595
+ if (!args2.workerId) throw new Error("workerId is required");
24596
+ const lines = typeof args2.lines === "number" ? args2.lines : 80;
24597
+ const r = await apiRequest("GET", `/dispatcher/worker-log/${encodeURIComponent(String(args2.workerId))}?lines=${lines}`, void 0, true);
24598
+ if (!r?.tail || !Array.isArray(r.tail)) return `No log found for worker ${args2.workerId}.`;
24599
+ if (r.tail.length === 0) return `Worker ${args2.workerId} has no log entries yet.`;
24600
+ return `Worker ${args2.workerId} log (last ${r.lines} of ${r.bytes} bytes):
24601
+ ${r.tail.join("\n")}`;
24602
+ }
24577
24603
  case "check_activity": {
24578
24604
  const r = await apiRequest("GET", "/dispatcher/activity", void 0, true);
24579
24605
  const filterAgent = typeof args2.agent === "string" ? args2.agent.toLowerCase() : "";
@@ -24585,14 +24611,24 @@ ${r.agents.map(
24585
24611
  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
24612
  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
24613
  }
24614
+ const fmtDur = (ms) => {
24615
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
24616
+ if (ms < 36e5) return `${Math.floor(ms / 6e4)}m${Math.floor(ms % 6e4 / 1e3)}s`;
24617
+ return `${Math.floor(ms / 36e5)}h${Math.floor(ms % 36e5 / 6e4)}m`;
24618
+ };
24588
24619
  const fmt = (w, prefix) => {
24589
- const dur = w.durationMs ? `${(w.durationMs / 1e3).toFixed(1)}s` : "?";
24620
+ const dur = w.durationMs ? fmtDur(w.durationMs) : "?";
24590
24621
  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
24622
  const from = w.trigger?.from ? ` (from ${w.trigger.from})` : "";
24592
24623
  const preview = w.resultPreview ? `
24593
24624
  \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}`;
24625
+ let status = w.endedAtMs ? w.ok === false ? "failed" : "finished" : "running";
24626
+ if (!w.endedAtMs && w.stale) status = "running (stale heartbeat)";
24627
+ const turns = !w.endedAtMs && typeof w.turnCount === "number" ? ` \xB7 ${w.turnCount} tool calls` : "";
24628
+ const tool = !w.endedAtMs && w.lastTool ? ` \xB7 last tool: ${w.lastTool}` : "";
24629
+ const idHint = !w.endedAtMs ? `
24630
+ id: ${w.workerId} (use tail_worker for the log)` : "";
24631
+ return ` ${prefix} ${w.agentName} [${w.kind}] ${status} ${dur}${turns}${tool}${trig}${from}${preview}${idHint}`;
24596
24632
  };
24597
24633
  const lines = [];
24598
24634
  if (activeList.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/mcp",
3
- "version": "0.7.7",
3
+ "version": "0.7.8",
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",