@agenticmail/mcp 0.7.3 → 0.7.5
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 +5 -1
- package/dist/index.js +119 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/agenticmail/agenticmail/main/docs/images/logo-200.png" alt="AgenticMail logo (pink bow)" width="180" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">@agenticmail/mcp</h1>
|
|
2
6
|
|
|
3
7
|
The MCP (Model Context Protocol) server for [AgenticMail](https://github.com/agenticmail/agenticmail) — gives any MCP-compatible AI client full email and SMS capabilities.
|
|
4
8
|
|
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. */
|
|
@@ -23227,6 +23233,17 @@ var toolDefinitions = [
|
|
|
23227
23233
|
required: ["action"]
|
|
23228
23234
|
}
|
|
23229
23235
|
},
|
|
23236
|
+
{
|
|
23237
|
+
name: "check_activity",
|
|
23238
|
+
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.",
|
|
23239
|
+
inputSchema: {
|
|
23240
|
+
type: "object",
|
|
23241
|
+
properties: {
|
|
23242
|
+
agent: { type: "string", description: "Filter to a specific agent by name (case-insensitive). Omit to see every active and recently-finished worker." },
|
|
23243
|
+
includeRecent: { type: "boolean", description: "Include workers that finished in the last ~2 minutes (default: true). Set false to see only currently-running workers." }
|
|
23244
|
+
}
|
|
23245
|
+
}
|
|
23246
|
+
},
|
|
23230
23247
|
{
|
|
23231
23248
|
name: "check_tasks",
|
|
23232
23249
|
description: "Check for pending tasks assigned to you (or a specific agent) or tasks you assigned to others",
|
|
@@ -24519,6 +24536,38 @@ ${r.agents.map(
|
|
|
24519
24536
|
}
|
|
24520
24537
|
throw new Error("Invalid action. Use: list_inactive, cleanup, or set_persistent");
|
|
24521
24538
|
}
|
|
24539
|
+
case "check_activity": {
|
|
24540
|
+
const r = await apiRequest("GET", "/dispatcher/activity", void 0, true);
|
|
24541
|
+
const filterAgent = typeof args2.agent === "string" ? args2.agent.toLowerCase() : "";
|
|
24542
|
+
const includeRecent = args2.includeRecent !== false;
|
|
24543
|
+
const matchesFilter = (w) => !filterAgent || (w.agentName ?? "").toLowerCase().includes(filterAgent);
|
|
24544
|
+
const activeList = Array.isArray(r?.active) ? r.active.filter(matchesFilter) : [];
|
|
24545
|
+
const recentList = includeRecent && Array.isArray(r?.recent) ? r.recent.filter(matchesFilter) : [];
|
|
24546
|
+
if (activeList.length === 0 && recentList.length === 0) {
|
|
24547
|
+
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.`;
|
|
24548
|
+
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`).";
|
|
24549
|
+
}
|
|
24550
|
+
const fmt = (w, prefix) => {
|
|
24551
|
+
const dur = w.durationMs ? `${(w.durationMs / 1e3).toFixed(1)}s` : "?";
|
|
24552
|
+
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)}` : "";
|
|
24553
|
+
const from = w.trigger?.from ? ` (from ${w.trigger.from})` : "";
|
|
24554
|
+
const preview = w.resultPreview ? `
|
|
24555
|
+
\u2192 ${String(w.resultPreview).slice(0, 140).replace(/\s+/g, " ").trim()}` : "";
|
|
24556
|
+
const status = w.endedAtMs ? w.ok === false ? "failed" : "finished" : "running";
|
|
24557
|
+
return ` ${prefix} ${w.agentName} [${w.kind}] ${status} ${dur}${trig}${from}${preview}`;
|
|
24558
|
+
};
|
|
24559
|
+
const lines = [];
|
|
24560
|
+
if (activeList.length > 0) {
|
|
24561
|
+
lines.push(`Active workers (${activeList.length}):`);
|
|
24562
|
+
for (const w of activeList) lines.push(fmt(w, "\u25CF"));
|
|
24563
|
+
}
|
|
24564
|
+
if (recentList.length > 0) {
|
|
24565
|
+
if (lines.length > 0) lines.push("");
|
|
24566
|
+
lines.push(`Recently finished (last 2 min, ${recentList.length}):`);
|
|
24567
|
+
for (const w of recentList) lines.push(fmt(w, "\u25CB"));
|
|
24568
|
+
}
|
|
24569
|
+
return lines.join("\n");
|
|
24570
|
+
}
|
|
24522
24571
|
case "check_tasks": {
|
|
24523
24572
|
let endpoint = args2.direction === "outgoing" ? "/tasks/assigned" : "/tasks/pending";
|
|
24524
24573
|
if (args2.direction !== "outgoing" && args2.assignee) {
|
|
@@ -24945,6 +24994,69 @@ ${lines.join("\n")}`;
|
|
|
24945
24994
|
import { setTelemetryVersion } from "@agenticmail/core";
|
|
24946
24995
|
import { createServer } from "http";
|
|
24947
24996
|
import { randomUUID } from "crypto";
|
|
24997
|
+
|
|
24998
|
+
// src/coerce.ts
|
|
24999
|
+
function coerceToArray(value, itemKind) {
|
|
25000
|
+
if (Array.isArray(value)) return value;
|
|
25001
|
+
if (typeof value !== "string") return value;
|
|
25002
|
+
const trimmed = value.trim();
|
|
25003
|
+
if (trimmed.startsWith("[")) {
|
|
25004
|
+
try {
|
|
25005
|
+
const parsed = JSON.parse(trimmed);
|
|
25006
|
+
if (Array.isArray(parsed)) return parsed;
|
|
25007
|
+
} catch {
|
|
25008
|
+
return value;
|
|
25009
|
+
}
|
|
25010
|
+
}
|
|
25011
|
+
if (itemKind === "number" || itemKind === "integer" || itemKind === "string") {
|
|
25012
|
+
const parts = trimmed.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
25013
|
+
if (itemKind === "number" || itemKind === "integer") {
|
|
25014
|
+
return parts.map((s) => {
|
|
25015
|
+
const n = Number(s);
|
|
25016
|
+
return Number.isNaN(n) ? s : n;
|
|
25017
|
+
});
|
|
25018
|
+
}
|
|
25019
|
+
return parts;
|
|
25020
|
+
}
|
|
25021
|
+
return value;
|
|
25022
|
+
}
|
|
25023
|
+
function coerceToObject(value) {
|
|
25024
|
+
if (value && typeof value === "object" && !Array.isArray(value)) return value;
|
|
25025
|
+
if (typeof value !== "string") return value;
|
|
25026
|
+
const trimmed = value.trim();
|
|
25027
|
+
if (!trimmed.startsWith("{")) return value;
|
|
25028
|
+
try {
|
|
25029
|
+
const parsed = JSON.parse(trimmed);
|
|
25030
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
25031
|
+
} catch {
|
|
25032
|
+
}
|
|
25033
|
+
return value;
|
|
25034
|
+
}
|
|
25035
|
+
function coerceToNumber(value) {
|
|
25036
|
+
if (typeof value === "number") return value;
|
|
25037
|
+
if (typeof value === "string") {
|
|
25038
|
+
const trimmed = value.trim();
|
|
25039
|
+
if (trimmed === "") return value;
|
|
25040
|
+
const n = Number(trimmed);
|
|
25041
|
+
if (!Number.isNaN(n)) return n;
|
|
25042
|
+
}
|
|
25043
|
+
return value;
|
|
25044
|
+
}
|
|
25045
|
+
function coerceToBoolean(value) {
|
|
25046
|
+
if (typeof value === "boolean") return value;
|
|
25047
|
+
if (typeof value === "string") {
|
|
25048
|
+
const v = value.trim().toLowerCase();
|
|
25049
|
+
if (v === "true" || v === "yes" || v === "1") return true;
|
|
25050
|
+
if (v === "false" || v === "no" || v === "0") return false;
|
|
25051
|
+
}
|
|
25052
|
+
if (typeof value === "number") {
|
|
25053
|
+
if (value === 1) return true;
|
|
25054
|
+
if (value === 0) return false;
|
|
25055
|
+
}
|
|
25056
|
+
return value;
|
|
25057
|
+
}
|
|
25058
|
+
|
|
25059
|
+
// src/index.ts
|
|
24948
25060
|
setTelemetryVersion("0.5.55");
|
|
24949
25061
|
function jsonSchemaToZod(schema, topLevel = false) {
|
|
24950
25062
|
if (!schema || typeof schema !== "object") return topLevel ? {} : external_exports.any();
|
|
@@ -24952,16 +25064,18 @@ function jsonSchemaToZod(schema, topLevel = false) {
|
|
|
24952
25064
|
if (schema.type === "string") {
|
|
24953
25065
|
result = schema.enum?.length ? external_exports.enum(schema.enum) : external_exports.string();
|
|
24954
25066
|
} else if (schema.type === "number" || schema.type === "integer") {
|
|
24955
|
-
result = external_exports.number();
|
|
25067
|
+
result = external_exports.preprocess(coerceToNumber, external_exports.number());
|
|
24956
25068
|
} else if (schema.type === "boolean") {
|
|
24957
|
-
result = external_exports.boolean();
|
|
25069
|
+
result = external_exports.preprocess(coerceToBoolean, external_exports.boolean());
|
|
24958
25070
|
} else if (schema.type === "array") {
|
|
24959
25071
|
const hasItems = !!schema.items && typeof schema.items === "object" && Object.keys(schema.items).length > 0;
|
|
24960
|
-
|
|
25072
|
+
const inner = external_exports.array(hasItems ? jsonSchemaToZod(schema.items, false) : external_exports.any());
|
|
25073
|
+
const itemKind = schema.items?.type;
|
|
25074
|
+
result = external_exports.preprocess((v) => coerceToArray(v, itemKind), inner);
|
|
24961
25075
|
} else if (schema.type === "object") {
|
|
24962
25076
|
if (!schema.properties || Object.keys(schema.properties).length === 0) {
|
|
24963
25077
|
if (topLevel) return {};
|
|
24964
|
-
result = external_exports.record(external_exports.string(), external_exports.any());
|
|
25078
|
+
result = external_exports.preprocess(coerceToObject, external_exports.record(external_exports.string(), external_exports.any()));
|
|
24965
25079
|
} else {
|
|
24966
25080
|
const shape = {};
|
|
24967
25081
|
const required2 = new Set(schema.required ?? []);
|
|
@@ -24971,7 +25085,7 @@ function jsonSchemaToZod(schema, topLevel = false) {
|
|
|
24971
25085
|
shape[key] = child;
|
|
24972
25086
|
}
|
|
24973
25087
|
if (topLevel) return shape;
|
|
24974
|
-
result = external_exports.object(shape);
|
|
25088
|
+
result = external_exports.preprocess(coerceToObject, external_exports.object(shape));
|
|
24975
25089
|
}
|
|
24976
25090
|
} else {
|
|
24977
25091
|
result = external_exports.any();
|