@agentcomms/resend 0.13.0 → 0.14.0
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 +9 -7
- package/dist/cli.mjs +121 -62
- package/dist/index.d.mts +12914 -12032
- package/dist/index.mjs +5 -6
- package/dist/{send-D2ZOWO_6.mjs → send-9pskzeUY.mjs} +9346 -4699
- package/dist/{server-CLjdcZDg.mjs → server-DFbgMT3K.mjs} +41 -18
- package/dist/{stdio-entry-BCnq_EyF.mjs → stdio-entry-PsvT2AI2.mjs} +1 -1
- package/package.json +8 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as CHANGE_POLICIES, C as policyChange,
|
|
1
|
+
import { A as CHANGE_POLICIES, C as policyChange, Ct as waitCallOptions, E as removeAccountChange, I as CommsError, K as changeToolResult, M as SEND_POLICIES, Nt as VERSION, O as showAccount, P as strictToolArguments, S as policyApprovalRefusal, St as updateToolGate, T as policyWanted, _ as runDoctor, b as listAccounts, c as downloadReceived, d as listReceived, et as gatedChange, f as listScheduled, g as showSentEmail, h as showReceived, i as prepareSend, j as MODES, k as ResendContext, l as getMetrics, lt as refuseUnclaimedApproval, m as listSuppressions, n as executeSend, o as sendStatus, p as listSentEmails, q as checkForUpdates, s as cancelScheduledChange, u as listDomains, w as policyReport, wt as waitForApproval, yt as toCommsError, z as SEND_LOOKUP } from "./send-9pskzeUY.mjs";
|
|
2
2
|
import { S as union, c as boolean, g as object, h as number, s as array, x as string } from "./iso-USuVU_sk.mjs";
|
|
3
3
|
import { t as McpServer } from "./mcp-DXXb3Vv3-kCxsVLO4.mjs";
|
|
4
4
|
//#region src/mcp/server.ts
|
|
@@ -29,19 +29,19 @@ async function buildInstructions(context, pinned) {
|
|
|
29
29
|
"",
|
|
30
30
|
"Sending needs a person’s yes to that exact email. `resend_send_prepare` returns a preview: show it in full and",
|
|
31
31
|
"wait. Under the account’s `chat` policy `resend_send_execute` then sends it, once. Under `confirm` — and always",
|
|
32
|
-
"above 10 recipients — the person runs
|
|
33
|
-
"yourself, so say so
|
|
34
|
-
"it with `resend_send_status`.",
|
|
32
|
+
"above 10 recipients — the person runs the approve command the preparation gives, at their own terminal;",
|
|
33
|
+
"you cannot approve it yourself, so say so; resend_send_wait tells you when they have. Under `never` nothing",
|
|
34
|
+
"sends. Never repeat a send whose outcome is unknown: check it with `resend_send_status`.",
|
|
35
35
|
"",
|
|
36
|
-
"Read-only is enforced by
|
|
37
|
-
"A key is added only by a person at
|
|
36
|
+
"Read-only is enforced by this package’s own code, not by the key: Resend has no read-only key.",
|
|
37
|
+
"A key is added only by a person, at their own terminal. Never ask for one in chat.",
|
|
38
38
|
"",
|
|
39
39
|
pinned ? `This server is pinned to "${pinned}"; the account argument may be omitted.` : "Pass `account` on every call — there is no default.",
|
|
40
40
|
names.length > 0 ? `Known accounts — "can send" means only after a person approves: ${listOf(names)}.` : "No account is connected yet.",
|
|
41
41
|
"",
|
|
42
42
|
"Changing an account (send mode, a looser policy, removing it) or cancelling an email scheduled elsewhere returns",
|
|
43
43
|
"`approvalRequired` and a preview: show it and ask. Under the `chat` change policy call again with `approvalId`",
|
|
44
|
-
"after their yes; under `confirm` they run
|
|
44
|
+
"after their yes; under `confirm` they first run the approve command the result gives. Tightening applies at once."
|
|
45
45
|
].join("\n");
|
|
46
46
|
}
|
|
47
47
|
async function createResendMcpServer(options = {}) {
|
|
@@ -56,7 +56,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
56
56
|
version: VERSION
|
|
57
57
|
}, { instructions: await buildInstructions(context, pinned) });
|
|
58
58
|
const reply = (data) => {
|
|
59
|
-
const structured = data;
|
|
59
|
+
const structured = JSON.parse(JSON.stringify(data));
|
|
60
60
|
return {
|
|
61
61
|
structuredContent: structured,
|
|
62
62
|
content: [{
|
|
@@ -67,12 +67,12 @@ async function createResendMcpServer(options = {}) {
|
|
|
67
67
|
};
|
|
68
68
|
const fail = (error) => {
|
|
69
69
|
const comms = toCommsError(error);
|
|
70
|
-
const structured = { error: {
|
|
70
|
+
const structured = JSON.parse(JSON.stringify({ error: {
|
|
71
71
|
code: comms.code,
|
|
72
72
|
message: comms.message,
|
|
73
73
|
hint: comms.hint ?? null,
|
|
74
74
|
...comms.details !== void 0 ? { details: comms.details } : {}
|
|
75
|
-
} };
|
|
75
|
+
} }));
|
|
76
76
|
return {
|
|
77
77
|
isError: true,
|
|
78
78
|
structuredContent: structured,
|
|
@@ -89,7 +89,10 @@ async function createResendMcpServer(options = {}) {
|
|
|
89
89
|
channel: "resend",
|
|
90
90
|
running: VERSION,
|
|
91
91
|
exempt: ["resend_doctor"],
|
|
92
|
-
approvals: {
|
|
92
|
+
approvals: {
|
|
93
|
+
resend_send_status: SEND_LOOKUP,
|
|
94
|
+
resend_send_wait: { lookup: true }
|
|
95
|
+
},
|
|
93
96
|
refresh: () => checkForUpdates(context.core, context.env)
|
|
94
97
|
}));
|
|
95
98
|
/** Which account a call acts on. A pinned server refuses any other, and re-checks the pin against the id. */
|
|
@@ -104,9 +107,9 @@ async function createResendMcpServer(options = {}) {
|
|
|
104
107
|
return named;
|
|
105
108
|
};
|
|
106
109
|
const runChange = async (change, approvalId) => changeToolResult(await gatedChange(context.core, change, {
|
|
110
|
+
channel: "resend",
|
|
107
111
|
surface: "mcp",
|
|
108
112
|
approvalId,
|
|
109
|
-
approveCommand: "agent-resend approve",
|
|
110
113
|
platform: context.platform
|
|
111
114
|
}));
|
|
112
115
|
const readsResend = {
|
|
@@ -118,7 +121,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
118
121
|
openWorldHint: false
|
|
119
122
|
};
|
|
120
123
|
const accountArg = { account: string().optional().describe("which account, as `organisation/resend`") };
|
|
121
|
-
const approvalArg = { approvalId: string().optional().describe("the approval the preview named, once the person has agreed (or run
|
|
124
|
+
const approvalArg = { approvalId: string().optional().describe("the approval the preview named, once the person has agreed (or run the approve command it gave)") };
|
|
122
125
|
const number$1 = union([number(), string()]);
|
|
123
126
|
const words = (values) => string().meta({ enum: [...values] });
|
|
124
127
|
const paging = {
|
|
@@ -134,7 +137,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
134
137
|
};
|
|
135
138
|
server.registerTool("resend_accounts_list", {
|
|
136
139
|
title: "List accounts",
|
|
137
|
-
description: "The connected Resend accounts: each key’s permission, its mode, its send policy, and who enforces what. Read-only is
|
|
140
|
+
description: "The connected Resend accounts: each key’s permission, its mode, its send policy, and who enforces what. Read-only is this package’s own promise, never the key’s.",
|
|
138
141
|
inputSchema: {},
|
|
139
142
|
annotations: readsLocal
|
|
140
143
|
}, wrapped(async () => {
|
|
@@ -149,7 +152,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
149
152
|
}, wrapped(async (args) => showAccount(context, await resolve(args.account))));
|
|
150
153
|
server.registerTool("resend_account_remove", {
|
|
151
154
|
title: "Remove an account",
|
|
152
|
-
description: "Forget an account and delete its key from this machine. Returns `approvalRequired` and a preview first: show it and ask; call again with `approvalId` after their yes (under `confirm`, after they run
|
|
155
|
+
description: "Forget an account and delete its key from this machine. Returns `approvalRequired` and a preview first: show it and ask; call again with `approvalId` after their yes (under `confirm`, after they run the approve command the result gives — you cannot approve it yourself).",
|
|
153
156
|
inputSchema: {
|
|
154
157
|
...accountArg,
|
|
155
158
|
...approvalArg
|
|
@@ -195,7 +198,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
195
198
|
}));
|
|
196
199
|
server.registerTool("resend_doctor", {
|
|
197
200
|
title: "Doctor",
|
|
198
|
-
description: "What works and what does not, per account — and, plainly, that read-only is enforced by
|
|
201
|
+
description: "What works and what does not, per account — and, plainly, that read-only is enforced by this package’s code, not by the key.",
|
|
199
202
|
inputSchema: {
|
|
200
203
|
...accountArg,
|
|
201
204
|
offline: boolean().optional().describe("do not ask Resend anything")
|
|
@@ -339,7 +342,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
339
342
|
}));
|
|
340
343
|
server.registerTool("resend_send_execute", {
|
|
341
344
|
title: "Send a prepared email",
|
|
342
|
-
description: "Send a prepared email, once, after the person approved its preview. Under `confirm` the person must first run
|
|
345
|
+
description: "Send a prepared email, once, after the person approved its preview. Under `confirm` the person must first run the approve command `resend_send_prepare` gave, at their own terminal — you cannot approve it yourself. `expect` restates the recipients and subject shown. Never call it again for an email whose outcome is unknown: use `resend_send_status`.",
|
|
343
346
|
inputSchema: {
|
|
344
347
|
...accountArg,
|
|
345
348
|
approvalId: string().describe("the approval `resend_send_prepare` returned"),
|
|
@@ -365,7 +368,7 @@ async function createResendMcpServer(options = {}) {
|
|
|
365
368
|
}));
|
|
366
369
|
server.registerTool("resend_send_status", {
|
|
367
370
|
title: "Send status",
|
|
368
|
-
description: "What happened to a send: the approval, the local record, and Resend’s last event. Read only — it never sends again.",
|
|
371
|
+
description: "What happened to a send: the approval, the local record, and its current `outcome` as Resend’s own last event reports it. One event for the whole email, attributed to Resend — never a word about every recipient; an event this version does not interpret comes only inside <untrusted-content>. Read only — it never sends again.",
|
|
369
372
|
inputSchema: {
|
|
370
373
|
...accountArg,
|
|
371
374
|
approvalId: string()
|
|
@@ -375,6 +378,26 @@ async function createResendMcpServer(options = {}) {
|
|
|
375
378
|
const name = await resolve(args.account);
|
|
376
379
|
return sendStatus(context, name, args.approvalId);
|
|
377
380
|
}));
|
|
381
|
+
server.registerTool("resend_send_wait", {
|
|
382
|
+
title: "Wait for an approval",
|
|
383
|
+
description: `Wait for an approval — a send or a change — to be usable or finished, and say where it stands: pending (with \`claimable\` true when a yes in the chat can use it), approved, being sent, used, failed, unknown, expired, revoked or corrupt. \`waitSeconds\` is 30 when left out, 300 at most, and 0 for its status now. It only looks: it never approves, claims or sends, and never asks Resend. Ended still waiting, wait again — never prepare it again while it is pending or being sent. The same as \`send wait\` in the Resend CLI.`,
|
|
384
|
+
inputSchema: {
|
|
385
|
+
approvalId: string().describe("the approval to wait for"),
|
|
386
|
+
waitSeconds: number().int().min(0).max(300).optional().describe(`how long to wait: 30 when left out, 300 at most, 0 for the status now`)
|
|
387
|
+
},
|
|
388
|
+
annotations: readsLocal
|
|
389
|
+
}, async (args, ctx) => {
|
|
390
|
+
try {
|
|
391
|
+
return reply(await waitForApproval(context.core, args.approvalId, {
|
|
392
|
+
waitSeconds: args.waitSeconds,
|
|
393
|
+
channel: "resend",
|
|
394
|
+
...pinnedId === void 0 ? {} : { owner: pinnedId },
|
|
395
|
+
...waitCallOptions(ctx)
|
|
396
|
+
}));
|
|
397
|
+
} catch (error) {
|
|
398
|
+
return fail(error);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
378
401
|
server.registerTool("resend_scheduled_list", {
|
|
379
402
|
title: "Scheduled emails",
|
|
380
403
|
description: "Emails waiting to be sent later, among the most recent 300 sent, and whether this machine scheduled each.",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createResendMcpServer } from "./server-
|
|
1
|
+
import { t as createResendMcpServer } from "./server-DFbgMT3K.mjs";
|
|
2
2
|
//#region src/mcp/stdio-entry.ts
|
|
3
3
|
/**
|
|
4
4
|
* Starting the stdio server. On stdio, **stdout is the protocol**: one stray `console.log` corrupts the stream, so
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentcomms/resend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Resend for coding agents: read domains, sent and received mail, metrics and suppressions, and send mail that nothing sends without a person's approval of exactly what goes out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
"LICENSE",
|
|
31
31
|
"THIRD_PARTY_LICENSES"
|
|
32
32
|
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@agentcomms/core": "0.14.0"
|
|
35
|
+
},
|
|
33
36
|
"optionalDependencies": {
|
|
34
37
|
"@napi-rs/keyring": "2.1.0"
|
|
35
38
|
},
|
|
@@ -37,8 +40,7 @@
|
|
|
37
40
|
"@modelcontextprotocol/client": "2.0.0",
|
|
38
41
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
39
42
|
"commander": "^15.0.0",
|
|
40
|
-
"zod": "^4.6.5"
|
|
41
|
-
"@agentcomms/core": "0.13.0"
|
|
43
|
+
"zod": "^4.6.5"
|
|
42
44
|
},
|
|
43
45
|
"publishConfig": {
|
|
44
46
|
"access": "public"
|
|
@@ -65,7 +67,7 @@
|
|
|
65
67
|
"guarantee": {
|
|
66
68
|
"ceiling": "code",
|
|
67
69
|
"floor": "code",
|
|
68
|
-
"why": "Resend has no read-only key, and a full-access key can also manage domains and keys: read mode, and send mode's limit to sending, are enforced by
|
|
70
|
+
"why": "Resend has no read-only key, and a full-access key can also manage domains and keys: read mode, and send mode's limit to sending, are enforced by this package's own code. A sending-access key can only send, and Resend enforces that."
|
|
69
71
|
}
|
|
70
72
|
},
|
|
71
73
|
"narrowing": [
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
"inbound-cdn.resend.com"
|
|
85
87
|
],
|
|
86
88
|
"approve": "agent-resend approve",
|
|
89
|
+
"approvalGrouping": "draft",
|
|
87
90
|
"skills": {
|
|
88
91
|
"prefix": "resend-",
|
|
89
92
|
"contract": "skills/_shared/contract-resend.md"
|
|
@@ -94,5 +97,5 @@
|
|
|
94
97
|
"typecheck": "tsc -p tsconfig.json",
|
|
95
98
|
"test": "node --experimental-strip-types --test --test-timeout=600000 \"test/**/*.test.ts\""
|
|
96
99
|
},
|
|
97
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "6f6a9de4c7e18e88d779f04de384fbc4e5397352"
|
|
98
101
|
}
|