@retensy/mcp 0.19.0 → 0.21.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/.claude-plugin/marketplace.json +13 -13
- package/.claude-plugin/plugin.json +12 -12
- package/README.md +322 -316
- package/package.json +2 -2
- package/skills/build-bot-funnel/SKILL.md +108 -108
- package/skills/build-bot-funnel/reference/schema.md +483 -467
- package/skills/build-bot-funnel/reference/validation.md +134 -134
- package/skills/build-bot-funnel/validate.mjs +680 -649
- package/skills/build-site/SKILL.md +105 -105
- package/skills/send-broadcast/SKILL.md +49 -49
- package/src/index.mjs +144 -8
package/README.md
CHANGED
|
@@ -1,316 +1,322 @@
|
|
|
1
|
-
# retensy-mcp
|
|
2
|
-
|
|
3
|
-
[](https://github.com/retensy/retensy-mcp/actions/workflows/ci.yml)
|
|
4
|
-
[](https://www.npmjs.com/package/@retensy/mcp)
|
|
5
|
-
[](https://nodejs.org)
|
|
6
|
-
[](LICENSE)
|
|
7
|
-
|
|
8
|
-
MCP-сервер (+ скилл для Claude Code) для **сборки и публикации воронок/автоматизаций ботов (Telegram, MAX и Instagram)** в сервисе [retensy `/bots`](https://bots.retensy.com/bots): из текстового описания → валидный граф сценария → заливка и публикация через API.
|
|
9
|
-
|
|
10
|
-
- 🤖 **Сценарии ботов**: `list_bots`, `list_graphs`, `list_channels`, `get_graph`, `create_graph`, `update_graph`, `edit_graph_live`, `patch_graph`, `dry_run`, `publish_graph`, `import_funnel`, `list_templates`, `create_graph_from_template`, `clone_graph`, `copy_graph`, `rename_graph`, `set_active_graph`, `delete_graph`, `upload_file`, `list_files`, `delete_file`, `graph_analytics`, `list_bot_users`, `list_links` (+ `setup`/`set_token`).
|
|
11
|
-
- 🔌 **Боты и сервисы**: `create_bot` (Telegram/MAX по токену), `bot_stop`/`bot_resume`, `connect_integration`/`disconnect_integration` (amoCRM, Битрикс24, GetCourse, Я.Метрика, ЮKassa; Google Таблицы — ссылкой на вход Google; креды хранятся зашифрованными и не возвращаются), `integration_catalog`/`integration_status`/`integration_test` (каталог Integration Core и живая проверка подключения), `integration_ingress_url` (URL ингресса «Внешних событий» — Tilda, JivoSite, WooCommerce, amoCRM, Битрикс24, GetCourse, CloudPayments, Robokassa, Т-Банк, Prodamus — для `TRIGGER_WEBHOOK`), `channel_post` (пост в канал Telegram/MAX).
|
|
12
|
-
- 📣 **Рассылки**: `broadcast_preview` (размер аудитории), `broadcast_send` (сейчас или по расписанию, сразу по нескольким ботам; сообщения или запуск сценария), `broadcast_list`/`broadcast_get`/`broadcast_cancel`, повторяющиеся (`broadcast_recurring`), черновики (`broadcast_drafts`, `broadcast_duplicate`) + скилл `send-broadcast`.
|
|
13
|
-
- 🔗 **Ссылка вместо отказа**: что нельзя сделать через API (вход через Google/Facebook, оплата тарифа, вход в аккаунт) — инструмент возвращает прямую ссылку и одну строку, что сделать.
|
|
14
|
-
- 📝 **Статьи блога** (тот же токен `zmcp_…`): `article_publish`, `article_update`, `article_list`, `article_get` — публикация статей в Markdown (как README на GitHub) в раздел **/articles**.
|
|
15
|
-
- 🧠 **ИИ-агенты и база знаний**: `agent_list`/`agent_get`/`agent_create`/`agent_update`/`agent_publish`/`agent_health`/`agent_test_chat`/`agent_unanswered`, `kb_docs`/`kb_add_qa`/`kb_add_text`/`kb_add_site`/`kb_reindex` — настройка ИИ-агента и его базы знаний (раздел «ИИ-агенты»).
|
|
16
|
-
- 📎 **Медиа**: `upload_file` грузит фото/видео/документы в библиотеку **/bots/files** (до 50 МБ) и возвращает публичный URL — его вставляешь в медиа-карточку сценария.
|
|
17
|
-
- 🌐 **Сайты из блоков** (раздел «Страницы»): создание, правка операциями (блоки, Zero-блок со свободной вёрсткой, код блока, папки страниц, дизайны, шаблоны из библиотеки), публикация и откат, свои домены, заявки из форм и куда их доставлять — инструменты `site_*` + скилл `build-site`.
|
|
18
|
-
- 🧠 **Скилл `build-bot-funnel`**: учит агента собирать корректный граф (типы узлов, ветки, кнопки, задержки) и проверять его перед публикацией. Поддерживает Telegram, MAX и Instagram.
|
|
19
|
-
- 📦 **Без зависимостей** — чистый Node ≥18, ставится и запускается сразу.
|
|
20
|
-
|
|
21
|
-
### Поддерживаемые платформы
|
|
22
|
-
|
|
23
|
-
| Платформа | Онбординг | Триггеры входа | Ограничения |
|
|
24
|
-
|---|---|---|---|
|
|
25
|
-
| **Telegram** | Токен бота (BotFather) → `create_bot` | `/start`, команды, callback, текст, рассылки | Полный функционал |
|
|
26
|
-
| **MAX** | Токен бота (MasterBot в MAX) → `create_bot` | Команды, callback, текст | Без SUBSCRIBED/reply-клавиатур (мягкие предупреждения) |
|
|
27
|
-
| **Instagram** ⏸ | OAuth в `/bots/instagram` (без токена) — **сейчас выключен в сервисе** (подключение новых IG-ботов скрыто, флаг `instagram.enabled`) | Комментарий/Direct/Ответ на историю/Упоминание | Ограниченный набор узлов; DELAY ≤ 24ч; ASK_QUESTION только TEXT/EMAIL/PHONE/NUMBER/CONTACT (CONTACT = ручной ввод номера); без рассылок |
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Установка
|
|
32
|
-
|
|
33
|
-
### Вариант A — как плагин Claude Code (рекомендуется)
|
|
34
|
-
|
|
35
|
-
```text
|
|
36
|
-
/plugin marketplace add retensy/retensy-mcp
|
|
37
|
-
/plugin install retensy-mcp@retensy
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Подтянутся MCP-сервер и скиллы `build-bot-funnel`, `build-site`, `send-broadcast`. Проверить: `/mcp` и `/plugin`.
|
|
41
|
-
|
|
42
|
-
### Вариант B — как обычный MCP-сервер (Claude Code / Cursor / Windsurf / любой MCP-клиент)
|
|
43
|
-
|
|
44
|
-
Через `npx` без установки. Пример конфига (`.mcp.json` / настройки клиента):
|
|
45
|
-
|
|
46
|
-
```json
|
|
47
|
-
{
|
|
48
|
-
"mcpServers": {
|
|
49
|
-
"retensy-mcp": {
|
|
50
|
-
"command": "npx",
|
|
51
|
-
"args": ["-y", "@retensy/mcp@latest"],
|
|
52
|
-
"env": {
|
|
53
|
-
"RETENSY_BASE_URL": "https://bots.retensy.com",
|
|
54
|
-
"RETENSY_MCP_TOKEN": "zmcp_ваш_токен"
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
См. также [`examples/.mcp.json`](examples/.mcp.json).
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Авторизация — персональный токен
|
|
66
|
-
|
|
67
|
-
Токен даёт **полный доступ** к управлению твоими ботами (как вход в аккаунт).
|
|
68
|
-
|
|
69
|
-
1. Залогинься на https://bots.retensy.com → открой **`/bots/mcp-tokens`**.
|
|
70
|
-
2. Создай токен → скопируй секрет `zmcp_...` (показывается один раз).
|
|
71
|
-
3. Передай токен любым способом:
|
|
72
|
-
- **просто пришли его агенту в чат** — он вызовет инструмент `set_token` и сохранит токен в `~/.retensy-bot-graph/token` (применяется сразу, без рестарта), **или**
|
|
73
|
-
- `env` в `.mcp.json` (Вариант B), **или**
|
|
74
|
-
- переменной окружения: PowerShell `setx RETENSY_MCP_TOKEN "zmcp_..."`, bash `export RETENSY_MCP_TOKEN="zmcp_..."`.
|
|
75
|
-
|
|
76
|
-
Отозвать токен можно там же — доступ блокируется мгновенно.
|
|
77
|
-
|
|
78
|
-
> **Не знаешь, что делать?** Скажи агенту «настрой подключение» — он вызовет `setup`, объяснит шаги и попросит токен. Любой инструмент при отсутствии токена тоже вернёт пошаговую инструкцию.
|
|
79
|
-
|
|
80
|
-
> Дев-окружение: `RETENSY_BASE_URL=http://localhost:8066`.
|
|
81
|
-
> Fallback без токена: `RETENSY_SESSION_COOKIE` = значение куки `SESSION` из браузера.
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## Использование
|
|
86
|
-
|
|
87
|
-
Опиши воронку словами — агент соберёт граф и (через MCP) опубликует:
|
|
88
|
-
|
|
89
|
-
> «Собери бота: `/start` → приветствие с кнопкой подписки на канал → вопрос с 3 кнопками (бизнес / эксперт / просто смотрю) → для каждой свою цепочку из 2 сообщений с задержкой 1 день → финал с регистрацией на вебинар. Залей в бота и опубликуй.»
|
|
90
|
-
|
|
91
|
-
Под капотом скилл соберёт `nodes/edges`, прогонит локальную проверку и вызовет `import_funnel` → создаст граф, зальёт узлы, прогонит `dry-run /start`, опубликует. При ошибках публикации — разберёт по `code`/`nodeId`, починит, повторит.
|
|
92
|
-
|
|
93
|
-
### Инструменты
|
|
94
|
-
|
|
95
|
-
| Tool | Назначение |
|
|
96
|
-
|---|---|
|
|
97
|
-
| `setup` | статус авторизации + пошаговая инструкция подключения |
|
|
98
|
-
| `set_token` | сохранить присланный токен `zmcp_…` (без env/рестарта) |
|
|
99
|
-
| `list_bots` | список ботов |
|
|
100
|
-
| `create_bot(platform, token?, name?)` | подключить бота Telegram/MAX по токену; `WEB` — чат-виджет для сайта без токена → botId, key, snippet (Instagram → ссылка на кабинет) |
|
|
101
|
-
| `web_widget_snippet(botId)` | код вставки чат-виджета на сайт |
|
|
102
|
-
| `bot_stop(botId)` / `bot_resume(botId)` | остановить / запустить бота |
|
|
103
|
-
| `list_graphs(botId)` | графы (сценарии) бота |
|
|
104
|
-
| `list_channels(botId)` | каналы/группы, подключённые к боту (chatId для условия SUBSCRIBED) |
|
|
105
|
-
| `list_integrations()` | подключённые сервисы (amoCRM, Битрикс24, GetCourse, Я.Метрика, ЮKassa): `id` = `connectionId` для действий сценария |
|
|
106
|
-
| `connect_integration(provider, creds?, title?, connectionId?)` | подключить/обновить сервис; без кредов — какие поля нужны; Google Таблицы → ссылка входа Google, Instagram → ссылка на кабинет |
|
|
107
|
-
| `disconnect_integration(connectionId)` | удалить подключение |
|
|
108
|
-
| `integration_catalog()` | каталог Integration Core: поля подключения (`configSchema`) и действия (`actions[].kind`) сервисов |
|
|
109
|
-
| `integration_status(connectionId)` | статус подключения: `OK` / `NEEDS_REAUTH` / `ERROR` / `UNKNOWN`, последняя проверка и ошибка |
|
|
110
|
-
| `integration_test(connectionId)` | живая проверка ключа во внешнем сервисе от имени владельца (без побочных эффектов) |
|
|
111
|
-
| `integration_ingress_url(connectionId, rotate?)` | URL ингресса для триггера «Внешние события» (`TRIGGER_WEBHOOK` с `provider`+`connectionId`+`event`); `rotate:true` — выпустить новый, старый отключается сразу |
|
|
112
|
-
| `channel_post(botId, chatId, text?, mediaUrl?)` | разовый пост в канал/группу Telegram или MAX (раздел «Публикации»); файл — из `upload_file` |
|
|
113
|
-
| `get_graph(graphId, [summary], [saveToFile])` | получить граф; `summary:true` — компактная сводка (id/type/title + рёбра), `saveToFile` — записать полный JSON на диск (для больших графов, чтобы не упереться в лимит токенов) |
|
|
114
|
-
| `create_graph(botId, name)` | создать пустой граф (DRAFT) |
|
|
115
|
-
| `update_graph(graphId, graphFile\|graph\|nodes,edges)` | залить узлы/рёбра (PUT); `graphFile` — путь к локальному JSON, граф не нужно слать инлайном |
|
|
116
|
-
| `edit_graph_live(graphId, graphFile\|graph\|nodes,edges)` | правка живого графа НА МЕСТЕ + авто-бэкап (рекомендуется для прода) |
|
|
117
|
-
| `patch_graph(graphId, replacements)` | строковые замены в JSON графа на сервере (для больших/живых графов) |
|
|
118
|
-
| `dry_run(graphId, kind, value)` | прогон без публикации |
|
|
119
|
-
| `publish_graph(graphId)` | публикация (вернёт `errors[]` при провале) |
|
|
120
|
-
| `import_funnel(botId, name, graphFile\|graph)` | всё за раз: create → update → dry-run → publish |
|
|
121
|
-
| `list_templates()` | готовые шаблоны воронок |
|
|
122
|
-
| `create_graph_from_template(botId, templateId, name)` | граф из шаблона (DRAFT) |
|
|
123
|
-
| `clone_graph(graphId)` | копия графа в новый DRAFT |
|
|
124
|
-
| `rename_graph(graphId, name)` | переименовать сценарий |
|
|
125
|
-
| `set_active_graph(botId, graphId)` | переключить активный (живой) граф бота |
|
|
126
|
-
| `delete_graph(graphId)` | удалить граф (активный — нельзя, 409) |
|
|
127
|
-
| `upload_file(path\|url)` | загрузить файл в /bots/files → публичный `url` для медиа-карточки |
|
|
128
|
-
| `list_files()` | файлы библиотеки /bots/files + использовано/лимит байт |
|
|
129
|
-
| `delete_file(id)` | удалить файл из /bots/files |
|
|
130
|
-
| `graph_analytics(graphId)` | прохождение сценария по узлам (где отваливается воронка) |
|
|
131
|
-
| `list_bot_users(botId)` | подписчики/лиды бота (постранично, поиск `query`) |
|
|
132
|
-
| `list_links(botId)` | стартовые трекинговые ссылки бота с UTM |
|
|
133
|
-
| `site_list()` | сайты пользователя (id, mode, url, publishedRevision) |
|
|
134
|
-
| `site_create(title, slug?, template?)` | новый сайт из блоков → `id`; `template` (`starter`/`blank`/`mini-landing`) — сразу черновик из
|
|
135
|
-
| `site_get(siteId, saveToFile?)` | модель сайта (`revision`, `draft`, `versions[]` публикаций) |
|
|
136
|
-
| `site_schema()` | JSON Schema модели и операций — читать перед правкой |
|
|
137
|
-
| `site_edit(siteId, ops[]?, revision?, init?)` | правка операциями (`init`: `starter`/`blank`/`mini-landing`; только `init` — черновик из шаблона), всё или ничего: страницы и папки, блоки, Zero-элементы, код блока (`get/set/add_block_code`), дизайны и их кадры, шаблоны (`add_template`), тема, попапы |
|
|
138
|
-
| `site_templates(category?, full?)` | библиотека шаблонов блоков для `add_template` |
|
|
139
|
-
| `site_publish(siteId)` | опубликовать черновик → `url` |
|
|
140
|
-
| `site_rollback(siteId, revision)` | вернуть прошлую публикацию |
|
|
141
|
-
| `site_upload_asset(siteId, path\|url)` | картинка/видео в сайт → `assets/…` |
|
|
142
|
-
| `site_domains(siteId, action, host?, withWww?, domainId?)` | свои домены: list / add / check / remove (число — по тарифу) |
|
|
143
|
-
| `site_leads(siteId, page?, size?)` | заявки из форм (поля, UTM, статус доставки) |
|
|
144
|
-
| `site_lead_settings(siteId, settings?)` | куда доставлять заявки: бот уведомлений, почта, вебхук, вебхук-сценарий, amoCRM, «Интеграция» (`coreDelivery {connectionId, kind, params}` из `coreConnections`) |
|
|
145
|
-
| `broadcast_list(botId?, group?, page?, size?)` | рассылки + счётчики разделов (черновики/запланированные/отправленные/повторы) |
|
|
146
|
-
| `broadcast_get(broadcastId)` | рассылка целиком: статус, счётчики, сообщения, причины ошибок |
|
|
147
|
-
| `broadcast_preview(botIds, tagsAll?, tagsNone?)` | сколько подписчиков получат рассылку |
|
|
148
|
-
| `broadcast_send(name, botIds, messages \| graphId, tagsAll?, tagsNone?, scheduledAt?, draftId?)` | отправить сейчас / запланировать; по нескольким ботам; или запуск сценария |
|
|
149
|
-
| `broadcast_cancel(broadcastId)` | отменить запланированную/идущую |
|
|
150
|
-
| `broadcast_recurring(action, …)` | повторяющиеся рассылки: list / create (DAILY·MONTHLY·YEARLY) / stop |
|
|
151
|
-
| `broadcast_drafts(action, …)` | черновики: list / get / create / update / delete |
|
|
152
|
-
| `broadcast_duplicate(broadcastId` или `draftId)` | копия рассылки или черновика — новый черновик «… (копия)» |
|
|
153
|
-
| `article_list()` | свои статьи блога (id, slug, title, просмотры) |
|
|
154
|
-
| `article_get(slug)` | статья по slug (Markdown content, excerpt, обложка) |
|
|
155
|
-
| `article_publish(content, title?, cover?, excerpt?)` | новая статья (Markdown; title из `# ...`, если не задан; обложка из `cover`-URL или 1-й картинки → OG; `excerpt` явно или авто) → id, slug, URL |
|
|
156
|
-
| `article_update(id, content, title?)` | обновить свою статью по id |
|
|
157
|
-
| `agent_list()` | список ИИ-агентов (id, имя, статус) |
|
|
158
|
-
| `agent_get(agentId)` | настройки агента: язык, тон, длина/формат ответа, инструкции, темы, `kbId` базы знаний, статус |
|
|
159
|
-
| `agent_create(name?, description?)` | создать агента; вместе с ним создаётся база знаний (`kbId` в ответе) |
|
|
160
|
-
| `agent_update(agentId, patch)` | частично изменить настройки (`patch` — только меняемые поля: `tone`, `language`, `instructions` и т.п.) |
|
|
161
|
-
| `agent_publish(agentId)` | опубликовать; 409 `CHECKLIST_FAILED`, если агент не готов |
|
|
162
|
-
| `agent_health(agentId)` | счётчики документов/фрагментов базы знаний |
|
|
163
|
-
| `agent_test_chat(agentId, question, history?)` | проверить ответ в песочнице (**тратит бюджет ИИ** — не вызывай массово) |
|
|
164
|
-
| `agent_unanswered(agentId, days?)` | вопросы без ответа за период (7\|30\|90, по умолчанию 30) |
|
|
165
|
-
| `kb_docs(kbId)` | документы базы знаний агента (источник, статус, фрагменты) |
|
|
166
|
-
| `kb_add_qa(kbId, pairs)` | добавить пары вопрос-ответ (`pairs: [{question, answer}]`, до 200 за раз) |
|
|
167
|
-
| `kb_add_text(kbId, title, text)` | добавить источник «Текст/инструкция» |
|
|
168
|
-
| `kb_add_site(kbId, url, schedule?)` | добавить сайт обходом страниц; `schedule`: `NEVER`\|`DAILY`\|`WEEKLY`\|`MONTHLY` |
|
|
169
|
-
| `kb_reindex(kbId, docId, headerRow?)` | переиндексировать файл из оригинала («Повторить»); `headerRow` — для таблиц, если шапка определилась неверно |
|
|
170
|
-
| `kb_list()` / `kb_create(name)` | базы знаний: список / новая (база агента создаётся с ним — `kbId` в `agent_get`) (id → `knowledgeBaseId` узла `AI_REPLY mode:"agent"`) |
|
|
171
|
-
| `kb_delete_doc(kbId, docId)` | удалить документ из базы знаний вместе с фрагментами |
|
|
172
|
-
| `bot_user_get(botId, chatId)` | карточка подписчика: теги, переменные, ai_summary |
|
|
173
|
-
| `bot_user_runs(botId, chatId)` | журнал запусков с шагами — проверка, что сценарий реально выполнил действия (CRM, уведомление, HTTP) |
|
|
174
|
-
| `dialog_messages(botId, chatId)` / `dialog_reply(botId, chatId, text)` | переписка с подписчиком / ответ оператора (уходит реальному человеку) |
|
|
175
|
-
| `dialog_handoff(botId, chatId, active)` | передать диалог оператору (бот и ИИ молчат) / вернуть боту
|
|
176
|
-
| `bot_users_import(botId, rows)` | добавить подписчикам метки и новые поля (`rows: [{chatId, tags?, variables?}]`; существующие поля не перезаписываются) |
|
|
177
|
-
| `bot_runs(botId` или `runId)` | журнал прогонов бота / один прогон с шагами (статус `PARTIAL` — «завершён с ошибками») |
|
|
178
|
-
| `scenario_runs(graphId, page?, size?)` | журнал прогонов одного сценария, включая headless (вебхук, заявки сайта, `TRIGGER_SCHEDULE`)
|
|
179
|
-
| `bot_delete(botId, confirm:true)` | удалить бота навсегда (только по явной просьбе) |
|
|
180
|
-
| `web_widget_settings(botId, settings?)` | вид чат-виджета: прочитать / изменить (поля накладываются на текущие) |
|
|
181
|
-
| `integration_update(connectionId, title?, creds?)` | переименовать подключение или заменить ключи |
|
|
182
|
-
| `integration_calls(connectionId?, ok?, limit?)` | журнал вызовов внешних сервисов из сценариев (ошибки, попытки, runId)
|
|
183
|
-
| `site_lead_status(siteId, leadId, status)` | статус заявки сайта: `NEW`\|`IN_PROGRESS`\|`DONE`\|`REJECTED` (фильтр — `site_leads(status)`)
|
|
184
|
-
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
1
|
+
# retensy-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/retensy/retensy-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@retensy/mcp)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
MCP-сервер (+ скилл для Claude Code) для **сборки и публикации воронок/автоматизаций ботов (Telegram, MAX и Instagram)** в сервисе [retensy `/bots`](https://bots.retensy.com/bots): из текстового описания → валидный граф сценария → заливка и публикация через API.
|
|
9
|
+
|
|
10
|
+
- 🤖 **Сценарии ботов**: `list_bots`, `list_graphs`, `list_channels`, `get_graph`, `create_graph`, `update_graph`, `edit_graph_live`, `patch_graph`, `dry_run`, `publish_graph`, `import_funnel`, `list_templates`, `create_graph_from_template`, `clone_graph`, `copy_graph`, `rename_graph`, `set_active_graph`, `delete_graph`, `upload_file`, `list_files`, `delete_file`, `graph_analytics`, `list_bot_users`, `list_links` (+ `setup`/`set_token`).
|
|
11
|
+
- 🔌 **Боты и сервисы**: `create_bot` (Telegram/MAX по токену), `bot_stop`/`bot_resume`, `connect_integration`/`disconnect_integration` (amoCRM, Битрикс24, GetCourse, Я.Метрика, ЮKassa; Google Таблицы — ссылкой на вход Google; креды хранятся зашифрованными и не возвращаются), `integration_catalog`/`integration_status`/`integration_test` (каталог Integration Core и живая проверка подключения), `integration_ingress_url` (URL ингресса «Внешних событий» — Tilda, JivoSite, WooCommerce, amoCRM, Битрикс24, GetCourse, CloudPayments, Robokassa, Т-Банк, Prodamus — для `TRIGGER_WEBHOOK`), `channel_post` (пост в канал Telegram/MAX).
|
|
12
|
+
- 📣 **Рассылки**: `broadcast_preview` (размер аудитории), `broadcast_send` (сейчас или по расписанию, сразу по нескольким ботам; сообщения или запуск сценария), `broadcast_list`/`broadcast_get`/`broadcast_cancel`, повторяющиеся (`broadcast_recurring`), черновики (`broadcast_drafts`, `broadcast_duplicate`) + скилл `send-broadcast`.
|
|
13
|
+
- 🔗 **Ссылка вместо отказа**: что нельзя сделать через API (вход через Google/Facebook, оплата тарифа, вход в аккаунт) — инструмент возвращает прямую ссылку и одну строку, что сделать.
|
|
14
|
+
- 📝 **Статьи блога** (тот же токен `zmcp_…`): `article_publish`, `article_update`, `article_list`, `article_get` — публикация статей в Markdown (как README на GitHub) в раздел **/articles**.
|
|
15
|
+
- 🧠 **ИИ-агенты и база знаний**: `agent_list`/`agent_get`/`agent_create`/`agent_update`/`agent_publish`/`agent_health`/`agent_test_chat`/`agent_unanswered`, `kb_docs`/`kb_add_qa`/`kb_add_text`/`kb_add_site`/`kb_reindex` — настройка ИИ-агента и его базы знаний (раздел «ИИ-агенты»).
|
|
16
|
+
- 📎 **Медиа**: `upload_file` грузит фото/видео/документы в библиотеку **/bots/files** (до 50 МБ) и возвращает публичный URL — его вставляешь в медиа-карточку сценария.
|
|
17
|
+
- 🌐 **Сайты из блоков** (раздел «Страницы»): создание, правка операциями (блоки, Zero-блок со свободной вёрсткой, код блока, папки страниц, дизайны, шаблоны из библиотеки), публикация и откат, свои домены, заявки из форм и куда их доставлять — инструменты `site_*` + скилл `build-site`.
|
|
18
|
+
- 🧠 **Скилл `build-bot-funnel`**: учит агента собирать корректный граф (типы узлов, ветки, кнопки, задержки) и проверять его перед публикацией. Поддерживает Telegram, MAX и Instagram.
|
|
19
|
+
- 📦 **Без зависимостей** — чистый Node ≥18, ставится и запускается сразу.
|
|
20
|
+
|
|
21
|
+
### Поддерживаемые платформы
|
|
22
|
+
|
|
23
|
+
| Платформа | Онбординг | Триггеры входа | Ограничения |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| **Telegram** | Токен бота (BotFather) → `create_bot` | `/start`, команды, callback, текст, рассылки | Полный функционал |
|
|
26
|
+
| **MAX** | Токен бота (MasterBot в MAX) → `create_bot` | Команды, callback, текст | Без SUBSCRIBED/reply-клавиатур (мягкие предупреждения) |
|
|
27
|
+
| **Instagram** ⏸ | OAuth в `/bots/instagram` (без токена) — **сейчас выключен в сервисе** (подключение новых IG-ботов скрыто, флаг `instagram.enabled`) | Комментарий/Direct/Ответ на историю/Упоминание | Ограниченный набор узлов; DELAY ≤ 24ч; ASK_QUESTION только TEXT/EMAIL/PHONE/NUMBER/CONTACT (CONTACT = ручной ввод номера); без рассылок |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Установка
|
|
32
|
+
|
|
33
|
+
### Вариант A — как плагин Claude Code (рекомендуется)
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
/plugin marketplace add retensy/retensy-mcp
|
|
37
|
+
/plugin install retensy-mcp@retensy
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Подтянутся MCP-сервер и скиллы `build-bot-funnel`, `build-site`, `send-broadcast`. Проверить: `/mcp` и `/plugin`.
|
|
41
|
+
|
|
42
|
+
### Вариант B — как обычный MCP-сервер (Claude Code / Cursor / Windsurf / любой MCP-клиент)
|
|
43
|
+
|
|
44
|
+
Через `npx` без установки. Пример конфига (`.mcp.json` / настройки клиента):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"retensy-mcp": {
|
|
50
|
+
"command": "npx",
|
|
51
|
+
"args": ["-y", "@retensy/mcp@latest"],
|
|
52
|
+
"env": {
|
|
53
|
+
"RETENSY_BASE_URL": "https://bots.retensy.com",
|
|
54
|
+
"RETENSY_MCP_TOKEN": "zmcp_ваш_токен"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
См. также [`examples/.mcp.json`](examples/.mcp.json).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Авторизация — персональный токен
|
|
66
|
+
|
|
67
|
+
Токен даёт **полный доступ** к управлению твоими ботами (как вход в аккаунт).
|
|
68
|
+
|
|
69
|
+
1. Залогинься на https://bots.retensy.com → открой **`/bots/mcp-tokens`**.
|
|
70
|
+
2. Создай токен → скопируй секрет `zmcp_...` (показывается один раз).
|
|
71
|
+
3. Передай токен любым способом:
|
|
72
|
+
- **просто пришли его агенту в чат** — он вызовет инструмент `set_token` и сохранит токен в `~/.retensy-bot-graph/token` (применяется сразу, без рестарта), **или**
|
|
73
|
+
- `env` в `.mcp.json` (Вариант B), **или**
|
|
74
|
+
- переменной окружения: PowerShell `setx RETENSY_MCP_TOKEN "zmcp_..."`, bash `export RETENSY_MCP_TOKEN="zmcp_..."`.
|
|
75
|
+
|
|
76
|
+
Отозвать токен можно там же — доступ блокируется мгновенно.
|
|
77
|
+
|
|
78
|
+
> **Не знаешь, что делать?** Скажи агенту «настрой подключение» — он вызовет `setup`, объяснит шаги и попросит токен. Любой инструмент при отсутствии токена тоже вернёт пошаговую инструкцию.
|
|
79
|
+
|
|
80
|
+
> Дев-окружение: `RETENSY_BASE_URL=http://localhost:8066`.
|
|
81
|
+
> Fallback без токена: `RETENSY_SESSION_COOKIE` = значение куки `SESSION` из браузера.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Использование
|
|
86
|
+
|
|
87
|
+
Опиши воронку словами — агент соберёт граф и (через MCP) опубликует:
|
|
88
|
+
|
|
89
|
+
> «Собери бота: `/start` → приветствие с кнопкой подписки на канал → вопрос с 3 кнопками (бизнес / эксперт / просто смотрю) → для каждой свою цепочку из 2 сообщений с задержкой 1 день → финал с регистрацией на вебинар. Залей в бота и опубликуй.»
|
|
90
|
+
|
|
91
|
+
Под капотом скилл соберёт `nodes/edges`, прогонит локальную проверку и вызовет `import_funnel` → создаст граф, зальёт узлы, прогонит `dry-run /start`, опубликует. При ошибках публикации — разберёт по `code`/`nodeId`, починит, повторит.
|
|
92
|
+
|
|
93
|
+
### Инструменты
|
|
94
|
+
|
|
95
|
+
| Tool | Назначение |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `setup` | статус авторизации + пошаговая инструкция подключения |
|
|
98
|
+
| `set_token` | сохранить присланный токен `zmcp_…` (без env/рестарта) |
|
|
99
|
+
| `list_bots` | список ботов |
|
|
100
|
+
| `create_bot(platform, token?, name?)` | подключить бота Telegram/MAX по токену; `WEB` — чат-виджет для сайта без токена → botId, key, snippet (Instagram → ссылка на кабинет) |
|
|
101
|
+
| `web_widget_snippet(botId)` | код вставки чат-виджета на сайт |
|
|
102
|
+
| `bot_stop(botId)` / `bot_resume(botId)` | остановить / запустить бота |
|
|
103
|
+
| `list_graphs(botId)` | графы (сценарии) бота |
|
|
104
|
+
| `list_channels(botId)` | каналы/группы, подключённые к боту (chatId для условия SUBSCRIBED) |
|
|
105
|
+
| `list_integrations()` | подключённые сервисы (amoCRM, Битрикс24, GetCourse, Я.Метрика, ЮKassa): `id` = `connectionId` для действий сценария |
|
|
106
|
+
| `connect_integration(provider, creds?, title?, connectionId?)` | подключить/обновить сервис; без кредов — какие поля нужны; Google Таблицы → ссылка входа Google, Instagram → ссылка на кабинет |
|
|
107
|
+
| `disconnect_integration(connectionId)` | удалить подключение |
|
|
108
|
+
| `integration_catalog()` | каталог Integration Core: поля подключения (`configSchema`) и действия (`actions[].kind`) сервисов |
|
|
109
|
+
| `integration_status(connectionId)` | статус подключения: `OK` / `NEEDS_REAUTH` / `ERROR` / `UNKNOWN`, последняя проверка и ошибка |
|
|
110
|
+
| `integration_test(connectionId)` | живая проверка ключа во внешнем сервисе от имени владельца (без побочных эффектов) |
|
|
111
|
+
| `integration_ingress_url(connectionId, rotate?)` | URL ингресса для триггера «Внешние события» (`TRIGGER_WEBHOOK` с `provider`+`connectionId`+`event`); `rotate:true` — выпустить новый, старый отключается сразу |
|
|
112
|
+
| `channel_post(botId, chatId, text?, mediaUrl?)` | разовый пост в канал/группу Telegram или MAX (раздел «Публикации»); файл — из `upload_file` |
|
|
113
|
+
| `get_graph(graphId, [summary], [saveToFile])` | получить граф; `summary:true` — компактная сводка (id/type/title + рёбра), `saveToFile` — записать полный JSON на диск (для больших графов, чтобы не упереться в лимит токенов) |
|
|
114
|
+
| `create_graph(botId, name)` | создать пустой граф (DRAFT) |
|
|
115
|
+
| `update_graph(graphId, graphFile\|graph\|nodes,edges)` | залить узлы/рёбра (PUT); `graphFile` — путь к локальному JSON, граф не нужно слать инлайном |
|
|
116
|
+
| `edit_graph_live(graphId, graphFile\|graph\|nodes,edges)` | правка живого графа НА МЕСТЕ + авто-бэкап (рекомендуется для прода) |
|
|
117
|
+
| `patch_graph(graphId, replacements)` | строковые замены в JSON графа на сервере (для больших/живых графов) |
|
|
118
|
+
| `dry_run(graphId, kind, value)` | прогон без публикации |
|
|
119
|
+
| `publish_graph(graphId)` | публикация (вернёт `errors[]` при провале) |
|
|
120
|
+
| `import_funnel(botId, name, graphFile\|graph)` | всё за раз: create → update → dry-run → publish |
|
|
121
|
+
| `list_templates()` | готовые шаблоны воронок |
|
|
122
|
+
| `create_graph_from_template(botId, templateId, name)` | граф из шаблона (DRAFT) |
|
|
123
|
+
| `clone_graph(graphId)` | копия графа в новый DRAFT |
|
|
124
|
+
| `rename_graph(graphId, name)` | переименовать сценарий |
|
|
125
|
+
| `set_active_graph(botId, graphId)` | переключить активный (живой) граф бота |
|
|
126
|
+
| `delete_graph(graphId)` | удалить граф (активный — нельзя, 409) |
|
|
127
|
+
| `upload_file(path\|url)` | загрузить файл в /bots/files → публичный `url` для медиа-карточки |
|
|
128
|
+
| `list_files()` | файлы библиотеки /bots/files + использовано/лимит байт |
|
|
129
|
+
| `delete_file(id)` | удалить файл из /bots/files |
|
|
130
|
+
| `graph_analytics(graphId)` | прохождение сценария по узлам (где отваливается воронка) |
|
|
131
|
+
| `list_bot_users(botId)` | подписчики/лиды бота (постранично, поиск `query`) |
|
|
132
|
+
| `list_links(botId)` | стартовые трекинговые ссылки бота с UTM |
|
|
133
|
+
| `site_list()` | сайты пользователя (id, mode, url, publishedRevision, status — `BLOCKED` у заблокированных модерацией, blockedReason) |
|
|
134
|
+
| `site_create(title, slug?, template?)` | новый сайт из блоков → `id`; `template` (`starter`/`blank`/`mini-landing`) — сразу черновик из шаблона; число сайтов ограничено тарифом — сверх лимита HTTP 402 с причиной и ссылкой на смену тарифа |
|
|
135
|
+
| `site_get(siteId, saveToFile?)` | модель сайта (`revision`, `draft`, `versions[]` публикаций) |
|
|
136
|
+
| `site_schema()` | JSON Schema модели и операций — читать перед правкой |
|
|
137
|
+
| `site_edit(siteId, ops[]?, revision?, init?)` | правка операциями (`init`: `starter`/`blank`/`mini-landing`; только `init` — черновик из шаблона), всё или ничего: страницы и папки, блоки, Zero-элементы, код блока (`get/set/add_block_code`), дизайны и их кадры, шаблоны (`add_template`), тема, попапы |
|
|
138
|
+
| `site_templates(category?, full?)` | библиотека шаблонов блоков для `add_template` |
|
|
139
|
+
| `site_publish(siteId)` | опубликовать черновик → `url` |
|
|
140
|
+
| `site_rollback(siteId, revision)` | вернуть прошлую публикацию |
|
|
141
|
+
| `site_upload_asset(siteId, path\|url)` | картинка/видео в сайт → `assets/…` |
|
|
142
|
+
| `site_domains(siteId, action, host?, withWww?, domainId?)` | свои домены: list / add / check / remove (число — по тарифу) |
|
|
143
|
+
| `site_leads(siteId, page?, size?)` | заявки из форм (поля, UTM, статус доставки) |
|
|
144
|
+
| `site_lead_settings(siteId, settings?)` | куда доставлять заявки: бот уведомлений, почта, вебхук, вебхук-сценарий, amoCRM, «Интеграция» (`coreDelivery {connectionId, kind, params}` из `coreConnections`) |
|
|
145
|
+
| `broadcast_list(botId?, group?, page?, size?)` | рассылки + счётчики разделов (черновики/запланированные/отправленные/повторы) |
|
|
146
|
+
| `broadcast_get(broadcastId)` | рассылка целиком: статус, счётчики, сообщения, причины ошибок |
|
|
147
|
+
| `broadcast_preview(botIds, tagsAll?, tagsNone?)` | сколько подписчиков получат рассылку |
|
|
148
|
+
| `broadcast_send(name, botIds, messages \| graphId, tagsAll?, tagsNone?, scheduledAt?, draftId?)` | отправить сейчас / запланировать; по нескольким ботам; или запуск сценария |
|
|
149
|
+
| `broadcast_cancel(broadcastId)` | отменить запланированную/идущую |
|
|
150
|
+
| `broadcast_recurring(action, …)` | повторяющиеся рассылки: list / create (DAILY·MONTHLY·YEARLY) / stop |
|
|
151
|
+
| `broadcast_drafts(action, …)` | черновики: list / get / create / update / delete |
|
|
152
|
+
| `broadcast_duplicate(broadcastId` или `draftId)` | копия рассылки или черновика — новый черновик «… (копия)» |
|
|
153
|
+
| `article_list()` | свои статьи блога (id, slug, title, просмотры) |
|
|
154
|
+
| `article_get(slug)` | статья по slug (Markdown content, excerpt, обложка) |
|
|
155
|
+
| `article_publish(content, title?, cover?, excerpt?)` | новая статья (Markdown; title из `# ...`, если не задан; обложка из `cover`-URL или 1-й картинки → OG; `excerpt` явно или авто) → id, slug, URL |
|
|
156
|
+
| `article_update(id, content, title?)` | обновить свою статью по id |
|
|
157
|
+
| `agent_list()` | список ИИ-агентов (id, имя, статус) |
|
|
158
|
+
| `agent_get(agentId)` | настройки агента: язык, тон, длина/формат ответа, инструкции, темы, `kbId` базы знаний, статус |
|
|
159
|
+
| `agent_create(name?, description?)` | создать агента; вместе с ним создаётся база знаний (`kbId` в ответе) |
|
|
160
|
+
| `agent_update(agentId, patch)` | частично изменить настройки (`patch` — только меняемые поля: `tone`, `language`, `instructions` и т.п.) |
|
|
161
|
+
| `agent_publish(agentId)` | опубликовать; 409 `CHECKLIST_FAILED`, если агент не готов |
|
|
162
|
+
| `agent_health(agentId)` | счётчики документов/фрагментов базы знаний |
|
|
163
|
+
| `agent_test_chat(agentId, question, history?)` | проверить ответ в песочнице (**тратит бюджет ИИ** — не вызывай массово) |
|
|
164
|
+
| `agent_unanswered(agentId, days?)` | вопросы без ответа за период (7\|30\|90, по умолчанию 30) |
|
|
165
|
+
| `kb_docs(kbId)` | документы базы знаний агента (источник, статус, фрагменты) |
|
|
166
|
+
| `kb_add_qa(kbId, pairs)` | добавить пары вопрос-ответ (`pairs: [{question, answer}]`, до 200 за раз) |
|
|
167
|
+
| `kb_add_text(kbId, title, text)` | добавить источник «Текст/инструкция» |
|
|
168
|
+
| `kb_add_site(kbId, url, schedule?)` | добавить сайт обходом страниц; `schedule`: `NEVER`\|`DAILY`\|`WEEKLY`\|`MONTHLY` |
|
|
169
|
+
| `kb_reindex(kbId, docId, headerRow?)` | переиндексировать файл из оригинала («Повторить»); `headerRow` — для таблиц, если шапка определилась неверно |
|
|
170
|
+
| `kb_list()` / `kb_create(name)` | базы знаний: список / новая (база агента создаётся с ним — `kbId` в `agent_get`) (id → `knowledgeBaseId` узла `AI_REPLY mode:"agent"`) |
|
|
171
|
+
| `kb_delete_doc(kbId, docId)` | удалить документ из базы знаний вместе с фрагментами |
|
|
172
|
+
| `bot_user_get(botId, chatId)` | карточка подписчика: теги, переменные, ai_summary |
|
|
173
|
+
| `bot_user_runs(botId, chatId)` | журнал запусков с шагами — проверка, что сценарий реально выполнил действия (CRM, уведомление, HTTP) |
|
|
174
|
+
| `dialog_messages(botId, chatId)` / `dialog_reply(botId, chatId, text)` | переписка с подписчиком / ответ оператора (уходит реальному человеку) |
|
|
175
|
+
| `dialog_handoff(botId, chatId, active)` | передать диалог оператору (бот и ИИ молчат) / вернуть боту |
|
|
176
|
+
| `bot_users_import(botId, rows)` | добавить подписчикам метки и новые поля (`rows: [{chatId, tags?, variables?}]`; существующие поля не перезаписываются) |
|
|
177
|
+
| `bot_runs(botId` или `runId)` | журнал прогонов бота / один прогон с шагами (статус `PARTIAL` — «завершён с ошибками») |
|
|
178
|
+
| `scenario_runs(graphId, page?, size?)` | журнал прогонов одного сценария, включая headless (вебхук, заявки сайта, `TRIGGER_SCHEDULE`) |
|
|
179
|
+
| `bot_delete(botId, confirm:true)` | удалить бота навсегда (только по явной просьбе) |
|
|
180
|
+
| `web_widget_settings(botId, settings?)` | вид чат-виджета: прочитать / изменить (поля накладываются на текущие) |
|
|
181
|
+
| `integration_update(connectionId, title?, creds?)` | переименовать подключение или заменить ключи |
|
|
182
|
+
| `integration_calls(connectionId?, ok?, limit?)` | журнал вызовов внешних сервисов из сценариев (ошибки, попытки, runId) |
|
|
183
|
+
| `site_lead_status(siteId, leadId, status)` | статус заявки сайта: `NEW`\|`IN_PROGRESS`\|`DONE`\|`REJECTED` (фильтр — `site_leads(status)`) |
|
|
184
|
+
| `bot_rename(botId, name)` / `bot_change_token(botId, token)` | переименовать бота (пустое имя — `@username`) / сменить токен после перевыпуска |
|
|
185
|
+
| `bot_channel_list(botId)` / `bot_channel_add(botId, token, name?)` / `bot_channel_delete(botId, channelId, confirm:true)` | дополнительные Telegram-боты (мультиканальность); каналы/группы для постинга — `list_channels` |
|
|
186
|
+
| `link_create(botId, name?, targetNodeId?)` / `link_delete(linkId, confirm:true)` | стартовая ссылка (диплинк на узел) / удаление; список — `list_links` |
|
|
187
|
+
| `utm_sources(botId)` / `ab_results(graphId, branchNodeId, period?)` | UTM-источники подписчиков / итоги A/B-развилки (`period`: `24h`, `7d`, `30d`) |
|
|
188
|
+
| `kb_delete(kbId, confirm:true)` | удалить базу знаний целиком (база агента — только вместе с агентом) |
|
|
189
|
+
| `agent_unpublish(agentId)` / `agent_delete(agentId, confirm:true)` | снять агента с публикации / удалить (409 `AGENT_IN_USE`, пока подключён к сценариям) |
|
|
190
|
+
| `site_leads_mark_read(siteId)` / `site_lead_delete(siteId, leadId, confirm:true)` / `site_leads_export(siteId, savePath?)` | заявки сайта: всё прочитано / удалить заявку / CSV |
|
|
191
|
+
| `bot_users_export(botId, format?, savePath?)` | выгрузка подписчиков `csv`\|`json` (с `savePath` — в файл) |
|
|
192
|
+
| `bot_user_reset(botId, chatId, confirm:true)` | сбросить сессию подписчика: позиция, метки, переменные (для повторного теста воронки) |
|
|
193
|
+
| `booking_calendar_list()` / `booking_calendar_get(calendarId)` | календари записи (id → `calendarId` действий сценария `booking_*`) |
|
|
194
|
+
| `booking_calendar_create(name, zone?, slotMinutes?, hours?, exceptions?, botId?)` | новый календарь: окна `{day:1–7, from:"HH:mm", to:"HH:mm"}`, исключения `{date, from?, to?}` |
|
|
195
|
+
| `booking_calendar_update(calendarId, …поля)` / `booking_calendar_delete(calendarId, confirm:true)` | правка (поля накладываются на текущие) / удаление |
|
|
196
|
+
| `booking_slots(calendarId, from?, to?, limit?)` | свободные слоты `[{at, label}]`, даты ГГГГ-ММ-ДД в зоне календаря |
|
|
197
|
+
| `booking_list(calendarId, from?)` / `booking_create(calendarId, slotAt, name?, phone?)` / `booking_cancel(calendarId, bookingId)` | брони: список / ручная запись (занятый слот — ошибка «занят») / отмена |
|
|
198
|
+
|
|
199
|
+
### Рассылки
|
|
200
|
+
|
|
201
|
+
Сообщение рассылки — как в мастере кабинета: `{type, text?, mediaUrl?, mediaUrls?, buttons?}`, до 5 сообщений.
|
|
202
|
+
|
|
203
|
+
| type | Обязательно | Текст | Кнопки |
|
|
204
|
+
|---|---|---|---|
|
|
205
|
+
| `TEXT` | `text` (до 4096) | Telegram-HTML | до 8 URL-кнопок |
|
|
206
|
+
| `PHOTO` `VIDEO` `AUDIO` `FILE` `VOICE` | `mediaUrl` | подпись до 1024 | до 8 |
|
|
207
|
+
| `VIDEONOTE` (кружок) | `mediaUrl` | нет | до 8 |
|
|
208
|
+
| `GALLERY` | `mediaUrls` — 2–10 картинок | подпись до 1024 | нет |
|
|
209
|
+
|
|
210
|
+
- HTML: `<b> <i> <u> <s> <code> <pre> <blockquote> <tg-spoiler> <a href="https://…">`, перенос строки — `\n`.
|
|
211
|
+
- Кнопки только URL `[{text, url}]` — callback-кнопок в рассылке нет. Медиа — сначала `upload_file`, потом его `url`.
|
|
212
|
+
- Аудитория — подписчики бота, фильтр тегами: `tagsAll` (есть все), `tagsNone` (нет ни одного). До 50 000 на бота, до 20 ботов одного владельца за раз.
|
|
213
|
+
- `scheduledAt` — ISO 8601; без часового пояса считается московским. Пусто — отправить сейчас.
|
|
214
|
+
- Рассылки — на платном тарифе; квота получателей месячная. При нехватке — ошибка с прямой ссылкой на смену тарифа.
|
|
215
|
+
- У Instagram-ботов рассылок нет.
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{"name": "Распродажа", "botIds": ["<id>"], "tagsAll": ["клиент"], "scheduledAt": "2026-10-10T10:00",
|
|
219
|
+
"messages": ["<b>Только сегодня</b> — скидка 30%",
|
|
220
|
+
{"type": "PHOTO", "mediaUrl": "https://…/sale.jpg", "text": "Успей до полуночи",
|
|
221
|
+
"buttons": [{"text": "В магазин", "url": "https://shop.example"}]}]}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Когда нужен браузер
|
|
225
|
+
|
|
226
|
+
Через API не делается то, что требует входа пользователя у стороннего сервиса, оплаты или входа в аккаунт.
|
|
227
|
+
Такие инструменты не падают, а возвращают `{needsBrowser: true, url, instruction}` или ошибку со ссылкой:
|
|
228
|
+
|
|
229
|
+
| Ситуация | Ссылка |
|
|
230
|
+
|---|---|
|
|
231
|
+
| нет токена / токен отозван | `/bots/mcp-tokens` — создать токен и прислать агенту |
|
|
232
|
+
| Google Таблицы (`connect_integration`) | одноразовая ссылка согласия Google (OAuth) |
|
|
233
|
+
| Instagram (`create_bot`, `connect_integration`) | `/bots/connect` — подключается входом через Facebook; сейчас выключен в сервисе |
|
|
234
|
+
| лимит тарифа, рассылки на бесплатном (HTTP 402) | `upgradeUrl` из ответа или `/bots/subscription` |
|
|
235
|
+
| свой домен сайта | DNS у регистратора: A-запись на `dnsTarget` из `site_domains` |
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Формат графа и проверка
|
|
240
|
+
|
|
241
|
+
Граф — контейнер `retensy-bot-graph` (`nodes[]` + `edges[]`). Полная схема узлов/хэндлов и правила валидатора — в скилле:
|
|
242
|
+
- [`skills/build-bot-funnel/reference/schema.md`](skills/build-bot-funnel/reference/schema.md)
|
|
243
|
+
- [`skills/build-bot-funnel/reference/validation.md`](skills/build-bot-funnel/reference/validation.md)
|
|
244
|
+
|
|
245
|
+
Локальная проверка графа перед заливкой:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Telegram (по умолчанию)
|
|
249
|
+
node skills/build-bot-funnel/validate.mjs path/to/import.json
|
|
250
|
+
# Instagram-бот
|
|
251
|
+
node skills/build-bot-funnel/validate.mjs path/to/import.json --platform=INSTAGRAM
|
|
252
|
+
# MAX-бот
|
|
253
|
+
node skills/build-bot-funnel/validate.mjs path/to/import.json --platform=MAX
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Разработка
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
git clone https://github.com/retensy/retensy-mcp
|
|
262
|
+
cd retensy-mcp
|
|
263
|
+
RETENSY_MCP_TOKEN=zmcp_... node src/index.mjs # стартует stdio MCP-сервер
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Зависимостей нет — это голый JSON-RPC по stdio (протокол MCP `2024-11-05`).
|
|
267
|
+
|
|
268
|
+
## Обновления
|
|
269
|
+
|
|
270
|
+
При старте сервер сверяет свою версию с npm (результат кэшируется на 6 часов в
|
|
271
|
+
`~/.retensy-bot-graph/update-check.json`). Если вышла новая — уведомление появится в `setup` и
|
|
272
|
+
в первом ответе инструмента.
|
|
273
|
+
|
|
274
|
+
- **Установка через npx** (вариант B): держите в конфиге `@retensy/mcp@latest` — тогда свежая
|
|
275
|
+
версия подтягивается при запуске. Если пакет установлен глобально, сервер сам запустит
|
|
276
|
+
`npm i -g @retensy/mcp@latest` в фоне (отключается `RETENSY_MCP_AUTOUPDATE=0`).
|
|
277
|
+
- **Установка как плагин** (вариант A): обновляйте плагин/`git pull` — npm тут не при чём,
|
|
278
|
+
исполняется файл репозитория.
|
|
279
|
+
|
|
280
|
+
Важно: запущенный процесс не может подменить собственный код — **обновление вступает в силу после
|
|
281
|
+
перезапуска MCP-сервера**. Нет сети или npm недоступен — проверка молча пропускается, работа не ломается.
|
|
282
|
+
|
|
283
|
+
## Отчёты о неудачах (телеметрия)
|
|
284
|
+
|
|
285
|
+
Чтобы мы узнавали, каких возможностей не хватает, при неудаче инструмента отправляется **анонимный**
|
|
286
|
+
отчёт: неизвестный инструмент, отказ публикации (`errors[]`), ошибка API.
|
|
287
|
+
|
|
288
|
+
Отчёт уходит на **`POST {RETENSY_BASE_URL}/api/mcp/report`** — то есть на тот же сервер, с которым
|
|
289
|
+
вы и так работаете. Адреса чата/вебхука, куда мы складываем отчёты, в пакете нет: он живёт в
|
|
290
|
+
переменной окружения на сервере. Так его нельзя вытащить из пакета и залить, а мы можем сменить
|
|
291
|
+
приёмник без выпуска новой версии.
|
|
292
|
+
|
|
293
|
+
**Что уходит:** имя инструмента, категория неудачи, текст ошибки, ключи аргументов, версия, платформа
|
|
294
|
+
и анонимный id установки (хэш от имени хоста и домашнего каталога — не сами значения).
|
|
295
|
+
**Что НЕ уходит никогда:** токены, cookie, пароли, креды интеграций, содержимое графов и текстов
|
|
296
|
+
рассылок. Значения аргументов по умолчанию скрыты — присылаются только безопасные поля вроде
|
|
297
|
+
`graphId`/`botId`/`kind`.
|
|
298
|
+
|
|
299
|
+
Если персональный токен настроен, он прикладывается к отчёту — тогда мы видим, у кого именно
|
|
300
|
+
не хватило возможности, и можем ответить. Токен прикладывается **только** когда приёмник совпадает
|
|
301
|
+
с `RETENSY_BASE_URL`: на сторонний `RETENSY_MCP_REPORT_URL` он не отправляется.
|
|
302
|
+
|
|
303
|
+
| Переменная | Значение |
|
|
304
|
+
|---|---|
|
|
305
|
+
| `RETENSY_MCP_TELEMETRY=off` | полностью выключить отчёты |
|
|
306
|
+
| `RETENSY_MCP_TELEMETRY=full` | присылать и значения аргументов (для отладки своей установки) |
|
|
307
|
+
| `RETENSY_MCP_REPORT_URL=<url>` | свой приёмник (напр. локальный сервер), вместо `/api/mcp/report` |
|
|
308
|
+
|
|
309
|
+
Отчёты дедуплицируются и ограничены 20 на запуск, отправка не блокирует ответ инструмента
|
|
310
|
+
(таймаут 4 с) и при сбое сети молча игнорируется. На сервере — свои лимиты (30 в час с адреса,
|
|
311
|
+
500 в час всего), так что отчёты нельзя использовать для заливки.
|
|
312
|
+
|
|
313
|
+
Отдельно: если токен ещё не настроен вовсе, отчёт **не** отправляется — это обычное состояние
|
|
314
|
+
нового пользователя, а не пробел в возможностях.
|
|
315
|
+
|
|
316
|
+
## Безопасность
|
|
317
|
+
|
|
318
|
+
Токен = доступ к аккаунту по API. Не коммить его; держи в `env`. В конфигах храни ссылку `${RETENSY_MCP_TOKEN}`, не само значение.
|
|
319
|
+
|
|
320
|
+
## Лицензия
|
|
321
|
+
|
|
322
|
+
MIT — см. [LICENSE](LICENSE).
|