@retensy/mcp 0.52.0 → 0.54.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 +27 -0
- package/package.json +1 -1
- package/src/index.mjs +36 -1
package/README.md
CHANGED
|
@@ -302,9 +302,16 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
302
302
|
| `booking_slots(calendarId, from?, to?, limit?)` | свободные слоты `[{at, label}]`, даты ГГГГ-ММ-ДД в зоне календаря |
|
|
303
303
|
| `booking_list(calendarId, from?, pendingOnly?)` / `booking_create(calendarId, slotAt, name?, phone?, email?, comment?, customAnswers?, meetingTypeId?)` / `booking_cancel(calendarId, bookingId)` | брони: список (или только ждущие подтверждения) / ручная запись (занятый слот — ошибка «занят») / отмена |
|
|
304
304
|
| `booking_confirm(calendarId, bookingId)` / `booking_reject(calendarId, bookingId)` | подтвердить/отклонить бронь при `confirmationMode:"MANUAL"` (прочие поля календаря: `breaks`, `meetingTypes`, буферы, `horizonDays`, `intakeFields`, `notifyOwner`, `slug`+`enabled` — публичная ссылка `/book/<slug>` — в `booking_calendar_create`/`_update`) |
|
|
305
|
+
| `event_list` / `event_get(eventId)` / `event_create(title, startsAt, ...)` / `event_update(eventId, ...)` / `ticket_type_upsert(eventId, name, price, limit, ...)` / `tickets_list(eventId, q?, status?)` / `ticket_checkin(eventId, ticketId)` / `ticket_cancel(eventId, ticketId, refund?)` | билеты на события: события и типы билетов, участники, ручная отметка входа и отмена (последние два с подтверждением) |
|
|
305
306
|
| `audience_fields(botId, search?, limit?)` | ключи переменных (с выведенным типом) и теги бота — для построителя фильтра |
|
|
306
307
|
| `audience_search(botId?, botIds?, filter?, q?, sort?, dir?, page?, size?)` | фильтр+сортировка подписчиков: один бот или кросс-бот (без `botId`); `filter` — полный `AudienceFilter` (теги any/all/none, диапазоны дат, `blocked`, `variableConditions`) |
|
|
307
308
|
| `audience_tag_edit(botId, chatIds, add?, remove?)` / `audience_variable_edit(botId, chatIds, set?, unset?)` | массово добавить/снять теги / установить/снять переменные у выбранных подписчиков |
|
|
309
|
+
| `subscribers_overview(days?)` | **из каталога сервера.** Подписчики по ВСЕМ ботам за один вызов: новые, активные, всего, заблокировали, итого и топ ботов. Считает сервер, ботов по одному запрашивать не нужно |
|
|
310
|
+
| `leads_overview(siteIds?, days?)` | **из каталога сервера.** Точная сводка заявок по всем сайтам: счётчики по статусам, сайтам и `utm_source`, пять новых заявок. Без листания страниц |
|
|
311
|
+
| `bookings_overview()` | **из каталога сервера.** Записи по всем календарям: сколько ждут подтверждения и сколько предстоящих |
|
|
312
|
+
| `leads_bulk_status(toStatus, fromStatuses?, siteIds?, utmSource?, days?)` | **из каталога сервера.** Массово сменить статус заявок по условию, до 500 за раз, id не нужны. Только свои сайты. Нужен `confirmToken`: сервер возвращает сводку «что и сколько», повтор с токеном выполняет (токен действует, пока число подходящих заявок не изменилось). Право `write:sites` |
|
|
313
|
+
| `bookings_bulk_decide(action, calendarIds?, bookingIds?, from?, to?)` | **из каталога сервера.** Массово подтвердить (`CONFIRM`), отклонить (`REJECT`) ждущие записи или отменить активные (`CANCEL`, только с `from`+`to` или `bookingIds`), до 100 за раз. Клиентам уходят уведомления как при одиночном действии. Нужен `confirmToken`. Право `crm` |
|
|
314
|
+
| `audience_bulk_tag(add?, remove?, botIds?, filter?, q?)` | **из каталога сервера.** Поставить/снять теги всем подписчикам, подходящим под условие (`filter` как в `audience_search`), без chatId, до 5000 за раз. Нужен `confirmToken`. Право `crm` |
|
|
308
315
|
| `audience_export(botId?, botIds?, filter?, q?, format, savePath?)` | потоковая выгрузка ТЕКУЩЕЙ отфильтрованной выборки, `csv`\|`xlsx` (xlsx требует `savePath` — бинарный формат), потолок 100000 строк |
|
|
309
316
|
| `dialog_search(q, limit?)` | кросс-бот поиск по «Диалогам» — имя/username/id/текст сообщения |
|
|
310
317
|
| `publications_usage(botId)` | месячная квота публикаций владельца (общая для Telegram/MAX/Instagram/VK) |
|
|
@@ -351,6 +358,26 @@ MCP-сервер (+ скилл для Claude Code) для **сборки и пу
|
|
|
351
358
|
| `catalog_category_list()` | категории магазина: `id`, `name`, `parentId` |
|
|
352
359
|
| `catalog_category_upsert(name, id?, parentId?, confirm:true)` | создать (без `id`) или переименовать (с `id`) категорию; без `parentId` при обновлении родитель сохраняется |
|
|
353
360
|
|
|
361
|
+
### Промокоды, возвраты и настройки кабинета (из каталога сервера)
|
|
362
|
+
|
|
363
|
+
Эти инструменты приходят из каталога сервера (`GET /api/agent-tools/catalog`) и появляются без обновления пакета. Все изменяющие требуют `confirm:true` и `confirmToken` (сервер сначала возвращает сводку «что будет сделано»).
|
|
364
|
+
|
|
365
|
+
| Tool | Назначение |
|
|
366
|
+
|---|---|
|
|
367
|
+
| `promo_list()` / `promo_create(code, kind, value, maxUses?, expiresAt?, minOrder?)` / `promo_toggle(promoId, active)` / `promo_delete(promoId)` | промокоды заказов магазина: `kind` = `percent`\|`fixed`, лимит применений, срок, минимальная сумма; скидка считается от суммы товаров, действует на сайте и в боте |
|
|
368
|
+
| `order_refunds(orderId)` / `order_refund(orderId, requestId, amount?, reason?)` | возвраты денег по заказу через ЮKassa: без `amount` вернуть остаток целиком, с `amount` — часть. `requestId` — ключ операции (16–100 символов), повтор с тем же ключом не вернёт деньги второй раз. Нужно право `billing` |
|
|
369
|
+
| `order_refund_retry(orderId, refundId)` / `order_refund_manual(orderId, refundId)` / `order_refund_abandon(orderId, refundId)` | повторить непрошедший возврат (при неизвестном исходе — с тем же ключом), отметить «вернул вручную в кабинете ЮKassa», отказаться от точно непрошедшего возврата |
|
|
370
|
+
| `operator_duty_get(botId)` / `operator_duty_set(botId, enabled, workFrom?, workTo?, workDays?, timezone?, offlineReply?, slaMinutes?)` | рабочее время оператора, автоответ вне часов, SLA-предупреждение владельцу; настройка заменяется целиком |
|
|
371
|
+
| `payment_reminder_get(botId)` / `payment_reminder_set(botId, enabled, afterMinutes?, text?)` / `payment_reminder_stats(botId)` | напоминание тем, кто начал оплату и не закончил, и результат |
|
|
372
|
+
| `tg_business_status(botId)` | подключён ли бот к Telegram Business и какие аккаунты (подключение — в приложении Telegram) |
|
|
373
|
+
| `managed_bot_config()` / `managed_bot_start(name?)` / `managed_bot_status(managedId)` | создание бота через Managed Bots без ручного токена |
|
|
374
|
+
| `consents_history(botId, chatId)` / `consent_revoke(botId, chatId, documentKey?)` / `consents_export(botId, chatId?)` | согласия клиентов (152-ФЗ): журнал, отзыв, выгрузка CSV (персональные данные, право `destructive`) |
|
|
375
|
+
| `linked_chats_list(botId)` | каналы и группы, где бот администратор (публикация — `channel_post`) |
|
|
376
|
+
| `graph_validate(graphId)` | проверить сценарий без публикации: ошибки и предупреждения |
|
|
377
|
+
| `kb_search(kbId, q)` / `kb_doc_history(kbId, docId)` | поиск по базе знаний и история пересборок документа |
|
|
378
|
+
| `agent_checklist(agentId)` / `agent_checks_latest(agentId)` / `agent_analytics(agentId, days?)` / `agent_insights(agentId)` | чек-лист, последняя проверка, аналитика (7/30/90 дней) и рекомендации ИИ-агента |
|
|
379
|
+
| `attention_get()` | счётчики «требует внимания»: заявки, диалоги без ответа, интеграции, боты на паузе |
|
|
380
|
+
|
|
354
381
|
### Рассылки
|
|
355
382
|
|
|
356
383
|
Сообщение рассылки — как в мастере кабинета: `{type, text?, mediaUrl?, mediaUrls?, buttons?}`, до 5 сообщений.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retensy/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
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": {
|
package/src/index.mjs
CHANGED
|
@@ -1196,6 +1196,14 @@ const TOOLS = [
|
|
|
1196
1196
|
{ name: "booking_cancel", description: "Отменить бронь и освободить слот (POST /api/bots/booking/calendars/{calendarId}/bookings/{bookingId}/cancel). Повторная отмена — без ошибки. bookingId — из booking_list.", inputSchema: { type: "object", properties: { calendarId: { type: "string" }, bookingId: { type: "string" } }, required: ["calendarId", "bookingId"] } },
|
|
1197
1197
|
{ name: "booking_confirm", description: "Подтвердить бронь, ждущую решения владельца (MANUAL confirmationMode) — POST .../bookings/{bookingId}/confirm. Клиенту уходит уведомление, если бронь пришла из чата бота. HTTP 404 — бронь не этого календаря, 409 — уже не ждёт решения (подтверждена/отменена/истёк pendingHoldHours).", inputSchema: { type: "object", properties: { calendarId: { type: "string" }, bookingId: { type: "string" } }, required: ["calendarId", "bookingId"] } },
|
|
1198
1198
|
{ name: "booking_reject", description: "Отклонить бронь, ждущую решения владельца (MANUAL confirmationMode) — POST .../bookings/{bookingId}/reject: освобождает слот, клиенту уходит «отклонено владельцем» (в отличие от booking_cancel — то работает на любой активной брони и ничего не присылает клиенту). HTTP 404/409 — как у booking_confirm.", inputSchema: { type: "object", properties: { calendarId: { type: "string" }, bookingId: { type: "string" } }, required: ["calendarId", "bookingId"] } },
|
|
1199
|
+
{ name: "event_list", description: "События с билетами (GET /api/bots/tickets/events): id, title, startsAt, status, sold, checkedIn, revenue, publicUrl. Read-only.", inputSchema: { type: "object", properties: {} } },
|
|
1200
|
+
{ name: "event_get", description: "Событие с типами билетов (GET /api/bots/tickets/events/{eventId}). Read-only.", inputSchema: { type: "object", properties: { eventId: { type: "string" } }, required: ["eventId"] } },
|
|
1201
|
+
{ name: "event_create", description: "Создать событие (POST /api/bots/tickets/events), по умолчанию черновик; опубликовать — status:\"published\". Типы билетов — ticket_type_upsert.", inputSchema: { type: "object", properties: { title: { type: "string" }, description: { type: "string" }, startsAt: { type: "string", description: "ISO-8601 UTC" }, endsAt: { type: "string" }, timezone: { type: "string", description: "IANA, напр. Europe/Moscow" }, venueType: { type: "string", enum: ["offline", "online"] }, venue: { type: "string", description: "Адрес" }, onlineUrl: { type: "string" }, coverUrl: { type: "string" }, capacity: { type: "number", description: "Общая вместимость" }, status: { type: "string", enum: ["draft", "published", "cancelled"] } }, required: ["title", "startsAt"] } },
|
|
1202
|
+
{ name: "event_update", description: "Изменить событие (PUT /api/bots/tickets/events/{eventId}), переданные поля заменяют текущие. status:\"cancelled\" — отмена события.", inputSchema: { type: "object", properties: { eventId: { type: "string" }, title: { type: "string" }, description: { type: "string" }, startsAt: { type: "string", description: "ISO-8601 UTC" }, endsAt: { type: "string" }, timezone: { type: "string", description: "IANA, напр. Europe/Moscow" }, venueType: { type: "string", enum: ["offline", "online"] }, venue: { type: "string", description: "Адрес" }, onlineUrl: { type: "string" }, coverUrl: { type: "string" }, capacity: { type: "number", description: "Общая вместимость" }, status: { type: "string", enum: ["draft", "published", "cancelled"] } }, required: ["eventId"] } },
|
|
1203
|
+
{ name: "ticket_type_upsert", description: "Создать/изменить тип билета (POST /api/bots/tickets/events/{eventId}/types): без id — новый, с id — правка. price 0 = бесплатный; limit — число билетов типа.", inputSchema: { type: "object", properties: { eventId: { type: "string" }, id: { type: "string" }, name: { type: "string" }, price: { type: "number" }, limit: { type: "number" }, salesStart: { type: "string" }, salesEnd: { type: "string" } }, required: ["eventId", "name", "price", "limit"] } },
|
|
1204
|
+
{ name: "tickets_list", description: "Билеты/участники события (GET /api/bots/tickets/events/{eventId}/tickets): q — поиск по имени/номеру, status, page с 0, size. Read-only.", inputSchema: { type: "object", properties: { eventId: { type: "string" }, q: { type: "string" }, status: { type: "string", enum: ["pending", "paid", "valid", "used", "cancelled", "refunded"] }, page: { type: "number" }, size: { type: "number" } }, required: ["eventId"] } },
|
|
1205
|
+
{ name: "ticket_checkin", description: "Отметить билет использованным вручную (POST .../tickets/{ticketId}/checkin). Необратимо, нужен confirmToken. Ответ: status VALID | ALREADY_USED | CANCELLED | NOT_PAID.", inputSchema: { type: "object", properties: { eventId: { type: "string" }, ticketId: { type: "string" } }, required: ["eventId", "ticketId"] } },
|
|
1206
|
+
{ name: "ticket_cancel", description: "Отменить билет и освободить место (POST .../tickets/{ticketId}/cancel). refund:true — пометить возврат (деньги в ЮKassa возвращаются вручную). Необратимо, нужен confirmToken.", inputSchema: { type: "object", properties: { eventId: { type: "string" }, ticketId: { type: "string" }, refund: { type: "boolean" } }, required: ["eventId", "ticketId"] } },
|
|
1199
1207
|
{ 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 категории. Ответ также содержит siteTemplates — стартовые шаблоны сайта (starter, blank, mini-landing, shop-starter) с описаниями: для site_create template / site_edit init.", inputSchema: { type: "object", properties: { category: { type: "string" } } } },
|
|
1200
1208
|
// ---- Паритет платформы, часть 2: бот, база, агент, заявки, подписчики, каналы, ссылки, аналитика ----
|
|
1201
1209
|
{ name: "bot_rename", description: "Переименовать бота (PATCH /api/bots/{botId} {name}): отображаемое имя в кабинете, до 250 символов. Пустое name сбрасывает имя на @username. Имя в самом Telegram/MAX не меняется.", inputSchema: { type: "object", properties: { botId: { type: "string" }, name: { type: "string" } }, required: ["botId", "name"] } },
|
|
@@ -1800,6 +1808,33 @@ async function handleCall(params) {
|
|
|
1800
1808
|
if (g.pending) return g.pending;
|
|
1801
1809
|
return okResult(`✅ Бронь ${bookingId} отменена, слот свободен.`);
|
|
1802
1810
|
}
|
|
1811
|
+
case "event_list": return okResult(await api("/api/bots/tickets/events"));
|
|
1812
|
+
case "event_get": return okResult(await api(`/api/bots/tickets/events/${idArg(a.eventId, "eventId")}`));
|
|
1813
|
+
case "event_create":
|
|
1814
|
+
case "event_update": {
|
|
1815
|
+
const keys = ["title", "description", "startsAt", "endsAt", "timezone", "venueType", "venue", "onlineUrl", "coverUrl", "capacity", "status"];
|
|
1816
|
+
const body = Object.fromEntries(keys.filter((k) => a[k] !== undefined).map((k) => [k, a[k]]));
|
|
1817
|
+
if (params.name === "event_create") return okResult(await api("/api/bots/tickets/events", { method: "POST", body }));
|
|
1818
|
+
return okResult(await api(`/api/bots/tickets/events/${idArg(a.eventId, "eventId")}`, { method: "PUT", body }));
|
|
1819
|
+
}
|
|
1820
|
+
case "ticket_type_upsert": {
|
|
1821
|
+
const body = { name: String(a.name), price: a.price, limit: a.limit };
|
|
1822
|
+
for (const k of ["id", "salesStart", "salesEnd"]) if (a[k] !== undefined) body[k] = a[k];
|
|
1823
|
+
return okResult(await api(`/api/bots/tickets/events/${idArg(a.eventId, "eventId")}/types`, { method: "POST", body }));
|
|
1824
|
+
}
|
|
1825
|
+
case "tickets_list": {
|
|
1826
|
+
const q = {};
|
|
1827
|
+
for (const k of ["q", "status", "page", "size"]) if (a[k] !== undefined && a[k] !== "") q[k] = a[k];
|
|
1828
|
+
return okResult(await api(`/api/bots/tickets/events/${idArg(a.eventId, "eventId")}/tickets${qs(q)}`));
|
|
1829
|
+
}
|
|
1830
|
+
case "ticket_checkin":
|
|
1831
|
+
case "ticket_cancel": {
|
|
1832
|
+
const args = { eventId: idArg(a.eventId, "eventId"), ticketId: idArg(a.ticketId, "ticketId") };
|
|
1833
|
+
if (params.name === "ticket_cancel" && a.refund != null) args.refund = !!a.refund;
|
|
1834
|
+
const g = await invokeGuarded(params.name, args, a);
|
|
1835
|
+
if (g.pending) return g.pending;
|
|
1836
|
+
return okResult(g.data);
|
|
1837
|
+
}
|
|
1803
1838
|
case "booking_confirm":
|
|
1804
1839
|
case "booking_reject": {
|
|
1805
1840
|
const id = uuidArg(a.calendarId, "calendarId");
|
|
@@ -2835,7 +2870,7 @@ async function invokeGuarded(name, args, a) {
|
|
|
2835
2870
|
}
|
|
2836
2871
|
/** Обратимые правки: сервер обычно не требует подтверждения, токен нужен лишь при явном 409. */
|
|
2837
2872
|
const SOFT_CONFIRM_TOOLS = new Set(["site_edit", "agent_update", "kb_add_site", "chain_enable"]);
|
|
2838
|
-
const GUARDED_TOOLS = new Set(["publish_graph", "site_publish", "site_rollback", "agent_publish", "booking_cancel", "bot_delete", "broadcast_cancel", "broadcast_send",
|
|
2873
|
+
const GUARDED_TOOLS = new Set(["publish_graph", "site_publish", "site_rollback", "agent_publish", "booking_cancel", "ticket_checkin", "ticket_cancel", "bot_delete", "broadcast_cancel", "broadcast_send",
|
|
2839
2874
|
"delete_graph", "agent_update", "chain_enable", "kb_add_site", "create_bot", "bot_stop", "dialog_reply", "site_edit"]);
|
|
2840
2875
|
for (const t of TOOLS) {
|
|
2841
2876
|
if (!GUARDED_TOOLS.has(t.name)) continue;
|