@retensy/mcp 0.15.1 → 0.15.2

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 CHANGED
@@ -140,13 +140,13 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
140
140
  | `site_leads(siteId, page?, size?)` | заявки из форм (поля, UTM, статус доставки) |
141
141
  | `site_lead_settings(siteId, settings?)` | куда доставлять заявки: бот уведомлений, почта, вебхук, вебхук-сценарий, amoCRM, «Интеграция» (`coreDelivery {connectionId, kind, params}` из `coreConnections`) |
142
142
  | `broadcast_list(botId?, group?, page?, size?)` | рассылки + счётчики разделов (черновики/запланированные/отправленные/повторы) |
143
- | `broadcast_get(broadcastId)` | рассылка целиком: статус, счётчики, сообщения |
143
+ | `broadcast_get(broadcastId)` | рассылка целиком: статус, счётчики, сообщения, причины ошибок |
144
144
  | `broadcast_preview(botIds, tagsAll?, tagsNone?)` | сколько подписчиков получат рассылку |
145
145
  | `broadcast_send(name, botIds, messages \| graphId, tagsAll?, tagsNone?, scheduledAt?, draftId?)` | отправить сейчас / запланировать; по нескольким ботам; или запуск сценария |
146
146
  | `broadcast_cancel(broadcastId)` | отменить запланированную/идущую |
147
147
  | `broadcast_recurring(action, …)` | повторяющиеся рассылки: list / create (DAILY·MONTHLY·YEARLY) / stop |
148
148
  | `broadcast_drafts(action, …)` | черновики: list / get / create / update / delete |
149
- | `broadcast_duplicate(broadcastId)` | копия рассылки как черновик |
149
+ | `broadcast_duplicate(broadcastId` или `draftId)` | копия рассылки или черновика — новый черновик «… (копия)» |
150
150
  | `article_list()` | свои статьи блога (id, slug, title, просмотры) |
151
151
  | `article_get(slug)` | статья по slug (Markdown content, excerpt, обложка) |
152
152
  | `article_publish(content, title?, cover?, excerpt?)` | новая статья (Markdown; title из `# ...`, если не задан; обложка из `cover`-URL или 1-й картинки → OG; `excerpt` явно или авто) → id, slug, URL |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retensy/mcp",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "MCP server to build and publish Telegram and MAX bot funnels/automations, broadcasts, service integrations, block-based websites (incl. free-layout Zero blocks, designs, templates, custom domains, form leads) and Markdown blog articles in the Retensy Bots service. Zero dependencies.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,8 @@ description: Сделать рассылку подписчикам ботов r
16
16
  5. `broadcast_send {name, botIds, messages, tagsAll?, tagsNone?, scheduledAt?}` → `{broadcastIds, totalAudience}`.
17
17
  Не уверен в тексте — сначала `broadcast_drafts {action: "create", …}`: пользователь увидит черновик в кабинете,
18
18
  отправка — `broadcast_send {draftId}` (черновик после отправки удаляется).
19
- 6. Статус — `broadcast_get {broadcastId}` / `broadcast_list`; остановить — `broadcast_cancel`.
19
+ 6. Статус — `broadcast_get {broadcastId}` (с причинами ошибок) / `broadcast_list`; остановить — `broadcast_cancel`.
20
+ Повторить или взять за основу — `broadcast_duplicate {broadcastId | draftId}` → черновик «… (копия)».
20
21
 
21
22
  ## Сообщение
22
23
 
package/src/index.mjs CHANGED
@@ -27,7 +27,7 @@ import os from "node:os";
27
27
  import fs from "node:fs";
28
28
  import path from "node:path";
29
29
 
30
- const VERSION = "0.15.1";
30
+ const VERSION = "0.15.2";
31
31
  /** С чего начать пустой сайт (init у /document/ops; на сайте с черновиком игнорируется). */
32
32
  const SITE_INITS = ["starter", "blank", "mini-landing"];
33
33
  /** Безвредная операция, когда нужен только init: бэкенд не принимает пустой ops[]. */
@@ -652,7 +652,7 @@ const TOOLS = [
652
652
  { name: "disconnect_integration", description: "Удалить подключение сервиса по id из list_integrations (DELETE /api/bots/integrations/{id}). Действия сценария с этим connectionId перестанут работать.", inputSchema: { type: "object", properties: { connectionId: { type: "string" } }, required: ["connectionId"] } },
653
653
  // ---- Рассылки ----
654
654
  { name: "broadcast_list", description: "Рассылки. Без botId — по всем ботам постранично (GET /api/bots/broadcasts): {counts: {drafts, scheduled, sent, recurring}, page: {content: [{id, botId, botUsername, name, status, direct, totalJobs, sentJobs, failedJobs, skippedByQuota, scheduledAt, createdAt}], totalElements…}}; group: scheduled (ещё не начали) | sent (идут/завершены). С botId — полная история одного бота. status: EXPANDING/MATERIALIZING/READY (ждёт) → RUNNING → DONE | CANCELLING → CANCELLED | FAILED. Read-only.", inputSchema: { type: "object", properties: { botId: { type: "string" }, group: { type: "string", enum: ["scheduled", "sent"] }, page: { type: "number" }, size: { type: "number", description: "до 100, по умолчанию 20" } } } },
655
- { name: "broadcast_get", description: "Рассылка целиком по id (GET /api/bots/broadcasts/{id}): статус, счётчики отправки, фильтр аудитории, сообщения, время. Read-only.", inputSchema: { type: "object", properties: { broadcastId: { type: "string" } }, required: ["broadcastId"] } },
655
+ { name: "broadcast_get", description: "Рассылка целиком по id (GET /api/bots/broadcasts/{id}): статус, счётчики отправки, фильтр аудитории, сообщения, время. При failedJobs > 0 — ещё errors: топ-5 причин ошибок [{error, count}] (GET …/{id}/errors; детали живут 30 дней). Read-only.", inputSchema: { type: "object", properties: { broadcastId: { type: "string" } }, required: ["broadcastId"] } },
656
656
  { name: "broadcast_preview", description: "Сколько подписчиков получат рассылку (POST /api/bots/{botId}/broadcasts/preview) — по каждому боту и всего. Фильтр по тегам: tagsAll — есть ВСЕ эти теги, tagsNone — нет НИ ОДНОГО; без тегов — все подписчики бота. Лимит — 50 000 получателей на бота. Ничего не отправляет.", inputSchema: { type: "object", properties: { botIds: { type: "array", items: { type: "string" } }, botId: { type: "string" }, tagsAll: { type: "array", items: { type: "string" } }, tagsNone: { type: "array", items: { type: "string" } } } } },
657
657
  { name: "broadcast_send", description: "Отправить рассылку сейчас или запланировать (scheduledAt). " +
658
658
  "Прямая (по умолчанию, POST /api/bots/broadcasts/direct): name, botIds[] (1–20 ботов ОДНОГО владельца; по каждому создаётся своя рассылка), messages[] (1–5), tagsAll?/tagsNone? (фильтр по тегам). " +
@@ -664,7 +664,7 @@ const TOOLS = [
664
664
  { name: "broadcast_cancel", description: "Отменить рассылку (POST /api/bots/broadcasts/{id}/cancel): запланированная не уйдёт, идущая остановится (статус CANCELLING → CANCELLED). Уже завершённую отменить нельзя — HTTP 409.", inputSchema: { type: "object", properties: { broadcastId: { type: "string" } }, required: ["broadcastId"] } },
665
665
  { name: "broadcast_recurring", description: "Повторяющиеся рассылки (/api/bots/broadcasts/recurring). action: list — правила (активные и остановленные); create {name, botIds[], messages[], tagsAll?, tagsNone?, recurrence: DAILY|MONTHLY|YEARLY, firstRunAt} — сообщения как в broadcast_send, firstRunAt — первый запуск в будущем (ISO 8601, без пояса — московское), дальше в то же время суток/число (Москва); stop {ruleId} — остановить правило (уже отправленные прогоны не трогаются). Нужен платный тариф (402 со ссылкой).", inputSchema: { type: "object", properties: { action: { type: "string", enum: ["list", "create", "stop"] }, ruleId: { type: "string" }, name: { type: "string" }, botIds: { type: "array", items: { type: "string" } }, botId: { type: "string" }, messages: { type: "array", items: {} }, tagsAll: { type: "array", items: { type: "string" } }, tagsNone: { type: "array", items: { type: "string" } }, recurrence: { type: "string", enum: ["DAILY", "MONTHLY", "YEARLY"] }, firstRunAt: { type: "string" } }, required: ["action"] } },
666
666
  { name: "broadcast_drafts", description: "Черновики рассылок (/api/bots/broadcasts/drafts) — те же, что в мастере кабинета. action: list · get {draftId} · create {name?, botIds?, messages?, tagsAll?, tagsNone?, scheduledAt?} · update {draftId, …те же поля — переданные заменяют, остальные остаются} · delete {draftId}. Черновик не проверяется на полноту; отправить — broadcast_send {draftId}. Лимит — 200 черновиков.", inputSchema: { type: "object", properties: { action: { type: "string", enum: ["list", "get", "create", "update", "delete"] }, draftId: { type: "string" }, name: { type: "string" }, botIds: { type: "array", items: { type: "string" } }, messages: { type: "array", items: {} }, tagsAll: { type: "array", items: { type: "string" } }, tagsNone: { type: "array", items: { type: "string" } }, scheduledAt: { type: "string" } }, required: ["action"] } },
667
- { name: "broadcast_duplicate", description: "Копия прямой рассылки как черновик «Копия — …» (POST /api/bots/broadcasts/{id}/duplicate): бот, фильтр, сообщения. Рассылку по сценарию не дублировать — HTTP 409. Дальше broadcast_drafts update / broadcast_send {draftId}.", inputSchema: { type: "object", properties: { broadcastId: { type: "string" } }, required: ["broadcastId"] } },
667
+ { name: "broadcast_duplicate", description: "Копия как новый черновик «<имя> (копия)»: исходник не меняется, время отправки и статистика не переносятся. broadcastId — прямая рассылка (POST /api/bots/broadcasts/{id}/duplicate: бот, фильтр, сообщения; по сценарию — HTTP 409); draftId — черновик (POST /api/bots/broadcasts/drafts/{id}/duplicate). Дальше broadcast_drafts update / broadcast_send {draftId}.", inputSchema: { type: "object", properties: { broadcastId: { type: "string" }, draftId: { type: "string" } } } },
668
668
  // ---- Сайты: библиотека шаблонов ----
669
669
  { name: "site_templates", description: "Библиотека шаблонов блоков сайта (GET /api/bots/pages/templates): {categories: [{id, title, description?}], templates: [{id, category, title, description?, blocks: сколько блоков вставится}]}. Вставка — site_edit add_template {container, templateId, after?} (results.id — первый блок, results.ids — все); дальше блоки правятся как обычные. category — фильтр по id категории.", inputSchema: { type: "object", properties: { category: { type: "string" } } } },
670
670
  ];
@@ -1034,7 +1034,11 @@ async function handleCall(params) {
1034
1034
  try { counts = await api("/api/bots/broadcasts/counts"); } catch { /* счётчики не обязательны */ }
1035
1035
  return okResult({ counts, page });
1036
1036
  }
1037
- case "broadcast_get": return okResult(await api(`/api/bots/broadcasts/${a.broadcastId}`));
1037
+ case "broadcast_get": {
1038
+ const b = await api(`/api/bots/broadcasts/${a.broadcastId}`);
1039
+ if (b && b.failedJobs > 0) b.errors = await api(`/api/bots/broadcasts/${a.broadcastId}/errors`).catch(() => []);
1040
+ return okResult(b);
1041
+ }
1038
1042
  case "broadcast_preview": {
1039
1043
  const ids = botIdsOf(a);
1040
1044
  await assertBroadcastBots(ids);
@@ -1131,6 +1135,8 @@ async function handleCall(params) {
1131
1135
  throw new Error("action: list | get | create | update | delete.");
1132
1136
  }
1133
1137
  case "broadcast_duplicate":
1138
+ if (a.draftId) return okResult(await api(`/api/bots/broadcasts/drafts/${a.draftId}/duplicate`, { method: "POST" }));
1139
+ if (!a.broadcastId) throw new Error("Передай broadcastId или draftId.");
1134
1140
  return okResult(await api(`/api/bots/broadcasts/${a.broadcastId}/duplicate`, { method: "POST" }));
1135
1141
  case "site_templates": {
1136
1142
  const r = await api("/api/bots/pages/templates");