bitrix24-mcp-bridge 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/api-notes.md CHANGED
@@ -7,22 +7,28 @@
7
7
  ([`apidocs.bitrix24.com`](https://apidocs.bitrix24.com); агенту с MCP context7 — библиотека
8
8
  `/bitrix24/b24restdocs`). **Внутренние ajax-контроллеры** (`im.v2.*`, `tasks.v2.*`, `ui.entityselector.*`)
9
9
  публичных доков не имеют — всё ниже добыто живым реверсом; конверт и регистр полей у них могут
10
- отличаться от 📖-аналогов. Имена полей стандартны для облачного Bitrix24; на другом портале сверяйся
11
- реверсом (`docs/reconnaissance.md`).
10
+ отличаться от 📖-аналогов. Имена полей стандартны для облачного Bitrix24; на другом портале ответ
11
+ может отличаться.
12
12
 
13
13
  ---
14
14
 
15
15
  ## 1. Как вызывать
16
16
 
17
- - **Типизированные инструменты** (`bitrix_tasks_list`, `bitrix_task_get`, `bitrix_chat_load`, …) —
18
- обёртки с разумными дефолтами; их полный список и описания видны среди MCP-инструментов. Точная
19
- выборка — опциональным `params`: он мержится **последним** и перекрывает дефолты.
20
- - **`bitrix_call { name, params }`** — любое имя из каталога (`actions.json`), `params` в нативном
21
- формате Bitrix (§3). Полный список имён отдаёт сам `bitrix_call` в своём описании.
22
- - Каталог может содержать **мутирующие** вызовы: наличие записи = разрешение вызвать. Это не режим
23
- «только чтение».
24
- - У обёрток есть дефолты (напр. `bitrix_tasks_list` сортирует `{"ID":"desc"}`), у `bitrix_call` их нет —
25
- один и тот же фильтр даст разные страницы. Сравниваешь выдачи — задавай `order` явно.
17
+ - **Каждый инструмент `bitrix_*` — встроенная операция моста** с типизированными аргументами
18
+ (`taskId`, `chatId`, `query`, …) и разумными дефолтами; полный список — §3 и описания MCP-инструментов.
19
+ Вызвать произвольный метод Bitrix по имени нельзя — только эти операции.
20
+ - **`params`** (необязательный, у большинства операций — пометка «+ `params`» в §3) — объект в
21
+ **нативном формате Bitrix** (`select`/`filter`/`order`/пагинация, §4). Он мержится **последним** и
22
+ перекрывает дефолты операции. Ключи `action`, `c`, `mode`, `sessid` в `params` запрещены — их задаёт
23
+ сама операция; вызов с ними вернёт ошибку `invalid arguments…`, запрос не уйдёт.
24
+ - **`portal`** (необязательный, у всех) — alias портала; по умолчанию — портал по умолчанию из настроек.
25
+ - У операций есть дефолты (напр. `bitrix_tasks_list` сортирует `{"ID":"desc"}`) — сравниваешь выдачи
26
+ с разными `params`, задавай `order` явно.
27
+ - **Мутирующие** операции (⚠ в §3, полный список — после таблицы) меняют данные на портале от имени
28
+ пользователя, сразу и без отмены. По умолчанию они включены; пользователь может выключить их
29
+ переключателем мутаций — тогда вызов вернёт ошибку `operation <имя> changes data, but mutations are
30
+ disabled…`; это настройка пользователя, обойти её нельзя — сообщи пользователю. Включены ли они сейчас —
31
+ поле `mutations` в `bitrix_status`. Операции чтения переключатель не трогает.
26
32
  - Ответ `invalid_csrf` / `invalid_authentication` = сессия портала протухла → перелогинься в браузере
27
33
  на вкладке портала.
28
34
 
@@ -44,39 +50,203 @@ Ajax-контроллеры (`/bitrix/services/main/ajax.php`) отвечают
44
50
 
45
51
  ---
46
52
 
47
- ## 3. Каталог: имя → action → params
53
+ ## 3. Инструменты: что делает → ключевые аргументы
48
54
 
49
- Форма `params` различается по методу: где-то плоско, где-то вложенно, где-то обёрнуто в `params[…]` —
50
- колонка «params» показывает точную форму (кодирование тела мост берёт на себя).
55
+ `params` в таблице не повторяется — он есть у всех операций с пометкой «+ `params`» (§1). Форма
56
+ `params` различается по методу: где-то плоско, где-то вложенно, где-то обёрнуто в `params[…]` — колонка
57
+ «params / пагинация» показывает точную форму (кодирование тела мост берёт на себя).
51
58
 
52
- | Имя (`bitrix_call`) | action / endpoint | params | Пагинация |
59
+ | Инструмент | Что делает | Ключевые аргументы | params / пагинация |
53
60
  |---|---|---|---|
54
- | `tasks.list` | `tasks.task.list` | верхний уровень: `filter{RESPONSIBLE_ID,REAL_STATUS,GROUP_ID,…}`, `select[]`, `order{}` | **`PAGEN_1`** — номер страницы (1, 2, 3…), страница = 20 задач; `start` **не работает** (вернёт ту же первую страницу) |
55
- | `task.get` | `tasks.task.get` | верхний уровень: `taskId`, `select[]` | — |
56
- | `task.v2.get` | `tasks.v2.Task.get` | вложенно: `{"task":{"id":N}}` | — |
57
- | `task.scrum.info` | `tasks.v2.Scrum.getTaskInfo` | `{"taskId":N}` | — |
58
- | `task.files` | `tasks.v2.File.listObjects` | `{"ids":[N,…]}` | — |
59
- | `task.views.count` | `tasks.v2.Task.View.User.count` | вложенно: `{"task":{"id":N}}` | — |
60
- | `task.subtasks` | `tasks.v2.Task.Relation.Child.list` | `{"taskId":N,"withIds":true,"navigation":{"size":N}}` | `navigation` |
61
- | `task.related` | `tasks.v2.Task.Relation.Related.list` | как `task.subtasks` | `navigation` |
62
- | `projects.list` | `socialnetwork.api.workgroup.list` | верхний уровень: `select[]`, `order{}`, `filter{}` | `start` (шаг 50; `start=(N-1)*50`, `-1` — ответ без `total`) 📖 |
63
- | `projects.get` | `socialnetwork.api.workgroup.get` | **обёрнуто**: `params[groupId]`, `params[select][]` | — |
64
- | `chats.recent` | `/rest/im.recent.list.json` | плоско: `LIMIT`, `SKIP_OPENLINES`, `UNREAD_ONLY` | `LIMIT` |
65
- | `recent.load` | `im.v2.Recent.load` | плоско: `limit`, `filter[recentSection]` (`tasksTask`/`collab`/…), `filter[unread]`, `filter[parentId]` | `recent.tail` |
66
- | `recent.tail` | `im.v2.Recent.tail` | плоско: `limit`, `filter[lastMessageDate]` (курсор), `filter[recentSection]` | `filter[lastMessageDate]` |
67
- | `chat.load` | `im.v2.Chat.load` | плоско: `dialogId`\|`chatId`, `messageLimit` | — |
68
- | `chat.dialogId` | `im.v2.Chat.getDialogId` | плоско: `externalId` (напр. `"sg"+groupId`) | — |
69
- | `chat.messages` | `im.v2.Chat.Message.list` | плоско: `chatId`, `limit` | только последняя страница — назад **не листает**, используй `chat.messages.tail` |
70
- | `chat.messages.tail` | `im.v2.Chat.Message.tail` | плоско: `chatId`, `limit`, `filter[lastId]`, `order[id]` | `filter[lastId]` (§5.1) |
71
- | `chat.message.read` | `im.v2.Chat.Message.read` | плоско: `chatId`, `ids[]`, `actionUuid` | ⚠ мутирующий |
72
- | `chat.read.all` | `im.v2.Chat.readAll` | без параметров | ⚠ мутирующий |
73
- | `im.user.get` | `/rest/im.user.get.json` | плоско: `ID` | — |
74
- | `im.chat.get` | `/rest/im.chat.get.json` | плоско: `ENTITY_TYPE`, `ENTITY_ID` (напр. `TASKS_TASK`+taskId) | — |
75
- | `entityselector.load` | `ui.entityselector.load` | `{"dialog":{entities,preselectedItems,…}}` | — |
76
- | `entityselector.search` | `ui.entityselector.doSearch` | `{"dialog":{…},"searchQuery":{"query":"…","queryWords":["…"]}}` | — |
77
- | `call.detail` | `GET /call/detail/{callId}` | `callId` (подставляется в путь), `IFRAME=Y`, `IFRAME_TYPE=SIDE_SLIDER` → HTML | см. §5.4 |
78
- | `task.comments.page` | `GET /task/comments/{taskId}/` | `taskId` (в путь), `IFRAME=Y`, `IFRAME_TYPE=SIDE_SLIDER` → HTML старых комментариев | см. §5.6 |
79
- | `task.comments.navigate` | `bitrix:forum.comments` → `navigateComment` | форма: `ENTITY_XML_ID=TASK_<id>`, `EXEMPLAR_ID`, `signedParameters` (оба — из HTML первой страницы), `FILTER[<ID]` | `FILTER[<ID]` — курсор; проще `bitrix_task_comments` (§5.6) |
61
+ | `bitrix_help` | эта справка | — | — |
62
+ | `bitrix_status` | какие порталы сконфигурированы и подключены, версии моста и расширения | — | — |
63
+ | *Задачи* | | | |
64
+ | `bitrix_tasks_list` | список задач | + `params` | верхний уровень: `filter{RESPONSIBLE_ID,REAL_STATUS,GROUP_ID,…}`, `select[]`, `order{}`; **`PAGEN_1`** — номер страницы (1, 2, 3…), страница = 20 задач; `start` **не работает** (вернёт ту же первую страницу) |
65
+ | `bitrix_task_get` | карточка задачи (в т.ч. `CHAT_ID`) | `taskId` + `params` | верхний уровень: `select[]` |
66
+ | `bitrix_task_get_v2` | карточка задачи через v2-подсистему | `taskId` + `params` | — |
67
+ | `bitrix_task_scrum_info` | спринт / эпик / story points задачи | `taskId` + `params` | — |
68
+ | `bitrix_task_files` | файлы задачи (ссылки для скачивания) | `ids[]` — id **прикреплённых объектов** (§4), не задач + `params` | `downloadUrl` в ответе относительный — допиши origin портала |
69
+ | `bitrix_task_views_count` | сколько пользователей просмотрели задачу | `taskId` + `params` | — |
70
+ | `bitrix_task_subtasks` / `bitrix_task_related` | подзадачи / связанные задачи | `taskId` + `params` | `navigation{size}` (дефолт 10) |
71
+ | `bitrix_task_comments` | старые комментарии задачи (форум), §5.6 | `taskId`, `limit?`, `maxPages?`, `beforeId?`, `output?` | `beforeId` — курсор |
72
+ | `bitrix_task_description_set` ⚠ | **заменить** описание задачи целиком (`""` — очистить) | `taskId`, `text` (≤ 100 000) | без `params`; разметка — BBCode описания (ниже); описание перечитывается, ответ `{ taskId, length }` |
73
+ | `bitrix_task_description_append` ⚠ | **дописать** в конец описания через пустую строку; старое (файлы `[disk file id=…]`, таблицы) не трогает | `taskId`, `text` (≤ 100 000) | без `params`; описание перечитывается, ответ `{ taskId, length }` |
74
+ | `bitrix_task_description_replace` ⚠ | **точечная правка** описания: фрагмент `find` → `replace` (`""` — удалить фрагмент), остальное как было | `taskId`, `find`, `replace`, `all?` | без `params`; `find` — точная подстрока сырого BBCode (`bitrix_task_get_v2` → `description`), с регистром и переводами строк. Нет совпадений или их больше одного без `all: true` — ошибка, ничего не записано. Описание перечитывается; ответ `{ taskId, replaced, length }` |
75
+ | `bitrix_task_tags` ⚠ | добавить / убрать **теги** | `taskIds[]` (1–50), `add[]?`, `remove[]?` — названия, без учёта регистра | без `params`; пакетный ответ (ниже), поля `tags`, `changed` |
76
+ | `bitrix_task_checklist` | **чек-лист** задачи плоским списком `{ taskId, items: [{ id, parentId, title, done }] }` | `taskId` | без `params`; `parentId: 0` — группа, остальные — пункты группы `parentId` |
77
+ | `bitrix_task_checklist_edit` ⚠ | изменить чек-лист: добавить, переименовать, отметить / снять отметку, удалить | `taskId`, `add[]?` (названия), `rename[{ itemId, title }]?`, `complete[]?`, `reopen[]?`, `remove[]?` | без `params`; id — из `bitrix_task_checklist`; ≤ 50 действий за вызов; ответ `{ taskId, added, items }` (перечитан) |
78
+ | `bitrix_task_plan` ⚠ | **планируемые** даты начала / завершения | `taskId`, `start?`, `end?` — дата (ниже) или `null` (очистить) | без `params`; хотя бы одна; не переданная остаётся как есть; `start` не позже `end`; ответ `{ taskId, start, end }` |
79
+ | `bitrix_task_priority` ⚠ | **важность**: `high` — «Важная задача», `average` — обычная | `taskIds[]` (1–50), `priority` | без `params`; пакетный ответ, поле `priority` |
80
+ | `bitrix_task_deadline` ⚠ | **крайний срок** | `taskIds[]` (1–50), `deadline` — дата или `null` (убрать), `reason?` (причина переноса, простой текст ≤ 1000) | без `params`; пакетный ответ, поле `deadline` |
81
+ | `bitrix_task_close` ⚠ | **закрыть** задачу; Definition of Done не обходится — два шага, §5.7 | `taskId`; шаг 2 — плюс `typeId`, `confirmItems: true` | без `params`; ответ `{ taskId, status, changed, typeId? }` или `{ taskId, needsConfirmation: true, types }` |
82
+ | `bitrix_task_reopen` ⚠ | **возобновить** завершённые задачи | `taskIds[]` (1–50) | без `params`; пакетный ответ, поля `status`, `changed` |
83
+ | `bitrix_task_result_add` ⚠ | добавить один и тот же **результат** задачам: закреплён в карточке, анонс в чате задачи | `taskIds[]` (1–50), `text` (≤ 20 000) | без `params`; пакетный ответ (ниже), поле `resultId` |
84
+ | `bitrix_task_file_attach` ⚠ | прикрепить **локальный файл** к задаче, §5.8 | `taskId`, `path` (абсолютный), `name?` | без `params`; файл ≤ 10 МБ уходит на Диск пользователя; ответ `{ taskId, diskFileId, name, size, attachmentId }` |
85
+ | `bitrix_task_mute` ⚠ | выключить (`true`) / включить (`false`) **свои** уведомления по задаче | `taskId`, `muted` | без `params`; ответ `{ taskId, muted }` |
86
+ | `bitrix_task_reminders` | напоминания по задаче, §5.9 | `taskId` | без `params` |
87
+ | `bitrix_task_reminder_set` ⚠ | поставить новое **своё** напоминание или изменить своё (`reminderId`) | `taskId`, `at` (дата в будущем), `via` (`notification` \| `email`), `reminderId?` | без `params`; ответ `{ taskId, reminder }` |
88
+ | `bitrix_task_reminder_delete` ⚠ | удалить **своё** напоминание | `taskId`, `reminderId` | без `params`; ответ `{ taskId, reminderId, deleted: true }` |
89
+ | *Участники задач* | | | |
90
+ | `bitrix_task_delegate` ⚠ | **делегировать**: `userId` становится ответственным | `taskIds[]` (1–50), `userId` | без `params`; пакетный ответ, поле `responsibleId` (перечитан) |
91
+ | `bitrix_task_accomplices` / `bitrix_task_auditors` ⚠ | добавить / убрать **соисполнителей** / **наблюдателей** | `taskIds[]` (1–50), `add[]?`, `remove[]?` — userId | без `params`; пакетный ответ, поля `accomplices` / `auditors` (перечитаны), `changed` |
92
+ | `bitrix_user_find` | найти пользователей по фамилии `[{ id, name, lastName, active, workPosition }]` | `lastName` | без `params`; в выдаче и **неактивные** (уволенные, `active: false`) — не назначай их на рабочие задачи |
93
+ | *Связи задач* | | | |
94
+ | `bitrix_task_related_edit` ⚠ | добавить / убрать **связанные** задачи (блок «Связанные задачи») | `taskId`, `add[]?`, `remove[]?` — id задач | без `params`; ответ `{ taskId, related, changed }`; задачи со 100 и более связанными не правятся |
95
+ | `bitrix_task_parent` ⚠ | сделать **подзадачей** задачи `parentId`; `null` — отвязать от родителя | `taskId`, `parentId` | без `params`; ответ `{ taskId, parentId, previousParentId, changed }` |
96
+ | `bitrix_task_gantt_link` ⚠ | связь Ганта «окончание → начало»: `dependentId` начинается после завершения `taskId` | `taskId`, `dependentId`, `remove?`, `type?` (только `"finish_start"`, только при добавлении) | без `params`; отдельную связь прочитать нельзя — проверка по признаку «у `dependentId` есть связи Ганта»: `confirmed: true` — подтверждено, `confirmed: false` + `note` — подтвердить нельзя (у задачи были / остались другие связи); нет связей после добавления — ошибка; ответ `{ taskId, dependentId, linked, confirmed, note? }` |
97
+ | *Scrum* | | | |
98
+ | `bitrix_sprint_columns` | колонки доски **активного** спринта `[{ id, name, type }]` | `groupId` (= `GROUP_ID` задачи) | без `params`; `type` — `NEW`/`WORK`/`FINISH`, у своих колонок пустой; в колонку `FINISH` операции задачи не ставят |
99
+ | `bitrix_task_move` ⚠ | перенести задачи в колонку спринта | `taskIds[]` (1–50), `column` (id или название, без учёта регистра) | без `params`; колонку типа `FINISH` указать нельзя — закрывай через `bitrix_task_close`; пакетный ответ (ниже), поля `stageId`, `column`, `status` — перенос может переоткрыть закрытую задачу |
100
+ | `bitrix_task_to_sprint` ⚠ | поставить задачи на доску **активного** спринта: из бэклога — в спринт и в колонку, уже стоящие в нём — в колонку | `taskIds[]` (1–50), `column?` (без него — колонка типа `NEW`) | без `params`; колонку типа `FINISH` указать нельзя — закрывай через `bitrix_task_close`; пакетный ответ, поля `sprintId`, `stageId`, `column`, `status`, `fromBacklog`; задачи других спринтов — ошибка |
101
+ | `bitrix_task_to_backlog` ⚠ | вернуть задачи в **бэклог** проекта | `taskIds[]` (1–50) | без `params`; пакетный ответ, поля `backlogId`, `changed` |
102
+ | `bitrix_task_create` ⚠ | **создать** задачу сразу на доске активного спринта, как «+» на доске | `groupId`, `title` (≤ 255, простой текст), `column?` (без него — колонка типа `NEW`) | без `params`; колонку типа `FINISH` указать нельзя; ответ `{ taskId, sprintId, stageId, column }`; остальные поля — потом отдельными операциями |
103
+ | *Проекты* | | | |
104
+ | `bitrix_projects_list` | рабочие группы / проекты | + `params` | верхний уровень: `select[]`, `order{}`, `filter{}`; `start` (шаг 50; `start=(N-1)*50`, `-1` — ответ без `total`) 📖 |
105
+ | `bitrix_project_get` | карточка группы (участники, `CHAT_ID`) | `groupId` + `params` | **обёрнуто**: `params[groupId]`, `params[select][]` |
106
+ | *Чаты* | | | |
107
+ | `bitrix_chats_recent` | недавние диалоги (без чатов задач) | + `params` | плоско: `LIMIT`, `SKIP_OPENLINES`, `UNREAD_ONLY` |
108
+ | `bitrix_recent_load` | недавние по секции (`tasksTask` — чаты задач) | `section?`, `limit?`, `unread?`, `parentId?` + `params` | дальше — `bitrix_recent_tail` |
109
+ | `bitrix_recent_tail` | листать недавние вглубь | `lastMessageDate` (курсор), `section?`, `limit?`, `unread?` + `params` | `lastMessageDate` |
110
+ | `bitrix_chat_load` | открыть чат, первые сообщения, числовой `chatId` | `dialogId` \| `chatId`, `messageLimit?` + `params` | — |
111
+ | `bitrix_chat_get_dialog_id` | `externalId` → `dialogId` (напр. `"sg"+groupId`) | `externalId` + `params` | — |
112
+ | `bitrix_chat_messages` | последние сообщения чата | `chatId`, `limit?` + `params` | только последняя страница — назад **не листает**, используй `bitrix_chat_history` |
113
+ | `bitrix_chat_history` | листать историю чата вглубь | `chatId`, `beforeId?`, `limit?` + `params` | `beforeId` (§5.1) |
114
+ | `bitrix_chat_mark_read` ⚠ | пометить сообщения прочитанными | `chatId`, `ids[]`, `actionUuid?` + `params` | — |
115
+ | `bitrix_chat_read_all` ⚠ | пометить **все** чаты прочитанными | + `params` | — |
116
+ | `bitrix_chat_send` ⚠ | отправить сообщение (видят все участники чата) | `chatId` \| `dialogId` (ровно одно), `text` (≤ 20 000), `replyTo?` (id сообщения этого чата — ответ на него) | без `params`; разметка — подмножество чата (ниже); ответ `{ chatId?, dialogId, messageId }` |
117
+ | `bitrix_chat_message_edit` ⚠ | заменить текст **своего** сообщения целиком | `messageId`, `text` (≤ 20 000, не пустой) | без `params`; чужое сообщение Bitrix изменить не даст — ошибка |
118
+ | `bitrix_chat_reaction` ⚠ | поставить реакцию на сообщение | `messageId`, `reaction` (латиница; проверены `like` 👍, `whiteHeavyCheckMark` ✅) | без `params`; другие имена уходят как есть, без проверки |
119
+ | `bitrix_task_chat_post` ⚠ | одно и то же сообщение в **чаты задач** (чат каждой — по её `CHAT_ID`) | `taskIds[]` (1–50), `text` (≤ 20 000) | без `params`; пакетный ответ, поля `chatId`, `messageId`; задача без чата — ошибка этой задачи |
120
+ | *Люди / поиск* | | | |
121
+ | `bitrix_user_get` | карточка пользователя мессенджера | `userId` + `params` | — |
122
+ | `bitrix_entity_search` | текстовый поиск чатов / людей | `query`, `section?`, `dialog?` + `params` | — |
123
+ | `bitrix_entity_selector` | загрузка entityselector со своим `dialog` | `dialog` + `params` | `{"dialog":{entities,preselectedItems,…}}` |
124
+ | `bitrix_entity_chat` | `chatId` чата, привязанного к объекту | `entityType`, `entityId` + `params` | — |
125
+ | *Созвоны и файлы* | | | |
126
+ | `bitrix_chat_calls` | звонки в чате (`callId` + резюме), §5.4 | `chatId`, `limit?`, `maxPages?`, `beforeId?` + `params` | `beforeId` — курсор |
127
+ | `bitrix_call_detail` | всё по звонку, §5.4 | `callId`, `transcript?` + `params` | — |
128
+ | `bitrix_call_recording` | скачать аудиозапись звонка, §5.5 | `callId`, `savePath?`, `overwrite?` | — |
129
+ | `bitrix_file_download` | скачать файл портала на диск, §5.5 | `url`, `savePath?`, `overwrite?` | — |
130
+
131
+ **Мутирующие операции** (⚠) — по умолчанию включены:
132
+
133
+ - задачи: `bitrix_task_description_set`, `bitrix_task_description_append`,
134
+ `bitrix_task_description_replace`, `bitrix_task_tags`, `bitrix_task_checklist_edit`, `bitrix_task_plan`,
135
+ `bitrix_task_priority`, `bitrix_task_deadline`, `bitrix_task_close`, `bitrix_task_reopen`,
136
+ `bitrix_task_result_add`, `bitrix_task_file_attach`, `bitrix_task_mute`, `bitrix_task_reminder_set`,
137
+ `bitrix_task_reminder_delete`;
138
+ - участники: `bitrix_task_delegate`, `bitrix_task_accomplices`, `bitrix_task_auditors`;
139
+ - связи: `bitrix_task_related_edit`, `bitrix_task_parent`, `bitrix_task_gantt_link`;
140
+ - scrum: `bitrix_task_move`, `bitrix_task_to_sprint`, `bitrix_task_to_backlog`, `bitrix_task_create`;
141
+ - чаты: `bitrix_chat_send`, `bitrix_chat_message_edit`, `bitrix_chat_reaction`, `bitrix_task_chat_post`,
142
+ `bitrix_chat_mark_read`, `bitrix_chat_read_all`.
143
+
144
+ Выключает их пользователь (агенту это недоступно): `"mutations": false` в `config.json` моста, env
145
+ `BITRIX_MCP_MUTATIONS=off` у процесса daemon (перекрывает `config.json`) или `setup` → `[m]`. Текущее
146
+ состояние — `bitrix_status` → `mutations`; выключенная операция отвечает ошибкой из §1 и в Bitrix24 не
147
+ уходит. `bitrix_task_comments` ничего не помечает прочитанным и мутирующим не считается.
148
+
149
+ **Каждая мутация — от имени пользователя, сразу и без отмены.** Делай только то, о чём он просил; если
150
+ просьба шире или неоднозначна (кого назначить, какую задачу закрыть, какой файл отправить) — сначала
151
+ спроси. Уведомление, ушедшее человеку, не отзывается.
152
+
153
+ **Пакетные операции** (`taskIds[]`, 1–50 id без повторов: `bitrix_task_tags`, `bitrix_task_priority`,
154
+ `bitrix_task_deadline`, `bitrix_task_reopen`, `bitrix_task_result_add`, `bitrix_task_delegate`,
155
+ `bitrix_task_accomplices`, `bitrix_task_auditors`, `bitrix_task_move`, `bitrix_task_to_sprint`,
156
+ `bitrix_task_to_backlog`, `bitrix_task_chat_post`) обрабатывают задачи по очереди и отвечают
157
+ `{ results: [{ taskId, ok, error?, …поля операции }] }` в порядке `taskIds`. Ошибка одной задачи
158
+ (`ok: false`, текст в `error`) не останавливает остальные — проверяй `ok` у каждой. Сама операция
159
+ падает целиком только на неверных аргументах (и на колонке типа `FINISH` у `bitrix_task_move` /
160
+ `_to_sprint` — тогда не тронута ни одна задача). Ближе к концу отведённого времени пакет перестаёт
161
+ начинать новые задачи: они приходят с `ok: false` и «не выполнено: истекло время пакета…» — повтори
162
+ только их, перечитав состояние. Результаты и сообщения неидемпотентны: повтор создаст дубль.
163
+
164
+ **Ошибка после записи — не повод повторять вслепую.** Большинство мутаций перечитывают то, что
165
+ записали, и по тексту ошибки видно, что случилось:
166
+
167
+ - «…ничего не изменено / ничего не записано / ничего не удалено», ошибки аргументов
168
+ (`invalid arguments…`) — запроса на запись не было; поправь аргументы и вызывай снова.
169
+ - «запись отправлена, но перечитать не удалось (проверь через …)» и его варианты («перенос /
170
+ делегирование / закрытие / возобновление отправлено, но перечитать задачу не удалось») — запись ушла,
171
+ а итог неизвестен: проверь названным инструментом, не повторяй.
172
+ - «сообщение могло уйти», «задача могла создаться», «результат мог добавиться», «описание могло
173
+ измениться», «файл мог загрузиться на Диск», «вложение могло создаться», «напоминание могло создаться» —
174
+ портал мог всё сделать, но ответа не дал (таймаут, неожиданный ответ): сначала проверь (чат, доска
175
+ спринта, карточка задачи, `bitrix_task_get_v2`, Диск, файлы задачи, `bitrix_task_reminders`), повтор без
176
+ проверки создаст дубль (а `bitrix_task_description_append` допишет текст второй раз).
177
+ - «Bitrix ответил успехом, но …», «Bitrix не применил: …» — перечитанное состояние не то, что просили; в
178
+ ошибке — как сейчас. Не повторяй тот же вызов вслепую — скажи пользователю.
179
+ - Многошаговые правки называют, что уже сделано: `bitrix_task_checklist_edit` — «до этого сделано: …»,
180
+ `bitrix_task_parent` — прежнего родителя и вызов, которым его вернуть, `bitrix_task_to_sprint` — «верни
181
+ её в бэклог (`bitrix_task_to_backlog`) и повтори».
182
+
183
+ **Списки целиком.** Соисполнителей, наблюдателей, теги и описание Bitrix хранит и перезаписывает
184
+ целиком, поэтому `bitrix_task_accomplices`, `bitrix_task_auditors`, `bitrix_task_tags`,
185
+ `bitrix_task_description_append` / `_replace` сами читают текущее значение **каждой** задачи, меняют в нём
186
+ только названное и записывают обратно; если прочитать не удалось — ничего не пишут. Передавай только
187
+ `add` / `remove` (фрагмент, дописку), а не весь список; если менять нечего — `changed: false`, записи нет.
188
+ Так же `bitrix_task_related_edit` добавляет и убирает только названные связи, а `bitrix_task_plan`
189
+ сохраняет непереданную дату. `bitrix_task_description_set` — единственная, что заменяет описание целиком.
190
+
191
+ **Кто это увидит и кого уведомят.**
192
+
193
+ | Операции | Видят | Уведомление |
194
+ |---|---|---|
195
+ | `bitrix_chat_send`, `bitrix_task_chat_post` | все участники чата | упомянутым `[user=ID]Имя[/user]` |
196
+ | `bitrix_chat_message_edit`, `bitrix_chat_reaction` | все участники чата | не проверено (новое упоминание при правке; автору — о реакции) |
197
+ | `bitrix_task_delegate` | история задачи | новому ответственному |
198
+ | `bitrix_task_accomplices`, `bitrix_task_auditors` | история задачи | каждому добавленному |
199
+ | `bitrix_task_close`, `bitrix_task_reopen` | все, кто видит задачу | участникам задачи |
200
+ | `bitrix_task_result_add` | карточка задачи; анонс в её чате видят все его участники | — |
201
+ | описание, теги, важность, срок, планируемые даты | все, кто видит задачу; история задачи | — |
202
+ | `bitrix_task_checklist_edit`, связи, родитель, связь Ганта | все, кто видит задачу | — |
203
+ | `bitrix_task_file_attach` | все, кто видит задачу (и могут скачать) | — |
204
+ | `bitrix_task_create`, `bitrix_task_move`, `_to_sprint`, `_to_backlog` | участники проекта на scrum-доске | — |
205
+ | `bitrix_task_mute`, напоминания | **только ты** | только тебе (напоминания) |
206
+
207
+ «—» — не проверено: операция об уведомлениях ничего не утверждает, но Bitrix может сам слать
208
+ участникам уведомления об изменении задачи. Чат задачи — `CHAT_ID` из `bitrix_task_get` (или
209
+ `bitrix_entity_chat { entityType:"TASKS_TASK" }`). userId для участников — `bitrix_user_find` (по
210
+ фамилии) или поля задачи; людей из выдачи `bitrix_user_find` с `active: false` на рабочие задачи не
211
+ назначай.
212
+
213
+ **`bitrix_task_move`** работает только для задачи, которая уже на доске спринта (не в бэклоге):
214
+ `task.stages.movetask` отвечает `true`, ничего не сделав, — мост перечитывает задачу и в этом случае
215
+ возвращает ошибку по этой задаче. Задачу из бэклога ставит на доску `bitrix_task_to_sprint` (переносит в
216
+ активный спринт, ставит на доску, перечитывает спринт и колонку); задачи запланированных и завершённых
217
+ спринтов он не трогает. Если перенос отправлен, а перечитать задачу не удалось, ошибка так и говорит —
218
+ колонку тогда проверь через `bitrix_task_get`. `task.stages.get` отдаёт старый канбан группы, а не
219
+ колонки спринта. Перенос в колонку может переоткрыть закрытую задачу — смотри `status` в ответе.
220
+
221
+ **Колонка типа `FINISH`** (обычно «Готово», см. `type` в `bitrix_sprint_columns`) завершает задачу,
222
+ а Definition of Done спрашивает только всплывающее окно веб-интерфейса. Поэтому `bitrix_task_move`,
223
+ `bitrix_task_to_sprint` и `bitrix_task_create` такую колонку не принимают — ни по названию, ни по id:
224
+ «колонка «…» завершает задачу — закрыть задачу можно только через `bitrix_task_close` …; ничего не
225
+ изменено». У пакетных операций отказ — на весь вызов: сначала читаются все задачи, и если колонка
226
+ хоть у одной из них (в её проекте) — `FINISH`, не переносится ни одна. Закрыть задачу —
227
+ `bitrix_task_close` (§5.7).
228
+
229
+ **Даты** (`bitrix_task_plan`, `bitrix_task_deadline`, `bitrix_task_reminder_set`) — ISO 8601 **со
230
+ смещением**: `"2026-12-01T09:00:00+03:00"` или `"…Z"`; без смещения — ошибка аргументов. В ответе даты в
231
+ UTC. Bitrix хранит время задач с точностью до минуты: секунды не считаются расхождением.
232
+
233
+ **Разметка текста.**
234
+
235
+ - **Описание задачи** (`bitrix_task_description_*`) и **результат** (`bitrix_task_result_add`) — полный
236
+ BBCode: `[b] [i] [u] [s]`, `[url=…]…[/url]`, `[user=ID]Имя[/user]`, списки `[list]` / `[list=1]` с
237
+ пунктами `[*]`, `[quote]`, `[code]`, `[spoiler=Заголовок]…[/spoiler]`, таблицы `[table][tr][th]/[td]`.
238
+ Теги `[disk file id=…]` — это прикреплённые файлы, сохраняй их. Как BBCode результата выглядит в его
239
+ карточке в чате, не проверено.
240
+ - **Сообщение в чат** (`bitrix_chat_send`, `bitrix_chat_message_edit`, `bitrix_task_chat_post`) — только
241
+ то, что рендерят и веб, и мобильное приложение: `[b] [i] [u] [s]`, `[url=…]…[/url]`,
242
+ `[user=ID]Имя[/user]`, `[code]`, `[color=#hex]…[/color]`, `[br]`. Цитата — строка, начинающаяся с `>>`,
243
+ или блок между двумя строками из дефисов; список — строки, начинающиеся с `•`. `[quote]`, `[list]`,
244
+ `[spoiler]`, таблицы и Markdown в чате **не рендерятся**. Длиннее 20 000 символов Bitrix молча обрежет —
245
+ мост такое не отправит.
246
+ - **Простой текст:** название задачи (`bitrix_task_create` — BBCode в названии не работает), теги, причина
247
+ переноса срока. Названия пунктов чек-листа — тоже простой текст (как в них рендерится BBCode, не
248
+ проверено).
249
+ - Markdown не рендерится нигде.
80
250
 
81
251
  ---
82
252
 
@@ -85,7 +255,9 @@ Ajax-контроллеры (`/bitrix/services/main/ajax.php`) отвечают
85
255
  **Задача** (`tasks.task.*`) — поля для `select`/`filter` в UPPER_CASE: `ID`, `TITLE`, `DESCRIPTION`,
86
256
  `STATUS`, `REAL_STATUS`, `RESPONSIBLE_ID`, `CREATED_BY`, `CREATED_DATE`, `CHANGED_DATE`, `DEADLINE`,
87
257
  `CLOSED_DATE`, `PRIORITY`, `GROUP_ID`, `TAGS`, `TIME_ESTIMATE`, **`CHAT_ID`** (id чата-обсуждения
88
- задачи — прямой резолвер `taskId → chatId`, §5.2), `UF_*`. Ответ подкладывает объекты `group`,
258
+ задачи — прямой резолвер `taskId → chatId`, §5.2), `COMMENTS_COUNT` (§5.6), **`UF_TASK_WEBDAV_FILES`**
259
+ (id **прикреплённых объектов** — именно их ждёт `bitrix_task_files`; с id задачи он вернёт пустой
260
+ список без ошибки), `UF_*`. Ответ подкладывает объекты `group`,
89
261
  `responsible`, `creator`, `action`.
90
262
  📖 (`tasks.task.get`/`list`) — сверх этого: `parentId`, `stageId`, `sprintId`, `backlogId`,
91
263
  `commentsCount`, `timeSpentInLogs`, `favorite`, `flowId`, `mark`, `accomplices[]`, `auditors[]`,
@@ -117,7 +289,7 @@ WITH_PARSED_DESCRIPTION}`.
117
289
  > **Scrum-задачи (спринты).** Поле `SPRINT_ID` задачи и жёсткий `filter[SPRINT_ID]` могут расходиться:
118
290
  > задача числится за спринтом по своему полю, но не попадает в выборку по фильтру (возвращена в бэклог
119
291
  > или в иной stage). Если по фильтру «маловато» — перепроверь без него и отфильтруй по
120
- > `SPRINT_ID`/`STAGE_ID` у себя. Метода «колонки scrum-доски» (`STAGE_ID` → имя колонки) в каталоге нет.
292
+ > `SPRINT_ID`/`STAGE_ID` у себя. `STAGE_ID` → имя колонки — `bitrix_sprint_columns { groupId }` (§3).
121
293
 
122
294
  **Группа/проект — список** (`workgroup.list`): `ID`, `NAME`, `DESCRIPTION`, `NUMBER_OF_MEMBERS`,
123
295
  `OWNER_ID`, `DATE_CREATE`, `PROJECT` (Y=проект/N=группа), `TYPE`; **без `select` вернётся только `ID`**.
@@ -148,12 +320,13 @@ WITH_PARSED_DESCRIPTION}`.
148
320
  ```jsonc
149
321
  // открытые задачи ответственного 55, по дедлайну, вторая страница
150
322
  bitrix_tasks_list { "params": { "filter": {"RESPONSIBLE_ID":55,"REAL_STATUS":2},
151
- "order": {"DEADLINE":"asc"}, "start": 50 } }
323
+ "order": {"DEADLINE":"asc"}, "PAGEN_1": 2 } }
152
324
 
153
325
  // карточка задачи с расширенным набором полей; v2-подсистема; файлы, просмотры, связи
154
326
  bitrix_task_get { "taskId": 4229, "params": { "select": ["ID","TITLE","DESCRIPTION","TAGS"] } }
155
327
  bitrix_task_get_v2 { "taskId": 4229 } // → { "task": { "id": 4229 } }
156
- bitrix_call { "name": "task.files", "params": { "ids": [4229] } }
328
+ bitrix_task_get { "taskId": 4229, "params": { "select": ["ID","UF_TASK_WEBDAV_FILES"] } }
329
+ bitrix_task_files { "ids": [<id из UF_TASK_WEBDAV_FILES>] } // НЕ id задачи
157
330
  bitrix_task_subtasks { "taskId": 4229 }
158
331
  bitrix_task_related { "taskId": 4229 }
159
332
 
@@ -274,7 +447,7 @@ AI-анализ звонка (BitrixGPT Follow-Up) живёт на сервер
274
447
 
275
448
  ```jsonc
276
449
  bitrix_chat_calls { "chatId": 9876 } // чат проекта: bitrix_project_get → CHAT_ID
277
- bitrix_chat_calls { "chatId": 9876, "maxPages": 20, "beforeId": 5001 } // продолжить вглубь
450
+ bitrix_chat_calls { "chatId": 9876, "maxPages": 10, "beforeId": 5001 } // продолжить вглубь (maxPages ≤ 10)
278
451
  ```
279
452
 
280
453
  Ответ: `calls[] { callId, startedAt, startedBy, startMessageId, events[], summaryMessageId }` плюс
@@ -304,7 +477,7 @@ bitrix_call_detail { "callId": 4242, "transcript": "file" } // всегда
304
477
  **Расшифровка длинного звонка не приходит в ответе.** У часовой встречи она даёт ~70 КБ из 80 КБ, поэтому
305
478
  свыше ~20 КБ (режим `"auto"` = умолчание) пишется на диск, а в ответе остаются `transcript: []`,
306
479
  `transcriptCount` и **`files`**: `files.transcript` — `call-<id>-transcript.txt`, где строка = реплика
307
- (`[11:10—11:24] Генрих Богацкий: …`), её удобно **грепать** (найденная строка сама несёт таймкод и
480
+ (`[11:10—11:24] Имя Фамилия: …`), её удобно **грепать** (найденная строка сама несёт таймкод и
308
481
  спикера); `files.json` — полный ответ с расшифровкой. Оба файла — кеш звонка, перезаписываются.
309
482
 
310
483
  Тонкости:
@@ -330,7 +503,11 @@ bitrix_file_download { "url": "…", "savePath": "/tmp/photo.png", "overwrite":
330
503
  трактуется как имя внутри этой папки. Потолок — 512 МБ.
331
504
 
332
505
  Тонкости:
333
- - **Граница безопасности — origin**: скачивается только с origin сконфигурированного портала.
506
+ - **Только ссылки на файлы** сконфигурированного портала: `/bitrix/services/main/ajax.php` с `action`
507
+ `disk.api.file.download` / `disk.attachedObject.download` / `call.Track.download` или
508
+ `/bitrix/tools/disk/uf.php` с `action` `download` / `show` / `downloadArchiveByEntity`. Чужой origin
509
+ → `not a configured portal`; другой путь, другой, повторённый или `action[]` → `not a portal file
510
+ link`. Бери ссылки из ответов моста, не собирай их сам.
334
511
  - **Имя даёт портал** (`Content-Disposition`), поэтому без `savePath` угадывать его не нужно.
335
512
  - **Повторное скачивание** того же файла падает с `already exists` — передай `overwrite: true`.
336
513
 
@@ -350,7 +527,7 @@ bitrix_task_comments { "taskId": 1234, "beforeId": 5678 } // продол
350
527
 
351
528
  Ответ: `comments[]` по порядку (старые → новые) — `{ id, authorId, author, date, dateIso, text, isNew,
352
529
  system, files[] }`, плюс `total`, `oldestId`, `scannedPages` и **`reachedHistoryStart`**: если он
353
- `false` (упёрлись в `maxPages`, умолчание 10, или в `limit`), продолжай с `beforeId: <oldestId>`.
530
+ `false` (упёрлись в `maxPages` — умолчание и максимум 10 — или в `limit`), продолжай с `beforeId: <oldestId>`.
354
531
 
355
532
  - **`system: true`** — служебные записи («вы назначены исполнителем», смена срока, пинги), не слова людей.
356
533
  - **`date`** — как на портале («9 марта 2024 08:15»), **`dateIso`** — то же в `2024-03-09T08:15`
@@ -366,7 +543,87 @@ system, files[] }`, плюс `total`, `oldestId`, `scannedPages` и **`reachedHi
366
543
  `viewedDate` задачи после чтения не меняется. `isNew: true` — комментарий не прочитан пользователем.
367
544
  - Нет доступа к задаче / протухла сессия → внятная ошибка (портал отдаёт HTML логина).
368
545
 
546
+ ### 5.7. Закрыть задачу: Definition of Done
547
+
548
+ В scrum-проекте задача закрывается через критерии готовности (DoD), как в карточке задачи, и **мост их
549
+ не обходит**: отметить критерии выполненными может только второй вызов — после явного согласия
550
+ пользователя. Перенос в колонку типа `FINISH` закрыл бы задачу мимо DoD, поэтому операции доски такую
551
+ колонку не принимают (§3) — закрывай только так.
552
+
553
+ ```jsonc
554
+ // шаг 1
555
+ bitrix_task_close { "taskId": 4229 }
556
+ // не scrum-проект или DoD не нужен → задача сразу закрыта: { taskId, status: 5, changed: true }
557
+ // DoD нужен → задача НЕ закрыта:
558
+ // { taskId, needsConfirmation: true,
559
+ // types: [{ id: 1, name: "…", required: true, items: [{ title: "…", group: "…" }, …] }, …] }
560
+
561
+ // шаг 2 — только после «да» пользователя на критерии выбранного типа
562
+ bitrix_task_close { "taskId": 4229, "typeId": 1, "confirmItems": true }
563
+ // → { taskId, status: 5, changed: true, typeId: 1 }
564
+ ```
565
+
566
+ - `types` — типы задач проекта и критерии каждого; `required: true` — DoD для типа обязателен. `group` —
567
+ название группы чек-листа, в которой лежит критерий (сама группа в `items` не попадает). Покажи
568
+ пользователю критерии и получи его явное согласие отметить их выполненными для выбранного типа. Сам за
569
+ пользователя не решай: нет согласия — шаг 2 не вызывай. **Тип выбирает пользователь**: тип с
570
+ `required: false` закроет задачу без обязательных критериев — его тоже бери только с согласия
571
+ пользователя.
572
+ - На шаге 2 отмечаются **все** критерии типа, затем задача закрывается и статус перечитывается (не
573
+ закрылась — ошибка). `typeId` и `confirmItems: true` передаются только вместе; задаче не из
574
+ scrum-проекта они не нужны (ошибка — закрой её без них).
575
+ - Уже закрытая задача не трогается (`changed: false`). Закрытие видят все, кто видит задачу; участники
576
+ получают уведомление. Возобновить — `bitrix_task_reopen { "taskIds": [4229] }`.
577
+ - «критерии DoD отмечены выполненными, но закрыть задачу не удалось» — критерии уже отмечены, задача
578
+ открыта. «…— закрой задачу в интерфейсе» — мост не смог прочитать DoD из ответа Bitrix; предложи
579
+ пользователю закрыть задачу в веб-интерфейсе.
580
+
581
+ ### 5.8. Прикрепить локальный файл к задаче
582
+
583
+ ```jsonc
584
+ bitrix_task_file_attach { "taskId": 4229, "path": "/tmp/report.pdf" }
585
+ bitrix_task_file_attach { "taskId": 4229, "path": "/tmp/out.csv", "name": "итоги.csv" }
586
+ // → { taskId, diskFileId, name, size, attachmentId }
587
+ ```
588
+
589
+ - **Файл уходит с машины**: он загружается в корень Диска Битрикс24 пользователя и прикрепляется к
590
+ задаче — его увидят и смогут скачать все, кто видит задачу. Прикрепляй только то, что пользователь
591
+ явно попросил; любой другой файл — сначала спроси.
592
+ - `path` — **абсолютный** путь к обычному непустому файлу до 10 МБ: операция выполняется в процессе
593
+ daemon, а не в твоём рабочем каталоге. `name` — имя в Битрикс24 (по умолчанию — из `path`, без
594
+ разделителей пути); если имя на Диске занято, Битрикс24 добавит суффикс — итоговое имя в ответе.
595
+ - Из служебного каталога моста (`~/.bitrix24-mcp-bridge` или `BITRIX24_MCP_BRIDGE_HOME`; там настройки и
596
+ токен) прикрепляются только файлы, скачанные мостом, — из `downloads/` (их можно прикрепить к другой
597
+ задаче). Всё остальное в нём — отказ, в том числе через симлинк или `..`.
598
+ - Нужно право прикреплять файлы к задаче: тому, кто задачу только видит, Bitrix может отказать уже после
599
+ загрузки. Если прикрепить не удалось, файл **остаётся на Диске** пользователя — ошибка называет его (имя
600
+ и id); скажи об этом пользователю.
601
+ - «файл мог загрузиться на Диск» — проверь корневую папку Диска перед повтором; «вложение могло
602
+ создаться» — проверь файлы задачи (`bitrix_task_get` с `select: ["UF_TASK_WEBDAV_FILES"]` →
603
+ `bitrix_task_files`). После прикрепления файлы задачи перечитываются; вложения нет — ошибка.
604
+
605
+ ### 5.9. Напоминания и свои уведомления по задаче
606
+
607
+ Напоминания и выключение уведомлений касаются **только текущего пользователя**: другие участники их не
608
+ видят и получают уведомления как прежде.
609
+
610
+ ```jsonc
611
+ bitrix_task_reminders { "taskId": 4229 }
612
+ // → { taskId, reminders: [{ id, at, via, remindBy, recipient, userId, mine }] }
613
+ bitrix_task_reminder_set { "taskId": 4229, "at": "2026-12-01T09:00:00+03:00", "via": "notification" } // новое — тебе
614
+ bitrix_task_reminder_set { "taskId": 4229, "reminderId": 61, "at": "2026-12-02T06:00:00Z", "via": "email" }
615
+ bitrix_task_reminder_delete { "taskId": 4229, "reminderId": 61 }
616
+ bitrix_task_mute { "taskId": 4229, "muted": true } // выключить свои уведомления по задаче
617
+ ```
618
+
619
+ - Менять и удалять можно только **свои** напоминания — `mine: true` в `bitrix_task_reminders`; чужое или
620
+ не этой задачи — ошибка, ничего не меняется.
621
+ - `at` — абсолютная дата **в будущем** (формат — «Даты», §3); `via` — `notification` (уведомление в
622
+ Битрикс24) или `email`. Напоминание относительно срока (`remindBy: "deadline"`) после правки становится
623
+ напоминанием на дату; получатель (`recipient`) остаётся прежним.
624
+ - После записи напоминание и состояние уведомлений перечитываются; если они не те — ошибка.
625
+
369
626
  ---
370
627
 
371
- Расширение каталога новыми методами, транспорт (`bodyType`, `responseType`, path-параметры) и
372
- доставка правок в живой daemon — `docs/reconnaissance.md`.
628
+ Не хватает инструмента под нужное действие — скажи пользователю: новые операции добавляет
629
+ мейнтейнер моста (процесс — `docs/reconnaissance.md` в репозитории моста).