supersendtx-mcp 0.6.32 → 0.6.35
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 +7 -2
- package/dist/index.js +132 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,14 +134,19 @@ These call the app host and need a full-access key (OAuth sign-in and dashboard
|
|
|
134
134
|
|
|
135
135
|
| Tool | Purpose |
|
|
136
136
|
|------|---------|
|
|
137
|
-
| `arc_ensure_thread` / `arc_list_threads` | Durable thread for this client |
|
|
137
|
+
| `arc_ensure_thread` / `arc_list_threads` | Durable thread for this client; list threads a page at a time |
|
|
138
|
+
| `arc_get_thread` | Read a thread's messages, artifacts and waiting approvals |
|
|
138
139
|
| `arc_message` | Send text to Ranla and wait for the turn — returns `text`, `artifacts`, and `pendingApproval` |
|
|
139
140
|
| `arc_list_approvals` / `arc_approve` / `arc_reject` | Answer approvals |
|
|
140
141
|
| `arc_request_connection` | Connect link for a missing integration |
|
|
141
|
-
| `arc_<tool>` | Read-only Ranla tools, listed from the account with input schemas |
|
|
142
|
+
| `arc_<tool>` | Read-only Ranla tools, listed from the account with input schemas. Results say in `forCaller` when a step needs `arc_message` |
|
|
142
143
|
|
|
143
144
|
Flow: `arc_ensure_thread` → `arc_message` → if a step needs approval, `arc_list_approvals` → `arc_approve` or `arc_reject`.
|
|
144
145
|
|
|
146
|
+
An SEO page approval also carries `actionId`: pass it to `arc_seo_page_package` to read the draft, for example to build the page in your own repo.
|
|
147
|
+
|
|
148
|
+
Every tool has a `title` and `readOnlyHint` / `destructiveHint` annotations, so clients can run reads without asking and confirm writes.
|
|
149
|
+
|
|
145
150
|
Full reference: https://docs.supersendtx.com/ai/mcp
|
|
146
151
|
|
|
147
152
|
## License
|
package/dist/index.js
CHANGED
|
@@ -84,7 +84,63 @@ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprot
|
|
|
84
84
|
import { SuperSendTX } from "supersendtx";
|
|
85
85
|
|
|
86
86
|
// package.json
|
|
87
|
-
var version = "0.6.
|
|
87
|
+
var version = "0.6.35";
|
|
88
|
+
|
|
89
|
+
// src/annotations.ts
|
|
90
|
+
var READ = { readOnlyHint: true };
|
|
91
|
+
var WRITE = { readOnlyHint: false, destructiveHint: false };
|
|
92
|
+
var DELETE = { readOnlyHint: false, destructiveHint: true };
|
|
93
|
+
var FIXED_TOOL_HINTS = {
|
|
94
|
+
send_email: { ...WRITE, openWorldHint: true },
|
|
95
|
+
list_emails: READ,
|
|
96
|
+
get_email: READ,
|
|
97
|
+
cancel_email: DELETE,
|
|
98
|
+
list_received_emails: READ,
|
|
99
|
+
get_received_email: READ,
|
|
100
|
+
list_domains: READ,
|
|
101
|
+
get_domain: READ,
|
|
102
|
+
create_domain: WRITE,
|
|
103
|
+
apply_domain_dns: { ...WRITE, title: "Apply domain DNS records", openWorldHint: true },
|
|
104
|
+
verify_domain: { ...WRITE, idempotentHint: true },
|
|
105
|
+
list_webhooks: READ,
|
|
106
|
+
create_webhook: WRITE,
|
|
107
|
+
delete_webhook: DELETE,
|
|
108
|
+
list_suppressions: READ,
|
|
109
|
+
add_suppression: { ...WRITE, idempotentHint: true },
|
|
110
|
+
remove_suppression: DELETE,
|
|
111
|
+
list_templates: READ,
|
|
112
|
+
get_template: READ,
|
|
113
|
+
create_template: WRITE,
|
|
114
|
+
publish_template: WRITE,
|
|
115
|
+
send_test_webhook_event: { ...WRITE, openWorldHint: true },
|
|
116
|
+
get_deliverability: READ,
|
|
117
|
+
arc_list_threads: { ...READ, title: "List Ranla threads" },
|
|
118
|
+
arc_get_thread: { ...READ, title: "Read a Ranla thread" },
|
|
119
|
+
arc_ensure_thread: { ...WRITE, title: "Open a Ranla thread", idempotentHint: true },
|
|
120
|
+
arc_message: { ...WRITE, title: "Message Ranla" },
|
|
121
|
+
arc_list_approvals: { ...READ, title: "List pending approvals" },
|
|
122
|
+
/** Approving can send email to real people. */
|
|
123
|
+
arc_approve: { ...WRITE, title: "Approve a Ranla step", openWorldHint: true },
|
|
124
|
+
/** Rejecting discards the proposal. */
|
|
125
|
+
arc_reject: { ...DELETE, title: "Reject a Ranla step" }
|
|
126
|
+
};
|
|
127
|
+
var UPPER = /* @__PURE__ */ new Set(["ai", "aeo", "api", "dns", "id", "seo", "url"]);
|
|
128
|
+
function titleFromToolName(name) {
|
|
129
|
+
const words = name.replace(/^arc_/, "").split("_").filter(Boolean);
|
|
130
|
+
return words.map((word, index) => {
|
|
131
|
+
if (UPPER.has(word)) return word.toUpperCase();
|
|
132
|
+
return index === 0 ? word.charAt(0).toUpperCase() + word.slice(1) : word;
|
|
133
|
+
}).join(" ");
|
|
134
|
+
}
|
|
135
|
+
function mcpToolAnnotations(tool) {
|
|
136
|
+
const fixed = FIXED_TOOL_HINTS[tool.name];
|
|
137
|
+
if (fixed) {
|
|
138
|
+
const { title: title2, ...hints } = fixed;
|
|
139
|
+
return { title: title2 ?? titleFromToolName(tool.name), ...hints };
|
|
140
|
+
}
|
|
141
|
+
const title = titleFromToolName(tool.name);
|
|
142
|
+
return tool.readOnly === true ? { title, ...READ } : { title, ...WRITE };
|
|
143
|
+
}
|
|
88
144
|
|
|
89
145
|
// src/arc-talk-tools.ts
|
|
90
146
|
var ARC_MCP_TALK_GROWTH_TOOL_NAMES = [
|
|
@@ -96,6 +152,10 @@ var ARC_MCP_TALK_GROWTH_TOOL_NAMES = [
|
|
|
96
152
|
// A canvas document Ranla wrote, as it stands now. Writing to one mutates
|
|
97
153
|
// and goes through `arc_message` like every other write.
|
|
98
154
|
"read_canvas",
|
|
155
|
+
// The ids read_canvas takes; nothing else an external agent can call returns them.
|
|
156
|
+
"list_documents",
|
|
157
|
+
// Every image in the account, with public URLs an external agent can use as they are.
|
|
158
|
+
"list_library_images",
|
|
99
159
|
"get_setup_status",
|
|
100
160
|
"get_growth_health",
|
|
101
161
|
"get_revenue_health",
|
|
@@ -107,6 +167,7 @@ var ARC_MCP_TALK_GROWTH_TOOL_NAMES = [
|
|
|
107
167
|
"list_goals",
|
|
108
168
|
"list_lists",
|
|
109
169
|
"list_segments",
|
|
170
|
+
"get_segment",
|
|
110
171
|
"get_tracking_snippet",
|
|
111
172
|
"verify_tracking_install",
|
|
112
173
|
"list_automations",
|
|
@@ -134,9 +195,10 @@ var ARC_MCP_TALK_GROWTH_TOOL_NAMES = [
|
|
|
134
195
|
"get_ad_delivery_diagnostics",
|
|
135
196
|
"get_search_term_evidence",
|
|
136
197
|
"list_proposed_ad_campaigns",
|
|
137
|
-
"recommend_ad_landings",
|
|
138
198
|
"read_campaign_design",
|
|
139
199
|
"list_campaign_replies",
|
|
200
|
+
// The inbox as conversations, with the replies Ranla drafted.
|
|
201
|
+
"read_inbox",
|
|
140
202
|
"get_learnings",
|
|
141
203
|
"read_repo_activity",
|
|
142
204
|
"get_codebase_digest",
|
|
@@ -194,7 +256,8 @@ var TALK_READ_TOOLS = ARC_MCP_TALK_GROWTH_TOOL_NAMES.map((growthTool) => ({
|
|
|
194
256
|
description: `Read-only Ranla tool: ${growthTool.replace(/_/g, " ")}.`,
|
|
195
257
|
inputSchema: openObjectSchema("Pass the tool arguments as fields."),
|
|
196
258
|
kind: "growth",
|
|
197
|
-
growthTool
|
|
259
|
+
growthTool,
|
|
260
|
+
readOnly: true
|
|
198
261
|
}));
|
|
199
262
|
var SETUP_TOOLS = [
|
|
200
263
|
{
|
|
@@ -209,14 +272,40 @@ var SETUP_TOOLS = [
|
|
|
209
272
|
required: ["slot"]
|
|
210
273
|
},
|
|
211
274
|
kind: "growth",
|
|
212
|
-
growthTool: "request_connection"
|
|
275
|
+
growthTool: "request_connection",
|
|
276
|
+
readOnly: false
|
|
213
277
|
}
|
|
214
278
|
];
|
|
215
279
|
var META_TOOLS = [
|
|
216
280
|
{
|
|
217
281
|
name: "arc_list_threads",
|
|
218
|
-
description: "List Ranla chat threads for this account.",
|
|
219
|
-
inputSchema:
|
|
282
|
+
description: "List Ranla chat threads for this account, most recent first: id, title, desk, last activity and a one-line preview. Pass nextBefore as before for older threads. Read one with arc_get_thread.",
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: "object",
|
|
285
|
+
properties: {
|
|
286
|
+
limit: { type: "integer", description: "Threads per page. Default 50, max 100." },
|
|
287
|
+
before: {
|
|
288
|
+
type: "string",
|
|
289
|
+
description: "ISO timestamp from nextBefore: only threads last active before it."
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
kind: "meta"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: "arc_get_thread",
|
|
297
|
+
description: "Read a Ranla thread: its messages (role, text, tools used, artifacts by id, approvals waiting on arc_approve), newest page first. Pass earlierBefore as before for older messages.",
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
threadId: { type: "string", description: "From arc_list_threads or arc_ensure_thread." },
|
|
302
|
+
before: {
|
|
303
|
+
type: "string",
|
|
304
|
+
description: "ISO timestamp from earlierBefore: the page of messages older than it."
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
required: ["threadId"]
|
|
308
|
+
},
|
|
220
309
|
kind: "meta"
|
|
221
310
|
},
|
|
222
311
|
{
|
|
@@ -246,7 +335,7 @@ var META_TOOLS = [
|
|
|
246
335
|
},
|
|
247
336
|
{
|
|
248
337
|
name: "arc_list_approvals",
|
|
249
|
-
description: "List pending Ranla
|
|
338
|
+
description: "List pending Ranla approvals across threads.",
|
|
250
339
|
inputSchema: openObjectSchema(),
|
|
251
340
|
kind: "meta"
|
|
252
341
|
},
|
|
@@ -334,7 +423,9 @@ async function loadArcMcpTools(apiKey, baseUrl) {
|
|
|
334
423
|
description: `${entry.mutates ? RANLA_AGENT_NAME : `${RANLA_AGENT_NAME}, read-only`}: ${entry.description}`,
|
|
335
424
|
inputSchema: entry.inputSchema,
|
|
336
425
|
kind: "growth",
|
|
337
|
-
growthTool: entry.name
|
|
426
|
+
growthTool: entry.name,
|
|
427
|
+
// Missing `mutates` is not a promise of read-only: only an explicit false is.
|
|
428
|
+
readOnly: entry.mutates === false
|
|
338
429
|
}))
|
|
339
430
|
];
|
|
340
431
|
}
|
|
@@ -361,7 +452,13 @@ async function callArcMcpTool(apiKey, name, args, baseUrl) {
|
|
|
361
452
|
}
|
|
362
453
|
switch (name) {
|
|
363
454
|
case "arc_list_threads": {
|
|
364
|
-
const
|
|
455
|
+
const query = new URLSearchParams();
|
|
456
|
+
const limit = optString(args, "limit");
|
|
457
|
+
const before = optString(args, "before");
|
|
458
|
+
if (limit) query.set("limit", limit);
|
|
459
|
+
if (before) query.set("before", before);
|
|
460
|
+
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
461
|
+
const response = await arcFetch(origin, apiKey, `/api/growth/threads${suffix}`);
|
|
365
462
|
if (!response.ok) {
|
|
366
463
|
throw new Error(
|
|
367
464
|
typeof response.body.error === "string" ? response.body.error : `List threads failed (${response.status})`
|
|
@@ -369,6 +466,22 @@ async function callArcMcpTool(apiKey, name, args, baseUrl) {
|
|
|
369
466
|
}
|
|
370
467
|
return response.body;
|
|
371
468
|
}
|
|
469
|
+
case "arc_get_thread": {
|
|
470
|
+
const threadId = optString(args, "threadId");
|
|
471
|
+
if (!threadId) throw new Error("Missing required argument: threadId");
|
|
472
|
+
const before = optString(args, "before");
|
|
473
|
+
const response = await arcFetch(
|
|
474
|
+
origin,
|
|
475
|
+
apiKey,
|
|
476
|
+
`/api/growth/threads/${encodeURIComponent(threadId)}${before ? `?before=${encodeURIComponent(before)}` : ""}`
|
|
477
|
+
);
|
|
478
|
+
if (!response.ok) {
|
|
479
|
+
throw new Error(
|
|
480
|
+
typeof response.body.error === "string" ? response.body.error : `Get thread failed (${response.status})`
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
return response.body;
|
|
484
|
+
}
|
|
372
485
|
case "arc_ensure_thread": {
|
|
373
486
|
const existingId = optString(args, "threadId");
|
|
374
487
|
if (existingId) {
|
|
@@ -1135,11 +1248,16 @@ function createMcpServer(apiKey, baseUrl) {
|
|
|
1135
1248
|
{ capabilities: { tools: {} } }
|
|
1136
1249
|
);
|
|
1137
1250
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
1138
|
-
tools: [...MCP_TOOLS, ...await loadArcMcpTools(apiKey, baseUrl)].map((tool) =>
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1251
|
+
tools: [...MCP_TOOLS, ...await loadArcMcpTools(apiKey, baseUrl)].map((tool) => {
|
|
1252
|
+
const annotations = mcpToolAnnotations(tool);
|
|
1253
|
+
return {
|
|
1254
|
+
name: tool.name,
|
|
1255
|
+
title: annotations.title,
|
|
1256
|
+
description: tool.description,
|
|
1257
|
+
inputSchema: tool.inputSchema,
|
|
1258
|
+
annotations
|
|
1259
|
+
};
|
|
1260
|
+
})
|
|
1143
1261
|
}));
|
|
1144
1262
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
1145
1263
|
const result = await callMcpTool(client, request.params.name, request.params.arguments ?? {}, {
|