supersendtx-mcp 0.5.9 → 0.6.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/dist/index.js +299 -67
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -82,63 +82,295 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
82
82
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
83
83
|
import { SuperSendTX } from "supersendtx";
|
|
84
84
|
|
|
85
|
+
// src/arc-talk-tools.ts
|
|
86
|
+
var ARC_MCP_TALK_GROWTH_TOOL_NAMES = [
|
|
87
|
+
"get_business_brief",
|
|
88
|
+
"research_marketing_site",
|
|
89
|
+
"get_setup_status",
|
|
90
|
+
"get_growth_health",
|
|
91
|
+
"list_product_events",
|
|
92
|
+
"inspect_attribute_values",
|
|
93
|
+
"list_campaigns",
|
|
94
|
+
"list_goals",
|
|
95
|
+
"list_lists",
|
|
96
|
+
"list_segments",
|
|
97
|
+
"get_tracking_snippet",
|
|
98
|
+
"verify_tracking_install",
|
|
99
|
+
"list_automations",
|
|
100
|
+
"get_setup_run",
|
|
101
|
+
"propose_lifecycle_events",
|
|
102
|
+
"list_plan",
|
|
103
|
+
"get_job_schedule",
|
|
104
|
+
"list_opportunities",
|
|
105
|
+
"list_ideas",
|
|
106
|
+
"get_comms_prefs",
|
|
107
|
+
"list_audience",
|
|
108
|
+
"preview_segment",
|
|
109
|
+
"estimate_reach",
|
|
110
|
+
"list_templates",
|
|
111
|
+
"get_campaign_performance",
|
|
112
|
+
"list_campaign_replies",
|
|
113
|
+
"get_learnings",
|
|
114
|
+
"read_repo_activity",
|
|
115
|
+
"get_codebase_digest",
|
|
116
|
+
"read_product_context",
|
|
117
|
+
"search_codebase",
|
|
118
|
+
"read_repo_file",
|
|
119
|
+
"query_product_analytics"
|
|
120
|
+
];
|
|
121
|
+
|
|
85
122
|
// src/arc-mcp.ts
|
|
86
|
-
var
|
|
123
|
+
var DEFAULT_APP_ORIGIN = "https://app.supersendtx.com";
|
|
124
|
+
var DEFAULT_RANLA_APP_ORIGIN = "https://app.ranla.ai";
|
|
125
|
+
var MCP_THREAD_TITLE = "MCP";
|
|
126
|
+
function openObjectSchema(description) {
|
|
127
|
+
return {
|
|
128
|
+
type: "object",
|
|
129
|
+
properties: {},
|
|
130
|
+
additionalProperties: true,
|
|
131
|
+
...description ? { description } : {}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
var TALK_READ_TOOLS = ARC_MCP_TALK_GROWTH_TOOL_NAMES.map((growthTool) => ({
|
|
135
|
+
name: `arc_${growthTool}`,
|
|
136
|
+
description: `Read-only Arc tool: ${growthTool.replace(/_/g, " ")}.`,
|
|
137
|
+
inputSchema: openObjectSchema("Tool input fields (see Ranla Arc tool docs)."),
|
|
138
|
+
kind: "growth",
|
|
139
|
+
growthTool
|
|
140
|
+
}));
|
|
141
|
+
var SETUP_TOOLS = [
|
|
142
|
+
{
|
|
143
|
+
name: "arc_request_connection",
|
|
144
|
+
description: "Surface a Connect card for a missing integration slot.",
|
|
145
|
+
inputSchema: {
|
|
146
|
+
type: "object",
|
|
147
|
+
properties: {
|
|
148
|
+
slot: { type: "string" },
|
|
149
|
+
reason: { type: "string" }
|
|
150
|
+
},
|
|
151
|
+
required: ["slot"]
|
|
152
|
+
},
|
|
153
|
+
kind: "growth",
|
|
154
|
+
growthTool: "request_connection"
|
|
155
|
+
}
|
|
156
|
+
];
|
|
157
|
+
var META_TOOLS = [
|
|
87
158
|
{
|
|
88
|
-
name: "
|
|
89
|
-
description: "
|
|
90
|
-
inputSchema:
|
|
91
|
-
|
|
159
|
+
name: "arc_list_threads",
|
|
160
|
+
description: "List Arc chat threads for this account.",
|
|
161
|
+
inputSchema: openObjectSchema(),
|
|
162
|
+
kind: "meta"
|
|
92
163
|
},
|
|
93
164
|
{
|
|
94
|
-
name: "
|
|
95
|
-
description: "
|
|
96
|
-
inputSchema: {
|
|
97
|
-
|
|
165
|
+
name: "arc_ensure_thread",
|
|
166
|
+
description: "Find or create a durable Arc thread for MCP (default title \u201CMCP\u201D). Returns { threadId, title }.",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: {
|
|
170
|
+
title: { type: "string", description: `Thread title (default ${MCP_THREAD_TITLE})` },
|
|
171
|
+
threadId: { type: "string", description: "Reuse this thread id if it still exists" }
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
kind: "meta"
|
|
98
175
|
},
|
|
99
176
|
{
|
|
100
|
-
name: "
|
|
101
|
-
description: "
|
|
177
|
+
name: "arc_message",
|
|
178
|
+
description: "Send a message to Arc and wait for the turn. Use for strategy and any mutating work. Returns text plus pendingApproval when HITL is required.",
|
|
102
179
|
inputSchema: {
|
|
103
180
|
type: "object",
|
|
104
|
-
properties: {
|
|
181
|
+
properties: {
|
|
182
|
+
text: { type: "string", description: "Message for Arc" },
|
|
183
|
+
threadId: { type: "string", description: "Arc thread id (from arc_ensure_thread)" }
|
|
184
|
+
},
|
|
185
|
+
required: ["text"]
|
|
105
186
|
},
|
|
106
|
-
|
|
187
|
+
kind: "meta"
|
|
107
188
|
},
|
|
108
189
|
{
|
|
109
|
-
name: "
|
|
110
|
-
description: "
|
|
190
|
+
name: "arc_list_approvals",
|
|
191
|
+
description: "List pending Arc approval cards across threads.",
|
|
192
|
+
inputSchema: openObjectSchema(),
|
|
193
|
+
kind: "meta"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "arc_approve",
|
|
197
|
+
description: "Approve a pending Arc HITL card and resume the run.",
|
|
111
198
|
inputSchema: {
|
|
112
199
|
type: "object",
|
|
113
200
|
properties: {
|
|
114
|
-
|
|
115
|
-
reason: { type: "string" }
|
|
201
|
+
messageId: { type: "string" }
|
|
116
202
|
},
|
|
117
|
-
required: ["
|
|
203
|
+
required: ["messageId"]
|
|
118
204
|
},
|
|
119
|
-
|
|
205
|
+
kind: "meta"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "arc_reject",
|
|
209
|
+
description: "Reject a pending Arc HITL card and resume the run.",
|
|
210
|
+
inputSchema: {
|
|
211
|
+
type: "object",
|
|
212
|
+
properties: {
|
|
213
|
+
messageId: { type: "string" }
|
|
214
|
+
},
|
|
215
|
+
required: ["messageId"]
|
|
216
|
+
},
|
|
217
|
+
kind: "meta"
|
|
120
218
|
}
|
|
121
219
|
];
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
|
|
220
|
+
var ARC_MCP_TOOLS = [...META_TOOLS, ...SETUP_TOOLS, ...TALK_READ_TOOLS];
|
|
221
|
+
function resolveArcAppOrigin(options = {}) {
|
|
222
|
+
const fromEnv = process.env.RANLA_APP_URL?.trim() || process.env.SUPERSENDTX_APP_URL?.trim() || "";
|
|
223
|
+
if (fromEnv) return fromEnv.replace(/\/$/, "");
|
|
224
|
+
const key = options.apiKey ?? process.env.SUPERSENDTX_API_KEY ?? process.env.RANLA_API_KEY ?? "";
|
|
225
|
+
if (key.startsWith("rnl_")) return DEFAULT_RANLA_APP_ORIGIN;
|
|
226
|
+
const apiUrl = (options.baseUrl ?? process.env.SUPERSENDTX_API_URL ?? "").replace(/\/$/, "");
|
|
227
|
+
if (apiUrl.includes("api.ranla.ai")) return DEFAULT_RANLA_APP_ORIGIN;
|
|
228
|
+
if (apiUrl.includes("app.ranla.ai")) return apiUrl;
|
|
229
|
+
if (apiUrl.includes("app.supersendtx.com")) return apiUrl;
|
|
230
|
+
return DEFAULT_APP_ORIGIN;
|
|
231
|
+
}
|
|
232
|
+
async function arcFetch(origin, apiKey, path, init = {}) {
|
|
233
|
+
const response = await fetch(`${origin}${path}`, {
|
|
234
|
+
...init,
|
|
131
235
|
headers: {
|
|
132
236
|
Authorization: `Bearer ${apiKey}`,
|
|
133
|
-
"Content-Type": "application/json"
|
|
134
|
-
|
|
135
|
-
|
|
237
|
+
"Content-Type": "application/json",
|
|
238
|
+
Accept: "application/json",
|
|
239
|
+
...init.headers ?? {}
|
|
240
|
+
}
|
|
136
241
|
});
|
|
137
242
|
const body = await response.json().catch(() => ({}));
|
|
138
|
-
|
|
139
|
-
|
|
243
|
+
return { ok: response.ok, status: response.status, body };
|
|
244
|
+
}
|
|
245
|
+
function optString(args, key) {
|
|
246
|
+
if (args[key] == null) return void 0;
|
|
247
|
+
const value = String(args[key]).trim();
|
|
248
|
+
return value || void 0;
|
|
249
|
+
}
|
|
250
|
+
async function callArcMcpTool(apiKey, name, args, baseUrl) {
|
|
251
|
+
const def = ARC_MCP_TOOLS.find((tool) => tool.name === name);
|
|
252
|
+
if (!def) return null;
|
|
253
|
+
const origin = resolveArcAppOrigin({ baseUrl, apiKey });
|
|
254
|
+
if (def.kind === "growth" && def.growthTool) {
|
|
255
|
+
const response = await arcFetch(origin, apiKey, `/api/growth/tools/${encodeURIComponent(def.growthTool)}`, {
|
|
256
|
+
method: "POST",
|
|
257
|
+
body: JSON.stringify({ input: args })
|
|
258
|
+
});
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
typeof response.body.error === "string" ? response.body.error : `Arc tool failed (${response.status})`
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return response.body.result ?? response.body;
|
|
265
|
+
}
|
|
266
|
+
switch (name) {
|
|
267
|
+
case "arc_list_threads": {
|
|
268
|
+
const response = await arcFetch(origin, apiKey, "/api/growth/threads");
|
|
269
|
+
if (!response.ok) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
typeof response.body.error === "string" ? response.body.error : `List threads failed (${response.status})`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
return response.body;
|
|
275
|
+
}
|
|
276
|
+
case "arc_ensure_thread": {
|
|
277
|
+
const existingId = optString(args, "threadId");
|
|
278
|
+
if (existingId) {
|
|
279
|
+
const byId = await arcFetch(
|
|
280
|
+
origin,
|
|
281
|
+
apiKey,
|
|
282
|
+
`/api/growth/threads/${encodeURIComponent(existingId)}`
|
|
283
|
+
);
|
|
284
|
+
if (byId.ok) {
|
|
285
|
+
const thread2 = byId.body.thread;
|
|
286
|
+
if (thread2?.id) {
|
|
287
|
+
return { threadId: thread2.id, title: thread2.title ?? null };
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
const title = optString(args, "title") ?? MCP_THREAD_TITLE;
|
|
292
|
+
const byTitle = await arcFetch(
|
|
293
|
+
origin,
|
|
294
|
+
apiKey,
|
|
295
|
+
`/api/growth/threads?title=${encodeURIComponent(title)}`
|
|
296
|
+
);
|
|
297
|
+
if (byTitle.ok) {
|
|
298
|
+
const threads = Array.isArray(byTitle.body.threads) ? byTitle.body.threads : [];
|
|
299
|
+
const hit = threads.find(
|
|
300
|
+
(row) => row && typeof row === "object" && row.title === title
|
|
301
|
+
);
|
|
302
|
+
if (hit) return { threadId: hit.id, title: hit.title ?? title };
|
|
303
|
+
}
|
|
304
|
+
const created = await arcFetch(origin, apiKey, "/api/growth/threads", {
|
|
305
|
+
method: "POST",
|
|
306
|
+
body: JSON.stringify({ title })
|
|
307
|
+
});
|
|
308
|
+
if (!created.ok) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
typeof created.body.error === "string" ? created.body.error : `Create thread failed (${created.status})`
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
const thread = created.body.thread;
|
|
314
|
+
if (!thread?.id) throw new Error("Create thread returned no id");
|
|
315
|
+
return { threadId: thread.id, title: thread.title ?? title };
|
|
316
|
+
}
|
|
317
|
+
case "arc_message": {
|
|
318
|
+
const text = optString(args, "text");
|
|
319
|
+
if (!text) throw new Error("Missing required argument: text");
|
|
320
|
+
let threadId = optString(args, "threadId");
|
|
321
|
+
if (!threadId) {
|
|
322
|
+
const ensured = await callArcMcpTool(apiKey, "arc_ensure_thread", {}, baseUrl);
|
|
323
|
+
threadId = ensured.threadId;
|
|
324
|
+
}
|
|
325
|
+
const response = await arcFetch(
|
|
326
|
+
origin,
|
|
327
|
+
apiKey,
|
|
328
|
+
`/api/growth/threads/${encodeURIComponent(threadId)}/messages`,
|
|
329
|
+
{
|
|
330
|
+
method: "POST",
|
|
331
|
+
body: JSON.stringify({ text, sync: true })
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
if (!response.ok && response.status !== 500) {
|
|
335
|
+
throw new Error(
|
|
336
|
+
typeof response.body.error === "string" ? response.body.error : `Arc message failed (${response.status})`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
return { threadId, ...response.body };
|
|
340
|
+
}
|
|
341
|
+
case "arc_list_approvals": {
|
|
342
|
+
const response = await arcFetch(origin, apiKey, "/api/growth/approvals");
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
throw new Error(
|
|
345
|
+
typeof response.body.error === "string" ? response.body.error : `List approvals failed (${response.status})`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
return response.body;
|
|
349
|
+
}
|
|
350
|
+
case "arc_approve":
|
|
351
|
+
case "arc_reject": {
|
|
352
|
+
const messageId = optString(args, "messageId");
|
|
353
|
+
if (!messageId) throw new Error("Missing required argument: messageId");
|
|
354
|
+
const decision = name === "arc_approve" ? "approve" : "reject";
|
|
355
|
+
const response = await arcFetch(
|
|
356
|
+
origin,
|
|
357
|
+
apiKey,
|
|
358
|
+
`/api/growth/approvals/${encodeURIComponent(messageId)}`,
|
|
359
|
+
{
|
|
360
|
+
method: "POST",
|
|
361
|
+
body: JSON.stringify({ decision, sync: true })
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
if (!response.ok && response.status !== 500) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
typeof response.body.error === "string" ? response.body.error : `Approval ${decision} failed (${response.status})`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
return response.body;
|
|
370
|
+
}
|
|
371
|
+
default:
|
|
372
|
+
throw new Error(`Unknown Arc MCP tool: ${name}`);
|
|
140
373
|
}
|
|
141
|
-
return body.result;
|
|
142
374
|
}
|
|
143
375
|
|
|
144
376
|
// src/tools.ts
|
|
@@ -148,7 +380,7 @@ function textResult(value, isError = false) {
|
|
|
148
380
|
...isError ? { isError: true } : {}
|
|
149
381
|
};
|
|
150
382
|
}
|
|
151
|
-
function
|
|
383
|
+
function optString2(args, key) {
|
|
152
384
|
if (args[key] == null) return void 0;
|
|
153
385
|
const value = String(args[key]).trim();
|
|
154
386
|
return value || void 0;
|
|
@@ -195,10 +427,10 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
195
427
|
}
|
|
196
428
|
switch (name) {
|
|
197
429
|
case "send_email": {
|
|
198
|
-
const from =
|
|
199
|
-
const to =
|
|
200
|
-
const subject =
|
|
201
|
-
const templateId =
|
|
430
|
+
const from = optString2(args, "from");
|
|
431
|
+
const to = optString2(args, "to");
|
|
432
|
+
const subject = optString2(args, "subject");
|
|
433
|
+
const templateId = optString2(args, "template_id") || optString2(args, "template_alias");
|
|
202
434
|
if (!from) return textResult("Missing required argument: from", true);
|
|
203
435
|
if (!to) return textResult("Missing required argument: to", true);
|
|
204
436
|
if (!templateId && !subject) {
|
|
@@ -209,9 +441,9 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
209
441
|
from,
|
|
210
442
|
to,
|
|
211
443
|
...subject ? { subject } : {},
|
|
212
|
-
html:
|
|
213
|
-
text:
|
|
214
|
-
reply_to:
|
|
444
|
+
html: optString2(args, "html"),
|
|
445
|
+
text: optString2(args, "text"),
|
|
446
|
+
reply_to: optString2(args, "reply_to"),
|
|
215
447
|
...templateId ? { template: { id: templateId, ...variables ? { variables } : {} } } : {}
|
|
216
448
|
});
|
|
217
449
|
return textResult(result);
|
|
@@ -219,12 +451,12 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
219
451
|
case "list_emails": {
|
|
220
452
|
const result = await client.emails.list({
|
|
221
453
|
limit: optNumber(args, "limit"),
|
|
222
|
-
cursor:
|
|
454
|
+
cursor: optString2(args, "cursor")
|
|
223
455
|
});
|
|
224
456
|
return textResult(result);
|
|
225
457
|
}
|
|
226
458
|
case "get_email": {
|
|
227
|
-
const id =
|
|
459
|
+
const id = optString2(args, "id");
|
|
228
460
|
if (!id) return textResult("Missing required argument: id", true);
|
|
229
461
|
return textResult(await client.emails.get(id));
|
|
230
462
|
}
|
|
@@ -248,7 +480,7 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
248
480
|
return textResult(result);
|
|
249
481
|
}
|
|
250
482
|
case "verify_domain": {
|
|
251
|
-
const domain =
|
|
483
|
+
const domain = optString2(args, "domain");
|
|
252
484
|
if (!domain) return textResult("Missing required argument: domain", true);
|
|
253
485
|
const result = await client.domains.verify(domain);
|
|
254
486
|
return textResult(result);
|
|
@@ -256,12 +488,12 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
256
488
|
case "list_domains": {
|
|
257
489
|
const result = await client.domains.list({
|
|
258
490
|
limit: optNumber(args, "limit"),
|
|
259
|
-
cursor:
|
|
491
|
+
cursor: optString2(args, "cursor")
|
|
260
492
|
});
|
|
261
493
|
return textResult(result);
|
|
262
494
|
}
|
|
263
495
|
case "create_domain": {
|
|
264
|
-
const domainName =
|
|
496
|
+
const domainName = optString2(args, "name");
|
|
265
497
|
if (!domainName) return textResult("Missing required argument: name", true);
|
|
266
498
|
const inbound = optBoolean(args, "inbound_enabled");
|
|
267
499
|
return textResult(
|
|
@@ -275,12 +507,12 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
275
507
|
return textResult(
|
|
276
508
|
await client.webhooks.list({
|
|
277
509
|
limit: optNumber(args, "limit"),
|
|
278
|
-
cursor:
|
|
510
|
+
cursor: optString2(args, "cursor")
|
|
279
511
|
})
|
|
280
512
|
);
|
|
281
513
|
}
|
|
282
514
|
case "create_webhook": {
|
|
283
|
-
const url =
|
|
515
|
+
const url = optString2(args, "url");
|
|
284
516
|
if (!url) return textResult("Missing required argument: url", true);
|
|
285
517
|
const events = optStringArray(args, "events");
|
|
286
518
|
return textResult(
|
|
@@ -291,7 +523,7 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
291
523
|
);
|
|
292
524
|
}
|
|
293
525
|
case "delete_webhook": {
|
|
294
|
-
const id =
|
|
526
|
+
const id = optString2(args, "id");
|
|
295
527
|
if (!id) return textResult("Missing required argument: id", true);
|
|
296
528
|
return textResult(await client.webhooks.delete(id));
|
|
297
529
|
}
|
|
@@ -299,67 +531,67 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
299
531
|
return textResult(
|
|
300
532
|
await client.suppressions.list({
|
|
301
533
|
limit: optNumber(args, "limit"),
|
|
302
|
-
cursor:
|
|
303
|
-
email:
|
|
534
|
+
cursor: optString2(args, "cursor"),
|
|
535
|
+
email: optString2(args, "email")
|
|
304
536
|
})
|
|
305
537
|
);
|
|
306
538
|
}
|
|
307
539
|
case "add_suppression": {
|
|
308
|
-
const email =
|
|
540
|
+
const email = optString2(args, "email");
|
|
309
541
|
if (!email) return textResult("Missing required argument: email", true);
|
|
310
542
|
return textResult(
|
|
311
543
|
await client.suppressions.create({
|
|
312
544
|
email,
|
|
313
|
-
reason:
|
|
545
|
+
reason: optString2(args, "reason")
|
|
314
546
|
})
|
|
315
547
|
);
|
|
316
548
|
}
|
|
317
549
|
case "remove_suppression": {
|
|
318
|
-
const idOrEmail =
|
|
550
|
+
const idOrEmail = optString2(args, "id") ?? optString2(args, "email");
|
|
319
551
|
if (!idOrEmail) {
|
|
320
552
|
return textResult("Missing required argument: id or email", true);
|
|
321
553
|
}
|
|
322
554
|
return textResult(await client.suppressions.remove(idOrEmail));
|
|
323
555
|
}
|
|
324
556
|
case "list_templates": {
|
|
325
|
-
const status =
|
|
557
|
+
const status = optString2(args, "status");
|
|
326
558
|
return textResult(
|
|
327
559
|
await client.templates.list({
|
|
328
560
|
limit: optNumber(args, "limit"),
|
|
329
|
-
cursor:
|
|
561
|
+
cursor: optString2(args, "cursor"),
|
|
330
562
|
...status === "draft" || status === "published" ? { status } : {}
|
|
331
563
|
})
|
|
332
564
|
);
|
|
333
565
|
}
|
|
334
566
|
case "get_template": {
|
|
335
|
-
const idOrAlias =
|
|
567
|
+
const idOrAlias = optString2(args, "id") ?? optString2(args, "alias");
|
|
336
568
|
if (!idOrAlias) return textResult("Missing required argument: id or alias", true);
|
|
337
569
|
return textResult(await client.templates.get(idOrAlias));
|
|
338
570
|
}
|
|
339
571
|
case "create_template": {
|
|
340
|
-
const name2 =
|
|
341
|
-
const subjectArg =
|
|
572
|
+
const name2 = optString2(args, "name");
|
|
573
|
+
const subjectArg = optString2(args, "subject");
|
|
342
574
|
if (!name2) return textResult("Missing required argument: name", true);
|
|
343
575
|
if (!subjectArg) return textResult("Missing required argument: subject", true);
|
|
344
|
-
const format =
|
|
576
|
+
const format = optString2(args, "format");
|
|
345
577
|
return textResult(
|
|
346
578
|
await client.templates.create({
|
|
347
579
|
name: name2,
|
|
348
580
|
subject: subjectArg,
|
|
349
581
|
...format === "blocks" || format === "html" ? { format } : {},
|
|
350
|
-
html:
|
|
351
|
-
text:
|
|
352
|
-
alias:
|
|
582
|
+
html: optString2(args, "html"),
|
|
583
|
+
text: optString2(args, "text"),
|
|
584
|
+
alias: optString2(args, "alias")
|
|
353
585
|
})
|
|
354
586
|
);
|
|
355
587
|
}
|
|
356
588
|
case "publish_template": {
|
|
357
|
-
const idOrAlias =
|
|
589
|
+
const idOrAlias = optString2(args, "id") ?? optString2(args, "alias");
|
|
358
590
|
if (!idOrAlias) return textResult("Missing required argument: id or alias", true);
|
|
359
591
|
return textResult(await client.templates.publish(idOrAlias));
|
|
360
592
|
}
|
|
361
593
|
case "send_test_webhook_event": {
|
|
362
|
-
const event =
|
|
594
|
+
const event = optString2(args, "event");
|
|
363
595
|
if (!event || !EMAIL_WEBHOOK_EVENTS.has(event)) {
|
|
364
596
|
return textResult(
|
|
365
597
|
`Missing or invalid event. Use one of: ${[...EMAIL_WEBHOOK_EVENTS].join(", ")}`,
|
|
@@ -369,7 +601,7 @@ async function callMcpTool(client, name, args, options = {}) {
|
|
|
369
601
|
return textResult(
|
|
370
602
|
await client.emails.testWebhook({
|
|
371
603
|
event,
|
|
372
|
-
email_id:
|
|
604
|
+
email_id: optString2(args, "email_id"),
|
|
373
605
|
deliver: optBoolean(args, "deliver")
|
|
374
606
|
})
|
|
375
607
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supersendtx-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SuperSend TX MCP server —
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "SuperSend TX MCP server — mail tools plus Arc agent-first tools for Cursor and Claude",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
43
|
-
"supersendtx": "0.15.
|
|
43
|
+
"supersendtx": "0.15.3"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"tsup": "^8.5.0",
|