@besales/mcp 0.45.0 → 0.47.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 (189) hide show
  1. package/README.md +96 -55
  2. package/dist/auth/connection-store.d.ts +21 -1
  3. package/dist/auth/connection-store.js +46 -2
  4. package/dist/auth/connection-store.js.map +1 -1
  5. package/dist/auth/oauth-client.d.ts +5 -1
  6. package/dist/auth/oauth-client.js +22 -12
  7. package/dist/auth/oauth-client.js.map +1 -1
  8. package/dist/cli.js +14 -5
  9. package/dist/cli.js.map +1 -1
  10. package/dist/http/api-client.d.ts +16 -1
  11. package/dist/http/api-client.js +50 -2
  12. package/dist/http/api-client.js.map +1 -1
  13. package/dist/instructions/server-instructions.d.ts +4 -13
  14. package/dist/instructions/server-instructions.js +68 -274
  15. package/dist/instructions/server-instructions.js.map +1 -1
  16. package/dist/prompts/registry.d.ts +15 -0
  17. package/dist/prompts/registry.js +83 -0
  18. package/dist/prompts/registry.js.map +1 -0
  19. package/dist/resources/concepts/feedback-sheets.md +7 -4
  20. package/dist/resources/concepts/handoff.md +4 -1
  21. package/dist/resources/concepts/sandbox.md +14 -5
  22. package/dist/resources/concepts/triggers.md +6 -2
  23. package/dist/resources/concepts/workbook-classification.md +26 -21
  24. package/dist/resources/docs/campaigns.md +20 -0
  25. package/dist/resources/docs/crm-integration.md +3 -1
  26. package/dist/resources/docs/follow-up.md +19 -0
  27. package/dist/resources/docs/platforms.md +2 -2
  28. package/dist/resources/docs/routing.md +18 -0
  29. package/dist/resources/docs/task-state.md +30 -0
  30. package/dist/resources/docs/trigger-actions.md +28 -0
  31. package/dist/resources/docs/variables.md +18 -0
  32. package/dist/resources/registry.js +51 -2
  33. package/dist/resources/registry.js.map +1 -1
  34. package/dist/resources/workflows/compare-models.md +4 -3
  35. package/dist/resources/workflows/connect-crm-from-scratch.md +8 -0
  36. package/dist/resources/workflows/extract-from-document.md +8 -1
  37. package/dist/resources/workflows/iterate-with-sandbox.md +5 -2
  38. package/dist/resources/workflows/platform-setup-from-scratch.md +90 -2
  39. package/dist/resources/workflows/production-readiness-check.md +22 -18
  40. package/dist/schemas/mcp-tools.json +1537 -177
  41. package/dist/server.d.ts +2 -0
  42. package/dist/server.js +8 -2
  43. package/dist/server.js.map +1 -1
  44. package/dist/tasks/task-state-store.d.ts +68 -0
  45. package/dist/tasks/task-state-store.js +278 -0
  46. package/dist/tasks/task-state-store.js.map +1 -0
  47. package/dist/tools/annotations.d.ts +7 -0
  48. package/dist/tools/annotations.js +16 -0
  49. package/dist/tools/annotations.js.map +1 -0
  50. package/dist/tools/contracts.js +7 -1
  51. package/dist/tools/contracts.js.map +1 -1
  52. package/dist/tools/definitions/agent-design.d.ts +49 -20
  53. package/dist/tools/definitions/agent-design.js +192 -19
  54. package/dist/tools/definitions/agent-design.js.map +1 -1
  55. package/dist/tools/definitions/analytics.d.ts +40 -0
  56. package/dist/tools/definitions/analytics.js +233 -0
  57. package/dist/tools/definitions/analytics.js.map +1 -0
  58. package/dist/tools/definitions/broadcast-analytics.d.ts +5 -4
  59. package/dist/tools/definitions/broadcast-analytics.js +26 -4
  60. package/dist/tools/definitions/broadcast-analytics.js.map +1 -1
  61. package/dist/tools/definitions/broadcast-mailing-variants.d.ts +2 -0
  62. package/dist/tools/definitions/broadcast-mailing-variants.js +10 -0
  63. package/dist/tools/definitions/broadcast-mailing-variants.js.map +1 -1
  64. package/dist/tools/definitions/broadcast-scheduler.d.ts +20 -1
  65. package/dist/tools/definitions/broadcast-scheduler.js +134 -8
  66. package/dist/tools/definitions/broadcast-scheduler.js.map +1 -1
  67. package/dist/tools/definitions/contacts.d.ts +15 -0
  68. package/dist/tools/definitions/contacts.js +84 -0
  69. package/dist/tools/definitions/contacts.js.map +1 -0
  70. package/dist/tools/definitions/crm-platform.d.ts +2 -0
  71. package/dist/tools/definitions/crm-platform.js +95 -5
  72. package/dist/tools/definitions/crm-platform.js.map +1 -1
  73. package/dist/tools/definitions/datasource.d.ts +1 -0
  74. package/dist/tools/definitions/datasource.js +16 -1
  75. package/dist/tools/definitions/datasource.js.map +1 -1
  76. package/dist/tools/definitions/dialogue-audit.d.ts +2 -2
  77. package/dist/tools/definitions/dialogue-audit.js +54 -16
  78. package/dist/tools/definitions/dialogue-audit.js.map +1 -1
  79. package/dist/tools/definitions/dialogue-export.d.ts +1 -1
  80. package/dist/tools/definitions/dialogue-export.js +12 -0
  81. package/dist/tools/definitions/dialogue-export.js.map +1 -1
  82. package/dist/tools/definitions/external-api-channels.js +39 -12
  83. package/dist/tools/definitions/external-api-channels.js.map +1 -1
  84. package/dist/tools/definitions/follow-up-funnel-test.js +4 -0
  85. package/dist/tools/definitions/follow-up-funnel-test.js.map +1 -1
  86. package/dist/tools/definitions/follow-up-setup.js +3 -0
  87. package/dist/tools/definitions/follow-up-setup.js.map +1 -1
  88. package/dist/tools/definitions/follow-up.d.ts +1 -1
  89. package/dist/tools/definitions/follow-up.js +6 -0
  90. package/dist/tools/definitions/follow-up.js.map +1 -1
  91. package/dist/tools/definitions/getcourse-anchor-refresh.d.ts +3 -0
  92. package/dist/tools/definitions/getcourse-anchor-refresh.js +29 -2
  93. package/dist/tools/definitions/getcourse-anchor-refresh.js.map +1 -1
  94. package/dist/tools/definitions/getcourse-cold-welcome.d.ts +20 -2
  95. package/dist/tools/definitions/getcourse-cold-welcome.js +128 -7
  96. package/dist/tools/definitions/getcourse-cold-welcome.js.map +1 -1
  97. package/dist/tools/definitions/getcourse-wave.js +14 -0
  98. package/dist/tools/definitions/getcourse-wave.js.map +1 -1
  99. package/dist/tools/definitions/help.d.ts +8 -0
  100. package/dist/tools/definitions/help.js +219 -0
  101. package/dist/tools/definitions/help.js.map +1 -0
  102. package/dist/tools/definitions/knowledge.d.ts +27 -5
  103. package/dist/tools/definitions/knowledge.js +200 -33
  104. package/dist/tools/definitions/knowledge.js.map +1 -1
  105. package/dist/tools/definitions/link-tracking.js +31 -0
  106. package/dist/tools/definitions/link-tracking.js.map +1 -1
  107. package/dist/tools/definitions/model-comparison.js +12 -3
  108. package/dist/tools/definitions/model-comparison.js.map +1 -1
  109. package/dist/tools/definitions/operational-overview.d.ts +3 -0
  110. package/dist/tools/definitions/operational-overview.js +23 -0
  111. package/dist/tools/definitions/operational-overview.js.map +1 -0
  112. package/dist/tools/definitions/operator-workflow.d.ts +20 -0
  113. package/dist/tools/definitions/operator-workflow.js +114 -0
  114. package/dist/tools/definitions/operator-workflow.js.map +1 -0
  115. package/dist/tools/definitions/platform-setup.d.ts +54 -3
  116. package/dist/tools/definitions/platform-setup.js +211 -5
  117. package/dist/tools/definitions/platform-setup.js.map +1 -1
  118. package/dist/tools/definitions/scheduled-tasks.js +2 -0
  119. package/dist/tools/definitions/scheduled-tasks.js.map +1 -1
  120. package/dist/tools/definitions/session.js +103 -5
  121. package/dist/tools/definitions/session.js.map +1 -1
  122. package/dist/tools/definitions/shared.d.ts +272 -10
  123. package/dist/tools/definitions/shared.js +154 -8
  124. package/dist/tools/definitions/shared.js.map +1 -1
  125. package/dist/tools/definitions/task-state.d.ts +76 -0
  126. package/dist/tools/definitions/task-state.js +301 -0
  127. package/dist/tools/definitions/task-state.js.map +1 -0
  128. package/dist/tools/definitions/trigger-contact-claims.d.ts +7 -0
  129. package/dist/tools/definitions/trigger-contact-claims.js +60 -0
  130. package/dist/tools/definitions/trigger-contact-claims.js.map +1 -0
  131. package/dist/tools/definitions.d.ts +334 -35
  132. package/dist/tools/definitions.js +14 -0
  133. package/dist/tools/definitions.js.map +1 -1
  134. package/dist/tools/description-localization.d.ts +2 -0
  135. package/dist/tools/description-localization.js +46 -0
  136. package/dist/tools/description-localization.js.map +1 -0
  137. package/dist/tools/incomplete-list.d.ts +23 -0
  138. package/dist/tools/incomplete-list.js +39 -0
  139. package/dist/tools/incomplete-list.js.map +1 -0
  140. package/dist/tools/inventory.d.ts +10 -0
  141. package/dist/tools/inventory.js +49 -0
  142. package/dist/tools/inventory.js.map +1 -0
  143. package/dist/tools/registry-mapping-cases-core.js +122 -4
  144. package/dist/tools/registry-mapping-cases-core.js.map +1 -1
  145. package/dist/tools/registry-mapping-cases-platform.js +69 -0
  146. package/dist/tools/registry-mapping-cases-platform.js.map +1 -1
  147. package/dist/tools/registry.d.ts +2 -0
  148. package/dist/tools/registry.js +60 -8
  149. package/dist/tools/registry.js.map +1 -1
  150. package/dist/tools/result-envelope.d.ts +46 -0
  151. package/dist/tools/result-envelope.js +184 -0
  152. package/dist/tools/result-envelope.js.map +1 -0
  153. package/dist/tools/result.d.ts +41 -3
  154. package/dist/tools/result.js +229 -27
  155. package/dist/tools/result.js.map +1 -1
  156. package/dist/tools/tool-title.d.ts +2 -0
  157. package/dist/tools/tool-title.js +12 -0
  158. package/dist/tools/tool-title.js.map +1 -0
  159. package/dist/tools/toolsets.d.ts +37 -0
  160. package/dist/tools/toolsets.js +64 -0
  161. package/dist/tools/toolsets.js.map +1 -0
  162. package/dist/tools/trigger-action-config.js +4 -0
  163. package/dist/tools/trigger-action-config.js.map +1 -1
  164. package/dist/tools/verify-with.d.ts +5 -0
  165. package/dist/tools/verify-with.js +36 -0
  166. package/dist/tools/verify-with.js.map +1 -0
  167. package/dist/types/api-contract.gen.d.ts +2612 -332
  168. package/dist/utils/logger.d.ts +11 -0
  169. package/dist/utils/logger.js +64 -8
  170. package/dist/utils/logger.js.map +1 -1
  171. package/docs/agent-usage-guide.full.ru.md +21 -15
  172. package/docs/agent-usage-guide.ru.md +24 -16
  173. package/docs/async-operation-lifecycle.md +46 -0
  174. package/docs/connect.ru.md +120 -0
  175. package/docs/evals/model-behavior-scorecard.md +80 -0
  176. package/docs/failure-semantics.md +56 -0
  177. package/docs/help-navigation.md +48 -0
  178. package/docs/host-compatibility-matrix.md +153 -0
  179. package/docs/host-setup.md +22 -6
  180. package/docs/operation-coverage.md +114 -0
  181. package/docs/pii-policy.md +46 -0
  182. package/docs/response-size-budget.md +150 -0
  183. package/docs/task-state.md +58 -0
  184. package/docs/tool-effects.md +46 -0
  185. package/docs/tool-surface.md +91 -0
  186. package/package.json +6 -2
  187. package/scripts/model-eval-server.js +213 -0
  188. package/scripts/probe-mcp-protocol.js +134 -0
  189. package/scripts/run-model-eval.js +447 -0
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "title": "besales-mcp Tool Definitions",
4
4
  "version": "1.3.0-draft",
5
- "lastUpdated": "2026-08-18",
5
+ "lastUpdated": "2026-09-11",
6
6
  "description": "MCP tool schemas для besales-mcp npm package. Active v1.5 set содержит PromptHub/ICP/Sandbox/Knowledge external-execution operations и stateless Platform Setup Bridge direct tools. Setup Pipeline session tools сохранены как Phase 4+ future design, но не входят в active toolset.",
7
7
  "executionModes": {
8
8
  "summary": "Каждая active LLM-операция имеет 2 MCP tools: get_instructions + submit. Claude локально между tools выполняет LLM-вызовы своими моделями. Auto-detection через JWT scope mcp:* → external default.",
@@ -237,7 +237,7 @@
237
237
  "type": "array",
238
238
  "items": {}
239
239
  },
240
- "language_style": {
240
+ "languageStyle": {
241
241
  "type": "object"
242
242
  }
243
243
  }
@@ -249,13 +249,13 @@
249
249
  "type": "object",
250
250
  "required": [
251
251
  "name",
252
- "segment_id"
252
+ "segmentId"
253
253
  ],
254
254
  "properties": {
255
255
  "name": {
256
256
  "type": "string"
257
257
  },
258
- "segment_id": {
258
+ "segmentId": {
259
259
  "type": "string",
260
260
  "format": "uuid",
261
261
  "description": "Existing segment id or id of a segment in this submit payload."
@@ -263,7 +263,7 @@
263
263
  "description": {
264
264
  "type": "string"
265
265
  },
266
- "pain_points": {
266
+ "painPoints": {
267
267
  "type": "array",
268
268
  "items": {}
269
269
  },
@@ -274,7 +274,7 @@
274
274
  "objections": {
275
275
  "type": "object"
276
276
  },
277
- "messaging_hints": {
277
+ "messagingHints": {
278
278
  "type": "object"
279
279
  }
280
280
  }
@@ -423,8 +423,11 @@
423
423
  "required": [
424
424
  "agent_id",
425
425
  "operation_id",
426
- "stages",
427
- "final_content"
426
+ "stages"
427
+ ],
428
+ "anyOf": [
429
+ { "required": ["final_content"] },
430
+ { "required": ["finalContent"] }
428
431
  ],
429
432
  "properties": {
430
433
  "agent_id": {
@@ -463,6 +466,10 @@
463
466
  "final_content": {
464
467
  "type": "string"
465
468
  },
469
+ "finalContent": {
470
+ "type": "string",
471
+ "description": "Имя из schema результата instructions; эквивалент final_content."
472
+ },
466
473
  "metadata": {
467
474
  "type": "object",
468
475
  "properties": {
@@ -524,8 +531,11 @@
524
531
  "required": [
525
532
  "agent_id",
526
533
  "operation_id",
527
- "stages",
528
- "aggregated_issues"
534
+ "stages"
535
+ ],
536
+ "anyOf": [
537
+ { "required": ["aggregated_issues"] },
538
+ { "required": ["aggregatedIssues"] }
529
539
  ],
530
540
  "properties": {
531
541
  "agent_id": {
@@ -566,6 +576,13 @@
566
576
  "items": {
567
577
  "type": "object"
568
578
  }
579
+ },
580
+ "aggregatedIssues": {
581
+ "type": "array",
582
+ "description": "Имя из schema результата instructions; эквивалент aggregated_issues.",
583
+ "items": {
584
+ "type": "object"
585
+ }
569
586
  }
570
587
  }
571
588
  }
@@ -607,6 +624,12 @@
607
624
  "type": "string",
608
625
  "format": "uuid"
609
626
  },
627
+ "candidate_prompt": {
628
+ "type": "string",
629
+ "minLength": 10,
630
+ "maxLength": 100000,
631
+ "description": "Неактивированный промпт для изолированного single_agent-прогона; production-конфигурация не меняется."
632
+ },
610
633
  "scenario_ids": {
611
634
  "type": "array",
612
635
  "items": {
@@ -673,6 +696,68 @@
673
696
  }
674
697
  }
675
698
  },
699
+ {
700
+ "name": "besales_sandbox_run_list",
701
+ "description": "Список sandbox-прогонов выбранного агента. Возвращает постраничные краткие состояния; продолжай по cursor до null, если нужен весь список.",
702
+ "inputSchema": {
703
+ "type": "object",
704
+ "required": ["agent_id"],
705
+ "properties": {
706
+ "agent_id": { "type": "string", "format": "uuid" },
707
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100 },
708
+ "cursor": { "type": "string" }
709
+ }
710
+ }
711
+ },
712
+ {
713
+ "name": "besales_sandbox_run_get",
714
+ "description": "Получить статус, прогресс, ошибки и результаты одного sandbox-прогона. QUEUED/RUNNING ещё не доказывают результат; терминальные статусы: COMPLETED, FAILED, CANCELLED. passRate — живучесть ответов, qualityRate и checksRate оцениваются отдельно.",
715
+ "inputSchema": {
716
+ "type": "object",
717
+ "required": ["run_id"],
718
+ "properties": {
719
+ "run_id": { "type": "string", "format": "uuid" }
720
+ }
721
+ }
722
+ },
723
+ {
724
+ "name": "besales_sandbox_run_cancel",
725
+ "description": "Идемпотентно отменить незавершённый sandbox-прогон. После ответа проверь тот же run_id через besales_sandbox_run_get.",
726
+ "inputSchema": {
727
+ "type": "object",
728
+ "required": ["run_id"],
729
+ "properties": {
730
+ "run_id": { "type": "string", "format": "uuid" }
731
+ }
732
+ }
733
+ },
734
+ {
735
+ "name": "besales_sandbox_run_feedback",
736
+ "description": "Сохранить человеческую оценку завершённого sandbox-прогона. Это отдельный отзыв проверяющего; автоматические findings отправляются через besales_sandbox_findings_submit.",
737
+ "inputSchema": {
738
+ "type": "object",
739
+ "required": ["run_id", "reviewed_issues"],
740
+ "properties": {
741
+ "run_id": { "type": "string", "format": "uuid" },
742
+ "reviewed_issues": {
743
+ "type": "array",
744
+ "items": {
745
+ "type": "object",
746
+ "properties": {
747
+ "scenario_id": { "type": "string", "format": "uuid" },
748
+ "turn_index": { "type": "integer", "minimum": 0 },
749
+ "category": {
750
+ "type": "string",
751
+ "enum": ["hallucination", "wrong_action", "bad_tone", "missed_context", "other"]
752
+ },
753
+ "description": { "type": "string" }
754
+ }
755
+ }
756
+ },
757
+ "general_comments": { "type": "string" }
758
+ }
759
+ }
760
+ },
676
761
  {
677
762
  "name": "besales_sandbox_findings_get_instructions",
678
763
  "description": "⭐ EXTERNAL EXECUTION (NEW v3.1) — получить instructions для analysis sandbox results. Claude локально получает sandbox report + ICP/ТЗ контекст из чата → выдаёт structured findings (категория / severity / suggestion). Это ключевой fix для кейса с irrelevant findings от gpt-4o-mini.",
@@ -696,7 +781,7 @@
696
781
  },
697
782
  {
698
783
  "name": "besales_sandbox_findings_submit",
699
- "description": "Submit Claude-generated sandbox findings. Findings сохраняются как SandboxRunFeedback с status=SUBMITTED (improvement-lab consumes). ВАЖНО: category — строго из enum ЭТОЙ submit-схемы (hallucination/wrong_action/wrong_routing/missed_trigger/wrong_pipeline_transition/rag_miss/bad_tone/other); он РАСХОДИТСЯ с enum в besales_sandbox_findings_get_instructions (там есть missed_context). Категорию из get_instructions, которой здесь нет (например missed_context), маппь на other — иначе 400.",
784
+ "description": "Сохранить findings sandbox-прогона. Поля и enum совпадают со schema, которую возвращает besales_sandbox_findings_get_instructions; legacy snake_case/message/suggestion по-прежнему принимаются рантаймом для совместимости.",
700
785
  "inputSchema": {
701
786
  "type": "object",
702
787
  "required": [
@@ -725,10 +810,10 @@
725
810
  "required": [
726
811
  "category",
727
812
  "severity",
728
- "message"
813
+ "description"
729
814
  ],
730
815
  "properties": {
731
- "scenario_id": {
816
+ "scenarioId": {
732
817
  "type": "string",
733
818
  "format": "uuid"
734
819
  },
@@ -738,8 +823,7 @@
738
823
  "hallucination",
739
824
  "wrong_action",
740
825
  "wrong_routing",
741
- "missed_trigger",
742
- "wrong_pipeline_transition",
826
+ "missed_context",
743
827
  "rag_miss",
744
828
  "bad_tone",
745
829
  "other"
@@ -753,13 +837,16 @@
753
837
  "critical"
754
838
  ]
755
839
  },
756
- "message": {
840
+ "description": {
757
841
  "type": "string"
758
842
  },
759
- "suggestion": {
843
+ "evidence": {
844
+ "type": "string"
845
+ },
846
+ "recommendation": {
760
847
  "type": "string"
761
848
  },
762
- "turn_index": {
849
+ "turnIndex": {
763
850
  "type": "integer"
764
851
  }
765
852
  }
@@ -822,7 +909,7 @@
822
909
  "message"
823
910
  ],
824
911
  "properties": {
825
- "dialogue_id": {
912
+ "dialogueId": {
826
913
  "type": "string",
827
914
  "format": "uuid"
828
915
  },
@@ -852,7 +939,7 @@
852
939
  "suggestion": {
853
940
  "type": "string"
854
941
  },
855
- "reference_message_index": {
942
+ "referenceMessageIndex": {
856
943
  "type": "integer"
857
944
  }
858
945
  }
@@ -900,8 +987,11 @@
900
987
  "type": "object",
901
988
  "required": [
902
989
  "agent_id",
903
- "operation_id",
904
- "qa_pairs"
990
+ "operation_id"
991
+ ],
992
+ "anyOf": [
993
+ { "required": ["qa_pairs"] },
994
+ { "required": ["qaPairs"] }
905
995
  ],
906
996
  "properties": {
907
997
  "agent_id": {
@@ -916,6 +1006,10 @@
916
1006
  "type": "string",
917
1007
  "format": "uuid"
918
1008
  },
1009
+ "knowledgeSpaceId": {
1010
+ "type": "string",
1011
+ "format": "uuid"
1012
+ },
919
1013
  "qa_pairs": {
920
1014
  "type": "array",
921
1015
  "items": {
@@ -939,6 +1033,19 @@
939
1033
  }
940
1034
  }
941
1035
  }
1036
+ },
1037
+ "qaPairs": {
1038
+ "type": "array",
1039
+ "description": "Имя из schema результата instructions; эквивалент qa_pairs.",
1040
+ "items": {
1041
+ "type": "object",
1042
+ "required": ["question", "answer"],
1043
+ "properties": {
1044
+ "question": { "type": "string" },
1045
+ "answer": { "type": "string" },
1046
+ "tags": { "type": "array", "items": { "type": "string" } }
1047
+ }
1048
+ }
942
1049
  }
943
1050
  }
944
1051
  }
@@ -1192,6 +1299,70 @@
1192
1299
  }
1193
1300
  }
1194
1301
  },
1302
+ {
1303
+ "name": "besales_workspace_navigate",
1304
+ "description": "Навигатор по намерению: возвращает цель, выбранные объекты, выполненное и недостающее, нужный ввод человека, один следующий tool с аргументами и проверкой результата. Учитывает тип FAQ/sales/booking/outbound/support и живой workspace overview; свободный вопрос не превращает в обязательный мастер.",
1305
+ "inputSchema": {
1306
+ "type": "object",
1307
+ "required": [
1308
+ "intent"
1309
+ ],
1310
+ "additionalProperties": false,
1311
+ "properties": {
1312
+ "workspace_id": {
1313
+ "type": "string",
1314
+ "format": "uuid"
1315
+ },
1316
+ "intent": {
1317
+ "type": "string",
1318
+ "enum": [
1319
+ "CREATE_BOT",
1320
+ "IMPROVE_AGENT",
1321
+ "DIAGNOSE_CONTACT",
1322
+ "AUDIT_DIALOGUES",
1323
+ "CAMPAIGN_REPORT",
1324
+ "CONNECT_CRM",
1325
+ "CONNECT_DATASOURCE",
1326
+ "CONFIGURE_FOLLOWUP",
1327
+ "CONTINUE_TASK",
1328
+ "FREEFORM"
1329
+ ]
1330
+ },
1331
+ "bot_type": {
1332
+ "type": "string",
1333
+ "enum": [
1334
+ "FAQ",
1335
+ "SALES",
1336
+ "BOOKING",
1337
+ "OUTBOUND",
1338
+ "SUPPORT",
1339
+ "UNKNOWN"
1340
+ ]
1341
+ },
1342
+ "platform_id": {
1343
+ "type": "string",
1344
+ "format": "uuid"
1345
+ },
1346
+ "agent_id": {
1347
+ "type": "string",
1348
+ "format": "uuid"
1349
+ },
1350
+ "contact_id": {
1351
+ "type": "string",
1352
+ "format": "uuid"
1353
+ },
1354
+ "task_id": {
1355
+ "type": "string",
1356
+ "format": "uuid"
1357
+ },
1358
+ "question": {
1359
+ "type": "string",
1360
+ "minLength": 2,
1361
+ "maxLength": 500
1362
+ }
1363
+ }
1364
+ }
1365
+ },
1195
1366
  {
1196
1367
  "name": "besales_platform_context_get",
1197
1368
  "description": "Get sanitized platform setup context first when user gives platformId. Returns platform, agents, router, triggers, behavior, follow-up, pipeline settings and readiness flags; never returns channel credentials or secrets.",
@@ -1204,13 +1375,51 @@
1204
1375
  "platform_id": {
1205
1376
  "type": "string",
1206
1377
  "format": "uuid"
1378
+ },
1379
+ "sections": {
1380
+ "type": "array",
1381
+ "minItems": 1,
1382
+ "items": {
1383
+ "type": "string",
1384
+ "enum": [
1385
+ "platform",
1386
+ "agent_summaries",
1387
+ "agents_full",
1388
+ "router",
1389
+ "behavior",
1390
+ "follow_up",
1391
+ "pipeline_settings",
1392
+ "readiness"
1393
+ ]
1394
+ },
1395
+ "description": "Необязательный срез большого снимка. agent_summaries не содержит compiledPrompt; agents_full содержит."
1396
+ }
1397
+ }
1398
+ }
1399
+ },
1400
+ {
1401
+ "name": "besales_trigger_action_catalog_get",
1402
+ "description": "Получить актуальную JSON-схему, минимальный валидный пример, имя входного config-поля, relation ответа, зависимости, эффект и способ проверки trigger action. Перед новым типом действия вызывай с action_type, чтобы не перебирать варианты через ошибки 400.",
1403
+ "inputSchema": {
1404
+ "type": "object",
1405
+ "required": [
1406
+ "platform_id"
1407
+ ],
1408
+ "properties": {
1409
+ "platform_id": {
1410
+ "type": "string",
1411
+ "format": "uuid"
1412
+ },
1413
+ "action_type": {
1414
+ "type": "string",
1415
+ "minLength": 1
1207
1416
  }
1208
1417
  }
1209
1418
  }
1210
1419
  },
1211
1420
  {
1212
1421
  "name": "besales_agent_list",
1213
- "description": "List agents attached to an existing platform. Use after context when the user wants to inspect or choose an agent before targeted setup mutations.",
1422
+ "description": "Компактно найти агентов существующей площадки по обычному имени. Возвращает summaries без полного compiledPrompt, точный total, selection.status и cursor. Непустой cursor означает, что показана только страница; для массовой операции дочитай все страницы.",
1214
1423
  "inputSchema": {
1215
1424
  "type": "object",
1216
1425
  "required": [
@@ -1220,10 +1429,53 @@
1220
1429
  "platform_id": {
1221
1430
  "type": "string",
1222
1431
  "format": "uuid"
1432
+ },
1433
+ "limit": {
1434
+ "type": "integer",
1435
+ "minimum": 1,
1436
+ "maximum": 200,
1437
+ "description": "Размер страницы. Без параметра список отдаётся целиком."
1438
+ },
1439
+ "cursor": {
1440
+ "type": "string",
1441
+ "minLength": 1,
1442
+ "description": "cursor предыдущей страницы."
1443
+ },
1444
+ "query": {
1445
+ "type": "string",
1446
+ "minLength": 1,
1447
+ "description": "Поиск без учёта регистра по name или displayName."
1448
+ }
1449
+ }
1450
+ }
1451
+ },
1452
+ {
1453
+ "name": "besales_agent_get",
1454
+ "description": "Прочитать полную карточку выбранного агента, включая текущий compiledPrompt и runtime-конфигурацию. Вызывай явно после выбора агента из компактного besales_agent_list.",
1455
+ "inputSchema": {
1456
+ "type": "object",
1457
+ "required": [
1458
+ "agent_id"
1459
+ ],
1460
+ "properties": {
1461
+ "agent_id": {
1462
+ "type": "string",
1463
+ "format": "uuid"
1223
1464
  }
1224
1465
  }
1225
1466
  }
1226
1467
  },
1468
+ {
1469
+ "name": "besales_agent_readiness_get",
1470
+ "description": "Проверить готовность выбранного агента: channel/prompt/greeting/knowledge/ICP/sandbox gates, findingsStatus, qualityRate, checksRate. Сейчас возвращает NOT_PROVEN: configurationCurrent=null, полная версия зависимых настроек не зафиксирована. promptAndAgentCurrent проверяет только промпт и запись агента; повтор sandbox не устраняет unverifiedDependencies. CRM live authorization проверяется отдельно.",
1471
+ "inputSchema": {
1472
+ "type": "object",
1473
+ "required": ["agent_id"],
1474
+ "properties": {
1475
+ "agent_id": { "type": "string", "format": "uuid" }
1476
+ }
1477
+ }
1478
+ },
1227
1479
  {
1228
1480
  "name": "besales_agent_variable_overrides_get",
1229
1481
  "description": "Read-only: current variable overrides set on an agent — workspaceOverrides[] (WorkspaceVariable, referenced as {{{name}}}) and customOverrides[] (platform CustomVariable, {name}), each with variable id, name, type, overrideValue. Read this BEFORE besales_agent_update: agent_workspace_variable_overrides / agent_variable_overrides replace the whole set (delete missing + upsert sent), so resend any existing override you want to keep.",
@@ -1325,7 +1577,7 @@
1325
1577
  "funnel": {
1326
1578
  "type": "string",
1327
1579
  "maxLength": 200,
1328
- "description": "Канонический ключ/название бизнес-воронки для аналитики. НЕ имя файла, batch/resend или дата запуска."
1580
+ "description": "Воронка ШКОЛЫ в форме «f11 — ДБО / NR / ВК / In Stream» — код fNN ОБЯЗАТЕЛЕН. ⚠️ Это НЕ когорта и НЕ подпись запуска: «reg-no-show», «post-web|дбо», «svs-zapusk» сюда класть нельзя — тип отбора идёт в segment, продукт в product_code, подпись запуска в cohort_label. Ось «Воронка» сравнивается по коду, поэтому значение без кода становится отдельной «воронкой» и засоряет фильтр аналитики."
1329
1581
  },
1330
1582
  "segment": {
1331
1583
  "type": "string",
@@ -1610,7 +1862,7 @@
1610
1862
  "funnel": {
1611
1863
  "type": "string",
1612
1864
  "maxLength": 200,
1613
- "description": "Canonical business-funnel key/name for analytics."
1865
+ "description": "Воронка ШКОЛЫ в форме «f11 — ДБО / NR / ВК / In Stream» — код fNN ОБЯЗАТЕЛЕН. ⚠️ Это НЕ когорта и НЕ подпись запуска: «reg-no-show», «post-web|дбо», «svs-zapusk» сюда класть нельзя — тип отбора идёт в segment, продукт в product_code, подпись запуска в cohort_label. Ось «Воронка» сравнивается по коду, поэтому значение без кода становится отдельной «воронкой» и засоряет фильтр аналитики."
1614
1866
  },
1615
1867
  "segment": {
1616
1868
  "type": "string",
@@ -2053,7 +2305,7 @@
2053
2305
  "funnel": {
2054
2306
  "type": "string",
2055
2307
  "maxLength": 200,
2056
- "description": "Canonical business-funnel key/name for analytics."
2308
+ "description": "Воронка ШКОЛЫ в форме «f11 — ДБО / NR / ВК / In Stream» — код fNN ОБЯЗАТЕЛЕН. ⚠️ Это НЕ когорта и НЕ подпись запуска: «reg-no-show», «post-web|дбо», «svs-zapusk» сюда класть нельзя — тип отбора идёт в segment, продукт в product_code, подпись запуска в cohort_label. Ось «Воронка» сравнивается по коду, поэтому значение без кода становится отдельной «воронкой» и засоряет фильтр аналитики."
2057
2309
  },
2058
2310
  "segment": {
2059
2311
  "type": "string",
@@ -4504,6 +4756,53 @@
4504
4756
  "type": "integer"
4505
4757
  },
4506
4758
  "description": "GetCourse offer ids whose paid orders are credited to us regardless of who created the order — the agent via GETCOURSE_CREATE_DEAL or a manager by hand in the GetCourse admin. Empty array turns the rule off. The set applies to the whole school (every platform sharing the GetCourse domain), not to a single platform. Changes money attribution retroactively — dangerous, requires explicit_confirmation."
4759
+ },
4760
+ "guard_active_series": {
4761
+ "type": [
4762
+ "string",
4763
+ "null"
4764
+ ],
4765
+ "enum": [
4766
+ "OFF",
4767
+ "WARN",
4768
+ "BLOCK",
4769
+ null
4770
+ ],
4771
+ "description": "Outbound guard: do not write while the person's webinar series is running. OFF — rule off; WARN — reason audited, send proceeds; BLOCK — send stopped. null = not configured (default: active_series BLOCK, others WARN). See docs/features/outbound-guards.md."
4772
+ },
4773
+ "guard_active_application": {
4774
+ "type": [
4775
+ "string",
4776
+ "null"
4777
+ ],
4778
+ "enum": [
4779
+ "OFF",
4780
+ "WARN",
4781
+ "BLOCK",
4782
+ null
4783
+ ],
4784
+ "description": "Outbound guard: do not write while a sales rep works an active application. OFF — rule off; WARN — reason audited, send proceeds; BLOCK — send stopped. null = not configured (default: active_series BLOCK, others WARN). See docs/features/outbound-guards.md."
4785
+ },
4786
+ "guard_paid": {
4787
+ "type": [
4788
+ "string",
4789
+ "null"
4790
+ ],
4791
+ "enum": [
4792
+ "OFF",
4793
+ "WARN",
4794
+ "BLOCK",
4795
+ null
4796
+ ],
4797
+ "description": "Outbound guard: do not write to someone who already paid for THIS product. OFF — rule off; WARN — reason audited, send proceeds; BLOCK — send stopped. null = not configured (default: active_series BLOCK, others WARN). See docs/features/outbound-guards.md."
4798
+ },
4799
+ "quiet_days": {
4800
+ "type": [
4801
+ "integer",
4802
+ "null"
4803
+ ],
4804
+ "minimum": 0,
4805
+ "description": "ТИХИЙ ПЕРИОД площадки в сутках: не писать человеку N суток после НАШЕГО касания — отправки или шага календарной цепочки. Считается ПО ЧЕЛОВЕКУ во всём воркспейсе, волна школы касанием НЕ считается (замер: широкий периметр отсекал бы 15,3 % отправок). null = «не настраивали», действующее значение 0 (правила нет); рекомендация владельца — 7. Расписание этим числом НЕ судится: у него своё поле cooldown_days. Перекрытие — у рассылки (quiet_days_override)."
4507
4806
  }
4508
4807
  }
4509
4808
  },
@@ -4512,60 +4811,174 @@
4512
4811
  },
4513
4812
  "confirmation_reason": {
4514
4813
  "type": "string"
4515
- }
4516
- }
4517
- }
4518
- },
4519
- {
4520
- "name": "besales_audit_revert",
4521
- "description": "Revert a reversible audit log. Передай `platform_id` для platform-scoped logs (записи через platform-setup-adapter); опусти для workspace-scoped logs (variables-adapter и аналоги).",
4522
- "inputSchema": {
4523
- "type": "object",
4524
- "required": [
4525
- "audit_log_id"
4526
- ],
4527
- "properties": {
4528
- "workspace_id": {
4529
- "type": "string",
4530
- "format": "uuid"
4531
- },
4532
- "platform_id": {
4533
- "type": "string",
4534
- "format": "uuid"
4535
- },
4536
- "audit_log_id": {
4537
- "type": "string",
4538
- "format": "uuid"
4539
- }
4540
- }
4541
- }
4542
- },
4543
- {
4544
- "name": "besales_feedback_sheet_link",
4545
- "description": "Привязать Google Sheets-таблицу с замечаниями тестировщиков к промпту агента. Принимает ссылку docs.google.com/spreadsheets/...; один файл можно привязать к нескольким промптам. В ответе — serviceAccountEmail: расшарьте таблицу на этот email (Viewer для READ_ONLY, Editor для EDITABLE).",
4546
- "inputSchema": {
4547
- "type": "object",
4548
- "required": [
4549
- "agent_id",
4550
- "source_url"
4551
- ],
4552
- "properties": {
4553
- "agent_id": {
4554
- "type": "string",
4555
- "format": "uuid"
4556
- },
4557
- "source_url": {
4558
- "type": "string",
4559
- "description": "Ссылка на Google Sheet (docs.google.com/spreadsheets/...)."
4560
- },
4561
- "access_mode": {
4562
- "type": "string",
4563
- "enum": [
4564
- "READ_ONLY",
4565
- "EDITABLE"
4566
- ],
4567
- "default": "READ_ONLY",
4568
- "description": "Намерение: READ_ONLY — только чтение; EDITABLE — Phase 2 запись статусов строк."
4814
+ },
4815
+ "funnel_analytics": {
4816
+ "type": "object",
4817
+ "description": "Настройки раздела «Воронка канала»: ворота решения (тройка стадий «отправлено → одобрено | отклонено»), целевая стадия «Пути до стадии», пороги вовлечённости и «застрял». null у ворот и цели — СБРОС, отсутствие поля — «не трогать». Запись делегируется сервисам раздела, поэтому их проверки (стадии разные, стадии есть в каталоге площадки) не обходятся.",
4818
+ "properties": {
4819
+ "decision_gate": {
4820
+ "type": [
4821
+ "object",
4822
+ "null"
4823
+ ],
4824
+ "required": [
4825
+ "submitted",
4826
+ "approved",
4827
+ "rejected"
4828
+ ],
4829
+ "properties": {
4830
+ "submitted": {
4831
+ "type": "object",
4832
+ "required": [
4833
+ "pipeline_crm_id",
4834
+ "pipeline_id",
4835
+ "status_id"
4836
+ ],
4837
+ "properties": {
4838
+ "pipeline_crm_id": {
4839
+ "type": "string"
4840
+ },
4841
+ "pipeline_id": {
4842
+ "type": "integer"
4843
+ },
4844
+ "status_id": {
4845
+ "type": "integer"
4846
+ }
4847
+ }
4848
+ },
4849
+ "approved": {
4850
+ "type": "object",
4851
+ "required": [
4852
+ "pipeline_crm_id",
4853
+ "pipeline_id",
4854
+ "status_id"
4855
+ ],
4856
+ "properties": {
4857
+ "pipeline_crm_id": {
4858
+ "type": "string"
4859
+ },
4860
+ "pipeline_id": {
4861
+ "type": "integer"
4862
+ },
4863
+ "status_id": {
4864
+ "type": "integer"
4865
+ }
4866
+ }
4867
+ },
4868
+ "rejected": {
4869
+ "type": "object",
4870
+ "required": [
4871
+ "pipeline_crm_id",
4872
+ "pipeline_id",
4873
+ "status_id"
4874
+ ],
4875
+ "properties": {
4876
+ "pipeline_crm_id": {
4877
+ "type": "string"
4878
+ },
4879
+ "pipeline_id": {
4880
+ "type": "integer"
4881
+ },
4882
+ "status_id": {
4883
+ "type": "integer"
4884
+ }
4885
+ }
4886
+ }
4887
+ }
4888
+ },
4889
+ "path_target_stage": {
4890
+ "type": [
4891
+ "object",
4892
+ "null"
4893
+ ],
4894
+ "required": [
4895
+ "pipeline_crm_id",
4896
+ "pipeline_id",
4897
+ "status_id"
4898
+ ],
4899
+ "properties": {
4900
+ "pipeline_crm_id": {
4901
+ "type": "string"
4902
+ },
4903
+ "pipeline_id": {
4904
+ "type": "integer"
4905
+ },
4906
+ "status_id": {
4907
+ "type": "integer"
4908
+ }
4909
+ }
4910
+ },
4911
+ "engaged_inbound_count": {
4912
+ "type": [
4913
+ "integer",
4914
+ "null"
4915
+ ],
4916
+ "minimum": 2,
4917
+ "maximum": 20
4918
+ },
4919
+ "stuck_threshold_hours": {
4920
+ "type": [
4921
+ "integer",
4922
+ "null"
4923
+ ],
4924
+ "minimum": 1,
4925
+ "maximum": 720
4926
+ }
4927
+ }
4928
+ }
4929
+ }
4930
+ }
4931
+ },
4932
+ {
4933
+ "name": "besales_audit_revert",
4934
+ "description": "Revert a reversible audit log. Передай `platform_id` для platform-scoped logs (записи через platform-setup-adapter); опусти для workspace-scoped logs (variables-adapter и аналоги).",
4935
+ "inputSchema": {
4936
+ "type": "object",
4937
+ "required": [
4938
+ "audit_log_id"
4939
+ ],
4940
+ "properties": {
4941
+ "workspace_id": {
4942
+ "type": "string",
4943
+ "format": "uuid"
4944
+ },
4945
+ "platform_id": {
4946
+ "type": "string",
4947
+ "format": "uuid"
4948
+ },
4949
+ "audit_log_id": {
4950
+ "type": "string",
4951
+ "format": "uuid"
4952
+ }
4953
+ }
4954
+ }
4955
+ },
4956
+ {
4957
+ "name": "besales_feedback_sheet_link",
4958
+ "description": "Привязать Google Sheets-таблицу с замечаниями тестировщиков к промпту агента. Принимает ссылку docs.google.com/spreadsheets/...; один файл можно привязать к нескольким промптам. В ответе — serviceAccountEmail: расшарьте таблицу на этот email (Viewer для READ_ONLY, Editor для EDITABLE).",
4959
+ "inputSchema": {
4960
+ "type": "object",
4961
+ "required": [
4962
+ "agent_id",
4963
+ "source_url"
4964
+ ],
4965
+ "properties": {
4966
+ "agent_id": {
4967
+ "type": "string",
4968
+ "format": "uuid"
4969
+ },
4970
+ "source_url": {
4971
+ "type": "string",
4972
+ "description": "Ссылка на Google Sheet (docs.google.com/spreadsheets/...)."
4973
+ },
4974
+ "access_mode": {
4975
+ "type": "string",
4976
+ "enum": [
4977
+ "READ_ONLY",
4978
+ "EDITABLE"
4979
+ ],
4980
+ "default": "READ_ONLY",
4981
+ "description": "Намерение: READ_ONLY — только чтение; EDITABLE — Phase 2 запись статусов строк."
4569
4982
  },
4570
4983
  "agent_version_id": {
4571
4984
  "type": "string",
@@ -4829,7 +5242,7 @@
4829
5242
  },
4830
5243
  {
4831
5244
  "name": "besales_prompt_patch_apply",
4832
- "description": "S3.8: применяет batch operations к draft.currentContent. Resets TTL на 24h (activity-based). Возвращает `appliedCount` + `skippedCount` (anchor не найден / growth guard >30%). Endpoint: PATCH /api/v2/agents/{agentId}/prompt/drafts/{draftId}/operations. Scope: write:prompt-drafts. ВАЖНО: ведущие и замыкающие пробелы/переводы строк в replacement_text срезаются — чтобы вставить пустую строку-разделитель между абзацами, держи перевод строки В СЕРЕДИНЕ replacement_text или включи окружающий текст в anchor/target; иначе соседние заголовки/абзацы склеятся. Ответ возвращает весь обновлённый currentContent (может быть очень большим) — сверяйся по appliedCount/skippedCount, не перечитывай весь контент между батчами.",
5245
+ "description": "S3.8: применяет batch operations к draft.currentContent. Resets TTL на 24h (activity-based). Возвращает `appliedCount` + `skippedCount` (anchor не найден / growth guard >30%). Endpoint: PATCH /api/v2/agents/{agentId}/prompt/drafts/{draftId}/operations. Scope: write:prompt-drafts. ВАЖНО: ведущие и замыкающие пробелы/переводы строк в replacement_text срезаются — чтобы вставить пустую строку-разделитель между абзацами, держи перевод строки В СЕРЕДИНЕ replacement_text или включи окружающий текст в anchor/target; иначе соседние заголовки/абзацы склеятся. Ответ НЕ содержит текст черновика: приезжают appliedCount/skippedCount, метаданные (draft.characters — длина после правки) и diff — построчная разница «до → после» (removedLines/addedLines, при обрезке truncated: true). ВНИМАНИЕ: пустые removedLines/addedLines НЕ означают «ничего не применилось» — diff строится как разность множеств строк, поэтому move_text_after_text и правка одних пробелов дают пустые списки; факт изменения читай по diff.contentChanged. Перечитать промпт целиком — besales_prompt_patch_get. между батчами.",
4833
5246
  "inputSchema": {
4834
5247
  "type": "object",
4835
5248
  "required": [
@@ -4892,7 +5305,7 @@
4892
5305
  },
4893
5306
  {
4894
5307
  "name": "besales_prompt_patch_commit",
4895
- "description": "S3.8: коммитит draft как новую PromptVersion. Pipeline: (1) Lint (PromptLintService) — hard_fail блокирует commit с 400; (2) Optimistic lock в prompt-services — `agentSideHash` server-side читается из AgentChat (если production prompt изменился между fork и commit → 409 PROMPT_DRAFT_REBASE_REQUIRED, discard и создай новый); (3) AgentChat sync с conditional UPDATE; (4) если sync упал после успешного PS commit → retry queue (success клиенту). Endpoint: POST /api/v2/agents/{agentId}/prompt/drafts/{draftId}/commit. Scope: write:prompt-drafts.",
5308
+ "description": "S3.8: коммитит draft как новую PromptVersion. Pipeline: (1) Lint (PromptLintService) — hard_fail блокирует commit с 400; (2) Optimistic lock в prompt-services — `agentSideHash` server-side читается из AgentChat (если production prompt изменился между fork и commit → 409 PROMPT_DRAFT_REBASE_REQUIRED, discard и создай новый); (3) AgentChat sync с conditional UPDATE; (4) если sync упал после успешного PS commit → retry queue (success клиенту). Endpoint: POST /api/v2/agents/{agentId}/prompt/drafts/{draftId}/commit. Scope: write:prompt-drafts. Ответ несёт только адресацию новой версии (newVersion.id + version) и метаданные черновика — текст промпта не дублируется.",
4896
5309
  "inputSchema": {
4897
5310
  "type": "object",
4898
5311
  "required": [
@@ -4940,7 +5353,8 @@
4940
5353
  "additionalProperties": false,
4941
5354
  "required": [
4942
5355
  "agent_ids",
4943
- "operations"
5356
+ "operations",
5357
+ "explicit_confirmation"
4944
5358
  ],
4945
5359
  "properties": {
4946
5360
  "agent_ids": {
@@ -5003,6 +5417,10 @@
5003
5417
  "platform_id": {
5004
5418
  "type": "string",
5005
5419
  "format": "uuid"
5420
+ },
5421
+ "explicit_confirmation": {
5422
+ "type": "boolean",
5423
+ "const": true
5006
5424
  }
5007
5425
  }
5008
5426
  }
@@ -5094,7 +5512,7 @@
5094
5512
  },
5095
5513
  {
5096
5514
  "name": "besales_workbook_inspect",
5097
- "description": "v1.5 workbook ingestion: открыть xlsx (по stored_file_id) или Google Sheets (по google_sheets_url) и вернуть структуру всех вкладок — sample rows с per-cell данными (value + hyperlink + formula) + per-column hyperlink статистика (lead/contact amoCRM). Создаёт SourceWorkbook record для provenance. Для xlsx — сначала загрузите файл через POST /api/v2/files. Для Google Sheets — если 403, response содержит serviceAccountEmail для расшарить. Sheet identifier в дальнейших вызовах — sheetTitle/sheetGid/sheetIndex в body. Scope: mcp:*.",
5515
+ "description": "Инвентаризация workbook: открыть ранее загруженный xlsx (stored_file_id) или Google Sheets и вернуть список всех вкладок с ограниченным sample. Создаёт SourceWorkbook для provenance. Это не полная вычитка: поздние строки и колонки читай через besales_workbook_sheet_read, а readError не трактуй как пустой лист. xlsx загружается через browser flow besales_file_upload_request/status. Scope: mcp:*.",
5098
5516
  "inputSchema": {
5099
5517
  "type": "object",
5100
5518
  "properties": {
@@ -5130,6 +5548,87 @@
5130
5548
  }
5131
5549
  }
5132
5550
  },
5551
+ {
5552
+ "name": "besales_workbook_get",
5553
+ "description": "Получить метаданные, classification и archivedAt зарегистрированного SourceWorkbook без чтения содержимого листов. Scope: mcp:*.",
5554
+ "inputSchema": {
5555
+ "type": "object",
5556
+ "required": ["workbook_id"],
5557
+ "properties": {
5558
+ "workspace_id": {
5559
+ "type": "string",
5560
+ "format": "uuid",
5561
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session (BESALES_WORKSPACE_ID or active connection)."
5562
+ },
5563
+ "workbook_id": { "type": "string", "format": "uuid" }
5564
+ }
5565
+ }
5566
+ },
5567
+ {
5568
+ "name": "besales_workbook_sheet_read",
5569
+ "description": "Постранично прочитать выбранный диапазон листа SourceWorkbook без записи в RAG. Возвращает hasMore/next offsets, известный либо null total и SHA-256 pageFingerprint для обнаружения изменений. Ровно один из sheet_title/sheet_gid/sheet_index обязателен. Scope: mcp:*.",
5570
+ "inputSchema": {
5571
+ "type": "object",
5572
+ "required": ["workbook_id"],
5573
+ "properties": {
5574
+ "workspace_id": {
5575
+ "type": "string",
5576
+ "format": "uuid",
5577
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session (BESALES_WORKSPACE_ID or active connection)."
5578
+ },
5579
+ "workbook_id": { "type": "string", "format": "uuid" },
5580
+ "sheet_title": { "type": "string" },
5581
+ "sheet_gid": { "type": "integer" },
5582
+ "sheet_index": { "type": "integer", "minimum": 0 },
5583
+ "row_offset": { "type": "integer", "minimum": 0, "default": 0 },
5584
+ "row_limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 50 },
5585
+ "column_offset": { "type": "integer", "minimum": 0, "default": 0 },
5586
+ "column_limit": {
5587
+ "type": "integer",
5588
+ "minimum": 1,
5589
+ "maximum": 100,
5590
+ "default": 50
5591
+ }
5592
+ }
5593
+ }
5594
+ },
5595
+ {
5596
+ "name": "besales_workbook_classification_update",
5597
+ "description": "Сохранить решения классификации вкладок в SourceWorkbook. Перед записью дочитай нужные страницы и проверь pageFingerprint. Scope: mcp:platform-setup.",
5598
+ "inputSchema": {
5599
+ "type": "object",
5600
+ "required": ["workbook_id", "classification"],
5601
+ "properties": {
5602
+ "workspace_id": {
5603
+ "type": "string",
5604
+ "format": "uuid",
5605
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session (BESALES_WORKSPACE_ID or active connection)."
5606
+ },
5607
+ "workbook_id": { "type": "string", "format": "uuid" },
5608
+ "classification": {
5609
+ "type": "array",
5610
+ "items": { "type": "object", "additionalProperties": true }
5611
+ }
5612
+ }
5613
+ }
5614
+ },
5615
+ {
5616
+ "name": "besales_workbook_archive",
5617
+ "description": "Архивировать SourceWorkbook после явного подтверждения. Созданные документы знаний сохраняются. Scope: mcp:platform-setup.",
5618
+ "inputSchema": {
5619
+ "type": "object",
5620
+ "required": ["workbook_id", "explicit_confirmation"],
5621
+ "properties": {
5622
+ "workspace_id": {
5623
+ "type": "string",
5624
+ "format": "uuid",
5625
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session (BESALES_WORKSPACE_ID or active connection)."
5626
+ },
5627
+ "workbook_id": { "type": "string", "format": "uuid" },
5628
+ "explicit_confirmation": { "type": "boolean", "const": true }
5629
+ }
5630
+ }
5631
+ },
5133
5632
  {
5134
5633
  "name": "besales_workbook_extract_amocrm_leads",
5135
5634
  "description": "v1.5 workbook ingestion: прочитать вкладку SourceWorkbook ЦЕЛИКОМ (без sample-лимита inspect) и извлечь все amoCRM lead-ID из ячеек (value + hyperlink + formula). Используй когда `inspect` sample недостаточен — например, для большого диалог-индекса с 100+ ссылок. Sheet identifier — один из sheet_title / sheet_gid / sheet_index. Опционально include_contacts=true возвращает также contacts. Hard cap 10000 строк на лист. Scope: mcp:*.",
@@ -5577,6 +6076,7 @@
5577
6076
  },
5578
6077
  "explicit_confirmation": {
5579
6078
  "type": "boolean",
6079
+ "const": true,
5580
6080
  "description": "Должен быть true. False → 400 BadRequest."
5581
6081
  }
5582
6082
  }
@@ -5841,6 +6341,7 @@
5841
6341
  },
5842
6342
  "explicit_confirmation": {
5843
6343
  "type": "boolean",
6344
+ "const": true,
5844
6345
  "description": "Должен быть true. False → 400 BadRequest."
5845
6346
  }
5846
6347
  }
@@ -5911,6 +6412,7 @@
5911
6412
  },
5912
6413
  "explicit_confirmation": {
5913
6414
  "type": "boolean",
6415
+ "const": true,
5914
6416
  "description": "Должен быть true. False → 400 BadRequest."
5915
6417
  }
5916
6418
  }
@@ -6036,6 +6538,7 @@
6036
6538
  },
6037
6539
  "explicit_confirmation": {
6038
6540
  "type": "boolean",
6541
+ "const": true,
6039
6542
  "description": "Должен быть true. False → 400 BadRequest."
6040
6543
  }
6041
6544
  }
@@ -6255,14 +6758,15 @@
6255
6758
  "format": "uuid"
6256
6759
  },
6257
6760
  "explicit_confirmation": {
6258
- "type": "boolean"
6761
+ "type": "boolean",
6762
+ "const": true
6259
6763
  }
6260
6764
  }
6261
6765
  }
6262
6766
  },
6263
6767
  {
6264
6768
  "name": "besales_knowledge_table_reindex",
6265
- "description": "v1.5 Increment 3: полная переиндексация таблицы (delete vectors + re-fetch CSV + re-embed + Pinecone upsert). SYNC operation — может занять время для больших таблиц. Scope: write:knowledge.",
6769
+ "description": "Запустить полную фоновую переиндексацию knowledge table: delete vectors + re-fetch CSV + re-embed + Pinecone upsert. Возвращает job_id; проверяй исход через besales_knowledge_table_reindex_status. Scope: write:knowledge.",
6266
6770
  "inputSchema": {
6267
6771
  "type": "object",
6268
6772
  "required": [
@@ -6284,18 +6788,47 @@
6284
6788
  "format": "uuid"
6285
6789
  },
6286
6790
  "explicit_confirmation": {
6287
- "type": "boolean"
6791
+ "type": "boolean",
6792
+ "const": true
6793
+ }
6794
+ }
6795
+ }
6796
+ },
6797
+ {
6798
+ "name": "besales_knowledge_table_reindex_status",
6799
+ "description": "Проверить состояние фоновой переиндексации knowledge table: QUEUED/RUNNING/COMPLETED/FAILED/EXPIRED, progress, result/error и timestamps. Состояние хранится 24 часа. Scope: read:knowledge.",
6800
+ "inputSchema": {
6801
+ "type": "object",
6802
+ "required": [
6803
+ "knowledge_space_id",
6804
+ "table_id"
6805
+ ],
6806
+ "additionalProperties": false,
6807
+ "properties": {
6808
+ "workspace_id": {
6809
+ "type": "string",
6810
+ "format": "uuid",
6811
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
6812
+ },
6813
+ "knowledge_space_id": {
6814
+ "type": "string",
6815
+ "format": "uuid"
6816
+ },
6817
+ "table_id": {
6818
+ "type": "string",
6819
+ "format": "uuid"
6288
6820
  }
6289
6821
  }
6290
6822
  }
6291
6823
  },
6292
6824
  {
6293
6825
  "name": "besales_knowledge_namespace_reindex",
6294
- "description": "Фоновая (BullMQ) переиндексация knowledge space: re-embed существующих Q&A + чанков документов из Postgres → Pinecone, идемпотентно (upsert по стабильному id). Восстанавливает поиск, когда данные есть в Postgres, но besales_knowledge_qa_search пуст (рассинхрон PG↔Pinecone после транзиентного сбоя upsert при сохранении или смены scope). ASYNC — итог в логах воркера, повтори поиск через ~минуту. types опционально (по умолчанию [qa, doc]). Scope: mcp:platform-setup.",
6826
+ "description": "Запустить фоновую переиндексацию knowledge space: re-embed существующих Q&A и чанков документов из Postgres → Pinecone. Возвращает job_id; проверяй исход через besales_knowledge_namespace_reindex_status. types опционально (по умолчанию [qa, doc]). Scope: mcp:platform-setup.",
6295
6827
  "inputSchema": {
6296
6828
  "type": "object",
6297
6829
  "required": [
6298
- "knowledge_space_id"
6830
+ "knowledge_space_id",
6831
+ "explicit_confirmation"
6299
6832
  ],
6300
6833
  "properties": {
6301
6834
  "workspace_id": {
@@ -6316,13 +6849,39 @@
6316
6849
  ]
6317
6850
  },
6318
6851
  "description": "Какие типы переиндексировать; default [qa, doc]"
6852
+ },
6853
+ "explicit_confirmation": {
6854
+ "type": "boolean",
6855
+ "const": true
6856
+ }
6857
+ }
6858
+ }
6859
+ },
6860
+ {
6861
+ "name": "besales_knowledge_namespace_reindex_status",
6862
+ "description": "Проверить состояние фоновой переиндексации knowledge space: QUEUED/RUNNING/COMPLETED/FAILED/EXPIRED, progress, result/error и timestamps. Состояние хранится 24 часа. Scope: read:knowledge.",
6863
+ "inputSchema": {
6864
+ "type": "object",
6865
+ "required": [
6866
+ "knowledge_space_id"
6867
+ ],
6868
+ "additionalProperties": false,
6869
+ "properties": {
6870
+ "workspace_id": {
6871
+ "type": "string",
6872
+ "format": "uuid",
6873
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
6874
+ },
6875
+ "knowledge_space_id": {
6876
+ "type": "string",
6877
+ "format": "uuid"
6319
6878
  }
6320
6879
  }
6321
6880
  }
6322
6881
  },
6323
6882
  {
6324
6883
  "name": "besales_variable_list",
6325
- "description": "v1.5 Increment 4a: список переменных. scope=WORKSPACE возвращает глобальные WorkspaceVariable (доступны всем платформам); scope=CHANNEL требует platform_id и возвращает CustomVariable одной платформы (filter: all|variables|constants). Референс в промпте/шаблоне: WORKSPACE → {{{name}}} (тройные фигурные), CHANNEL-константа → {{name}} (двойные). Scope: mcp:platform-setup.",
6884
+ "description": "Список переменных workspace или платформы. scope=WORKSPACE возвращает глобальные WorkspaceVariable; scope=CHANNEL требует platform_id и возвращает CustomVariable одной платформы (filter: all|variables|constants). Постраничная выдача: сервер ограничивает страницу, до 200 по limit. Если показана не вся выборка, ответ содержит nextCursor, а вызов без явных limit/cursor откажется возвращать неполный снимок. Дочитывайте страницы, пока nextCursor не опустеет. Референс: WORKSPACE → {{{name}}}, CHANNEL-константа → {{name}}. Scope: mcp:platform-setup.",
6326
6885
  "inputSchema": {
6327
6886
  "type": "object",
6328
6887
  "required": [
@@ -6354,6 +6913,17 @@
6354
6913
  "constants"
6355
6914
  ],
6356
6915
  "description": "Filter для CHANNEL scope; default=all"
6916
+ },
6917
+ "limit": {
6918
+ "type": "integer",
6919
+ "minimum": 1,
6920
+ "maximum": 200,
6921
+ "description": "Размер страницы. Умолчания у аргумента НЕТ намеренно: молча усечённый перечень настройки хуже отказа."
6922
+ },
6923
+ "cursor": {
6924
+ "type": "string",
6925
+ "minLength": 1,
6926
+ "description": "nextCursor предыдущей страницы."
6357
6927
  }
6358
6928
  }
6359
6929
  }
@@ -7452,14 +8022,29 @@
7452
8022
  }
7453
8023
  },
7454
8024
  {
7455
- "name": "besales_crm_field_mapping_get",
7456
- "description": "v1.5 Increment 5c: текущий маппинг полей CRM + доступные поля. Только AmoCRM/Bitrix24 (иначе unsupported_reason). Scope: mcp:platform-setup.",
8025
+ "name": "besales_crm_amocrm_channel_registration",
8026
+ "description": "Заявка на регистрацию чат-канала AmoCRM: адрес вебхука воркспейса + текст письма в техподдержку AmoCRM. Без зарегистрированного канала бот управляет сделкой, но переписка в её карточке не появляется — channelId/channelSecretKey выдаёт только их поддержка по письму заданной формы. Текст собирает бэкенд, тот же ответ показывает страница AmoCRM в интерфейсе: пересылай дословно, адрес сам не собирай. Scope: mcp:platform-setup.",
7457
8027
  "inputSchema": {
7458
8028
  "type": "object",
7459
- "required": [
7460
- "crm_id"
7461
- ],
7462
- "additionalProperties": false,
8029
+ "required": [],
8030
+ "properties": {
8031
+ "workspace_id": {
8032
+ "type": "string",
8033
+ "format": "uuid",
8034
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
8035
+ }
8036
+ }
8037
+ }
8038
+ },
8039
+ {
8040
+ "name": "besales_crm_field_mapping_get",
8041
+ "description": "v1.5 Increment 5c: текущий маппинг полей CRM + доступные поля. Только AmoCRM/Bitrix24 (иначе unsupported_reason). Scope: mcp:platform-setup.",
8042
+ "inputSchema": {
8043
+ "type": "object",
8044
+ "required": [
8045
+ "crm_id"
8046
+ ],
8047
+ "additionalProperties": false,
7463
8048
  "properties": {
7464
8049
  "workspace_id": {
7465
8050
  "type": "string",
@@ -7818,7 +8403,8 @@
7818
8403
  "required": [
7819
8404
  "data_source_id",
7820
8405
  "catalog_external_code",
7821
- "enabled"
8406
+ "enabled",
8407
+ "explicit_confirmation"
7822
8408
  ],
7823
8409
  "additionalProperties": false,
7824
8410
  "properties": {
@@ -7840,13 +8426,17 @@
7840
8426
  "name": {
7841
8427
  "type": "string",
7842
8428
  "description": "Опц. имя векторной таблицы при включении."
8429
+ },
8430
+ "explicit_confirmation": {
8431
+ "type": "boolean",
8432
+ "const": true
7843
8433
  }
7844
8434
  }
7845
8435
  }
7846
8436
  },
7847
8437
  {
7848
8438
  "name": "besales_workspace_use",
7849
- "description": "Привязать ТЕКУЩУЮ Claude-сессию к воркспейсу (in-memory, до конца сессии). Для GUI-хостов (Claude Desktop), где нельзя задать env на сессию: если подключено несколько воркспейсов — этим тулом биндишь сессию к нужному, не трогая другие сессии и keychain `active`. workspace_id бери из besales_workspace_current. Запрещён, если сессия запиннена через BESALES_WORKSPACE_ID.",
8439
+ "description": "Привязать ТЕКУЩУЮ Claude-сессию к выбранному workspace (in-memory, до конца сессии). Сначала вызови besales_workspace_current и покажи человеку названия компаний и безопасные подписи аккаунтов; UUID передай сам. Запрещён, если сессия запиннена через BESALES_WORKSPACE_ID.",
7850
8440
  "inputSchema": {
7851
8441
  "type": "object",
7852
8442
  "required": [
@@ -7856,20 +8446,117 @@
7856
8446
  "workspace_id": {
7857
8447
  "type": "string",
7858
8448
  "format": "uuid",
7859
- "description": "UUID подключённого воркспейса (см. besales_workspace_current.connected[].workspace_id)."
8449
+ "description": "UUID подключённого workspace из besales_workspace_current.connected[].workspace_id; человек выбирает по workspace_name/account_label, а не ищет UUID сам."
7860
8450
  }
7861
8451
  }
7862
8452
  }
7863
8453
  },
7864
8454
  {
7865
8455
  "name": "besales_workspace_current",
7866
- "description": "Показать воркспейс текущей сессии (+ source: env/session/active/sole/none) и список всех подключённых воркспейсов. Read-only, без обращения к backend. Зови перед besales_workspace_use, чтобы узнать доступные workspace_id.",
8456
+ "description": "Показать выбранный workspace, источник выбора (env/session/sole/ambiguous/none) и все подключения с workspace_name, безопасной account_label и свежестью подписи. Для неизвестных/устаревших подписей делает лёгкий scoped refresh без workspace overview. current/cached/stale/unknown и label_refresh_error различают свежесть, старый backend, ключ и scope. При ambiguous покажи названия человеку и сам передай UUID в besales_workspace_use.",
7867
8457
  "inputSchema": {
7868
8458
  "type": "object",
7869
8459
  "required": [],
7870
8460
  "properties": {}
7871
8461
  }
7872
8462
  },
8463
+ {
8464
+ "name": "besales_task_create",
8465
+ "description": "Сохранить цель и минимальный прогресс работы между MCP-сессиями на этой машине. Состояние workspace-scoped, не содержит credentials и не заменяет свежую проверку объектов/прав. Возвращает task_id и version для CAS-обновлений.",
8466
+ "inputSchema": {
8467
+ "type": "object",
8468
+ "required": ["goal"],
8469
+ "additionalProperties": false,
8470
+ "properties": {
8471
+ "workspace_id": { "type": "string", "format": "uuid" },
8472
+ "goal": { "type": "string", "minLength": 3, "maxLength": 500 },
8473
+ "context": { "type": "string", "minLength": 1, "maxLength": 2000 },
8474
+ "constraints": { "type": "array", "maxItems": 20, "items": { "type": "string", "minLength": 1, "maxLength": 500 }, "default": [] },
8475
+ "object_refs": { "type": "array", "maxItems": 100, "items": { "type": "object", "required": ["type", "id"], "additionalProperties": false, "properties": { "type": { "type": "string", "minLength": 1, "maxLength": 80 }, "id": { "type": "string", "minLength": 1, "maxLength": 200 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 } } }, "default": [] },
8476
+ "checkpoints": { "type": "array", "maxItems": 100, "items": { "type": "object", "required": ["key", "label", "status"], "additionalProperties": false, "properties": { "key": { "type": "string", "minLength": 1, "maxLength": 80 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 }, "status": { "type": "string", "enum": ["PENDING", "COMPLETED", "BLOCKED"] }, "evidence": { "type": "string", "minLength": 1, "maxLength": 500 } } }, "default": [] },
8477
+ "pending_operations": { "type": "array", "maxItems": 50, "items": { "type": "object", "required": ["operation", "status"], "additionalProperties": false, "properties": { "operation": { "type": "string", "minLength": 1, "maxLength": 120 }, "object_ref": { "type": "object", "required": ["type", "id"], "additionalProperties": false, "properties": { "type": { "type": "string", "minLength": 1, "maxLength": 80 }, "id": { "type": "string", "minLength": 1, "maxLength": 200 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 } } }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200 }, "verify_with": { "type": "string", "minLength": 1, "maxLength": 120 }, "status": { "type": "string", "enum": ["PLANNED", "AWAITING_USER", "OUTCOME_UNKNOWN"] } } }, "default": [] },
8478
+ "expected_user_action": { "type": ["string", "null"], "minLength": 1, "maxLength": 1000 },
8479
+ "retention_days": { "type": "integer", "minimum": 1, "maximum": 180 }
8480
+ }
8481
+ }
8482
+ },
8483
+ {
8484
+ "name": "besales_task_list",
8485
+ "description": "Список сохранённых задач только выбранного workspace. При нескольких задачах возвращает selection_required=true: выбери task_id явно, не продолжай самую новую автоматически.",
8486
+ "inputSchema": {
8487
+ "type": "object",
8488
+ "required": [],
8489
+ "additionalProperties": false,
8490
+ "properties": {
8491
+ "workspace_id": { "type": "string", "format": "uuid" },
8492
+ "status": { "type": "string", "enum": ["ACTIVE", "COMPLETED", "CANCELLED", "EXPIRED"] }
8493
+ }
8494
+ }
8495
+ },
8496
+ {
8497
+ "name": "besales_task_get",
8498
+ "description": "Прочитать сохранённую задачу по task_id в выбранном workspace. Перед продолжением перечитай актуальные объекты и besales_workspace_current: сохранённое состояние не доказывает текущую конфигурацию или права.",
8499
+ "inputSchema": {
8500
+ "type": "object",
8501
+ "required": ["task_id"],
8502
+ "additionalProperties": false,
8503
+ "properties": {
8504
+ "workspace_id": { "type": "string", "format": "uuid" },
8505
+ "task_id": { "type": "string", "format": "uuid" }
8506
+ }
8507
+ }
8508
+ },
8509
+ {
8510
+ "name": "besales_task_update",
8511
+ "description": "Обновить сохранённую ACTIVE-задачу с compare-and-swap по expected_version. При TASK_VERSION_CONFLICT перечитай задачу и согласуй изменения; не повторяй pending mutation автоматически.",
8512
+ "inputSchema": {
8513
+ "type": "object",
8514
+ "required": ["task_id", "expected_version"],
8515
+ "additionalProperties": false,
8516
+ "properties": {
8517
+ "workspace_id": { "type": "string", "format": "uuid" },
8518
+ "task_id": { "type": "string", "format": "uuid" },
8519
+ "expected_version": { "type": "integer", "minimum": 1 },
8520
+ "goal": { "type": "string", "minLength": 3, "maxLength": 500 },
8521
+ "context": { "type": "string", "minLength": 1, "maxLength": 2000 },
8522
+ "constraints": { "type": "array", "maxItems": 20, "items": { "type": "string", "minLength": 1, "maxLength": 500 } },
8523
+ "object_refs": { "type": "array", "maxItems": 100, "items": { "type": "object", "required": ["type", "id"], "additionalProperties": false, "properties": { "type": { "type": "string", "minLength": 1, "maxLength": 80 }, "id": { "type": "string", "minLength": 1, "maxLength": 200 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 } } } },
8524
+ "checkpoints": { "type": "array", "maxItems": 100, "items": { "type": "object", "required": ["key", "label", "status"], "additionalProperties": false, "properties": { "key": { "type": "string", "minLength": 1, "maxLength": 80 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 }, "status": { "type": "string", "enum": ["PENDING", "COMPLETED", "BLOCKED"] }, "evidence": { "type": "string", "minLength": 1, "maxLength": 500 } } } },
8525
+ "pending_operations": { "type": "array", "maxItems": 50, "items": { "type": "object", "required": ["operation", "status"], "additionalProperties": false, "properties": { "operation": { "type": "string", "minLength": 1, "maxLength": 120 }, "object_ref": { "type": "object", "required": ["type", "id"], "additionalProperties": false, "properties": { "type": { "type": "string", "minLength": 1, "maxLength": 80 }, "id": { "type": "string", "minLength": 1, "maxLength": 200 }, "label": { "type": "string", "minLength": 1, "maxLength": 200 } } }, "idempotency_key": { "type": "string", "minLength": 1, "maxLength": 200 }, "verify_with": { "type": "string", "minLength": 1, "maxLength": 120 }, "status": { "type": "string", "enum": ["PLANNED", "AWAITING_USER", "OUTCOME_UNKNOWN"] } } } },
8526
+ "expected_user_action": { "type": ["string", "null"], "minLength": 1, "maxLength": 1000 }
8527
+ }
8528
+ }
8529
+ },
8530
+ {
8531
+ "name": "besales_task_close",
8532
+ "description": "Закрыть ACTIVE-задачу как COMPLETED или CANCELLED с проверкой expected_version. Закрытая задача не возобновляется автоматически.",
8533
+ "inputSchema": {
8534
+ "type": "object",
8535
+ "required": ["task_id", "expected_version", "outcome"],
8536
+ "additionalProperties": false,
8537
+ "properties": {
8538
+ "workspace_id": { "type": "string", "format": "uuid" },
8539
+ "task_id": { "type": "string", "format": "uuid" },
8540
+ "expected_version": { "type": "integer", "minimum": 1 },
8541
+ "outcome": { "type": "string", "enum": ["COMPLETED", "CANCELLED"] }
8542
+ }
8543
+ }
8544
+ },
8545
+ {
8546
+ "name": "besales_task_delete",
8547
+ "description": "Безвозвратно удалить локальное состояние задачи. Требует точную expected_version и explicit_confirmation=true; не удаляет созданные объекты Besales.",
8548
+ "inputSchema": {
8549
+ "type": "object",
8550
+ "required": ["task_id", "expected_version", "explicit_confirmation"],
8551
+ "additionalProperties": false,
8552
+ "properties": {
8553
+ "workspace_id": { "type": "string", "format": "uuid" },
8554
+ "task_id": { "type": "string", "format": "uuid" },
8555
+ "expected_version": { "type": "integer", "minimum": 1 },
8556
+ "explicit_confirmation": { "type": "boolean", "const": true }
8557
+ }
8558
+ }
8559
+ },
7873
8560
  {
7874
8561
  "name": "besales_model_catalog_list",
7875
8562
  "description": "Каталог моделей для сравнения промпта (model bake-off): id, label, tier (budget/balanced/premium), bestFor-теги «когда что лучше», notes, viaOpenRouter, defaultSelected, available (доступен ли провайдер сейчас) + лимиты. По этим тегам ИИ выбирает ~5 моделей под use-case агента. Read-only.",
@@ -7882,7 +8569,7 @@
7882
8569
  },
7883
8570
  {
7884
8571
  "name": "besales_model_comparison_run_start",
7885
- "description": "Запустить прогон сравнения промпта агента на нескольких моделях (один и тот же набор диалогов, меняется только модель агента). ДОРОГО — только по явному запросу оператора, НЕ после каждого фикса. models опционально (по умолчанию ~5 defaultSelected из besales_model_catalog_list), 1..21. dialogue_count по умолчанию 5, до 20. Возвращает run_id для besales_model_comparison_get.",
8572
+ "description": "Запустить прогон сравнения промпта агента на нескольких моделях (один и тот же набор диалогов, меняется только модель агента). ДОРОГО — только по явному запросу оператора, НЕ после каждого фикса. models опционально (по умолчанию ~5 defaultSelected из besales_model_catalog_list), 1..26. dialogue_count по умолчанию 5, до 20. Возвращает run_id для besales_model_comparison_get.",
7886
8573
  "inputSchema": {
7887
8574
  "type": "object",
7888
8575
  "required": [
@@ -7900,8 +8587,8 @@
7900
8587
  "type": "string"
7901
8588
  },
7902
8589
  "minItems": 1,
7903
- "maxItems": 21,
7904
- "description": "Runnable id моделей из каталога (1..21). По умолчанию набор defaultSelected."
8590
+ "maxItems": 26,
8591
+ "description": "Runnable id моделей из каталога (1..26). По умолчанию набор defaultSelected."
7905
8592
  },
7906
8593
  "dialogue_count": {
7907
8594
  "type": "integer",
@@ -8008,7 +8695,7 @@
8008
8695
  },
8009
8696
  {
8010
8697
  "name": "besales_external_api_channel_create",
8011
- "description": "v1.5: создать канал External API (партнёрский relay, ChannelType.EXTERNAL_API). Ответ { channelId, apiKey, webhookSecret, ingestPath } — apiKey (Bearer для входящих партнёра) и webhookSecret (HMAC-подпись наших колбэков) показываются ОДИН раз. Перевыпуск — rotate-тулы. Scope: mcp:platform-setup.",
8698
+ "description": "v1.5: создать канал External API. Ответ { channelId, ingestPath, revealUrl, revealExpiresAt }; секреты через MCP не проходят. Человек открывает revealUrl, входит и получает ключ с webhook-подписью один раз. Scope: mcp:platform-setup.",
8012
8699
  "inputSchema": {
8013
8700
  "type": "object",
8014
8701
  "required": [
@@ -8043,7 +8730,7 @@
8043
8730
  },
8044
8731
  {
8045
8732
  "name": "besales_external_api_channel_rotate_key",
8046
- "description": "v1.5: перевыпустить bsl-ключ External API канала. Ответ { apiKey } — новый ключ, показывается ОДИН раз; старый ОТОЗВАН немедленно (партнёр должен обновить интеграцию). Scope: mcp:platform-setup.",
8733
+ "description": "v1.5: выдать browser-handoff ссылку на перевыпуск bsl-ключа. До открытия ссылки прежний ключ продолжает работать; новый ключ показывается вошедшему человеку один раз. Scope: mcp:platform-setup.",
8047
8734
  "inputSchema": {
8048
8735
  "type": "object",
8049
8736
  "required": [
@@ -8065,7 +8752,7 @@
8065
8752
  },
8066
8753
  {
8067
8754
  "name": "besales_external_api_channel_rotate_secret",
8068
- "description": "v1.5: перевыпустить webhook-secret External API канала. Ответ { webhookSecret } — новый секрет, показывается ОДИН раз; старый инвалидирован (партнёр должен обновить проверку подписи колбэков). Scope: mcp:platform-setup.",
8755
+ "description": "v1.5: выдать browser-handoff ссылку на замену webhook-secret. До открытия ссылки прежняя подпись действует; новая показывается вошедшему человеку один раз. Scope: mcp:platform-setup.",
8069
8756
  "inputSchema": {
8070
8757
  "type": "object",
8071
8758
  "required": [
@@ -8409,7 +9096,8 @@
8409
9096
  "type": "string",
8410
9097
  "enum": [
8411
9098
  "cohort",
8412
- "period"
9099
+ "period",
9100
+ "entry"
8413
9101
  ],
8414
9102
  "default": "period",
8415
9103
  "description": "period — по дате события (как вкладка по дням); cohort — по дате запуска волны."
@@ -8422,20 +9110,24 @@
8422
9110
  "0-7",
8423
9111
  "8-14",
8424
9112
  "15-30",
8425
- "31+"
9113
+ "31-45",
9114
+ "46-60",
9115
+ "61+"
8426
9116
  ]
8427
9117
  },
8428
9118
  {
8429
9119
  "type": "array",
8430
9120
  "minItems": 1,
8431
- "maxItems": 4,
9121
+ "maxItems": 6,
8432
9122
  "items": {
8433
9123
  "type": "string",
8434
9124
  "enum": [
8435
9125
  "0-7",
8436
9126
  "8-14",
8437
9127
  "15-30",
8438
- "31+"
9128
+ "31-45",
9129
+ "46-60",
9130
+ "61+"
8439
9131
  ]
8440
9132
  }
8441
9133
  }
@@ -8752,20 +9444,24 @@
8752
9444
  "0-7",
8753
9445
  "8-14",
8754
9446
  "15-30",
8755
- "31+"
9447
+ "31-45",
9448
+ "46-60",
9449
+ "61+"
8756
9450
  ]
8757
9451
  },
8758
9452
  {
8759
9453
  "type": "array",
8760
9454
  "minItems": 1,
8761
- "maxItems": 4,
9455
+ "maxItems": 6,
8762
9456
  "items": {
8763
9457
  "type": "string",
8764
9458
  "enum": [
8765
9459
  "0-7",
8766
9460
  "8-14",
8767
9461
  "15-30",
8768
- "31+"
9462
+ "31-45",
9463
+ "46-60",
9464
+ "61+"
8769
9465
  ]
8770
9466
  }
8771
9467
  }
@@ -8816,7 +9512,8 @@
8816
9512
  "type": "string",
8817
9513
  "enum": [
8818
9514
  "cohort",
8819
- "period"
9515
+ "period",
9516
+ "entry"
8820
9517
  ],
8821
9518
  "default": "period"
8822
9519
  },
@@ -8907,7 +9604,7 @@
8907
9604
  },
8908
9605
  {
8909
9606
  "name": "besales_followup_reactions",
8910
- "description": "Read-only аналитика дожимов: на какой шаг follow-up-цепочки контакт реально отреагировал. Метрик ТРИ — операционная (следует за длиной окна шага, шаги по ней сравнивать нельзя), сравнительная на равном горизонте (сравнивать можно только при comparableReliable=true) и runs — отклик на ПРОХОЖДЕНИЕ цепочки за run_window_days от входа, единственная, на которую не влияет частота шагов. Срезы по сегменту/продукту/мессенджеру доступны только у каналов с рассылками. Scope: read:analytics.",
9607
+ "description": "Read-only аналитика дожимов: на какой шаг follow-up-цепочки контакт реально отреагировал. Метрик ТРИ — операционная (следует за длиной окна шага, шаги по ней сравнивать нельзя), сравнительная на равном горизонте (сравнивать можно только при comparableReliable=true) и runs — отклик на ПРОХОЖДЕНИЕ цепочки за run_window_days от входа, единственная, на которую не влияет частота шагов. Срезы по сегменту/продукту/мессенджеру доступны только у каналов с рассылками. Scope: read:analytics. ⚠️ Реакцией считается не только ответ: `horizonEngaged` — ответили ИЛИ перешли по ссылке касания в том же горизонте, разность с `horizonReplied` даёт «не ответил, но кликнул». Складывать `horizonReplied` и `linkClicked` нельзя — ответивший часто ещё и кликает.",
8911
9608
  "inputSchema": {
8912
9609
  "type": "object",
8913
9610
  "required": [
@@ -9493,6 +10190,14 @@
9493
10190
  "ADD"
9494
10191
  ],
9495
10192
  "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
10193
+ },
10194
+ "quiet_days_override": {
10195
+ "type": [
10196
+ "integer",
10197
+ "null"
10198
+ ],
10199
+ "minimum": 0,
10200
+ "description": "ПЕРЕКРЫТИЕ тихого периода этой рассылкой, в сутках. 0 = «этот текст можно слать внутри тихого периода» — это и есть разрешение. null = рассылка не перекрывает, действует настройка площадки, затем воркспейса, затем 0. ⚠️ null и 0 — РАЗНЫЕ значения: не подставляй ноль вместо «не задано»."
9496
10201
  }
9497
10202
  }
9498
10203
  }
@@ -9657,6 +10362,14 @@
9657
10362
  "ADD"
9658
10363
  ],
9659
10364
  "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
10365
+ },
10366
+ "quiet_days_override": {
10367
+ "type": [
10368
+ "integer",
10369
+ "null"
10370
+ ],
10371
+ "minimum": 0,
10372
+ "description": "ПЕРЕКРЫТИЕ тихого периода этой рассылкой, в сутках. 0 = «этот текст можно слать внутри тихого периода» — это и есть разрешение. null = рассылка не перекрывает, действует настройка площадки, затем воркспейса, затем 0. ⚠️ null и 0 — РАЗНЫЕ значения: не подставляй ноль вместо «не задано»."
9660
10373
  }
9661
10374
  },
9662
10375
  "if": {
@@ -9704,6 +10417,72 @@
9704
10417
  }
9705
10418
  }
9706
10419
  },
10420
+ {
10421
+ "name": "besales_contact_search",
10422
+ "description": "Найти контакты по имени, email, телефону, внешнему ID или каналу / Search contacts by name, email, phone, external ID or channel. Возвращает cursor; страница не равна всему workspace.",
10423
+ "inputSchema": {
10424
+ "type": "object",
10425
+ "additionalProperties": false,
10426
+ "properties": {
10427
+ "workspace_id": { "type": "string", "format": "uuid", "description": "Подставляется из выбранного подключения." },
10428
+ "limit": { "type": "integer", "minimum": 1, "maximum": 50 },
10429
+ "cursor": { "type": "string", "minLength": 1 },
10430
+ "search": { "type": "string", "minLength": 1 },
10431
+ "external_id": { "type": "string", "minLength": 1, "description": "CSV provider:value, например getcourse:123." },
10432
+ "phone": { "type": "string", "minLength": 1, "description": "Один телефон или CSV." },
10433
+ "email": { "type": "string", "minLength": 1, "description": "Один email или CSV." },
10434
+ "channel_id": { "type": "string", "format": "uuid" }
10435
+ }
10436
+ }
10437
+ },
10438
+ {
10439
+ "name": "besales_contact_get",
10440
+ "description": "Прочитать карточку контакта и безопасный текущий снимок / Read one contact detail and safe current snapshot. Текст недавних сообщений зависит от effective scope read:conversations.",
10441
+ "inputSchema": {
10442
+ "type": "object",
10443
+ "required": ["contact_id"],
10444
+ "additionalProperties": false,
10445
+ "properties": {
10446
+ "contact_id": { "type": "string", "format": "uuid" }
10447
+ }
10448
+ }
10449
+ },
10450
+ {
10451
+ "name": "besales_contact_diagnostics_get",
10452
+ "description": "Объяснить, почему бот молчит, не передал оператору, не вызвал действие или не доставил ответ / Diagnose silence, operator handoff, actions and delivery from stored evidence. Не возвращает тексты сообщений, аргументы, результаты и raw errors; отсутствие RAG trace честно помечает unknown.",
10453
+ "inputSchema": {
10454
+ "type": "object",
10455
+ "required": ["contact_id"],
10456
+ "additionalProperties": false,
10457
+ "properties": {
10458
+ "contact_id": { "type": "string", "format": "uuid" },
10459
+ "message_id": { "type": "string", "format": "uuid", "description": "Если не задан, берётся последнее сообщение контакта." }
10460
+ }
10461
+ }
10462
+ },
10463
+ {
10464
+ "name": "besales_contact_touch_history",
10465
+ "description": "ИСТОРИЯ КАСАНИЙ человека школы: что мы ему отправляли и по какому праву. Сводит ТРИ источника с разными ключами: touches (журнал касаний — ПРАВО, взятое ДО отправки; строка есть и у попытки, которая никуда не ушла), sends (реестр получателей — пишется ПОСЛЕ доставки и best-effort, его отсутствие неотправки НЕ доказывает) и firstWelcomeAt (самая ранняя метка по карточкам). Складывать touches и sends нельзя — это ответы на разные вопросы. Инструмент только читает.",
10466
+ "inputSchema": {
10467
+ "type": "object",
10468
+ "required": [
10469
+ "getcourse_user_id"
10470
+ ],
10471
+ "additionalProperties": false,
10472
+ "properties": {
10473
+ "workspace_id": {
10474
+ "type": "string",
10475
+ "format": "uuid",
10476
+ "description": "Рабочее пространство. Подставляется из подключения, если не задано."
10477
+ },
10478
+ "getcourse_user_id": {
10479
+ "type": "integer",
10480
+ "minimum": 1,
10481
+ "description": "Идентификатор человека в школе GetCourse (getcourse_user_id). Ключ — ЧЕЛОВЕК, а не карточка: история включает касания со всех площадок воркспейса."
10482
+ }
10483
+ }
10484
+ }
10485
+ },
9707
10486
  {
9708
10487
  "name": "besales_getcourse_cold_welcome_preview",
9709
10488
  "description": "Охват рассылки «Первое сообщение» БЕЗ отправки: totalContacts (ещё могут получить), alreadyWelcomed (уже получали — первое сообщение одноразово на контакт), foundContacts.",
@@ -9782,6 +10561,16 @@
9782
10561
  "format": "uuid",
9783
10562
  "description": "Рассылка — источник каналов по умолчанию и «Платформы по умолчанию»."
9784
10563
  },
10564
+ "segment": {
10565
+ "type": "string",
10566
+ "maxLength": 200,
10567
+ "description": "Метка сегмента запуска. Ею считается правило «этим сегментом человеку уже уходило»: без неё прогноз правил (policyForecast) по этому правилу структурно пуст, и ноль читается как «проверили, никого». Аудиторию метка не отбирает."
10568
+ },
10569
+ "message": {
10570
+ "type": "string",
10571
+ "maxLength": 4000,
10572
+ "description": "Разовый текст запуска — им считается правило «тот же текст не дважды» (журнал касаний ключуется отпечатком шаблона). Для запуска с сохранённой рассылкой не нужен: текст берётся из неё тем же резолвером, что на старте."
10573
+ },
9785
10574
  "channels_mode": {
9786
10575
  "type": "string",
9787
10576
  "enum": [
@@ -9795,7 +10584,7 @@
9795
10584
  },
9796
10585
  {
9797
10586
  "name": "besales_getcourse_cold_welcome_start",
9798
- "description": "Запустить рассылку «Первое сообщение» (мы пишем первыми контактам без диалога). НЕОБРАТИМО: у GetCourse нет идемпотентности, отправку нельзя отозвать. Всегда сначала preview и подтверждение пользователя. Аудитория: по дате (created_after) или по файлу (contacts). Поля сделки штампуются после отправки. Если у рассылки заданы тексты по сегментам, значение segment ВЫБИРАЕТ текст: назови пользователю выбранный текст ДО подтверждения и не запускай посегментный текст по created_after.",
10587
+ "description": "Запустить рассылку «Первое сообщение» (мы пишем первыми тем, кому НАШЕГО исходящего ещё не было; человек, написавший школе и оставшийся без ответа, — законный адресат, исключать его не надо). НЕОБРАТИМО: у GetCourse нет идемпотентности, отправку нельзя отозвать. Всегда сначала preview и подтверждение пользователя. Аудитория: по дате (created_after) или по файлу (contacts). Поля сделки штампуются после отправки. Если у рассылки заданы тексты по сегментам, значение segment ВЫБИРАЕТ текст: назови пользователю выбранный текст ДО подтверждения и не запускай посегментный текст по created_after. Фоновый job проверяй через besales_getcourse_contact_import_status.",
9799
10588
  "inputSchema": {
9800
10589
  "type": "object",
9801
10590
  "required": [
@@ -9839,7 +10628,8 @@
9839
10628
  },
9840
10629
  "funnel": {
9841
10630
  "type": "string",
9842
- "maxLength": 200
10631
+ "maxLength": 200,
10632
+ "description": "Воронка ШКОЛЫ в форме «f11 — ДБО / NR / ВК / In Stream» — код fNN ОБЯЗАТЕЛЕН. ⚠️ Это НЕ когорта и НЕ подпись запуска: «reg-no-show», «post-web|дбо», «svs-zapusk» сюда класть нельзя — тип отбора идёт в segment, продукт в product_code, подпись запуска в cohort_label. Ось «Воронка» сравнивается по коду, поэтому значение без кода становится отдельной «воронкой» и засоряет фильтр аналитики. Файл из НЕСКОЛЬКИХ воронок — заполняй воронку построчно в contacts[].funnel."
9843
10633
  },
9844
10634
  "cohort_label": {
9845
10635
  "type": "string",
@@ -9877,6 +10667,12 @@
9877
10667
  "type": "string",
9878
10668
  "format": "date-time",
9879
10669
  "description": "Точный момент входа контакта в когорту (ISO с зоной). На нём считается свежесть в «Аналитике рассылок». Заполняй, когда предсписок собран ПРАВИЛОМ и у строки есть свой момент события. Дату запуска подставлять нельзя — она схлопнула бы месяцы когорт в одну."
10670
+ },
10671
+ "funnel": {
10672
+ "type": "string",
10673
+ "minLength": 1,
10674
+ "maxLength": 200,
10675
+ "description": "Воронка ЭТОГО контакта (например «f11 — ДБО / NR / ВК / In Stream»). Заполняй, когда файл собран из НЕСКОЛЬКИХ воронок: одна метка на запуск заставляет писать в поле воронки когорту («reg-no-show|дбо»), и фильтр по воронке перестаёт отвечать на свой вопрос. Не передан — берётся воронка запуска."
9880
10676
  }
9881
10677
  }
9882
10678
  }
@@ -9977,7 +10773,8 @@
9977
10773
  },
9978
10774
  "funnel": {
9979
10775
  "type": "string",
9980
- "maxLength": 200
10776
+ "maxLength": 200,
10777
+ "description": "Воронка ШКОЛЫ в форме «f11 — ДБО / NR / ВК / In Stream» — код fNN ОБЯЗАТЕЛЕН. ⚠️ Это НЕ когорта и НЕ подпись запуска: «reg-no-show», «post-web|дбо», «svs-zapusk» сюда класть нельзя — тип отбора идёт в segment, продукт в product_code, подпись запуска в cohort_label. Ось «Воронка» сравнивается по коду, поэтому значение без кода становится отдельной «воронкой» и засоряет фильтр аналитики."
9981
10778
  },
9982
10779
  "cohort_label": {
9983
10780
  "type": "string",
@@ -10052,13 +10849,47 @@
10052
10849
  "ADD"
10053
10850
  ],
10054
10851
  "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
10852
+ },
10853
+ "guards": {
10854
+ "type": "object",
10855
+ "additionalProperties": false,
10856
+ "description": "Перекрытие предохранителей на ЭТОТ пакет — аварийный обход одной отправки. Не передано — берутся настройки площадки. Значение сохраняется в план пакета, поэтому resume после рестарта доедет с тем же решением. Постоянное ослабление делается в besales_platform_settings_update, где его видно всей команде.",
10857
+ "properties": {
10858
+ "active_series": {
10859
+ "type": "string",
10860
+ "enum": [
10861
+ "OFF",
10862
+ "WARN",
10863
+ "BLOCK"
10864
+ ],
10865
+ "description": "Не писать, пока у человека идёт вебинарная серия. По умолчанию BLOCK: до внедрения правило уже блокировало внешними скриптами, и WARN снял бы действующую защиту."
10866
+ },
10867
+ "active_application": {
10868
+ "type": "string",
10869
+ "enum": [
10870
+ "OFF",
10871
+ "WARN",
10872
+ "BLOCK"
10873
+ ],
10874
+ "description": "Не писать при действующей (не отменённой) заявке — с человеком работает менеджер. По умолчанию WARN."
10875
+ },
10876
+ "paid": {
10877
+ "type": "string",
10878
+ "enum": [
10879
+ "OFF",
10880
+ "WARN",
10881
+ "BLOCK"
10882
+ ],
10883
+ "description": "Не писать оплатившему ЭТОТ продукт. Скоуп по продукту, а не «платил хоть раз». По умолчанию WARN."
10884
+ }
10885
+ }
10055
10886
  }
10056
10887
  }
10057
10888
  }
10058
10889
  },
10059
10890
  {
10060
10891
  "name": "besales_getcourse_cold_welcome_batch_status",
10061
- "description": "Состояние пакета: агрегат state и разбивка segments[] со своим статусом, importJobId и причиной отказа у каждого. stalled=true — драйвер оборвался, остаток пакета надо запустить заново.",
10892
+ "description": "Состояние пакета: агрегат state и разбивка segments[] со своим статусом, importJobId и причиной отказа у каждого. completedAt — момент закрытия ВСЕХ сегментов (null, пока пакет идёт). summary — план, доказанные доставки (реестр рассылок) и разбивка исходов; segmentsWithoutOutcomes>0 значит, что у стольких сегментов прогон оборвался, не записав итог, и их исходы в разбивку не вошли. stalled=true — драйвер оборвался: зови besales_getcourse_cold_welcome_batch_resume, а не запускай пакет заново. Опрашивать в цикле не нужно: о завершении и об обрыве платформа докладывает в чат уведомлений воркспейса.",
10062
10893
  "inputSchema": {
10063
10894
  "type": "object",
10064
10895
  "required": [
@@ -10152,7 +10983,7 @@
10152
10983
  },
10153
10984
  {
10154
10985
  "name": "besales_getcourse_contacts_import",
10155
- "description": "Импорт контактов GetCourse СПИСКОМ (без файла): заводит или обновляет их в базе платформы, чтобы по ним можно было запускать «Нашу отправку». НИЧЕГО НЕ ОТПРАВЛЯЕТ. Нужен ровно тогда, когда preview показал notInBase > 0: отправке нужен ChatUser, иначе контакт получает исход SKIPPED_NOT_IN_BASE. Матчинг существующих — по contact_id. Идёт фоном, вернётся jobId. Гейт «один активный импорт на воркспейс» общий с волнами и пакетами: 409 = идёт другой импорт, а не сбой. Максимум 5000 контактов. Scope: launch:campaigns.",
10986
+ "description": "Импорт контактов GetCourse СПИСКОМ (без файла): заводит или обновляет их в базе платформы, чтобы по ним можно было запускать «Нашу отправку». НИЧЕГО НЕ ОТПРАВЛЯЕТ. Нужен ровно тогда, когда preview показал notInBase > 0: отправке нужен ChatUser, иначе контакт получает исход SKIPPED_NOT_IN_BASE. Матчинг существующих — по contact_id. Идёт фоном, вернётся jobId; проверяй его через besales_getcourse_contact_import_status. Гейт «один активный импорт на воркспейс» общий с волнами и пакетами: 409 = идёт другой импорт, а не сбой. Максимум 5000 контактов. Scope: launch:campaigns.",
10156
10987
  "inputSchema": {
10157
10988
  "type": "object",
10158
10989
  "required": [
@@ -10230,6 +11061,29 @@
10230
11061
  }
10231
11062
  }
10232
11063
  },
11064
+ {
11065
+ "name": "besales_getcourse_contact_import_status",
11066
+ "description": "Статус фонового импорта контактов GetCourse и одиночного запуска «Первого сообщения» по jobId. Terminal states: COMPLETED, PARTIAL, FAILED; PARTIAL требует сверить successCount, failedCount и errors. Retained по правилам ImportJob. Scope: launch:campaigns.",
11067
+ "inputSchema": {
11068
+ "type": "object",
11069
+ "required": [
11070
+ "job_id"
11071
+ ],
11072
+ "additionalProperties": false,
11073
+ "properties": {
11074
+ "workspace_id": {
11075
+ "type": "string",
11076
+ "format": "uuid",
11077
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
11078
+ },
11079
+ "job_id": {
11080
+ "type": "string",
11081
+ "format": "uuid",
11082
+ "description": "jobId из besales_getcourse_contacts_import или besales_getcourse_cold_welcome_start."
11083
+ }
11084
+ }
11085
+ }
11086
+ },
10233
11087
  {
10234
11088
  "name": "besales_getcourse_anchor_refresh_preview",
10235
11089
  "description": "Что перепишет перечитывание календарных якорей (даты эфира) — БЕЗ обращений к школе: сколько контактов в отборе, скольким откажет отсутствие пина сделки и какие значения они несут сейчас.",
@@ -10286,7 +11140,7 @@
10286
11140
  },
10287
11141
  {
10288
11142
  "name": "besales_getcourse_anchor_refresh_start",
10289
- "description": "Перечитать календарные якоря контактов из ЗАПИНЁННОЙ сделки GetCourse. Единственный способ донести ПЕРЕНЕСЁННУЮ дату эфира: автоматический добор — set-if-absent и к заполненному значению не возвращается. Прогресс цепочек НЕ откатывается.",
11143
+ "description": "Перечитать календарные якоря контактов из ЗАПИНЁННОЙ сделки GetCourse. Единственный способ донести ПЕРЕНЕСЁННУЮ дату эфира: автоматический добор — set-if-absent и к заполненному значению не возвращается. Прогресс цепочек НЕ откатывается. Фоновый correlationId проверяй через besales_getcourse_anchor_refresh_status.",
10290
11144
  "inputSchema": {
10291
11145
  "type": "object",
10292
11146
  "required": [
@@ -10344,6 +11198,29 @@
10344
11198
  }
10345
11199
  }
10346
11200
  },
11201
+ {
11202
+ "name": "besales_getcourse_anchor_refresh_status",
11203
+ "description": "Статус фонового перечитывания календарных якорей по correlationId. Terminal states: COMPLETED, FAILED, STALLED. STALLED означает потерю lock без terminal status: часть дат могла быть переписана, поэтому перед повтором нужен аудит. Retained 24 часа. Отмены нет: частичные перезаписи необратимы. Scope: read:campaigns.",
11204
+ "inputSchema": {
11205
+ "type": "object",
11206
+ "required": [
11207
+ "correlation_id"
11208
+ ],
11209
+ "additionalProperties": false,
11210
+ "properties": {
11211
+ "workspace_id": {
11212
+ "type": "string",
11213
+ "format": "uuid",
11214
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
11215
+ },
11216
+ "correlation_id": {
11217
+ "type": "string",
11218
+ "pattern": "^anchor-refresh:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$",
11219
+ "description": "correlationId из besales_getcourse_anchor_refresh_start."
11220
+ }
11221
+ }
11222
+ }
11223
+ },
10347
11224
  {
10348
11225
  "name": "besales_broadcast_launches_list",
10349
11226
  "description": "История запусков рассылок одним списком: наша отправка (cold_welcome, со снимком текста и разбивкой исходов) и волны по файлу (wave).",
@@ -10365,6 +11242,11 @@
10365
11242
  "type": "integer",
10366
11243
  "minimum": 1,
10367
11244
  "maximum": 50
11245
+ },
11246
+ "schedule_id": {
11247
+ "type": "string",
11248
+ "format": "uuid",
11249
+ "description": "Только прогоны этого расписания. Ручные отправки и волны при этом не возвращаются вовсе: расписанием они не запускались."
10368
11250
  }
10369
11251
  }
10370
11252
  }
@@ -10404,7 +11286,7 @@
10404
11286
  },
10405
11287
  "cursor": {
10406
11288
  "type": "string",
10407
- "description": "nextCursor предыдущей страницы."
11289
+ "description": "ID последнего показанного прогона (UUID из nextCursor предыдущего ответа). Курсор, а не offset."
10408
11290
  },
10409
11291
  "limit": {
10410
11292
  "type": "integer",
@@ -10455,11 +11337,28 @@
10455
11337
  },
10456
11338
  "category": {
10457
11339
  "type": "string",
10458
- "description": "Категория находки."
11340
+ "enum": [
11341
+ "HALLUCINATION",
11342
+ "WRONG_ACTION",
11343
+ "WRONG_ROUTING",
11344
+ "BAD_TONE",
11345
+ "MISSED_CONTEXT",
11346
+ "RAG_MISS",
11347
+ "SCRIPT_DEVIATION",
11348
+ "PROMPT_VIOLATION",
11349
+ "CUSTOM_RULE_CONFLICT",
11350
+ "OTHER"
11351
+ ],
11352
+ "description": "Категория находки. Закрытый набор бэкенда: чужое значение отвергается с 400."
10459
11353
  },
10460
11354
  "severity": {
10461
11355
  "type": "string",
10462
- "description": "Важность находки."
11356
+ "enum": [
11357
+ "LOW",
11358
+ "MEDIUM",
11359
+ "CRITICAL"
11360
+ ],
11361
+ "description": "Важность находки. Значений ТРИ, «HIGH» среди них нет."
10463
11362
  },
10464
11363
  "status": {
10465
11364
  "type": "string",
@@ -10475,7 +11374,7 @@
10475
11374
  },
10476
11375
  {
10477
11376
  "name": "besales_dialogue_audit_run_start",
10478
- "description": "Запустить разбор сейчас. Durable: ответ приходит сразу с runId, работа идёт в очереди. Уже разобранное заново не оплачивается. 409 — на канале уже идёт прогон. Scope: mcp:platform-setup.",
11377
+ "description": "Запустить разбор сейчас. Durable: ответ приходит сразу с runId, работа идёт в очереди; проверяй через besales_dialogue_audit_run_get. Уже разобранное заново не оплачивается. 409 — на канале уже идёт прогон. Scope: mcp:platform-setup.",
10479
11378
  "inputSchema": {
10480
11379
  "type": "object",
10481
11380
  "required": [
@@ -10665,7 +11564,7 @@
10665
11564
  },
10666
11565
  {
10667
11566
  "name": "besales_tracked_link_list",
10668
- "description": "Каталог коротких трекинговых ссылок workspace со сводкой «выдано → клики → ответы → заявки → оплаты». Поле placeholder — готовый токен {{link:slug}} для текстов дожимов, рассылок и шаблонов: вставляется ИМЕННО он, сырой URL мимо трекинга не считается. staticUrl — анонимный короткий адрес для мест без персональной выдачи (промпт агента, письмо школы). Ответ постраничный; hasMore=true означает, что каталог не дочитан. Scope: read:analytics. ⚠️ Токен берётся ТОЛЬКО копированием поля placeholder: собранный вручную токен с неточным слагом вырезается вместе с маркером, и клиент получает фразу без ссылки. В промпт агента токен не кладут — там staticUrl.",
11567
+ "description": "Каталог коротких трекинговых ссылок workspace со сводкой «выдано → клики → ответы → заявки → оплаты». Поле placeholder — готовый токен {{link:slug}} для текстов дожимов, рассылок и шаблонов: вставляется ИМЕННО он, сырой URL мимо трекинга не считается. staticUrl — анонимный короткий адрес для мест без персональной выдачи (промпт агента, письмо школы). Ответ постраничный; hasMore=true означает, что каталог не дочитан. Scope: read:analytics. ⚠️ Токен берётся ТОЛЬКО копированием поля placeholder: собранный вручную токен с неточным слагом вырезается вместе с маркером, и клиент получает фразу без ссылки. В промпт агента токен не кладут — там staticUrl. ⚠️ days НЕ ЗАДАН — сводка за ВСЁ ВРЕМЯ (прежде подставлялось окно 60 дней, и оно расходилось само с собой: выданное раньше него показывалось как «выдано 0», тогда как выручка в той же строке считалась за всё время). Нужно окно — назови его явно.",
10669
11568
  "inputSchema": {
10670
11569
  "type": "object",
10671
11570
  "required": [],
@@ -10816,7 +11715,36 @@
10816
11715
  },
10817
11716
  {
10818
11717
  "name": "besales_tracked_link_breakdown",
10819
- "description": "Разрез одной ссылки по источникам выдачи: WAVE (волна), FOLLOWUP (дожим), CAMPAIGN (кампания), GREETING (приветствие), AGENT (обычный ответ агента) — с воронкой по каждому. Отвечает на вопрос «после чего по ссылке ходят», а не «каким сообщением она ушла». Оплата атрибутируется last-touch по ближайшему клику. Scope: read:analytics.",
11718
+ "description": "Разрез одной ссылки по источникам выдачи: WAVE (волна), FOLLOWUP (дожим), CAMPAIGN (кампания), GREETING (приветствие), AGENT (обычный ответ агента) — с воронкой по каждому. Отвечает на вопрос «после чего по ссылке ходят», а не «каким сообщением она ушла». Оплата атрибутируется last-touch по ближайшему клику. Scope: read:analytics. ⚠️ days НЕ ЗАДАН — сводка за ВСЁ ВРЕМЯ (прежде подставлялось окно 60 дней, и оно расходилось само с собой: выданное раньше него показывалось как «выдано 0», тогда как выручка в той же строке считалась за всё время). Нужно окно — назови его явно.",
11719
+ "inputSchema": {
11720
+ "type": "object",
11721
+ "required": [
11722
+ "link_id"
11723
+ ],
11724
+ "additionalProperties": false,
11725
+ "properties": {
11726
+ "workspace_id": {
11727
+ "type": "string",
11728
+ "format": "uuid",
11729
+ "description": "Optional override. Normally omit — defaults to the workspace bound to this session."
11730
+ },
11731
+ "link_id": {
11732
+ "type": "string",
11733
+ "format": "uuid",
11734
+ "description": "UUID ссылки из каталога."
11735
+ },
11736
+ "days": {
11737
+ "type": "integer",
11738
+ "minimum": 1,
11739
+ "maximum": 366,
11740
+ "description": "Глубина сводки в днях (по умолчанию 60)."
11741
+ }
11742
+ }
11743
+ }
11744
+ },
11745
+ {
11746
+ "name": "besales_tracked_link_reach",
11747
+ "description": "Разрез одной ссылки по МЕСТУ применения: площадка и агент, через которых она уходила людям. Отвечает на «где ссылка работает», тогда как besales_tracked_link_breakdown — на «после какого касания по ней ходят». Оси независимые: одна выдача принадлежит ровно одной площадке и одному агенту. null в оси — «не определён», отдельная строка, а не ноль. Пустое имя при заполненном id значит, что площадку или агента удалили: id хранится снимком без внешнего ключа, чтобы история кликов пережила удаление. Scope: read:analytics.",
10820
11748
  "inputSchema": {
10821
11749
  "type": "object",
10822
11750
  "required": [
@@ -10845,7 +11773,7 @@
10845
11773
  },
10846
11774
  {
10847
11775
  "name": "besales_tracked_link_clicks",
10848
- "description": "Лента переходов по ссылке: контакт, сообщение, источник выдачи и время. Клики-предпросмотры мессенджеров отсеяны. ⚠️ Анонимные переходы по staticUrl В ЛЕНТЕ ЕСТЬ — строками с null в chatUserId/contactName/messageId/issuedAt/sourceKind (у анонимного кода человека нет по построению); не считай их людьми, их суммарное число лежит в каталоге полем anonymousClicks. ⚠️ total — число КЛИКОВ (включая повторные и анонимные), а clicked в каталоге — число ВЫДАЧ с первым живым кликом: величины разные и сходиться не обязаны. Постранично: page + page_size (максимум 200). Scope: read:analytics + read:conversations (лента несёт имя контакта и id сообщения; композитный mcp:* покрывает оба).",
11776
+ "description": "Лента переходов по ссылке: контакт, сообщение, источник выдачи и время. Клики-предпросмотры мессенджеров отсеяны. ⚠️ Анонимные переходы по staticUrl В ЛЕНТЕ ЕСТЬ — строками с null в chatUserId/contactName/messageId/issuedAt/sourceKind (у анонимного кода человека нет по построению); не считай их людьми, их суммарное число лежит в каталоге полем anonymousClicks. ⚠️ total — число КЛИКОВ (включая повторные и анонимные), а clicked в каталоге — число ВЫДАЧ с первым живым кликом: величины разные и сходиться не обязаны. Постранично: page + page_size (максимум 200). Scope: read:analytics + read:conversations (лента несёт имя контакта и id сообщения; композитный mcp:* покрывает оба). ⚠️ days НЕ ЗАДАН — сводка за ВСЁ ВРЕМЯ (прежде подставлялось окно 60 дней, и оно расходилось само с собой: выданное раньше него показывалось как «выдано 0», тогда как выручка в той же строке считалась за всё время). Нужно окно — назови его явно.",
10849
11777
  "inputSchema": {
10850
11778
  "type": "object",
10851
11779
  "required": [
@@ -11006,7 +11934,7 @@
11006
11934
  "type": "integer",
11007
11935
  "minimum": 1,
11008
11936
  "maximum": 78,
11009
- "description": "Окно свежести: берём вошедших в сегмент за последние N дней"
11937
+ "description": "Окно свежести при window_mode=ROLLING: вошедшие в сегмент за последние N дней. При FIXED не читается"
11010
11938
  },
11011
11939
  "time_local": {
11012
11940
  "type": "string",
@@ -11023,6 +11951,16 @@
11023
11951
  "maxItems": 7,
11024
11952
  "description": "Дни недели ISO (1 = понедельник). Пусто = каждый день"
11025
11953
  },
11954
+ "days_of_month": {
11955
+ "type": "array",
11956
+ "items": {
11957
+ "type": "integer",
11958
+ "minimum": 1,
11959
+ "maximum": 31
11960
+ },
11961
+ "maxItems": 31,
11962
+ "description": "Числа месяца 1–31. Пусто = не по числам месяца. Взаимоисключимо с days_of_week: вместе они означают «31-е И понедельник». Число больше длины месяца попадает на ПОСЛЕДНИЙ его день, иначе «31-е» пропускало бы февраль целиком."
11963
+ },
11026
11964
  "daily_cap": {
11027
11965
  "type": "integer",
11028
11966
  "minimum": 1,
@@ -11074,6 +12012,24 @@
11074
12012
  "ADD"
11075
12013
  ],
11076
12014
  "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
12015
+ },
12016
+ "window_mode": {
12017
+ "type": "string",
12018
+ "enum": [
12019
+ "ROLLING",
12020
+ "FIXED"
12021
+ ],
12022
+ "description": "ROLLING (правый край окна — «сейчас», по умолчанию) или FIXED (явная пара дат)"
12023
+ },
12024
+ "window_from_local": {
12025
+ "type": "string",
12026
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12027
+ "description": "Начало окна при FIXED — ЛОКАЛЬНАЯ дата площадки ГГГГ-ММ-ДД (не момент: момент сдвинул бы границу на смещение зоны)"
12028
+ },
12029
+ "window_to_local": {
12030
+ "type": "string",
12031
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12032
+ "description": "Конец окна при FIXED, ВКЛЮЧИТЕЛЬНО: «по 20 августа» берёт весь двадцатый день"
11077
12033
  }
11078
12034
  },
11079
12035
  "required": [
@@ -11158,7 +12114,7 @@
11158
12114
  "type": "integer",
11159
12115
  "minimum": 1,
11160
12116
  "maximum": 78,
11161
- "description": "Окно свежести: берём вошедших в сегмент за последние N дней"
12117
+ "description": "Окно свежести при window_mode=ROLLING: вошедшие в сегмент за последние N дней. При FIXED не читается"
11162
12118
  },
11163
12119
  "time_local": {
11164
12120
  "type": "string",
@@ -11175,6 +12131,16 @@
11175
12131
  "maxItems": 7,
11176
12132
  "description": "Дни недели ISO (1 = понедельник). Пусто = каждый день"
11177
12133
  },
12134
+ "days_of_month": {
12135
+ "type": "array",
12136
+ "items": {
12137
+ "type": "integer",
12138
+ "minimum": 1,
12139
+ "maximum": 31
12140
+ },
12141
+ "maxItems": 31,
12142
+ "description": "Числа месяца 1–31. Пусто = не по числам месяца. Взаимоисключимо с days_of_week: вместе они означают «31-е И понедельник». Число больше длины месяца попадает на ПОСЛЕДНИЙ его день, иначе «31-е» пропускало бы февраль целиком."
12143
+ },
11178
12144
  "daily_cap": {
11179
12145
  "type": "integer",
11180
12146
  "minimum": 1,
@@ -11230,6 +12196,24 @@
11230
12196
  "ADD"
11231
12197
  ],
11232
12198
  "description": "⚠️ УСТАРЕЛО и на поведение НЕ влияет (с 23.08.2026). Список channels значит «слать сюда», а судьбу КАЖДОГО канала решает сервер: мессенджер (Telegram/VK/MAX) уходит, только если школа подтвердила его наличие у контакта; SMS — только при известном телефоне; Email, WhatsApp, Viber, Сайт, Chatium уходят вслепую всем выбранным. Просят «написать ещё и на почту» — добавь Email в channels и перечисли мессенджеры явно, иначе уедет только письмо. Поле принимается ради обратной совместимости и игнорируется."
12199
+ },
12200
+ "window_mode": {
12201
+ "type": "string",
12202
+ "enum": [
12203
+ "ROLLING",
12204
+ "FIXED"
12205
+ ],
12206
+ "description": "ROLLING (правый край окна — «сейчас», по умолчанию) или FIXED (явная пара дат)"
12207
+ },
12208
+ "window_from_local": {
12209
+ "type": "string",
12210
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12211
+ "description": "Начало окна при FIXED — ЛОКАЛЬНАЯ дата площадки ГГГГ-ММ-ДД (не момент: момент сдвинул бы границу на смещение зоны)"
12212
+ },
12213
+ "window_to_local": {
12214
+ "type": "string",
12215
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12216
+ "description": "Конец окна при FIXED, ВКЛЮЧИТЕЛЬНО: «по 20 августа» берёт весь двадцатый день"
11233
12217
  }
11234
12218
  },
11235
12219
  "required": [
@@ -11299,6 +12283,36 @@
11299
12283
  ]
11300
12284
  }
11301
12285
  },
12286
+ {
12287
+ "name": "besales_broadcast_schedule_pool_snapshots",
12288
+ "description": "Суточные снимки пула отбора по всем расписаниям воркспейса. Scope: read:campaigns. Строка на «расписание × локальный день площадки», включая дни без запуска и выключенные расписания. Три состояния РАЗНЫЕ: строки нет — не считали; status=FAILED — считали и не смогли (poolSize/selectedCount = null, причина в error); truncated — снимок упёрся в бюджет строк источника, показано начало окна, а не окно. Читается мгновенно, в отличие от besales_broadcast_schedule_preview.",
12289
+ "inputSchema": {
12290
+ "type": "object",
12291
+ "properties": {
12292
+ "workspace_id": {
12293
+ "type": "string",
12294
+ "description": "UUID воркспейса. Подставляется MCP-сервером из подключения — спрашивать у пользователя не нужно."
12295
+ },
12296
+ "from": {
12297
+ "type": "string",
12298
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12299
+ "description": "Начало периода включительно: локальный день ПЛОЩАДКИ в формате ГГГГ-ММ-ДД. Проверяется форма; существование даты сверяет сервер."
12300
+ },
12301
+ "to": {
12302
+ "type": "string",
12303
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
12304
+ "description": "Конец периода включительно: локальный день ПЛОЩАДКИ в формате ГГГГ-ММ-ДД."
12305
+ },
12306
+ "limit": {
12307
+ "type": "integer",
12308
+ "minimum": 1,
12309
+ "maximum": 2000,
12310
+ "description": "Сколько строк вернуть, считая от самого свежего дня. По умолчанию 2000. Ответ печатается целиком, поэтому у полного периода это мегабайты текста — спрашивай окно, которое читаешь."
12311
+ }
12312
+ },
12313
+ "required": []
12314
+ }
12315
+ },
11302
12316
  {
11303
12317
  "name": "besales_broadcast_segment_rule_set",
11304
12318
  "description": "Задать правило отбора сегмента: фасеты поведения, якорь свежести, окно ожидания и приоритет. Scope: launch:campaigns. ⚠️⚠️ 409 означает, что сегментом уже отправляли и правило заморожено — заведи НОВЫЙ сегмент, правка задним числом сделала бы разрез отчёта несопоставимым. Секунды, а не минуты: «от 120 минут» — это activeSecondsMin=7200.",
@@ -11372,6 +12386,42 @@
11372
12386
  "ANY"
11373
12387
  ],
11374
12388
  "description": "NOT_ANYWHERE исключает всех, кто когда-либо успешно платил (включая возврат)"
12389
+ },
12390
+ "prelist": {
12391
+ "type": "string",
12392
+ "enum": [
12393
+ "YES",
12394
+ "NO",
12395
+ "ANY"
12396
+ ],
12397
+ "description": "Предсписок: оформил заказ предсписка. Применимость и метки заказа объявляет ВОРОНКА в источнике фактов; если правило у воронки не задано или данные не готовы, строки приходят непроверяемыми и никому ничего не уйдёт"
12398
+ },
12399
+ "previousSegment": {
12400
+ "type": "object",
12401
+ "additionalProperties": false,
12402
+ "properties": {
12403
+ "key": {
12404
+ "type": "string",
12405
+ "minLength": 1,
12406
+ "maxLength": 64,
12407
+ "description": "Имя сегмента ПРЕДЫДУЩЕГО касания"
12408
+ },
12409
+ "minDaysSince": {
12410
+ "type": "integer",
12411
+ "minimum": 30,
12412
+ "maximum": 78,
12413
+ "description": "Сколько суток должно пройти с прошлого касания (минимум 30 — граница владельца)"
12414
+ }
12415
+ },
12416
+ "required": [
12417
+ "key",
12418
+ "minDaysSince"
12419
+ ],
12420
+ "description": "ПОВТОРНОЕ касание: сегмент уходит тем, у кого названный сегмент был ПОСЛЕДНИМ нашим касанием и кто нам не ответил. Снимает вечный одноразовый claim приветствия — единственную защиту от второго сообщения живому человеку"
12421
+ },
12422
+ "untouchedOnly": {
12423
+ "type": "boolean",
12424
+ "description": "Право первого касания: сегмент уходит только тем, кому мы ещё НИКОГДА не писали. Молчание значит true — сегодняшнее поведение платформы. Ставьте false осознанно: это разрешает второе первое сообщение человеку, уже получившему холодное приветствие."
11375
12425
  }
11376
12426
  },
11377
12427
  "required": [
@@ -11385,7 +12435,8 @@
11385
12435
  "SERIES_END",
11386
12436
  "SERIES_END_PLUS_WAIT",
11387
12437
  "LAST_APPLICATION",
11388
- "REGISTRATION"
12438
+ "REGISTRATION",
12439
+ "PRELIST"
11389
12440
  ],
11390
12441
  "description": "Откуда берётся момент входа контакта в сегмент"
11391
12442
  },
@@ -11393,7 +12444,7 @@
11393
12444
  "type": "integer",
11394
12445
  "minimum": 0,
11395
12446
  "maximum": 720,
11396
- "description": "Сколько ждать после эфира до признания «не пришёл». Разумный дефолт 48"
12447
+ "description": "Сколько ждать после эфира до признания «не пришёл». Дефолт 1 час: касание свежее, но явка к этому моменту досчитана у меньшинства (6 ч → 56 %, 24 ч → 74 %, 48 ч → 81 %), а недосчитанный контакт в отбор не попадает. При коротком ожидании ставьте freshness_days от 3: при 1 человека смотрят ровно один раз"
11397
12448
  },
11398
12449
  "priority": {
11399
12450
  "type": "integer",
@@ -11408,6 +12459,265 @@
11408
12459
  "freshness_anchor"
11409
12460
  ]
11410
12461
  }
12462
+ },
12463
+ {
12464
+ "name": "besales_trigger_claim_list",
12465
+ "description": "Read-only список одноразовых триггеров (runOncePerContact), уже сработавших на контакте. Право сжигается навсегда после первого срабатывания. Scope: mcp:platform-setup.",
12466
+ "inputSchema": {
12467
+ "type": "object",
12468
+ "required": [
12469
+ "chat_user_id"
12470
+ ],
12471
+ "additionalProperties": false,
12472
+ "properties": {
12473
+ "chat_user_id": {
12474
+ "type": "string",
12475
+ "format": "uuid",
12476
+ "description": "Контакт (ChatUser). Единица права — канал, а не человек."
12477
+ }
12478
+ }
12479
+ }
12480
+ },
12481
+ {
12482
+ "name": "besales_trigger_claim_reset",
12483
+ "description": "Возвращает контакту право на повторное срабатывание одноразового триггера. Триггер сможет повторить необратимые действия (запись в CRM, передача оператору), поэтому требуется explicit_confirmation. Scope: mcp:platform-setup.",
12484
+ "inputSchema": {
12485
+ "type": "object",
12486
+ "required": [
12487
+ "chat_user_id",
12488
+ "trigger_id",
12489
+ "explicit_confirmation"
12490
+ ],
12491
+ "additionalProperties": false,
12492
+ "properties": {
12493
+ "chat_user_id": {
12494
+ "type": "string",
12495
+ "format": "uuid",
12496
+ "description": "Контакт (ChatUser), которому возвращается право."
12497
+ },
12498
+ "trigger_id": {
12499
+ "type": "string",
12500
+ "format": "uuid",
12501
+ "description": "Одноразовый триггер, право на который снимается."
12502
+ },
12503
+ "explicit_confirmation": {
12504
+ "type": "boolean",
12505
+ "enum": [
12506
+ true
12507
+ ],
12508
+ "description": "Обязательное подтверждение оператора: триггер сможет повторить необратимые действия во внешних системах. Проверяется и на сервере."
12509
+ }
12510
+ }
12511
+ }
12512
+ },
12513
+ {
12514
+ "name": "besales_inbound_analytics_get",
12515
+ "description": "Входящая аналитика: органические диалоги, темы, скорость ответа, деньги, цикл сделки и качество данных. Не заменяется исходящей аналитикой рассылок. Scope: read:analytics.",
12516
+ "inputSchema": {
12517
+ "type": "object",
12518
+ "required": ["report"],
12519
+ "additionalProperties": false,
12520
+ "properties": {
12521
+ "workspace_id": { "type": "string", "format": "uuid" },
12522
+ "report": { "type": "string", "enum": ["summary", "topics", "speed", "money", "cycle", "quality"] },
12523
+ "platform_id": { "type": "string", "format": "uuid" },
12524
+ "channels": { "type": "array", "items": { "type": "string", "minLength": 1 }, "minItems": 1, "maxItems": 20 },
12525
+ "mode": { "type": "string", "enum": ["all", "days", "range"], "default": "days" },
12526
+ "days": { "type": "integer", "minimum": 1 },
12527
+ "from": { "type": "string", "format": "date-time" },
12528
+ "to": { "type": "string", "format": "date-time" }
12529
+ }
12530
+ }
12531
+ },
12532
+ {
12533
+ "name": "besales_funnel_analytics_get",
12534
+ "description": "Аналитика воронки площадки: meta принимает только platform_id/workspace_id; summary/cohorts требуют from/to; view доступен только summary, cohorts всегда считает cohort. manager_id доступен summary/cohorts. Scope: read:analytics.",
12535
+ "inputSchema": {
12536
+ "type": "object",
12537
+ "required": ["report", "platform_id"],
12538
+ "additionalProperties": false,
12539
+ "properties": {
12540
+ "workspace_id": { "type": "string", "format": "uuid" },
12541
+ "report": { "type": "string", "enum": ["meta", "summary", "cohorts"] },
12542
+ "platform_id": { "type": "string", "format": "uuid" },
12543
+ "from": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
12544
+ "to": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
12545
+ "view": { "type": "string", "enum": ["cohort", "period"] },
12546
+ "manager_id": { "type": "integer" }
12547
+ }
12548
+ }
12549
+ },
12550
+ {
12551
+ "name": "besales_ai_costs_get",
12552
+ "description": "Фактические AI-затраты из immutable usage ledger: summary, tasks и breakdown. group_by/page/limit доступны только breakdown; для него group_by обязателен. unpricedEvents остаются неизвестной стоимостью, а не нулём. Scope: read:analytics.",
12553
+ "inputSchema": {
12554
+ "type": "object",
12555
+ "required": ["report"],
12556
+ "additionalProperties": false,
12557
+ "properties": {
12558
+ "workspace_id": { "type": "string", "format": "uuid" },
12559
+ "report": { "type": "string", "enum": ["summary", "tasks", "breakdown"] },
12560
+ "mode": { "type": "string", "enum": ["all", "days", "range"], "default": "all" },
12561
+ "days": { "type": "integer", "minimum": 1 },
12562
+ "from": { "type": "string", "format": "date-time" },
12563
+ "to": { "type": "string", "format": "date-time" },
12564
+ "scope": { "type": "string", "enum": ["production", "with_tests"], "default": "production" },
12565
+ "group_by": { "type": "string", "enum": ["customer", "platform", "tag", "operation", "provider"] },
12566
+ "page": { "type": "integer", "minimum": 1 },
12567
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100 }
12568
+ }
12569
+ }
12570
+ },
12571
+ {
12572
+ "name": "besales_custom_report_list",
12573
+ "description": "Список сохранённых кастомных аналитических таблиц воркспейса без архивных. Scope: read:analytics.",
12574
+ "inputSchema": {
12575
+ "type": "object",
12576
+ "additionalProperties": false,
12577
+ "properties": { "workspace_id": { "type": "string", "format": "uuid" } }
12578
+ }
12579
+ },
12580
+ {
12581
+ "name": "besales_custom_report_get",
12582
+ "description": "Получить определение кастомного отчёта: источник, view, фильтры, оси, метрики и updatedAt. Scope: read:analytics.",
12583
+ "inputSchema": {
12584
+ "type": "object",
12585
+ "required": ["report_id"],
12586
+ "additionalProperties": false,
12587
+ "properties": {
12588
+ "workspace_id": { "type": "string", "format": "uuid" },
12589
+ "report_id": { "type": "string", "format": "uuid" }
12590
+ }
12591
+ }
12592
+ },
12593
+ {
12594
+ "name": "besales_custom_report_run",
12595
+ "description": "Рассчитать сохранённый кастомный отчёт за период с его каноническими source/view/grain. Scope: read:analytics.",
12596
+ "inputSchema": {
12597
+ "type": "object",
12598
+ "required": ["report_id", "from", "to"],
12599
+ "additionalProperties": false,
12600
+ "properties": {
12601
+ "workspace_id": { "type": "string", "format": "uuid" },
12602
+ "report_id": { "type": "string", "format": "uuid" },
12603
+ "from": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
12604
+ "to": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
12605
+ "granularity": { "type": "string", "enum": ["day", "week", "month", "total"] }
12606
+ }
12607
+ }
12608
+ },
12609
+ {
12610
+ "name": "besales_workspace_operational_overview",
12611
+ "description": "Эксплуатационная сводка: цепочки, расписания, ожидаемые и фактические запуски, durable jobs, ошибки действий и доступная очередь операторов. Scope: read:analytics; строки очереди требуют read:conversations.",
12612
+ "inputSchema": {
12613
+ "type": "object",
12614
+ "additionalProperties": false,
12615
+ "properties": {
12616
+ "workspace_id": { "type": "string", "format": "uuid" }
12617
+ }
12618
+ }
12619
+ },
12620
+ {
12621
+ "name": "besales_workspace_operator_list",
12622
+ "description": "Системные workspace operators Besales для фильтра и назначения. CRM operators не входят; assignable показывает текущую пригодность. Scope: read:conversations.",
12623
+ "inputSchema": {
12624
+ "type": "object",
12625
+ "additionalProperties": false,
12626
+ "properties": { "workspace_id": { "type": "string", "format": "uuid" } }
12627
+ }
12628
+ },
12629
+ {
12630
+ "name": "besales_workspace_operator_queue_list",
12631
+ "description": "Пагинированная очередь операторов с каноническим status, назначением и последним доказательством PlatformWorkLog. Scope: read:conversations.",
12632
+ "inputSchema": {
12633
+ "type": "object",
12634
+ "additionalProperties": false,
12635
+ "properties": {
12636
+ "workspace_id": { "type": "string", "format": "uuid" },
12637
+ "status": { "type": "string", "enum": ["WAITING_OPERATOR", "IN_PROGRESS", "WAITING_CUSTOMER", "RESOLVED"] },
12638
+ "workspace_operator_id": { "type": "string", "format": "uuid" },
12639
+ "contact_id": { "type": "string", "format": "uuid" },
12640
+ "page": { "type": "integer", "minimum": 1, "default": 1 },
12641
+ "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 20 }
12642
+ }
12643
+ }
12644
+ },
12645
+ {
12646
+ "name": "besales_workspace_operator_assignment_get",
12647
+ "description": "Текущее назначение workspace operator, operator status, CAS-версия assignedAt и workflow evidence конкретного чата. Scope: read:conversations.",
12648
+ "inputSchema": {
12649
+ "type": "object",
12650
+ "required": ["contact_id"],
12651
+ "additionalProperties": false,
12652
+ "properties": {
12653
+ "workspace_id": { "type": "string", "format": "uuid" },
12654
+ "contact_id": { "type": "string", "format": "uuid" }
12655
+ }
12656
+ }
12657
+ },
12658
+ {
12659
+ "name": "besales_workspace_operator_assignment_set",
12660
+ "description": "CAS-защищённо назначить, переназначить или снять workspace operator. Не меняет CRM, статус очереди и не отправляет сообщения. Требует explicit_confirmation и scope write:operators.",
12661
+ "inputSchema": {
12662
+ "type": "object",
12663
+ "required": ["contact_id", "workspace_operator_id", "expected_workspace_operator_id", "expected_assigned_operator_at", "explicit_confirmation"],
12664
+ "additionalProperties": false,
12665
+ "properties": {
12666
+ "workspace_id": { "type": "string", "format": "uuid" },
12667
+ "contact_id": { "type": "string", "format": "uuid" },
12668
+ "workspace_operator_id": { "type": ["string", "null"], "format": "uuid" },
12669
+ "expected_workspace_operator_id": { "type": ["string", "null"], "format": "uuid" },
12670
+ "expected_assigned_operator_at": { "type": ["string", "null"], "format": "date-time" },
12671
+ "explicit_confirmation": { "type": "boolean", "enum": [true] }
12672
+ }
12673
+ }
12674
+ },
12675
+ {
12676
+ "name": "besales_help_search",
12677
+ "description": "Найти актуальную справку Besales по обычному русскому или английскому описанию задачи. Возвращает URI и подходящие разделы; работает даже когда MCP resources не показаны модели хостом.",
12678
+ "inputSchema": {
12679
+ "type": "object",
12680
+ "required": ["query"],
12681
+ "properties": {
12682
+ "query": {
12683
+ "type": "string",
12684
+ "minLength": 2,
12685
+ "description": "Задача своими словами, например: настроить дожимы или бот молчит"
12686
+ },
12687
+ "limit": {
12688
+ "type": "integer",
12689
+ "minimum": 1,
12690
+ "maximum": 10,
12691
+ "default": 5
12692
+ }
12693
+ },
12694
+ "additionalProperties": false
12695
+ }
12696
+ },
12697
+ {
12698
+ "name": "besales_help_get",
12699
+ "description": "Прочитать индекс, один раздел или полную версию документа Besales из того же источника, что MCP resource. Сначала используй besales_help_search, если URI неизвестен.",
12700
+ "inputSchema": {
12701
+ "type": "object",
12702
+ "required": ["uri"],
12703
+ "properties": {
12704
+ "uri": {
12705
+ "type": "string",
12706
+ "pattern": "^besales://"
12707
+ },
12708
+ "section": {
12709
+ "type": "string",
12710
+ "minLength": 1,
12711
+ "description": "Точный или однозначный фрагмент заголовка раздела"
12712
+ },
12713
+ "full": {
12714
+ "type": "boolean",
12715
+ "default": false,
12716
+ "description": "Вернуть документ целиком; без section/full возвращается компактный индекс"
12717
+ }
12718
+ },
12719
+ "additionalProperties": false
12720
+ }
11411
12721
  }
11412
12722
  ],
11413
12723
  "resources": [
@@ -11596,54 +12906,63 @@
11596
12906
  "name": "Workflow: Compare models (model bake-off)",
11597
12907
  "description": "Маршрут прогона сравнения промпта на нескольких моделях: читай besales_model_catalog_list → выбери ~5 по bestFor под use-case агента → besales_model_comparison_run_start (по умолчанию 5 диалогов) → поллируй besales_model_comparison_get → суди по метрикам + диалогам → ответь оператору с аргументами и выдержками → besales_model_comparison_eval_submit. По запросу, дорого, НЕ после каждого фикса.",
11598
12908
  "mimeType": "text/markdown"
12909
+ },
12910
+ {
12911
+ "uri": "besales://docs/tools-catalog",
12912
+ "name": "Каталог инструментов",
12913
+ "description": "Динамический список фактически опубликованных tools по категориям с версией и точным количеством.",
12914
+ "mimeType": "text/markdown"
12915
+ },
12916
+ {
12917
+ "uri": "besales://docs/trigger-actions",
12918
+ "name": "Триггеры и действия",
12919
+ "description": "Чтение, конфигурация, полная замена и проверка trigger actions.",
12920
+ "mimeType": "text/markdown"
12921
+ },
12922
+ {
12923
+ "uri": "besales://docs/variables",
12924
+ "name": "Переменные",
12925
+ "description": "Workspace/channel variables и полные overrides агента.",
12926
+ "mimeType": "text/markdown"
12927
+ },
12928
+ {
12929
+ "uri": "besales://docs/routing",
12930
+ "name": "Маршрутизация агентов",
12931
+ "description": "Правила routing, router state и проверка multi-agent workflow.",
12932
+ "mimeType": "text/markdown"
12933
+ },
12934
+ {
12935
+ "uri": "besales://docs/follow-up",
12936
+ "name": "Follow-up и дожимы",
12937
+ "description": "Цепочки, статистика, реакции и безопасный funnel-test.",
12938
+ "mimeType": "text/markdown"
12939
+ },
12940
+ {
12941
+ "uri": "besales://docs/campaigns",
12942
+ "name": "Рассылки и кампании",
12943
+ "description": "Mailing variants, schedules, launches и каноническая аналитика рассылок.",
12944
+ "mimeType": "text/markdown"
12945
+ },
12946
+ {
12947
+ "uri": "besales://docs/task-state",
12948
+ "name": "Состояние длительной задачи",
12949
+ "description": "Как сохранить, выбрать, безопасно продолжить, закрыть или удалить длительную задачу между MCP-сессиями.",
12950
+ "mimeType": "text/markdown"
11599
12951
  }
11600
12952
  ],
11601
12953
  "summary": {
11602
- "total_tools": 209,
12954
+ "total_tools": 253,
11603
12955
  "tools_by_category": {
11604
- "getcourse_wave": 10,
11605
- "files_upload": 3,
11606
- "platform_provisioning": 3,
11607
- "crm_provisioning": 6,
11608
- "data_sources": 9,
11609
- "workspace_overview": 1,
11610
- "icp_management": 3,
11611
- "icp_external_execution": 2,
11612
- "icp_read": 4,
11613
- "test_scenario_generation_external": 2,
11614
- "prompt_generation_external": 2,
11615
- "prompt_analysis_external": 2,
11616
- "prompt_finalize": 1,
11617
- "sandbox_run_start": 1,
11618
- "sandbox_findings_external": 2,
11619
- "simulation_findings_external": 2,
11620
- "qa_generation_external": 2,
11621
- "platform_setup_bridge": 15,
11622
- "feedback_sheets": 5,
11623
- "facts_management": 2,
11624
- "prompt_lint_standalone": 1,
11625
- "prompt_drafts": 7,
11626
- "workbook_ingestion": 3,
11627
- "knowledge_spaces": 6,
11628
- "knowledge_documents": 4,
11629
- "knowledge_qa": 7,
11630
- "knowledge_websites": 4,
11631
- "knowledge_tables": 6,
11632
- "variables": 5,
11633
- "crm_pipelines": 11,
11634
- "platform_clone": 3,
11635
- "session_workspace": 2,
11636
- "model_comparison": 4,
11637
- "dialog_script": 2,
11638
- "broadcast_analytics": 2,
11639
- "scheduled_tasks": 2,
11640
- "follow_up_read": 3,
11641
- "follow_up_funnel_test": 4,
11642
- "dialogue_audit": 6,
11643
- "link_tracking": 6,
11644
- "dialogue_audit_external": 2,
11645
- "link_tracking_domain": 2,
11646
- "broadcast_scheduler": 6
12956
+ "workspace_and_help": 18,
12957
+ "agent_configuration": 14,
12958
+ "prompt_and_testing": 33,
12959
+ "icp": 9,
12960
+ "knowledge_and_content": 50,
12961
+ "crm_and_data_sources": 27,
12962
+ "channels_and_credentials": 14,
12963
+ "dialogues_and_contacts": 16,
12964
+ "automation": 5,
12965
+ "outbound_and_analytics": 67
11647
12966
  },
11648
12967
  "external_execution_pairs": [
11649
12968
  "besales_icp_analysis_get_instructions / submit",
@@ -11668,6 +12987,7 @@
11668
12987
  ],
11669
12988
  "newly_added_in_p3_x_platform_setup_bridge": [
11670
12989
  "besales_platform_context_get",
12990
+ "besales_trigger_action_catalog_get",
11671
12991
  "besales_agent_list",
11672
12992
  "besales_agent_variable_overrides_get",
11673
12993
  "besales_getcourse_departments_list",
@@ -11710,6 +13030,10 @@
11710
13030
  ],
11711
13031
  "newly_added_in_v1_5_workbook_ingestion": [
11712
13032
  "besales_workbook_inspect",
13033
+ "besales_workbook_get",
13034
+ "besales_workbook_sheet_read",
13035
+ "besales_workbook_classification_update",
13036
+ "besales_workbook_archive",
11713
13037
  "besales_workbook_extract_amocrm_leads",
11714
13038
  "besales_workbook_to_knowledge_document"
11715
13039
  ],
@@ -11731,7 +13055,8 @@
11731
13055
  "besales_knowledge_table_get",
11732
13056
  "besales_knowledge_table_patch",
11733
13057
  "besales_knowledge_table_delete",
11734
- "besales_knowledge_table_reindex"
13058
+ "besales_knowledge_table_reindex",
13059
+ "besales_knowledge_table_reindex_status"
11735
13060
  ],
11736
13061
  "modified_in_v1_5_increment_3": [
11737
13062
  "besales_agent_update",
@@ -11861,6 +13186,41 @@
11861
13186
  "besales_broadcast_schedule_delete",
11862
13187
  "besales_broadcast_schedule_runs",
11863
13188
  "besales_broadcast_segment_rule_set"
13189
+ ],
13190
+ "newly_added_in_amocrm_channel_registration": [
13191
+ "besales_crm_amocrm_channel_registration"
13192
+ ],
13193
+ "newly_added_in_trigger_contact_claims": [
13194
+ "besales_trigger_claim_list",
13195
+ "besales_trigger_claim_reset"
13196
+ ],
13197
+ "newly_added_in_broadcast_pool_snapshots": [
13198
+ "besales_broadcast_schedule_pool_snapshots"
13199
+ ],
13200
+ "newly_added_in_task_state": [
13201
+ "besales_task_create",
13202
+ "besales_task_list",
13203
+ "besales_task_get",
13204
+ "besales_task_update",
13205
+ "besales_task_close",
13206
+ "besales_task_delete"
13207
+ ],
13208
+ "newly_added_in_analytics": [
13209
+ "besales_inbound_analytics_get",
13210
+ "besales_funnel_analytics_get",
13211
+ "besales_ai_costs_get",
13212
+ "besales_custom_report_list",
13213
+ "besales_custom_report_get",
13214
+ "besales_custom_report_run"
13215
+ ],
13216
+ "newly_added_in_operational_overview": [
13217
+ "besales_workspace_operational_overview"
13218
+ ],
13219
+ "newly_added_in_operator_workflow": [
13220
+ "besales_workspace_operator_list",
13221
+ "besales_workspace_operator_queue_list",
13222
+ "besales_workspace_operator_assignment_get",
13223
+ "besales_workspace_operator_assignment_set"
11864
13224
  ]
11865
13225
  }
11866
13226
  }