@buzzposter/mcp 0.3.5 → 0.3.7
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 +540 -120
- package/dist/tools.d.ts +22 -1
- package/dist/tools.js +534 -120
- package/package.json +1 -1
package/dist/tools.js
CHANGED
|
@@ -112,6 +112,79 @@ var BuzzPosterClient = class {
|
|
|
112
112
|
async uploadFromUrl(data) {
|
|
113
113
|
return this.request("POST", "/api/v1/media/upload-from-url", data);
|
|
114
114
|
}
|
|
115
|
+
async uploadFile(filePath, filename) {
|
|
116
|
+
const fs4 = await import("fs");
|
|
117
|
+
const pathMod = await import("path");
|
|
118
|
+
const buffer = fs4.readFileSync(filePath);
|
|
119
|
+
const name = filename || pathMod.basename(filePath);
|
|
120
|
+
const ext = pathMod.extname(name).toLowerCase();
|
|
121
|
+
const mimeMap = {
|
|
122
|
+
".jpg": "image/jpeg",
|
|
123
|
+
".jpeg": "image/jpeg",
|
|
124
|
+
".png": "image/png",
|
|
125
|
+
".gif": "image/gif",
|
|
126
|
+
".webp": "image/webp",
|
|
127
|
+
".svg": "image/svg+xml",
|
|
128
|
+
".mp4": "video/mp4",
|
|
129
|
+
".mov": "video/quicktime",
|
|
130
|
+
".webm": "video/webm"
|
|
131
|
+
};
|
|
132
|
+
const mime = mimeMap[ext] || "application/octet-stream";
|
|
133
|
+
const formData = new FormData();
|
|
134
|
+
formData.append("file", new Blob([buffer], { type: mime }), name);
|
|
135
|
+
const url = new URL(`${this.baseUrl}/api/v1/media/upload`);
|
|
136
|
+
const headers = {
|
|
137
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
138
|
+
};
|
|
139
|
+
if (this.organizationId) {
|
|
140
|
+
headers["X-Organization-Id"] = this.organizationId;
|
|
141
|
+
}
|
|
142
|
+
const res = await fetch(url, { method: "POST", headers, body: formData });
|
|
143
|
+
if (!res.ok) {
|
|
144
|
+
const errorBody = await res.json().catch(() => ({ message: res.statusText }));
|
|
145
|
+
let message = `API error (${res.status})`;
|
|
146
|
+
if (errorBody && typeof errorBody === "object") {
|
|
147
|
+
const b = errorBody;
|
|
148
|
+
if (typeof b.message === "string" && b.message) message = b.message;
|
|
149
|
+
else if (typeof b.error === "string" && b.error) message = b.error;
|
|
150
|
+
}
|
|
151
|
+
throw new Error(`BuzzPoster API error (${res.status}): ${message}`);
|
|
152
|
+
}
|
|
153
|
+
const text = await res.text();
|
|
154
|
+
return text ? JSON.parse(text) : void 0;
|
|
155
|
+
}
|
|
156
|
+
async uploadBase64(data, filename, contentType) {
|
|
157
|
+
const buffer = Buffer.from(data, "base64");
|
|
158
|
+
const mime = contentType || "application/octet-stream";
|
|
159
|
+
const formData = new FormData();
|
|
160
|
+
formData.append("file", new Blob([buffer], { type: mime }), filename);
|
|
161
|
+
const url = new URL(`${this.baseUrl}/api/v1/media/upload`);
|
|
162
|
+
const headers = {
|
|
163
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
164
|
+
};
|
|
165
|
+
if (this.organizationId) {
|
|
166
|
+
headers["X-Organization-Id"] = this.organizationId;
|
|
167
|
+
}
|
|
168
|
+
const res = await fetch(url, { method: "POST", headers, body: formData });
|
|
169
|
+
if (!res.ok) {
|
|
170
|
+
const errorBody = await res.json().catch(() => ({ message: res.statusText }));
|
|
171
|
+
let message = `API error (${res.status})`;
|
|
172
|
+
if (errorBody && typeof errorBody === "object") {
|
|
173
|
+
const b = errorBody;
|
|
174
|
+
if (typeof b.message === "string" && b.message) message = b.message;
|
|
175
|
+
else if (typeof b.error === "string" && b.error) message = b.error;
|
|
176
|
+
}
|
|
177
|
+
throw new Error(`BuzzPoster API error (${res.status}): ${message}`);
|
|
178
|
+
}
|
|
179
|
+
const text = await res.text();
|
|
180
|
+
return text ? JSON.parse(text) : void 0;
|
|
181
|
+
}
|
|
182
|
+
async presignUpload(filename, contentType) {
|
|
183
|
+
return this.request("POST", "/api/v1/media/presign", { filename, content_type: contentType });
|
|
184
|
+
}
|
|
185
|
+
async confirmUpload(key, filename, contentType) {
|
|
186
|
+
return this.request("POST", "/api/v1/media/confirm-upload", { key, filename, content_type: contentType });
|
|
187
|
+
}
|
|
115
188
|
async listMedia() {
|
|
116
189
|
return this.request("GET", "/api/v1/media");
|
|
117
190
|
}
|
|
@@ -1252,14 +1325,17 @@ function registerMediaTools(server, client) {
|
|
|
1252
1325
|
"manage_media",
|
|
1253
1326
|
{
|
|
1254
1327
|
title: "Manage Media",
|
|
1255
|
-
description: "Browse assets gallery, upload from URL, list files, or delete media.",
|
|
1328
|
+
description: "Browse assets gallery, upload from URL, local file, or base64 data, list files, or delete media.",
|
|
1256
1329
|
inputSchema: {
|
|
1257
|
-
action: z3.enum(["get_assets", "upload", "list", "delete"]),
|
|
1330
|
+
action: z3.enum(["get_assets", "upload", "upload_file", "upload_base64", "presign", "confirm_upload", "list", "delete"]),
|
|
1258
1331
|
limit: z3.number().optional().describe("Max assets to return (get_assets, default 10, max 20)"),
|
|
1259
1332
|
url: z3.string().optional().describe("Public URL to upload (upload)"),
|
|
1260
|
-
|
|
1333
|
+
file_path: z3.string().optional().describe("Local file path to upload (upload_file)"),
|
|
1334
|
+
data: z3.string().optional().describe("Base64-encoded file contents (upload_base64)"),
|
|
1335
|
+
content_type: z3.string().optional().describe("MIME type e.g. image/png (upload_base64, presign, confirm_upload)"),
|
|
1336
|
+
filename: z3.string().optional().describe("Filename (upload, upload_file, upload_base64, presign, confirm_upload)"),
|
|
1261
1337
|
folder: z3.string().optional().describe("Storage folder path (upload)"),
|
|
1262
|
-
key: z3.string().optional().describe("Media file key/path (delete)"),
|
|
1338
|
+
key: z3.string().optional().describe("Media file key/path (delete, confirm_upload)"),
|
|
1263
1339
|
confirmed: z3.boolean().default(false).describe("Confirm deletion (delete)")
|
|
1264
1340
|
},
|
|
1265
1341
|
annotations: {
|
|
@@ -1336,6 +1412,92 @@ function registerMediaTools(server, client) {
|
|
|
1336
1412
|
content: [{ type: "text", text: lines.join("\n") }]
|
|
1337
1413
|
};
|
|
1338
1414
|
}
|
|
1415
|
+
if (args.action === "upload_file") {
|
|
1416
|
+
if (!args.file_path) {
|
|
1417
|
+
return { content: [{ type: "text", text: "file_path is required for upload_file." }], isError: true };
|
|
1418
|
+
}
|
|
1419
|
+
if (!fs2.existsSync(args.file_path)) {
|
|
1420
|
+
return { content: [{ type: "text", text: `File not found: ${args.file_path}` }], isError: true };
|
|
1421
|
+
}
|
|
1422
|
+
const result = await client.uploadFile(args.file_path, args.filename);
|
|
1423
|
+
const lines = [];
|
|
1424
|
+
lines.push("## Upload Complete");
|
|
1425
|
+
lines.push("");
|
|
1426
|
+
lines.push(`**URL:** ${result.url ?? "unknown"}`);
|
|
1427
|
+
lines.push(`**Filename:** ${result.filename ?? "unknown"}`);
|
|
1428
|
+
lines.push(`**Size:** ${formatSize(result.size)}`);
|
|
1429
|
+
lines.push(`**Type:** ${result.mimeType ?? "unknown"}`);
|
|
1430
|
+
return {
|
|
1431
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
if (args.action === "upload_base64") {
|
|
1435
|
+
if (!args.data) {
|
|
1436
|
+
return { content: [{ type: "text", text: "data (base64 string) is required for upload_base64." }], isError: true };
|
|
1437
|
+
}
|
|
1438
|
+
if (!args.filename) {
|
|
1439
|
+
return { content: [{ type: "text", text: "filename is required for upload_base64." }], isError: true };
|
|
1440
|
+
}
|
|
1441
|
+
const result = await client.uploadBase64(args.data, args.filename, args.content_type);
|
|
1442
|
+
const lines = [];
|
|
1443
|
+
lines.push("## Upload Complete");
|
|
1444
|
+
lines.push("");
|
|
1445
|
+
lines.push(`**URL:** ${result.url ?? "unknown"}`);
|
|
1446
|
+
lines.push(`**Filename:** ${result.filename ?? "unknown"}`);
|
|
1447
|
+
lines.push(`**Size:** ${formatSize(result.size)}`);
|
|
1448
|
+
lines.push(`**Type:** ${result.mimeType ?? "unknown"}`);
|
|
1449
|
+
return {
|
|
1450
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
if (args.action === "presign") {
|
|
1454
|
+
if (!args.filename) {
|
|
1455
|
+
return { content: [{ type: "text", text: "filename is required for presign." }], isError: true };
|
|
1456
|
+
}
|
|
1457
|
+
if (!args.content_type) {
|
|
1458
|
+
return { content: [{ type: "text", text: "content_type is required for presign (e.g. image/png)." }], isError: true };
|
|
1459
|
+
}
|
|
1460
|
+
const result = await client.presignUpload(args.filename, args.content_type);
|
|
1461
|
+
const lines = [];
|
|
1462
|
+
lines.push("## Presigned Upload URL");
|
|
1463
|
+
lines.push("");
|
|
1464
|
+
lines.push(`**Upload URL:** ${result.upload_url}`);
|
|
1465
|
+
lines.push(`**CDN URL:** ${result.cdn_url}`);
|
|
1466
|
+
lines.push(`**Key:** ${result.key}`);
|
|
1467
|
+
lines.push(`**Expires:** ${result.expires_at}`);
|
|
1468
|
+
lines.push("");
|
|
1469
|
+
lines.push("**Step 1:** Upload the file:");
|
|
1470
|
+
lines.push("```");
|
|
1471
|
+
lines.push(`curl -X PUT -H "Content-Type: ${args.content_type}" --data-binary @${args.filename} "${result.upload_url}"`);
|
|
1472
|
+
lines.push("```");
|
|
1473
|
+
lines.push("");
|
|
1474
|
+
lines.push(`**Step 2:** Register the upload by calling this tool with action=confirm_upload, key="${result.key}", filename="${args.filename}", content_type="${args.content_type}"`);
|
|
1475
|
+
return {
|
|
1476
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
if (args.action === "confirm_upload") {
|
|
1480
|
+
if (!args.key) {
|
|
1481
|
+
return { content: [{ type: "text", text: "key is required for confirm_upload." }], isError: true };
|
|
1482
|
+
}
|
|
1483
|
+
if (!args.filename) {
|
|
1484
|
+
return { content: [{ type: "text", text: "filename is required for confirm_upload." }], isError: true };
|
|
1485
|
+
}
|
|
1486
|
+
if (!args.content_type) {
|
|
1487
|
+
return { content: [{ type: "text", text: "content_type is required for confirm_upload." }], isError: true };
|
|
1488
|
+
}
|
|
1489
|
+
const result = await client.confirmUpload(args.key, args.filename, args.content_type);
|
|
1490
|
+
const lines = [];
|
|
1491
|
+
lines.push("## Upload Confirmed");
|
|
1492
|
+
lines.push("");
|
|
1493
|
+
lines.push(`**URL:** ${result.url}`);
|
|
1494
|
+
lines.push(`**Filename:** ${result.filename}`);
|
|
1495
|
+
lines.push(`**Size:** ${formatSize(result.size)}`);
|
|
1496
|
+
lines.push(`**Type:** ${result.mimeType}`);
|
|
1497
|
+
return {
|
|
1498
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1339
1501
|
if (args.action === "list") {
|
|
1340
1502
|
const result = await client.listMedia();
|
|
1341
1503
|
const items = result?.media ?? [];
|
|
@@ -1378,16 +1540,267 @@ This will permanently delete this media file. Call this tool again with confirme
|
|
|
1378
1540
|
);
|
|
1379
1541
|
}
|
|
1380
1542
|
|
|
1381
|
-
// src/tools/
|
|
1543
|
+
// src/tools/newsletter.ts
|
|
1382
1544
|
import { z as z4 } from "zod";
|
|
1545
|
+
function registerNewsletterTools(server, client, options = {}) {
|
|
1546
|
+
server.tool(
|
|
1547
|
+
"manage_newsletters",
|
|
1548
|
+
"Create, update, send, schedule, or list newsletters.\n\nIMPORTANT \u2014 Template-based creation:\n1. Call get_context with include_newsletter_template=true to get the user's template with section IDs\n2. Call create with template_id + sections array (NOT raw content HTML)\n3. The server assembles styled HTML from the template design + your section content\n\nOnly use raw content HTML if the user has no templates or explicitly asks for custom HTML.",
|
|
1549
|
+
{
|
|
1550
|
+
action: z4.enum(["create", "update", "send", "schedule", "list"]),
|
|
1551
|
+
broadcast_id: z4.string().optional().describe("Newsletter ID (update/send/schedule)"),
|
|
1552
|
+
subject: z4.string().optional().describe("Subject line (create/update, also search keyword for list)"),
|
|
1553
|
+
content: z4.string().optional().describe("Raw HTML content (create/update). Only use when no template is available or user explicitly requests custom HTML. When a template exists, use sections instead."),
|
|
1554
|
+
sections: z4.array(z4.object({
|
|
1555
|
+
section_id: z4.string().describe("Section ID from the template's section config"),
|
|
1556
|
+
heading: z4.string().optional(),
|
|
1557
|
+
body: z4.string().optional().describe("Section body (basic HTML OK: p, strong, em, a, ul/li)"),
|
|
1558
|
+
image_url: z4.string().optional(),
|
|
1559
|
+
image_alt: z4.string().optional(),
|
|
1560
|
+
cta_text: z4.string().optional(),
|
|
1561
|
+
cta_url: z4.string().optional(),
|
|
1562
|
+
quote: z4.string().optional(),
|
|
1563
|
+
quote_attribution: z4.string().optional()
|
|
1564
|
+
})).optional().describe("Structured section content matching the template's section IDs. PREFERRED over raw content \u2014 preserves the user's template design and style."),
|
|
1565
|
+
preview_text: z4.string().optional().describe("Preview text (create/update)"),
|
|
1566
|
+
template_id: z4.string().optional().describe("BuzzPoster template ID (from newsletter_templates). Used with sections to auto-generate HTML."),
|
|
1567
|
+
esp_template_id: z4.string().optional().describe("ESP-native template ID (Kit: email_template_id, Beehiiv: post_template_id). Distinct from template_id which references BuzzPoster templates."),
|
|
1568
|
+
scheduled_for: z4.string().optional().describe("ISO datetime (schedule)"),
|
|
1569
|
+
page: z4.string().optional().describe("Page number (list)"),
|
|
1570
|
+
status: z4.string().optional().describe("Filter status (list)"),
|
|
1571
|
+
from_date: z4.string().optional().describe("ISO date from (list)"),
|
|
1572
|
+
to_date: z4.string().optional().describe("ISO date to (list)"),
|
|
1573
|
+
confirmed: z4.boolean().default(false).describe("Confirm action (send/schedule)")
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
title: "Manage Newsletters",
|
|
1577
|
+
readOnlyHint: false,
|
|
1578
|
+
destructiveHint: true,
|
|
1579
|
+
idempotentHint: false,
|
|
1580
|
+
openWorldHint: true
|
|
1581
|
+
},
|
|
1582
|
+
async (args) => {
|
|
1583
|
+
if (args.action === "create") {
|
|
1584
|
+
if (!args.subject) {
|
|
1585
|
+
return { content: [{ type: "text", text: "subject is required for create." }], isError: true };
|
|
1586
|
+
}
|
|
1587
|
+
if (!args.content && !args.sections) {
|
|
1588
|
+
return { content: [{ type: "text", text: "content or sections is required for create." }], isError: true };
|
|
1589
|
+
}
|
|
1590
|
+
const payload = {
|
|
1591
|
+
subject: args.subject,
|
|
1592
|
+
previewText: args.preview_text
|
|
1593
|
+
};
|
|
1594
|
+
if (args.content) payload.content = args.content;
|
|
1595
|
+
if (args.sections) payload.sections = args.sections;
|
|
1596
|
+
if (args.template_id) payload.templateId = args.template_id;
|
|
1597
|
+
if (args.esp_template_id) payload.espTemplateId = args.esp_template_id;
|
|
1598
|
+
const result = await client.createBroadcast(payload);
|
|
1599
|
+
const r = result;
|
|
1600
|
+
const response = {
|
|
1601
|
+
id: r.id,
|
|
1602
|
+
subject: args.subject,
|
|
1603
|
+
content: args.content ?? r.renderedHtml ?? void 0,
|
|
1604
|
+
previewText: args.preview_text,
|
|
1605
|
+
previewUrl: r.previewUrl,
|
|
1606
|
+
editUrl: r.editUrl,
|
|
1607
|
+
status: "draft"
|
|
1608
|
+
};
|
|
1609
|
+
return {
|
|
1610
|
+
content: [
|
|
1611
|
+
{ type: "text", text: JSON.stringify(response) }
|
|
1612
|
+
]
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
if (args.action === "update") {
|
|
1616
|
+
if (!args.broadcast_id) {
|
|
1617
|
+
return { content: [{ type: "text", text: "broadcast_id is required for update." }], isError: true };
|
|
1618
|
+
}
|
|
1619
|
+
const data = {};
|
|
1620
|
+
if (args.subject) data.subject = args.subject;
|
|
1621
|
+
if (args.content) data.content = args.content;
|
|
1622
|
+
if (args.preview_text) data.previewText = args.preview_text;
|
|
1623
|
+
const result = await client.updateBroadcast(args.broadcast_id, data);
|
|
1624
|
+
const r = result;
|
|
1625
|
+
const response = {
|
|
1626
|
+
id: args.broadcast_id,
|
|
1627
|
+
subject: args.subject ?? r.subject,
|
|
1628
|
+
content: args.content ?? r.renderedHtml ?? void 0,
|
|
1629
|
+
previewText: args.preview_text,
|
|
1630
|
+
previewUrl: r.previewUrl,
|
|
1631
|
+
editUrl: r.editUrl,
|
|
1632
|
+
status: r.status ?? "draft"
|
|
1633
|
+
};
|
|
1634
|
+
return {
|
|
1635
|
+
content: [
|
|
1636
|
+
{ type: "text", text: JSON.stringify(response) }
|
|
1637
|
+
]
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
if (args.action === "send") {
|
|
1641
|
+
if (!options.allowDirectSend) {
|
|
1642
|
+
return {
|
|
1643
|
+
content: [{
|
|
1644
|
+
type: "text",
|
|
1645
|
+
text: "Direct send is disabled. Enable it in your BuzzPoster dashboard settings under Publishing Rules."
|
|
1646
|
+
}],
|
|
1647
|
+
isError: true
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
if (!args.broadcast_id) {
|
|
1651
|
+
return { content: [{ type: "text", text: "broadcast_id is required for send." }], isError: true };
|
|
1652
|
+
}
|
|
1653
|
+
if (args.confirmed !== true) {
|
|
1654
|
+
let subscriberCount = "unknown";
|
|
1655
|
+
let rulesText = "";
|
|
1656
|
+
try {
|
|
1657
|
+
const subData = await client.listSubscribers({ perPage: "1" });
|
|
1658
|
+
subscriberCount = String(subData?.totalCount ?? subData?.total ?? subData?.subscribers?.length ?? "unknown");
|
|
1659
|
+
} catch {
|
|
1660
|
+
}
|
|
1661
|
+
try {
|
|
1662
|
+
const rules = await client.getPublishingRules();
|
|
1663
|
+
rulesText = `
|
|
1664
|
+
### Safety Checks
|
|
1665
|
+
`;
|
|
1666
|
+
rulesText += `- Double confirmation required: ${rules.requireDoubleConfirmNewsletter ? "**yes**" : "no"}
|
|
1667
|
+
`;
|
|
1668
|
+
rulesText += `- Immediate send allowed: ${rules.allowImmediateSend ? "yes" : "**no**"}
|
|
1669
|
+
`;
|
|
1670
|
+
if (rules.requiredDisclaimer) {
|
|
1671
|
+
rulesText += `- Required disclaimer: "${rules.requiredDisclaimer}"
|
|
1672
|
+
`;
|
|
1673
|
+
}
|
|
1674
|
+
} catch {
|
|
1675
|
+
}
|
|
1676
|
+
let espText = "";
|
|
1677
|
+
try {
|
|
1678
|
+
const account = await client.getAccount();
|
|
1679
|
+
espText = account?.espProvider ? `**ESP:** ${account.espProvider}
|
|
1680
|
+
` : "";
|
|
1681
|
+
} catch {
|
|
1682
|
+
}
|
|
1683
|
+
const preview = `## Send Newsletter Confirmation
|
|
1684
|
+
|
|
1685
|
+
**Broadcast ID:** ${args.broadcast_id}
|
|
1686
|
+
**Subscribers:** ~${subscriberCount} recipients
|
|
1687
|
+
` + espText + rulesText + `
|
|
1688
|
+
**This action cannot be undone.** Once sent, the email goes to every subscriber.
|
|
1689
|
+
|
|
1690
|
+
Call this tool again with confirmed=true to send.`;
|
|
1691
|
+
return { content: [{ type: "text", text: preview }] };
|
|
1692
|
+
}
|
|
1693
|
+
await client.sendBroadcast(args.broadcast_id);
|
|
1694
|
+
return {
|
|
1695
|
+
content: [{ type: "text", text: "Newsletter sent successfully." }]
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
if (args.action === "schedule") {
|
|
1699
|
+
if (!args.broadcast_id) {
|
|
1700
|
+
return { content: [{ type: "text", text: "broadcast_id is required for schedule." }], isError: true };
|
|
1701
|
+
}
|
|
1702
|
+
if (!args.scheduled_for) {
|
|
1703
|
+
return { content: [{ type: "text", text: "scheduled_for is required for schedule." }], isError: true };
|
|
1704
|
+
}
|
|
1705
|
+
if (args.confirmed !== true) {
|
|
1706
|
+
let subscriberCount = "unknown";
|
|
1707
|
+
let rulesText = "";
|
|
1708
|
+
try {
|
|
1709
|
+
const subData = await client.listSubscribers({ perPage: "1" });
|
|
1710
|
+
subscriberCount = String(
|
|
1711
|
+
subData?.totalCount ?? subData?.total ?? subData?.subscribers?.length ?? "unknown"
|
|
1712
|
+
);
|
|
1713
|
+
} catch {
|
|
1714
|
+
}
|
|
1715
|
+
try {
|
|
1716
|
+
const rules = await client.getPublishingRules();
|
|
1717
|
+
rulesText = `
|
|
1718
|
+
### Safety Checks
|
|
1719
|
+
`;
|
|
1720
|
+
rulesText += `- Double confirmation required: ${rules.requireDoubleConfirmNewsletter ? "**yes**" : "no"}
|
|
1721
|
+
`;
|
|
1722
|
+
rulesText += `- Immediate send allowed: ${rules.allowImmediateSend ? "yes" : "**no**"}
|
|
1723
|
+
`;
|
|
1724
|
+
if (rules.requiredDisclaimer) {
|
|
1725
|
+
rulesText += `- Required disclaimer: "${rules.requiredDisclaimer}"
|
|
1726
|
+
`;
|
|
1727
|
+
}
|
|
1728
|
+
} catch {
|
|
1729
|
+
}
|
|
1730
|
+
let espText = "";
|
|
1731
|
+
try {
|
|
1732
|
+
const account = await client.getAccount();
|
|
1733
|
+
espText = account?.espProvider ? `**ESP:** ${account.espProvider}
|
|
1734
|
+
` : "";
|
|
1735
|
+
} catch {
|
|
1736
|
+
}
|
|
1737
|
+
const preview = `## Schedule Newsletter Confirmation
|
|
1738
|
+
|
|
1739
|
+
**Broadcast ID:** ${args.broadcast_id}
|
|
1740
|
+
**Scheduled for:** ${args.scheduled_for}
|
|
1741
|
+
**Subscribers:** ~${subscriberCount} recipients
|
|
1742
|
+
` + espText + rulesText + `
|
|
1743
|
+
Scheduling can typically be cancelled or rescheduled later, but please verify the time is correct.
|
|
1744
|
+
|
|
1745
|
+
Call this tool again with confirmed=true to schedule.`;
|
|
1746
|
+
return { content: [{ type: "text", text: preview }] };
|
|
1747
|
+
}
|
|
1748
|
+
await client.scheduleBroadcast(args.broadcast_id, {
|
|
1749
|
+
scheduledFor: args.scheduled_for
|
|
1750
|
+
});
|
|
1751
|
+
return {
|
|
1752
|
+
content: [{
|
|
1753
|
+
type: "text",
|
|
1754
|
+
text: `Newsletter scheduled successfully for ${args.scheduled_for}.`
|
|
1755
|
+
}]
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
if (args.action === "list") {
|
|
1759
|
+
const params = {};
|
|
1760
|
+
if (args.page) params.page = args.page;
|
|
1761
|
+
if (args.status) params.status = args.status;
|
|
1762
|
+
if (args.from_date) params.fromDate = args.from_date;
|
|
1763
|
+
if (args.to_date) params.toDate = args.to_date;
|
|
1764
|
+
if (args.subject) params.subject = args.subject;
|
|
1765
|
+
const result = await client.listBroadcasts(params);
|
|
1766
|
+
const broadcasts = result?.broadcasts ?? [];
|
|
1767
|
+
if (broadcasts.length === 0) {
|
|
1768
|
+
return {
|
|
1769
|
+
content: [{ type: "text", text: "No newsletters found matching your filters." }]
|
|
1770
|
+
};
|
|
1771
|
+
}
|
|
1772
|
+
let text = `## Newsletters (${broadcasts.length}`;
|
|
1773
|
+
if (result?.totalCount != null) text += ` of ${result.totalCount}`;
|
|
1774
|
+
text += ")\n\n";
|
|
1775
|
+
for (const b of broadcasts) {
|
|
1776
|
+
const status = (b.status ?? "unknown").toUpperCase();
|
|
1777
|
+
const date = b.sentAt ? new Date(b.sentAt).toLocaleString() : b.createdAt ? new Date(b.createdAt).toLocaleString() : "";
|
|
1778
|
+
text += `- **[${status}]** "${b.subject ?? "(no subject)"}"
|
|
1779
|
+
`;
|
|
1780
|
+
text += ` ID: ${b.id}`;
|
|
1781
|
+
if (date) text += ` | ${b.sentAt ? "Sent" : "Created"}: ${date}`;
|
|
1782
|
+
text += "\n";
|
|
1783
|
+
}
|
|
1784
|
+
return { content: [{ type: "text", text }] };
|
|
1785
|
+
}
|
|
1786
|
+
return {
|
|
1787
|
+
content: [{ type: "text", text: `Unknown action: ${args.action}` }],
|
|
1788
|
+
isError: true
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
// src/tools/rss.ts
|
|
1795
|
+
import { z as z5 } from "zod";
|
|
1383
1796
|
function registerRssTools(server, client) {
|
|
1384
1797
|
server.tool(
|
|
1385
1798
|
"rss",
|
|
1386
1799
|
"Fetch RSS/Atom feed entries or extract full article content from a URL. Returns og_image when available.",
|
|
1387
1800
|
{
|
|
1388
|
-
action:
|
|
1389
|
-
url:
|
|
1390
|
-
limit:
|
|
1801
|
+
action: z5.enum(["fetch_feed", "fetch_article"]),
|
|
1802
|
+
url: z5.string().describe("Feed or article URL"),
|
|
1803
|
+
limit: z5.number().optional().describe("Max feed entries (fetch_feed, default 100)")
|
|
1391
1804
|
},
|
|
1392
1805
|
{
|
|
1393
1806
|
title: "RSS Tools",
|
|
@@ -1457,13 +1870,13 @@ function registerRssTools(server, client) {
|
|
|
1457
1870
|
}
|
|
1458
1871
|
|
|
1459
1872
|
// src/tools/account.ts
|
|
1460
|
-
import { z as
|
|
1873
|
+
import { z as z6 } from "zod";
|
|
1461
1874
|
function registerAccountTools(server, client) {
|
|
1462
1875
|
server.tool(
|
|
1463
1876
|
"manage_account",
|
|
1464
1877
|
"Get account details/connections or check health status of connected social accounts.",
|
|
1465
1878
|
{
|
|
1466
|
-
action:
|
|
1879
|
+
action: z6.enum(["get_details", "check_health"])
|
|
1467
1880
|
},
|
|
1468
1881
|
{
|
|
1469
1882
|
title: "Manage Account",
|
|
@@ -1562,21 +1975,21 @@ ${lines.join("\n")}`;
|
|
|
1562
1975
|
}
|
|
1563
1976
|
|
|
1564
1977
|
// src/tools/brand-voice.ts
|
|
1565
|
-
import { z as
|
|
1978
|
+
import { z as z7 } from "zod";
|
|
1566
1979
|
function registerBrandVoiceTools(server, client) {
|
|
1567
1980
|
server.tool(
|
|
1568
1981
|
"manage_brand_voice",
|
|
1569
1982
|
"Get, create, or update the brand voice profile. Call with action 'get' before creating content.",
|
|
1570
1983
|
{
|
|
1571
|
-
action:
|
|
1572
|
-
name:
|
|
1573
|
-
description:
|
|
1574
|
-
dos:
|
|
1575
|
-
donts:
|
|
1576
|
-
platform_rules:
|
|
1577
|
-
platform_examples:
|
|
1578
|
-
example_posts:
|
|
1579
|
-
confirmed:
|
|
1984
|
+
action: z7.enum(["get", "create", "update"]),
|
|
1985
|
+
name: z7.string().max(80).optional().describe("Voice name (create required, update optional)"),
|
|
1986
|
+
description: z7.string().max(2e3).optional().describe("Voice description (create/update)"),
|
|
1987
|
+
dos: z7.array(z7.string().max(200)).max(15).optional().describe("Writing rules to follow (create/update)"),
|
|
1988
|
+
donts: z7.array(z7.string().max(200)).max(15).optional().describe("Things to avoid (create/update)"),
|
|
1989
|
+
platform_rules: z7.record(z7.string().max(300)).optional().describe("Per-platform guidelines (create/update)"),
|
|
1990
|
+
platform_examples: z7.record(z7.array(z7.string().max(500)).max(3)).optional().describe("Per-platform examples (create/update)"),
|
|
1991
|
+
example_posts: z7.array(z7.string().max(500)).max(5).optional().describe("Example posts (create/update)"),
|
|
1992
|
+
confirmed: z7.boolean().default(false).describe("Confirm write (create/update)")
|
|
1580
1993
|
},
|
|
1581
1994
|
{
|
|
1582
1995
|
title: "Manage Brand Voice",
|
|
@@ -1748,7 +2161,7 @@ function registerBrandVoiceTools(server, client) {
|
|
|
1748
2161
|
}
|
|
1749
2162
|
|
|
1750
2163
|
// src/tools/audience.ts
|
|
1751
|
-
import { z as
|
|
2164
|
+
import { z as z8 } from "zod";
|
|
1752
2165
|
function formatAudience(audience) {
|
|
1753
2166
|
const lines = [];
|
|
1754
2167
|
lines.push(`## ${audience.name}${audience.isDefault ? " (default)" : ""}`);
|
|
@@ -1795,17 +2208,17 @@ function registerAudienceTools(server, client) {
|
|
|
1795
2208
|
"manage_audiences",
|
|
1796
2209
|
"List, get, create, update, or delete audience profiles.",
|
|
1797
2210
|
{
|
|
1798
|
-
action:
|
|
1799
|
-
name:
|
|
1800
|
-
description:
|
|
1801
|
-
demographics:
|
|
1802
|
-
pain_points:
|
|
1803
|
-
motivations:
|
|
1804
|
-
preferred_platforms:
|
|
1805
|
-
tone_notes:
|
|
1806
|
-
content_preferences:
|
|
1807
|
-
is_default:
|
|
1808
|
-
confirmed:
|
|
2211
|
+
action: z8.enum(["list", "get", "create", "update", "delete"]),
|
|
2212
|
+
name: z8.string().max(100).optional().describe("Audience name (get/create/update/delete)"),
|
|
2213
|
+
description: z8.string().max(500).optional().describe("Description (create/update)"),
|
|
2214
|
+
demographics: z8.string().max(500).optional().describe("Demographics (create/update)"),
|
|
2215
|
+
pain_points: z8.array(z8.string().max(200)).max(10).optional().describe("Pain points, full list (create/update)"),
|
|
2216
|
+
motivations: z8.array(z8.string().max(200)).max(10).optional().describe("Motivations, full list (create/update)"),
|
|
2217
|
+
preferred_platforms: z8.array(z8.string()).max(6).optional().describe("Active platforms, full list (create/update)"),
|
|
2218
|
+
tone_notes: z8.string().max(500).optional().describe("Tone guidance (create/update)"),
|
|
2219
|
+
content_preferences: z8.string().max(500).optional().describe("Content preferences (create/update)"),
|
|
2220
|
+
is_default: z8.boolean().optional().describe("Set as default (create/update)"),
|
|
2221
|
+
confirmed: z8.boolean().default(false).describe("Confirm write (create/update/delete)")
|
|
1809
2222
|
},
|
|
1810
2223
|
{
|
|
1811
2224
|
title: "Manage Audiences",
|
|
@@ -2000,7 +2413,7 @@ Call again with confirmed=true to delete.` }]
|
|
|
2000
2413
|
}
|
|
2001
2414
|
|
|
2002
2415
|
// src/tools/calendar.ts
|
|
2003
|
-
import { z as
|
|
2416
|
+
import { z as z9 } from "zod";
|
|
2004
2417
|
import { registerAppTool as registerAppTool3 } from "@modelcontextprotocol/ext-apps/server";
|
|
2005
2418
|
var BASE_CHAR_LIMITS2 = {
|
|
2006
2419
|
twitter: 280,
|
|
@@ -2021,15 +2434,15 @@ function registerCalendarTools(server, client) {
|
|
|
2021
2434
|
title: "Manage Content Calendar",
|
|
2022
2435
|
description: "View content calendar, add posts to queue, or view queue schedule.",
|
|
2023
2436
|
inputSchema: {
|
|
2024
|
-
action:
|
|
2025
|
-
from:
|
|
2026
|
-
to:
|
|
2027
|
-
status:
|
|
2028
|
-
type:
|
|
2029
|
-
content:
|
|
2030
|
-
platforms:
|
|
2031
|
-
media_urls:
|
|
2032
|
-
confirmed:
|
|
2437
|
+
action: z9.enum(["get_calendar", "schedule_to_queue", "get_queue"]),
|
|
2438
|
+
from: z9.string().optional().describe("ISO date from (get_calendar)"),
|
|
2439
|
+
to: z9.string().optional().describe("ISO date to (get_calendar)"),
|
|
2440
|
+
status: z9.string().optional().describe("Filter status (get_calendar)"),
|
|
2441
|
+
type: z9.string().optional().describe("Filter type: social_post or newsletter (get_calendar)"),
|
|
2442
|
+
content: z9.string().optional().describe("Post text (schedule_to_queue)"),
|
|
2443
|
+
platforms: z9.array(z9.string()).optional().describe("Target platforms (schedule_to_queue)"),
|
|
2444
|
+
media_urls: z9.array(z9.string()).optional().describe("Media URLs (schedule_to_queue)"),
|
|
2445
|
+
confirmed: z9.boolean().default(false).describe("Confirm scheduling (schedule_to_queue)")
|
|
2033
2446
|
},
|
|
2034
2447
|
annotations: {
|
|
2035
2448
|
readOnlyHint: false,
|
|
@@ -2256,7 +2669,7 @@ Next slot: ${slotDate2.toLocaleString()} (${dayNames[slotDate2.getDay()]})
|
|
|
2256
2669
|
}
|
|
2257
2670
|
|
|
2258
2671
|
// src/tools/sources.ts
|
|
2259
|
-
import { z as
|
|
2672
|
+
import { z as z10 } from "zod";
|
|
2260
2673
|
var TYPE_LABELS = {
|
|
2261
2674
|
feed: "RSS Feed",
|
|
2262
2675
|
website: "Website",
|
|
@@ -2282,17 +2695,17 @@ function registerSourceTools(server, client) {
|
|
|
2282
2695
|
"manage_sources",
|
|
2283
2696
|
"List, add, update, or remove content sources (RSS feeds, websites, channels). Max 10 sources.",
|
|
2284
2697
|
{
|
|
2285
|
-
action:
|
|
2286
|
-
source_id:
|
|
2287
|
-
name:
|
|
2288
|
-
url:
|
|
2289
|
-
type:
|
|
2290
|
-
category:
|
|
2291
|
-
tags:
|
|
2292
|
-
notes:
|
|
2293
|
-
searchQuery:
|
|
2294
|
-
isActive:
|
|
2295
|
-
confirmed:
|
|
2698
|
+
action: z10.enum(["list", "add", "update", "remove"]),
|
|
2699
|
+
source_id: z10.number().optional().describe("Source ID (update/remove)"),
|
|
2700
|
+
name: z10.string().optional().describe("Display name (add/update)"),
|
|
2701
|
+
url: z10.string().optional().describe("Source URL (add/update)"),
|
|
2702
|
+
type: z10.enum(SOURCE_TYPES).optional().describe("Source type (add/update)"),
|
|
2703
|
+
category: z10.string().optional().describe("Category for organization (add/update)"),
|
|
2704
|
+
tags: z10.array(z10.string()).optional().describe("Tags for filtering (add/update)"),
|
|
2705
|
+
notes: z10.string().optional().describe("Notes about the source (add/update)"),
|
|
2706
|
+
searchQuery: z10.string().optional().describe("Search keyword for 'search' type (add/update)"),
|
|
2707
|
+
isActive: z10.boolean().optional().describe("Active status (update)"),
|
|
2708
|
+
confirmed: z10.boolean().default(false).describe("Confirm removal (remove)")
|
|
2296
2709
|
},
|
|
2297
2710
|
{
|
|
2298
2711
|
title: "Manage Content Sources",
|
|
@@ -2398,7 +2811,7 @@ This will permanently remove this content source. Call again with confirmed=true
|
|
|
2398
2811
|
}
|
|
2399
2812
|
|
|
2400
2813
|
// src/tools/wordpress.ts
|
|
2401
|
-
import { z as
|
|
2814
|
+
import { z as z11 } from "zod";
|
|
2402
2815
|
import { registerAppTool as registerAppTool4 } from "@modelcontextprotocol/ext-apps/server";
|
|
2403
2816
|
function mapWpStatus(wpStatus) {
|
|
2404
2817
|
switch (wpStatus) {
|
|
@@ -2447,26 +2860,26 @@ function registerWordPressTools(server, client) {
|
|
|
2447
2860
|
title: "Manage WordPress",
|
|
2448
2861
|
description: "CRUD WordPress posts/pages, upload media, list categories/tags.",
|
|
2449
2862
|
inputSchema: {
|
|
2450
|
-
action:
|
|
2451
|
-
post_id:
|
|
2452
|
-
title:
|
|
2453
|
-
content:
|
|
2454
|
-
wp_status:
|
|
2455
|
-
categories:
|
|
2456
|
-
tags:
|
|
2457
|
-
featured_media:
|
|
2458
|
-
excerpt:
|
|
2459
|
-
date:
|
|
2460
|
-
slug:
|
|
2461
|
-
per_page:
|
|
2462
|
-
page:
|
|
2463
|
-
search:
|
|
2464
|
-
filter_categories:
|
|
2465
|
-
filter_tags:
|
|
2466
|
-
force:
|
|
2467
|
-
url:
|
|
2468
|
-
filename:
|
|
2469
|
-
confirmed:
|
|
2863
|
+
action: z11.enum(["create_post", "update_post", "publish_post", "list_posts", "get_post", "create_page", "delete_post", "upload_media", "list_categories", "list_tags"]),
|
|
2864
|
+
post_id: z11.number().optional().describe("WordPress post/page ID (update/publish/get/delete)"),
|
|
2865
|
+
title: z11.string().optional().describe("Title (create_post/create_page/update)"),
|
|
2866
|
+
content: z11.string().optional().describe("HTML content (create_post/create_page/update)"),
|
|
2867
|
+
wp_status: z11.enum(["draft", "publish", "pending", "private", "future"]).optional().describe("Post status (create_post/create_page/update, default draft)"),
|
|
2868
|
+
categories: z11.array(z11.number()).optional().describe("Category IDs (create_post/update)"),
|
|
2869
|
+
tags: z11.array(z11.number()).optional().describe("Tag IDs (create_post/update)"),
|
|
2870
|
+
featured_media: z11.number().optional().describe("Featured image ID (create_post/create_page/update)"),
|
|
2871
|
+
excerpt: z11.string().optional().describe("Excerpt (create_post/create_page/update)"),
|
|
2872
|
+
date: z11.string().optional().describe("ISO 8601 date (create_post/update, required for 'future')"),
|
|
2873
|
+
slug: z11.string().optional().describe("URL slug (create_post/create_page/update)"),
|
|
2874
|
+
per_page: z11.string().optional().describe("Results per page (list_posts)"),
|
|
2875
|
+
page: z11.string().optional().describe("Page number (list_posts)"),
|
|
2876
|
+
search: z11.string().optional().describe("Search keyword (list_posts)"),
|
|
2877
|
+
filter_categories: z11.string().optional().describe("Filter by category IDs, comma-separated (list_posts)"),
|
|
2878
|
+
filter_tags: z11.string().optional().describe("Filter by tag IDs, comma-separated (list_posts)"),
|
|
2879
|
+
force: z11.boolean().default(false).describe("Permanent delete instead of trash (delete_post)"),
|
|
2880
|
+
url: z11.string().optional().describe("Public image URL (upload_media)"),
|
|
2881
|
+
filename: z11.string().optional().describe("Filename for upload (upload_media)"),
|
|
2882
|
+
confirmed: z11.boolean().default(false).describe("Confirm action (create non-draft/publish/delete)")
|
|
2470
2883
|
},
|
|
2471
2884
|
annotations: {
|
|
2472
2885
|
readOnlyHint: false,
|
|
@@ -2850,7 +3263,7 @@ ${args.force ? "WARNING: This will permanently delete the post and cannot be und
|
|
|
2850
3263
|
}
|
|
2851
3264
|
|
|
2852
3265
|
// src/tools/ghost.ts
|
|
2853
|
-
import { z as
|
|
3266
|
+
import { z as z12 } from "zod";
|
|
2854
3267
|
import { registerAppTool as registerAppTool5 } from "@modelcontextprotocol/ext-apps/server";
|
|
2855
3268
|
function mapGhostStatus(ghostStatus) {
|
|
2856
3269
|
switch (ghostStatus) {
|
|
@@ -2889,22 +3302,22 @@ function registerGhostTools(server, client) {
|
|
|
2889
3302
|
title: "Manage Ghost",
|
|
2890
3303
|
description: "CRUD Ghost posts, send newsletters, list members/newsletters.",
|
|
2891
3304
|
inputSchema: {
|
|
2892
|
-
action:
|
|
2893
|
-
post_id:
|
|
2894
|
-
title:
|
|
2895
|
-
html:
|
|
2896
|
-
status:
|
|
2897
|
-
tags:
|
|
2898
|
-
featured:
|
|
2899
|
-
custom_excerpt:
|
|
2900
|
-
feature_image:
|
|
2901
|
-
updated_at:
|
|
2902
|
-
newsletter_id:
|
|
2903
|
-
email_only:
|
|
2904
|
-
limit:
|
|
2905
|
-
page:
|
|
2906
|
-
filter:
|
|
2907
|
-
confirmed:
|
|
3305
|
+
action: z12.enum(["create", "update", "publish", "list", "get", "send_newsletter", "list_members", "list_newsletters"]),
|
|
3306
|
+
post_id: z12.string().optional().describe("Ghost post ID (update/publish/get/send_newsletter)"),
|
|
3307
|
+
title: z12.string().optional().describe("Post title (create/update)"),
|
|
3308
|
+
html: z12.string().optional().describe("HTML content (create/update)"),
|
|
3309
|
+
status: z12.enum(["draft", "published", "scheduled"]).optional().describe("Post status (create/update, default draft)"),
|
|
3310
|
+
tags: z12.array(z12.string()).optional().describe("Tag names (create/update)"),
|
|
3311
|
+
featured: z12.boolean().optional().describe("Featured flag (create/update)"),
|
|
3312
|
+
custom_excerpt: z12.string().optional().describe("Custom excerpt (create/update)"),
|
|
3313
|
+
feature_image: z12.string().optional().describe("Feature image URL (create/update)"),
|
|
3314
|
+
updated_at: z12.string().optional().describe("Collision detection timestamp (update/publish/send_newsletter)"),
|
|
3315
|
+
newsletter_id: z12.string().optional().describe("Newsletter ID (send_newsletter)"),
|
|
3316
|
+
email_only: z12.boolean().default(false).describe("Email only, no publish (send_newsletter)"),
|
|
3317
|
+
limit: z12.string().optional().describe("Results per page (list/list_members)"),
|
|
3318
|
+
page: z12.string().optional().describe("Page number (list/list_members)"),
|
|
3319
|
+
filter: z12.string().optional().describe("NQL filter (list_members)"),
|
|
3320
|
+
confirmed: z12.boolean().default(false).describe("Confirm action (create non-draft/publish/send_newsletter)")
|
|
2908
3321
|
},
|
|
2909
3322
|
annotations: {
|
|
2910
3323
|
readOnlyHint: false,
|
|
@@ -3278,7 +3691,7 @@ Call this tool again with confirmed=true to send.`;
|
|
|
3278
3691
|
}
|
|
3279
3692
|
|
|
3280
3693
|
// src/tools/image-templates.ts
|
|
3281
|
-
import { z as
|
|
3694
|
+
import { z as z13 } from "zod";
|
|
3282
3695
|
import {
|
|
3283
3696
|
registerAppResource as registerAppResource3,
|
|
3284
3697
|
registerAppTool as registerAppTool6,
|
|
@@ -3317,13 +3730,13 @@ function registerImageTemplateTools(server, client) {
|
|
|
3317
3730
|
title: "Manage Images",
|
|
3318
3731
|
description: "Generate branded images, list templates, or list formats/dimensions.",
|
|
3319
3732
|
inputSchema: {
|
|
3320
|
-
action:
|
|
3321
|
-
template_id:
|
|
3322
|
-
article_image_url:
|
|
3323
|
-
headline:
|
|
3324
|
-
summary:
|
|
3325
|
-
formats:
|
|
3326
|
-
platforms:
|
|
3733
|
+
action: z13.enum(["generate", "list_templates", "list_formats"]),
|
|
3734
|
+
template_id: z13.string().optional().describe("Image template ID, omit for default (generate)"),
|
|
3735
|
+
article_image_url: z13.string().optional().describe("Background image URL (generate)"),
|
|
3736
|
+
headline: z13.string().optional().describe("Headline text overlay (generate)"),
|
|
3737
|
+
summary: z13.string().optional().describe("Summary text below headline (generate)"),
|
|
3738
|
+
formats: z13.array(z13.string()).optional().describe("Output formats: square, portrait, landscape, wide, story (generate)"),
|
|
3739
|
+
platforms: z13.array(z13.string()).optional().describe("Platform shortcuts: instagram, facebook, linkedin, twitter (generate)")
|
|
3327
3740
|
},
|
|
3328
3741
|
annotations: {
|
|
3329
3742
|
readOnlyHint: false,
|
|
@@ -3463,21 +3876,21 @@ function registerImageTemplateTools(server, client) {
|
|
|
3463
3876
|
}
|
|
3464
3877
|
|
|
3465
3878
|
// src/tools/publishing-rules.ts
|
|
3466
|
-
import { z as
|
|
3879
|
+
import { z as z14 } from "zod";
|
|
3467
3880
|
function registerPublishingRulesTools(server, client) {
|
|
3468
3881
|
server.tool(
|
|
3469
3882
|
"manage_publishing_rules",
|
|
3470
3883
|
"Get or update publishing safety rules (immediate publish, blocked words, daily limits, default actions, Twitter Premium).",
|
|
3471
3884
|
{
|
|
3472
|
-
action:
|
|
3473
|
-
allow_immediate_publish:
|
|
3474
|
-
allow_immediate_send:
|
|
3475
|
-
social_default_action:
|
|
3476
|
-
newsletter_default_action:
|
|
3477
|
-
max_posts_per_day:
|
|
3478
|
-
blocked_words:
|
|
3479
|
-
twitter_premium:
|
|
3480
|
-
confirmed:
|
|
3885
|
+
action: z14.enum(["get", "update"]),
|
|
3886
|
+
allow_immediate_publish: z14.boolean().optional().describe("Allow immediate social publish (update)"),
|
|
3887
|
+
allow_immediate_send: z14.boolean().optional().describe("Allow immediate newsletter send (update)"),
|
|
3888
|
+
social_default_action: z14.enum(["draft", "schedule", "publish"]).optional().describe("Default social action (update)"),
|
|
3889
|
+
newsletter_default_action: z14.enum(["draft", "schedule", "send"]).optional().describe("Default newsletter action (update)"),
|
|
3890
|
+
max_posts_per_day: z14.number().int().min(1).max(100).nullable().optional().describe("Max posts/day, null=unlimited (update)"),
|
|
3891
|
+
blocked_words: z14.array(z14.string().max(100)).max(200).nullable().optional().describe("Blocked words list (update)"),
|
|
3892
|
+
twitter_premium: z14.boolean().optional().describe("Enable 25K char Twitter limit (update)"),
|
|
3893
|
+
confirmed: z14.boolean().default(false).describe("Confirm update (update)")
|
|
3481
3894
|
},
|
|
3482
3895
|
{
|
|
3483
3896
|
title: "Manage Publishing Rules",
|
|
@@ -3559,15 +3972,15 @@ function registerPublishingRulesTools(server, client) {
|
|
|
3559
3972
|
}
|
|
3560
3973
|
|
|
3561
3974
|
// src/tools/context.ts
|
|
3562
|
-
import { z as
|
|
3975
|
+
import { z as z15 } from "zod";
|
|
3563
3976
|
function registerContextTools(server, client) {
|
|
3564
3977
|
server.tool(
|
|
3565
3978
|
"get_context",
|
|
3566
3979
|
"Get brand voice, audience, and knowledge in one call for content creation.",
|
|
3567
3980
|
{
|
|
3568
|
-
platform:
|
|
3569
|
-
topic:
|
|
3570
|
-
include_newsletter_stats:
|
|
3981
|
+
platform: z15.string().optional().describe("Filter voice rules for platform"),
|
|
3982
|
+
topic: z15.string().optional().describe("Filter knowledge items by topic/tag"),
|
|
3983
|
+
include_newsletter_stats: z15.boolean().optional().describe("Include recent analytics")
|
|
3571
3984
|
},
|
|
3572
3985
|
{
|
|
3573
3986
|
title: "Get Context",
|
|
@@ -3641,13 +4054,13 @@ function registerContextTools(server, client) {
|
|
|
3641
4054
|
}
|
|
3642
4055
|
|
|
3643
4056
|
// src/tools/team.ts
|
|
3644
|
-
import { z as
|
|
4057
|
+
import { z as z16 } from "zod";
|
|
3645
4058
|
function registerTeamTools(server, client) {
|
|
3646
4059
|
server.tool(
|
|
3647
4060
|
"manage_team",
|
|
3648
4061
|
"Manage team members, invitations, and organizations. List members, invite or remove members, manage invitations, and list organizations.",
|
|
3649
4062
|
{
|
|
3650
|
-
action:
|
|
4063
|
+
action: z16.enum([
|
|
3651
4064
|
"list_members",
|
|
3652
4065
|
"invite_member",
|
|
3653
4066
|
"remove_member",
|
|
@@ -3655,10 +4068,10 @@ function registerTeamTools(server, client) {
|
|
|
3655
4068
|
"revoke_invitation",
|
|
3656
4069
|
"list_organizations"
|
|
3657
4070
|
]),
|
|
3658
|
-
email:
|
|
3659
|
-
role:
|
|
3660
|
-
member_id:
|
|
3661
|
-
invitation_id:
|
|
4071
|
+
email: z16.string().optional().describe("Email address (invite_member)"),
|
|
4072
|
+
role: z16.string().optional().describe("Role for the member (invite_member), e.g. 'admin', 'member'"),
|
|
4073
|
+
member_id: z16.string().optional().describe("Member ID (remove_member)"),
|
|
4074
|
+
invitation_id: z16.string().optional().describe("Invitation ID (revoke_invitation)")
|
|
3662
4075
|
},
|
|
3663
4076
|
{
|
|
3664
4077
|
title: "Manage Team",
|
|
@@ -3777,6 +4190,7 @@ export {
|
|
|
3777
4190
|
registerImageTemplateTools,
|
|
3778
4191
|
registerInsightsTools,
|
|
3779
4192
|
registerMediaTools,
|
|
4193
|
+
registerNewsletterTools,
|
|
3780
4194
|
registerPostPreviewResource,
|
|
3781
4195
|
registerPostTools,
|
|
3782
4196
|
registerPublishingRulesTools,
|