@retensy/mcp 0.29.0 → 0.30.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retensy/mcp",
3
- "version": "0.29.0",
3
+ "version": "0.30.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": {
@@ -253,7 +253,8 @@ IG-боты не поддерживают команды (`/start`). Вход
253
253
  `dateTime` (unix-секунды, по умолчанию «сейчас»).
254
254
  - **Единственное НЕ интегрированное действие**: `cancel_payment_subscription` —
255
255
  принимается как no-op с пометкой `integration_not_connected`.
256
- - **модерация группы**: `group_unban`, `group_kick`, `group_approve`, `group_decline`
256
+ - **модерация группы**: `group_unban`, `group_kick`, `group_approve`, `group_decline`. Поля: `chatId` (числовой id, `@username` или `{{var.*}}`; пусто — единственный привязанный к боту канал/группа), `userId` (пусто — текущий подписчик).
257
+ **`group_kick` — «выгнать или забанить»**: `mode:"kick"` — выгнать (Telegram: ban + сразу unban, человек может вернуться по ссылке-приглашению), `mode:"ban"` — забанить; опц. `untilDays` (1..366, только для `ban`; пусто = навсегда). Без `mode` — как раньше, бан навсегда. Бот должен быть админом чата с правом блокировать. Нет прав / человека нет в чате → выход «Ошибка» блока, сценарий не падает. MAX: «выгнать» и бан навсегда, бан на срок недоступен. VK: только `mode:"kick"` из беседы сообщества (`chatId` — номер беседы, бот админ беседы), бан и разбан недоступны. Dry-run ничего не вызывает. Цепочка «выгнал → удалил сообщение с инвайтом»: блок «Действия» с `group_kick` после отправки ссылки, затем `DELETE_MESSAGE` с `mode:"NODE"` на узел со ссылкой.
257
258
 
258
259
  ### Внешнее / прочее
259
260
  - `CALL_WEBHOOK` — `{ "url":"https://...", "method":"POST", "headersJson":"{\"X-Key\":\"…\"}",
@@ -461,6 +461,25 @@ for (const n of nodes) {
461
461
  }
462
462
  if (a.kind === "gsheets_send" && (!a.googleEmail || !a.spreadsheetId || !Array.isArray(a.cells) || a.cells.length === 0))
463
463
  errors.push(`ACTION_GSHEETS_INCOMPLETE: ${who} — gsheets_send требует googleEmail + spreadsheetId + непустой cells[] (Google-аккаунт подключается в вебе /bots, не через MCP).`);
464
+ if (a.kind === "group_kick") {
465
+ // «Выгнать или забанить» (зеркало GraphValidator.validateGroupKick)
466
+ if (!blank(a.mode) && a.mode !== "kick" && a.mode !== "ban")
467
+ errors.push(`GROUP_KICK_BAD_MODE: ${who} — group_kick.mode ∈ kick | ban.`);
468
+ if (!blank(a.untilDays)) {
469
+ const u = String(a.untilDays).trim();
470
+ if (a.mode === "kick")
471
+ errors.push(`GROUP_KICK_UNTIL_WITH_KICK: ${who} — untilDays в режиме kick не действует: человек может вернуться сразу.`);
472
+ else if (!u.includes("{{")) {
473
+ const d = Number(u.replace(",", "."));
474
+ if (!(d >= 1 && d <= 366 && Number.isInteger(d))) errors.push(`GROUP_KICK_BAD_UNTIL: ${who} — untilDays: число дней от 1 до 366 (пусто = навсегда).`);
475
+ }
476
+ }
477
+ if (!blank(a.chatId)) {
478
+ const c = String(a.chatId).trim();
479
+ if (!c.includes("{{") && !/^(-?\d{1,20}|@[A-Za-z0-9_]{4,64}|https:\/\/t\.me\/[A-Za-z0-9_]{4,64})$/.test(c))
480
+ errors.push(`GROUP_KICK_BAD_CHAT: ${who} — chatId: числовой id, @username или шаблон {{var.*}}.`);
481
+ }
482
+ }
464
483
  if (a.kind === "send_email") {
465
484
  // «Отправить письмо» (TASK-4): один получатель — email не массив, список адресов сюда не идёт.
466
485
  if (blank(a.email)) errors.push(`ACTION_SEND_EMAIL_NO_RECIPIENT: ${who} — send_email требует email (адрес или {{var.*}}).`);