@besales/mcp 0.43.0 → 0.45.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.
Files changed (39) hide show
  1. package/dist/instructions/server-instructions.d.ts +1 -1
  2. package/dist/instructions/server-instructions.js +5 -2
  3. package/dist/instructions/server-instructions.js.map +1 -1
  4. package/dist/schemas/mcp-tools.json +665 -22
  5. package/dist/tools/definitions/broadcast-analytics.js +3 -2
  6. package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
  7. package/dist/tools/definitions/broadcast-mailing-variants.js +8 -4
  8. package/dist/tools/definitions/broadcast-mailing-variants.js.map +1 -1
  9. package/dist/tools/definitions/broadcast-scheduler.d.ts +69 -0
  10. package/dist/tools/definitions/broadcast-scheduler.js +258 -0
  11. package/dist/tools/definitions/broadcast-scheduler.js.map +1 -0
  12. package/dist/tools/definitions/follow-up-setup.d.ts +6 -0
  13. package/dist/tools/definitions/follow-up-setup.js +31 -0
  14. package/dist/tools/definitions/follow-up-setup.js.map +1 -1
  15. package/dist/tools/definitions/follow-up.d.ts +18 -1
  16. package/dist/tools/definitions/follow-up.js +78 -5
  17. package/dist/tools/definitions/follow-up.js.map +1 -1
  18. package/dist/tools/definitions/getcourse-cold-welcome.d.ts +3 -0
  19. package/dist/tools/definitions/getcourse-cold-welcome.js +28 -5
  20. package/dist/tools/definitions/getcourse-cold-welcome.js.map +1 -1
  21. package/dist/tools/definitions/getcourse-wave.d.ts +3 -3
  22. package/dist/tools/definitions/getcourse-wave.js +5 -5
  23. package/dist/tools/definitions/getcourse-wave.js.map +1 -1
  24. package/dist/tools/definitions/platform-setup.d.ts +9 -3
  25. package/dist/tools/definitions/platform-setup.js +38 -1
  26. package/dist/tools/definitions/platform-setup.js.map +1 -1
  27. package/dist/tools/definitions/shared.d.ts +7 -5
  28. package/dist/tools/definitions/shared.js +7 -5
  29. package/dist/tools/definitions/shared.js.map +1 -1
  30. package/dist/tools/definitions.d.ts +72 -3
  31. package/dist/tools/definitions.js +2 -0
  32. package/dist/tools/definitions.js.map +1 -1
  33. package/dist/tools/registry-mapping-cases-platform.js +29 -0
  34. package/dist/tools/registry-mapping-cases-platform.js.map +1 -1
  35. package/dist/tools/trigger-action-config.d.ts +49 -0
  36. package/dist/tools/trigger-action-config.js +167 -0
  37. package/dist/tools/trigger-action-config.js.map +1 -0
  38. package/dist/types/api-contract.gen.d.ts +1289 -164
  39. package/package.json +1 -1
@@ -1305,10 +1305,22 @@
1305
1305
  "channels": {
1306
1306
  "type": "array",
1307
1307
  "items": {
1308
- "type": "string"
1308
+ "type": "string",
1309
+ "enum": [
1310
+ "Site",
1311
+ "Email",
1312
+ "SMS",
1313
+ "Telegram",
1314
+ "Facebook",
1315
+ "VK",
1316
+ "Chatium",
1317
+ "WhatsApp",
1318
+ "Viber",
1319
+ "MAX"
1320
+ ]
1309
1321
  },
1310
1322
  "minItems": 1,
1311
- "description": "Wave channels (GetCourseTransport: VK|Telegram|MAX|SMS|Email|Site) for analytics."
1323
+ "description": "Wave channels (full GetCourseTransport enum) for analytics. Only channels allowed by the platform will be delivered."
1312
1324
  },
1313
1325
  "funnel": {
1314
1326
  "type": "string",
@@ -1578,10 +1590,22 @@
1578
1590
  "channels": {
1579
1591
  "type": "array",
1580
1592
  "items": {
1581
- "type": "string"
1593
+ "type": "string",
1594
+ "enum": [
1595
+ "Site",
1596
+ "Email",
1597
+ "SMS",
1598
+ "Telegram",
1599
+ "Facebook",
1600
+ "VK",
1601
+ "Chatium",
1602
+ "WhatsApp",
1603
+ "Viber",
1604
+ "MAX"
1605
+ ]
1582
1606
  },
1583
1607
  "minItems": 1,
1584
- "description": "Wave channels (GetCourseTransport: VK|Telegram|MAX|SMS|Email|Site) for analytics."
1608
+ "description": "Wave channels (full GetCourseTransport enum) for analytics. Only channels allowed by the platform will be delivered."
1585
1609
  },
1586
1610
  "funnel": {
1587
1611
  "type": "string",
@@ -1997,10 +2021,22 @@
1997
2021
  "channels": {
1998
2022
  "type": "array",
1999
2023
  "items": {
2000
- "type": "string"
2024
+ "type": "string",
2025
+ "enum": [
2026
+ "Site",
2027
+ "Email",
2028
+ "SMS",
2029
+ "Telegram",
2030
+ "Facebook",
2031
+ "VK",
2032
+ "Chatium",
2033
+ "WhatsApp",
2034
+ "Viber",
2035
+ "MAX"
2036
+ ]
2001
2037
  },
2002
2038
  "minItems": 1,
2003
- "description": "Wave channels (GetCourseTransport: VK|Telegram|MAX|SMS|Email|Site) for analytics."
2039
+ "description": "Wave channels (full GetCourseTransport enum) for analytics. Only channels allowed by the platform will be delivered."
2004
2040
  },
2005
2041
  "deal_fields": {
2006
2042
  "type": "object",
@@ -2963,7 +2999,7 @@
2963
2999
  },
2964
3000
  {
2965
3001
  "name": "besales_trigger_upsert",
2966
- "description": "Create trigger, patch trigger metadata, or replace its full action set (replace_actions=true) for an agent. Without replace_actions existing actions are not bulk-replaced; webhook, operator, silent AI, CRM, calendar, outbound and follow-up actions require explicit_confirmation.",
3002
+ "description": "Create trigger, patch trigger metadata, or replace its full action set (replace_actions=true) for an agent. Without replace_actions existing actions are not bulk-replaced; webhook, operator, silent AI, CRM, calendar, outbound and follow-up actions require explicit_confirmation. Конфиг действия кладётся в поле, имя которого зависит от actionType — см. actions.description.",
2967
3003
  "inputSchema": {
2968
3004
  "type": "object",
2969
3005
  "required": [
@@ -3011,8 +3047,35 @@
3011
3047
  },
3012
3048
  "actions": {
3013
3049
  "type": "array",
3050
+ "description": "Полный набор действий триггера (при replace_actions=true — именно ПОЛНЫЙ, а не дельта). Конфиг действия кладётся в ОТДЕЛЬНОЕ поле, имя которого зависит от actionType: правило camelCase(actionType)+\"Config\" — CRM_UPDATE_FIELD → crmUpdateFieldConfig, HTTP_WEBHOOK → httpWebhookConfig, GETCOURSE_SET_DEAL_TAGS → getcourseSetDealTagsConfig. Пять исключений: CRM_MOVE_STAGE → crmConfig, SCHEDULE_FOLLOWUP → scheduleFollowUpConfig, SUMMARIZE_DIALOG → summarizeConfig, SEND_TELEGRAM_CHANNEL_MESSAGE → telegramChannelConfig, CRM_RENAME_DEAL → renameDealConfig. В ОТВЕТЕ API (besales_platform_context_get) тот же конфиг приходит под именем связи (crmMoveStage, scheduleFollowUp, summarizeAction, telegramChannelMessage, renameDeal) — прочитанное можно пересылать как есть: MCP переименует конфиг в ключ входа и снимет поля, которые ответ отдаёт, а вход не принимает (id, triggerId, createdAt, updatedAt, пустые связи чужих типов). Действие с обязательным конфигом, отправленное без него, отвергается.",
3014
3051
  "items": {
3015
- "type": "object"
3052
+ "type": "object",
3053
+ "required": [
3054
+ "actionType"
3055
+ ],
3056
+ "properties": {
3057
+ "actionType": {
3058
+ "type": "string",
3059
+ "description": "Тип действия (Prisma ActionType), например CRM_MOVE_STAGE."
3060
+ },
3061
+ "priority": {
3062
+ "type": "integer",
3063
+ "minimum": 1,
3064
+ "maximum": 100
3065
+ },
3066
+ "isEnabled": {
3067
+ "type": "boolean"
3068
+ },
3069
+ "continueOnError": {
3070
+ "type": "boolean",
3071
+ "description": "Следующие действия триггера выполнятся даже при падении этого."
3072
+ },
3073
+ "crmConfig": {
3074
+ "type": "object",
3075
+ "description": "Конфиг CRM_MOVE_STAGE: crmId (uuid интеграции), crmType (AMOCRM|BITRIX24|GETCOURSE), statusId (id стадии), pipelineId и pipelineCrmId (рекомендуются — без них стадия ищется по всем воронкам), note. В ответе API это поле называется crmMoveStage."
3076
+ }
3077
+ },
3078
+ "additionalProperties": true
3016
3079
  }
3017
3080
  },
3018
3081
  "replace_actions": {
@@ -3665,9 +3728,34 @@
3665
3728
  }
3666
3729
  }
3667
3730
  }
3731
+ },
3732
+ "skipIfContactRepliedSincePreviousSlot": {
3733
+ "type": "boolean",
3734
+ "description": "Не отправлять шаг, если клиент писал ПОСЛЕ предыдущего слота цепочки. Даёт правило «ответил — ближайшее касание пропускаем, через одно продолжаем»: ответ в 13:05 гасит касание в 16:00, а к 17:00 предыдущим слотом становится 16:00, ответ старше него — и цепочка идёт дальше. Прогресс при пропуске двигается, контакт не зависает. Только для календарного шага (scheduleMode=clock + anchorMode=variable): на остальных рантайм и так проверяет свежесть входящего, и флаг там отвергается."
3668
3735
  }
3669
3736
  }
3670
3737
  }
3738
+ },
3739
+ "sessionTimeVariable": {
3740
+ "type": "string",
3741
+ "minLength": 1,
3742
+ "description": "ИМЯ переменной контакта с ЧАСОМ события (ЧЧ:ММ), парное к anchorVariable шага, который задаёт ДАТУ. Нужно потому, что поле-якорь во внешней CRM хранит только дату, а разбор нормализует её в служебный ПОЛДЕНЬ: без этого поля агент в своём промпте видит «Эфир: 21.08.2026 12:00» при эфире в 19:00. Задаётся НА ЦЕПОЧКУ (час слота одинаков для всех касаний и всех дней — dayOffset сдвигает дату, не час). Хранится ИМЯ, а не сам час: цепочка отбирает контактов условием по этой же переменной, и вторая копия значения разошлась бы с отбором молча. На расписание НЕ влияет — его задают atTime шагов; поле читает только промпт агента. Значение у контакта вне ЧЧ:ММ игнорируется: печатается одна дата, выдуманный час не подставляется."
3743
+ },
3744
+ "sessionDayOffsets": {
3745
+ "type": "array",
3746
+ "items": {
3747
+ "type": "integer",
3748
+ "minimum": 0,
3749
+ "maximum": 30
3750
+ },
3751
+ "minItems": 1,
3752
+ "description": "На каких dayOffset цепочки проходят САМИ эфиры ([0,1,2] — три дня подряд от якоря). Вывести из шагов нельзя: касания стоят и на днях без эфира (у вебинарной цепочки шаги занимают дни 0–5, а эфиров три — дни 4 и 5 это продажа), поэтому дни объявляются явно, как явно объявлено время в sessionTimeVariable. На расписание НЕ влияет — его задают atTime/dayOffset шагов; поле читает только промпт агента. Без объявления блок печатает ОДИН эфир по якорю: якорь несёт дату лишь ПЕРВОГО эфира, и на второй день агент видел «был вчера», не зная, что сегодня вечером эфир есть. Порядок задаёт нумерацию («эфир 2 из 3») и нормализуется по возрастанию."
3753
+ },
3754
+ "sessionDurationMinutes": {
3755
+ "type": "integer",
3756
+ "exclusiveMinimum": 0,
3757
+ "description": "Сколько минут длится эфир. Объявляется, ТОЛЬКО если длительность действительно известна: с ней блок промпта утверждает «идёт сейчас» и перестаёт это утверждать по её истечении, без неё — только «уже начался», то есть факт, который нельзя опровергнуть временем. Дефолта нет намеренно: подставленная длительность это утверждение о мире, сделанное за клиента, а такие утверждения агент пересказывает человеку. Читается только при объявленном sessionDayOffsets.",
3758
+ "maximum": 1440
3671
3759
  }
3672
3760
  }
3673
3761
  },
@@ -3707,6 +3795,44 @@
3707
3795
  }
3708
3796
  }
3709
3797
  },
3798
+ {
3799
+ "name": "besales_followup_step_message_set",
3800
+ "description": "Replace the message text of ONE follow-up step without touching other steps, the sequence description, timing or conditions. Requires expected_content: the step is addressed by position, and positions shift when steps are inserted.",
3801
+ "inputSchema": {
3802
+ "type": "object",
3803
+ "required": [
3804
+ "platform_id",
3805
+ "sequence_id",
3806
+ "step_index",
3807
+ "content",
3808
+ "expected_content"
3809
+ ],
3810
+ "properties": {
3811
+ "platform_id": {
3812
+ "type": "string",
3813
+ "format": "uuid"
3814
+ },
3815
+ "sequence_id": {
3816
+ "type": "string",
3817
+ "format": "uuid"
3818
+ },
3819
+ "step_index": {
3820
+ "type": "integer",
3821
+ "minimum": 0,
3822
+ "description": "Zero-based position in config.steps"
3823
+ },
3824
+ "content": {
3825
+ "type": "string",
3826
+ "minLength": 1,
3827
+ "description": "New message text"
3828
+ },
3829
+ "expected_content": {
3830
+ "type": "string",
3831
+ "description": "Current text as the caller saw it; mismatch returns 409 with the actual text"
3832
+ }
3833
+ }
3834
+ }
3835
+ },
3710
3836
  {
3711
3837
  "name": "besales_pipeline_settings_update",
3712
3838
  "description": "Patch allowlisted platform PipelineSettings via typed sections (crm_pipeline_behavior, auto_finish). Phase B (2026-05-27): generic `updates` field удалён — отвергается с 400. CRM stage movement or lead/contact creation fields require explicit_confirmation.",
@@ -8781,7 +8907,7 @@
8781
8907
  },
8782
8908
  {
8783
8909
  "name": "besales_followup_reactions",
8784
- "description": "Read-only аналитика дожимов: на какой шаг follow-up-цепочки контакт реально отреагировал. Метрик ДВЕ — операционная (следует за длиной окна шага, шаги по ней сравнивать нельзя) и сравнительная на равном горизонте (сравнивать можно только при comparableReliable=true). Срезы по сегменту/продукту/мессенджеру доступны только у каналов с рассылками. Scope: read:analytics.",
8910
+ "description": "Read-only аналитика дожимов: на какой шаг follow-up-цепочки контакт реально отреагировал. Метрик ТРИ — операционная (следует за длиной окна шага, шаги по ней сравнивать нельзя), сравнительная на равном горизонте (сравнивать можно только при comparableReliable=true) и runs — отклик на ПРОХОЖДЕНИЕ цепочки за run_window_days от входа, единственная, на которую не влияет частота шагов. Срезы по сегменту/продукту/мессенджеру доступны только у каналов с рассылками. Scope: read:analytics.",
8785
8911
  "inputSchema": {
8786
8912
  "type": "object",
8787
8913
  "required": [
@@ -8846,6 +8972,18 @@
8846
8972
  "type": "string"
8847
8973
  },
8848
8974
  "description": "Транспорты волны (dimensions.channels): Telegram, WhatsApp, MAX, VK."
8975
+ },
8976
+ "run_window_days": {
8977
+ "type": "integer",
8978
+ "enum": [
8979
+ 1,
8980
+ 3,
8981
+ 5,
8982
+ 7,
8983
+ 14
8984
+ ],
8985
+ "default": 1,
8986
+ "description": "Окно ПРОХОЖДЕНИЯ цепочки для метрики runs: ответил ли человек хоть раз за N дней от входа. Не путать с horizon_minutes — там единица касание, здесь прохождение. У частых цепочек подходящего горизонта не существует, и тогда смотреть надо именно runs."
8849
8987
  }
8850
8988
  }
8851
8989
  }
@@ -9354,8 +9492,7 @@
9354
9492
  "RESTRICT",
9355
9493
  "ADD"
9356
9494
  ],
9357
- "default": "RESTRICT",
9358
- "description": "Как применять «Каналы первого сообщения» к КОНТАКТУ. RESTRICT (по умолчанию) — ФИЛЬТР поверх автоматического выбора: сужает набор и добавить канал НЕ МОЖЕТ, поэтому Email/WhatsApp/SMS в этом режиме не уедут никогда (их нет в bot_link школы). ADD — выбранные каналы добавляются КАЖДОМУ контакту сверх его мессенджеров. Едет ПАРОЙ со списком channels: перебил список на запуске — режим тоже берётся с запуска."
9495
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
9359
9496
  }
9360
9497
  }
9361
9498
  }
@@ -9519,8 +9656,7 @@
9519
9656
  "RESTRICT",
9520
9657
  "ADD"
9521
9658
  ],
9522
- "default": "RESTRICT",
9523
- "description": "Как применять «Каналы первого сообщения» к КОНТАКТУ. RESTRICT (по умолчанию) — ФИЛЬТР поверх автоматического выбора: сужает набор и добавить канал НЕ МОЖЕТ, поэтому Email/WhatsApp/SMS в этом режиме не уедут никогда (их нет в bot_link школы). ADD — выбранные каналы добавляются КАЖДОМУ контакту сверх его мессенджеров. Едет ПАРОЙ со списком channels: перебил список на запуске — режим тоже берётся с запуска."
9659
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
9524
9660
  }
9525
9661
  },
9526
9662
  "if": {
@@ -9613,6 +9749,11 @@
9613
9749
  "type": "string",
9614
9750
  "pattern": "^\\d+$",
9615
9751
  "description": "Пин сделки для штампа полей (число в строковом виде)"
9752
+ },
9753
+ "segment_entered_at": {
9754
+ "type": "string",
9755
+ "format": "date-time",
9756
+ "description": "Точный момент входа контакта в когорту (ISO с зоной). На нём считается свежесть в «Аналитике рассылок». Заполняй, когда предсписок собран ПРАВИЛОМ и у строки есть свой момент события. Дату запуска подставлять нельзя — она схлопнула бы месяцы когорт в одну."
9616
9757
  }
9617
9758
  }
9618
9759
  }
@@ -9647,8 +9788,7 @@
9647
9788
  "RESTRICT",
9648
9789
  "ADD"
9649
9790
  ],
9650
- "default": "RESTRICT",
9651
- "description": "Как применять «Каналы первого сообщения» к КОНТАКТУ. RESTRICT (по умолчанию) — ФИЛЬТР поверх автоматического выбора: сужает набор и добавить канал НЕ МОЖЕТ, поэтому Email/WhatsApp/SMS в этом режиме не уедут никогда (их нет в bot_link школы). ADD — выбранные каналы добавляются КАЖДОМУ контакту сверх его мессенджеров. Едет ПАРОЙ со списком channels: перебил список на запуске — режим тоже берётся с запуска."
9791
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
9652
9792
  }
9653
9793
  }
9654
9794
  }
@@ -9732,6 +9872,11 @@
9732
9872
  "type": "string",
9733
9873
  "pattern": "^\\d+$",
9734
9874
  "description": "Пин сделки для штампа полей (число в строковом виде)"
9875
+ },
9876
+ "segment_entered_at": {
9877
+ "type": "string",
9878
+ "format": "date-time",
9879
+ "description": "Точный момент входа контакта в когорту (ISO с зоной). На нём считается свежесть в «Аналитике рассылок». Заполняй, когда предсписок собран ПРАВИЛОМ и у строки есть свой момент события. Дату запуска подставлять нельзя — она схлопнула бы месяцы когорт в одну."
9735
9880
  }
9736
9881
  }
9737
9882
  }
@@ -9776,8 +9921,7 @@
9776
9921
  "RESTRICT",
9777
9922
  "ADD"
9778
9923
  ],
9779
- "default": "RESTRICT",
9780
- "description": "Как применять «Каналы первого сообщения» к КОНТАКТУ. RESTRICT (по умолчанию) — ФИЛЬТР поверх автоматического выбора: сужает набор и добавить канал НЕ МОЖЕТ, поэтому Email/WhatsApp/SMS в этом режиме не уедут никогда (их нет в bot_link школы). ADD — выбранные каналы добавляются КАЖДОМУ контакту сверх его мессенджеров. Едет ПАРОЙ со списком channels: перебил список на запуске — режим тоже берётся с запуска."
9924
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
9781
9925
  }
9782
9926
  }
9783
9927
  }
@@ -9865,6 +10009,11 @@
9865
10009
  "deal_id": {
9866
10010
  "type": "string",
9867
10011
  "pattern": "^\\d+$"
10012
+ },
10013
+ "segment_entered_at": {
10014
+ "type": "string",
10015
+ "format": "date-time",
10016
+ "description": "Точный момент входа контакта в когорту (ISO с зоной). На нём считается свежесть в «Аналитике рассылок». Заполняй, когда предсписок собран ПРАВИЛОМ и у строки есть свой момент события. Дату запуска подставлять нельзя — она схлопнула бы месяцы когорт в одну."
9868
10017
  }
9869
10018
  }
9870
10019
  }
@@ -9902,8 +10051,7 @@
9902
10051
  "RESTRICT",
9903
10052
  "ADD"
9904
10053
  ],
9905
- "default": "RESTRICT",
9906
- "description": "Как применять «Каналы первого сообщения» к КОНТАКТУ. RESTRICT (по умолчанию) — ФИЛЬТР поверх автоматического выбора: сужает набор и добавить канал НЕ МОЖЕТ, поэтому Email/WhatsApp/SMS в этом режиме не уедут никогда (их нет в bot_link школы). ADD — выбранные каналы добавляются КАЖДОМУ контакту сверх его мессенджеров. Едет ПАРОЙ со списком channels: перебил список на запуске — режим тоже берётся с запуска."
10054
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
9907
10055
  }
9908
10056
  }
9909
10057
  }
@@ -10774,6 +10922,492 @@
10774
10922
  }
10775
10923
  }
10776
10924
  }
10925
+ },
10926
+ {
10927
+ "name": "besales_broadcast_schedule_list",
10928
+ "description": "Список расписаний автоматических рассылок воркспейса. Scope: read:campaigns. isEnabled=false — расписание заведено, но крон его не берёт (нормальное состояние сразу после создания).",
10929
+ "inputSchema": {
10930
+ "type": "object",
10931
+ "properties": {
10932
+ "workspace_id": {
10933
+ "type": "string",
10934
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
10935
+ }
10936
+ },
10937
+ "required": []
10938
+ }
10939
+ },
10940
+ {
10941
+ "name": "besales_broadcast_schedule_preview",
10942
+ "description": "Предпросмотр отбора расписания БЕЗ отправки: тот же источник фактов, компилятор правила и исключения, что у крона. Scope: read:campaigns. ⚠️ Показывай пользователю excludedBy и unverifiable числами: unverifiable — «нечем проверить» (нет назначения серии, серия идёт, нет длительности), а не «не подходит». ⚠️⚠️ overlaps — контакты, которых за неделю подавали другие расписания: непустой список означает риск нескольких сообщений одному человеку.",
10943
+ "inputSchema": {
10944
+ "type": "object",
10945
+ "properties": {
10946
+ "workspace_id": {
10947
+ "type": "string",
10948
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
10949
+ },
10950
+ "segment_id": {
10951
+ "type": "string",
10952
+ "description": "UUID сегмента-правила (BroadcastSegment с фасетами)"
10953
+ },
10954
+ "mailing_variant_id": {
10955
+ "type": "string",
10956
+ "description": "UUID рассылки (текст сообщения)"
10957
+ },
10958
+ "platform_id": {
10959
+ "type": "string",
10960
+ "description": "UUID площадки отправки; её таймзона задаёт сутки расписания"
10961
+ },
10962
+ "mechanism": {
10963
+ "type": "string",
10964
+ "enum": [
10965
+ "cold_welcome"
10966
+ ],
10967
+ "description": "Механизм запуска. Пока поддержан только cold_welcome"
10968
+ },
10969
+ "funnels": {
10970
+ "description": "Коды воронок источника, либо \"all\" (без фильтра)",
10971
+ "oneOf": [
10972
+ {
10973
+ "type": "string",
10974
+ "enum": [
10975
+ "all"
10976
+ ]
10977
+ },
10978
+ {
10979
+ "type": "array",
10980
+ "items": {
10981
+ "type": "string"
10982
+ },
10983
+ "maxItems": 100
10984
+ }
10985
+ ]
10986
+ },
10987
+ "product_codes": {
10988
+ "description": "Канонические коды продуктов, либо \"all\" (без фильтра)",
10989
+ "oneOf": [
10990
+ {
10991
+ "type": "string",
10992
+ "enum": [
10993
+ "all"
10994
+ ]
10995
+ },
10996
+ {
10997
+ "type": "array",
10998
+ "items": {
10999
+ "type": "string"
11000
+ },
11001
+ "maxItems": 50
11002
+ }
11003
+ ]
11004
+ },
11005
+ "freshness_days": {
11006
+ "type": "integer",
11007
+ "minimum": 1,
11008
+ "maximum": 78,
11009
+ "description": "Окно свежести: берём вошедших в сегмент за последние N дней"
11010
+ },
11011
+ "time_local": {
11012
+ "type": "string",
11013
+ "pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$",
11014
+ "description": "Локальное время запуска HH:mm в таймзоне площадки"
11015
+ },
11016
+ "days_of_week": {
11017
+ "type": "array",
11018
+ "items": {
11019
+ "type": "integer",
11020
+ "minimum": 1,
11021
+ "maximum": 7
11022
+ },
11023
+ "maxItems": 7,
11024
+ "description": "Дни недели ISO (1 = понедельник). Пусто = каждый день"
11025
+ },
11026
+ "daily_cap": {
11027
+ "type": "integer",
11028
+ "minimum": 1,
11029
+ "maximum": 5000,
11030
+ "description": "Потолок ОТОБРАННЫХ за прогон (не доставленных)"
11031
+ },
11032
+ "selection_order": {
11033
+ "type": "string",
11034
+ "enum": [
11035
+ "FRESH_FIRST",
11036
+ "OLD_FIRST"
11037
+ ],
11038
+ "description": "Порядок отбора внутри пула"
11039
+ },
11040
+ "cooldown_days": {
11041
+ "type": "integer",
11042
+ "minimum": 0,
11043
+ "maximum": 365,
11044
+ "description": "Не писать контакту, если он получал любую нашу рассылку за N дней"
11045
+ },
11046
+ "is_enabled": {
11047
+ "type": "boolean",
11048
+ "description": "Включено ли расписание. Создавай выключенным и включай после предпросмотра"
11049
+ },
11050
+ "channels": {
11051
+ "type": "array",
11052
+ "maxItems": 20,
11053
+ "items": {
11054
+ "type": "string",
11055
+ "enum": [
11056
+ "Site",
11057
+ "Email",
11058
+ "SMS",
11059
+ "Telegram",
11060
+ "Facebook",
11061
+ "VK",
11062
+ "Chatium",
11063
+ "WhatsApp",
11064
+ "Viber",
11065
+ "MAX"
11066
+ ]
11067
+ },
11068
+ "description": "Каналы «Первого сообщения» (GetCourseTransport). Пусто или ключ не передан — дефолт рассылки. Канал вне списка площадки отвергается: школа не сужает набор, а отвергает его ЦЕЛИКОМ."
11069
+ },
11070
+ "channels_mode": {
11071
+ "type": "string",
11072
+ "enum": [
11073
+ "RESTRICT",
11074
+ "ADD"
11075
+ ],
11076
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
11077
+ }
11078
+ },
11079
+ "required": [
11080
+ "segment_id",
11081
+ "mailing_variant_id",
11082
+ "platform_id",
11083
+ "mechanism",
11084
+ "freshness_days",
11085
+ "time_local",
11086
+ "daily_cap",
11087
+ "selection_order",
11088
+ "cooldown_days"
11089
+ ]
11090
+ }
11091
+ },
11092
+ {
11093
+ "name": "besales_broadcast_schedule_upsert",
11094
+ "description": "Создать или обновить расписание автоматической рассылки (передай schedule_id для обновления). Scope: launch:campaigns. ⚠️ Включённое расписание начнёт слать ЖИВЫМ ЛЮДЯМ на ближайшем тике крона (каждые 5 минут) — создавай выключенным и включай после besales_broadcast_schedule_preview. time_local — в таймзоне ПЛОЩАДКИ.",
11095
+ "inputSchema": {
11096
+ "type": "object",
11097
+ "properties": {
11098
+ "workspace_id": {
11099
+ "type": "string",
11100
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
11101
+ },
11102
+ "segment_id": {
11103
+ "type": "string",
11104
+ "description": "UUID сегмента-правила (BroadcastSegment с фасетами)"
11105
+ },
11106
+ "mailing_variant_id": {
11107
+ "type": "string",
11108
+ "description": "UUID рассылки (текст сообщения)"
11109
+ },
11110
+ "platform_id": {
11111
+ "type": "string",
11112
+ "description": "UUID площадки отправки; её таймзона задаёт сутки расписания"
11113
+ },
11114
+ "mechanism": {
11115
+ "type": "string",
11116
+ "enum": [
11117
+ "cold_welcome"
11118
+ ],
11119
+ "description": "Механизм запуска. Пока поддержан только cold_welcome"
11120
+ },
11121
+ "funnels": {
11122
+ "description": "Коды воронок источника, либо \"all\" (без фильтра)",
11123
+ "oneOf": [
11124
+ {
11125
+ "type": "string",
11126
+ "enum": [
11127
+ "all"
11128
+ ]
11129
+ },
11130
+ {
11131
+ "type": "array",
11132
+ "items": {
11133
+ "type": "string"
11134
+ },
11135
+ "maxItems": 100
11136
+ }
11137
+ ]
11138
+ },
11139
+ "product_codes": {
11140
+ "description": "Канонические коды продуктов, либо \"all\" (без фильтра)",
11141
+ "oneOf": [
11142
+ {
11143
+ "type": "string",
11144
+ "enum": [
11145
+ "all"
11146
+ ]
11147
+ },
11148
+ {
11149
+ "type": "array",
11150
+ "items": {
11151
+ "type": "string"
11152
+ },
11153
+ "maxItems": 50
11154
+ }
11155
+ ]
11156
+ },
11157
+ "freshness_days": {
11158
+ "type": "integer",
11159
+ "minimum": 1,
11160
+ "maximum": 78,
11161
+ "description": "Окно свежести: берём вошедших в сегмент за последние N дней"
11162
+ },
11163
+ "time_local": {
11164
+ "type": "string",
11165
+ "pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$",
11166
+ "description": "Локальное время запуска HH:mm в таймзоне площадки"
11167
+ },
11168
+ "days_of_week": {
11169
+ "type": "array",
11170
+ "items": {
11171
+ "type": "integer",
11172
+ "minimum": 1,
11173
+ "maximum": 7
11174
+ },
11175
+ "maxItems": 7,
11176
+ "description": "Дни недели ISO (1 = понедельник). Пусто = каждый день"
11177
+ },
11178
+ "daily_cap": {
11179
+ "type": "integer",
11180
+ "minimum": 1,
11181
+ "maximum": 5000,
11182
+ "description": "Потолок ОТОБРАННЫХ за прогон (не доставленных)"
11183
+ },
11184
+ "selection_order": {
11185
+ "type": "string",
11186
+ "enum": [
11187
+ "FRESH_FIRST",
11188
+ "OLD_FIRST"
11189
+ ],
11190
+ "description": "Порядок отбора внутри пула"
11191
+ },
11192
+ "cooldown_days": {
11193
+ "type": "integer",
11194
+ "minimum": 0,
11195
+ "maximum": 365,
11196
+ "description": "Не писать контакту, если он получал любую нашу рассылку за N дней"
11197
+ },
11198
+ "is_enabled": {
11199
+ "type": "boolean",
11200
+ "description": "Включено ли расписание. Создавай выключенным и включай после предпросмотра"
11201
+ },
11202
+ "schedule_id": {
11203
+ "type": "string",
11204
+ "description": "UUID расписания для обновления. Без него создаётся новое"
11205
+ },
11206
+ "channels": {
11207
+ "type": "array",
11208
+ "maxItems": 20,
11209
+ "items": {
11210
+ "type": "string",
11211
+ "enum": [
11212
+ "Site",
11213
+ "Email",
11214
+ "SMS",
11215
+ "Telegram",
11216
+ "Facebook",
11217
+ "VK",
11218
+ "Chatium",
11219
+ "WhatsApp",
11220
+ "Viber",
11221
+ "MAX"
11222
+ ]
11223
+ },
11224
+ "description": "Каналы «Первого сообщения» (GetCourseTransport). Пусто или ключ не передан — дефолт рассылки. Канал вне списка площадки отвергается: школа не сужает набор, а отвергает его ЦЕЛИКОМ."
11225
+ },
11226
+ "channels_mode": {
11227
+ "type": "string",
11228
+ "enum": [
11229
+ "RESTRICT",
11230
+ "ADD"
11231
+ ],
11232
+ "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
11233
+ }
11234
+ },
11235
+ "required": [
11236
+ "segment_id",
11237
+ "mailing_variant_id",
11238
+ "platform_id",
11239
+ "mechanism",
11240
+ "freshness_days",
11241
+ "time_local",
11242
+ "daily_cap",
11243
+ "selection_order",
11244
+ "cooldown_days"
11245
+ ]
11246
+ }
11247
+ },
11248
+ {
11249
+ "name": "besales_broadcast_schedule_delete",
11250
+ "description": "Удалить расписание вместе с историей прогонов. Scope: launch:campaigns. ⚠️ Удаление уносит журнал подач — контакты, которым уже подавали, снова станут кандидатами. Чтобы просто остановить рассылку, сохрани расписание с is_enabled=false.",
11251
+ "inputSchema": {
11252
+ "type": "object",
11253
+ "properties": {
11254
+ "workspace_id": {
11255
+ "type": "string",
11256
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
11257
+ },
11258
+ "schedule_id": {
11259
+ "type": "string",
11260
+ "description": "UUID расписания"
11261
+ },
11262
+ "explicit_confirmation": {
11263
+ "type": "boolean",
11264
+ "enum": [
11265
+ true
11266
+ ],
11267
+ "description": "Явное подтверждение необратимого удаления"
11268
+ }
11269
+ },
11270
+ "required": [
11271
+ "schedule_id",
11272
+ "explicit_confirmation"
11273
+ ]
11274
+ }
11275
+ },
11276
+ {
11277
+ "name": "besales_broadcast_schedule_runs",
11278
+ "description": "История прогонов расписания со счётчиками исключений. Scope: read:campaigns. ⚠️ selectedCount — сколько ОТОБРАНО, launchedCount — сколько фактически доставлено; расхождение нормально. WAITING_RESOURCE — воркспейс был занят другим импортом, период не сгорел.",
11279
+ "inputSchema": {
11280
+ "type": "object",
11281
+ "properties": {
11282
+ "workspace_id": {
11283
+ "type": "string",
11284
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
11285
+ },
11286
+ "schedule_id": {
11287
+ "type": "string",
11288
+ "description": "UUID расписания"
11289
+ },
11290
+ "limit": {
11291
+ "type": "integer",
11292
+ "minimum": 1,
11293
+ "maximum": 100,
11294
+ "description": "Сколько прогонов вернуть (по умолчанию 30)"
11295
+ }
11296
+ },
11297
+ "required": [
11298
+ "schedule_id"
11299
+ ]
11300
+ }
11301
+ },
11302
+ {
11303
+ "name": "besales_broadcast_segment_rule_set",
11304
+ "description": "Задать правило отбора сегмента: фасеты поведения, якорь свежести, окно ожидания и приоритет. Scope: launch:campaigns. ⚠️⚠️ 409 означает, что сегментом уже отправляли и правило заморожено — заведи НОВЫЙ сегмент, правка задним числом сделала бы разрез отчёта несопоставимым. Секунды, а не минуты: «от 120 минут» — это activeSecondsMin=7200.",
11305
+ "inputSchema": {
11306
+ "type": "object",
11307
+ "properties": {
11308
+ "workspace_id": {
11309
+ "type": "string",
11310
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
11311
+ },
11312
+ "segment_id": {
11313
+ "type": "string",
11314
+ "description": "UUID сегмента"
11315
+ },
11316
+ "facets": {
11317
+ "type": "object",
11318
+ "description": "Закрытый набор фасетов поведения",
11319
+ "properties": {
11320
+ "attended": {
11321
+ "type": "string",
11322
+ "enum": [
11323
+ "YES",
11324
+ "NO",
11325
+ "ANY"
11326
+ ],
11327
+ "description": "Был на вебинаре. NO проходит только достоверный «не пришёл»"
11328
+ },
11329
+ "activeSecondsMin": {
11330
+ "type": "integer",
11331
+ "minimum": 0,
11332
+ "description": "Нижняя граница секунд просмотра"
11333
+ },
11334
+ "activeSecondsMax": {
11335
+ "type": "integer",
11336
+ "minimum": 0,
11337
+ "description": "Верхняя граница секунд просмотра"
11338
+ },
11339
+ "webinarDayMin": {
11340
+ "type": "integer",
11341
+ "minimum": 0,
11342
+ "description": "Нижняя граница достигнутого дня серии"
11343
+ },
11344
+ "webinarDayMax": {
11345
+ "type": "integer",
11346
+ "minimum": 0,
11347
+ "description": "Верхняя граница достигнутого дня серии"
11348
+ },
11349
+ "bannerClick": {
11350
+ "type": "string",
11351
+ "enum": [
11352
+ "YES",
11353
+ "NO",
11354
+ "ANY"
11355
+ ],
11356
+ "description": "Клик по баннеру"
11357
+ },
11358
+ "application": {
11359
+ "type": "string",
11360
+ "enum": [
11361
+ "NONE",
11362
+ "CANCELLED",
11363
+ "ANY"
11364
+ ],
11365
+ "description": "CANCELLED требует отменённой заявки И отсутствия живой"
11366
+ },
11367
+ "payment": {
11368
+ "type": "string",
11369
+ "enum": [
11370
+ "NOT_IN_FUNNEL",
11371
+ "NOT_ANYWHERE",
11372
+ "ANY"
11373
+ ],
11374
+ "description": "NOT_ANYWHERE исключает всех, кто когда-либо успешно платил (включая возврат)"
11375
+ }
11376
+ },
11377
+ "required": [
11378
+ "application",
11379
+ "payment"
11380
+ ]
11381
+ },
11382
+ "freshness_anchor": {
11383
+ "type": "string",
11384
+ "enum": [
11385
+ "SERIES_END",
11386
+ "SERIES_END_PLUS_WAIT",
11387
+ "LAST_APPLICATION",
11388
+ "REGISTRATION"
11389
+ ],
11390
+ "description": "Откуда берётся момент входа контакта в сегмент"
11391
+ },
11392
+ "wait_after_series_end_hours": {
11393
+ "type": "integer",
11394
+ "minimum": 0,
11395
+ "maximum": 720,
11396
+ "description": "Сколько ждать после эфира до признания «не пришёл». Разумный дефолт 48"
11397
+ },
11398
+ "priority": {
11399
+ "type": "integer",
11400
+ "minimum": -1000,
11401
+ "maximum": 1000,
11402
+ "description": "Приоритет при пересечении сегментов (больше = важнее)"
11403
+ }
11404
+ },
11405
+ "required": [
11406
+ "segment_id",
11407
+ "facets",
11408
+ "freshness_anchor"
11409
+ ]
11410
+ }
10777
11411
  }
10778
11412
  ],
10779
11413
  "resources": [
@@ -10965,7 +11599,7 @@
10965
11599
  }
10966
11600
  ],
10967
11601
  "summary": {
10968
- "total_tools": 202,
11602
+ "total_tools": 209,
10969
11603
  "tools_by_category": {
10970
11604
  "getcourse_wave": 10,
10971
11605
  "files_upload": 3,
@@ -10984,7 +11618,7 @@
10984
11618
  "sandbox_findings_external": 2,
10985
11619
  "simulation_findings_external": 2,
10986
11620
  "qa_generation_external": 2,
10987
- "platform_setup_bridge": 14,
11621
+ "platform_setup_bridge": 15,
10988
11622
  "feedback_sheets": 5,
10989
11623
  "facts_management": 2,
10990
11624
  "prompt_lint_standalone": 1,
@@ -11008,7 +11642,8 @@
11008
11642
  "dialogue_audit": 6,
11009
11643
  "link_tracking": 6,
11010
11644
  "dialogue_audit_external": 2,
11011
- "link_tracking_domain": 2
11645
+ "link_tracking_domain": 2,
11646
+ "broadcast_scheduler": 6
11012
11647
  },
11013
11648
  "external_execution_pairs": [
11014
11649
  "besales_icp_analysis_get_instructions / submit",
@@ -11218,6 +11853,14 @@
11218
11853
  "newly_added_in_link_tracking_domain": [
11219
11854
  "besales_link_domain_get",
11220
11855
  "besales_link_domain_set"
11856
+ ],
11857
+ "newly_added_in_broadcast_scheduler": [
11858
+ "besales_broadcast_schedule_list",
11859
+ "besales_broadcast_schedule_preview",
11860
+ "besales_broadcast_schedule_upsert",
11861
+ "besales_broadcast_schedule_delete",
11862
+ "besales_broadcast_schedule_runs",
11863
+ "besales_broadcast_segment_rule_set"
11221
11864
  ]
11222
11865
  }
11223
11866
  }