bitrix24-mcp-bridge 0.1.0 → 0.2.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/README.md +26 -15
- package/actions.example.json +27 -31
- package/dist/cli.js +190 -45
- package/docs/api-notes.md +234 -45
- package/extension/dist/connector.js +8 -4
- package/extension/dist/connector.js.map +2 -2
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Bitrix24 MCP Bridge
|
|
2
2
|
|
|
3
|
-
Локальный MCP-сервер, дающий ИИ-агенту
|
|
4
|
-
|
|
5
|
-
живую сессию. Без прав администратора и без
|
|
3
|
+
Локальный MCP-сервер, дающий ИИ-агенту доступ к задачам, проектам и чатам Bitrix24 (чтение
|
|
4
|
+
и — для вызовов из каталога — выполнение действий) — в объёме прав пользователя, через
|
|
5
|
+
браузерное расширение, переиспользующее живую сессию. Без прав администратора и без
|
|
6
|
+
официального REST-вебхука.
|
|
6
7
|
|
|
7
8
|
```
|
|
8
9
|
ИИ-агент ─stdio─► MCP-клиент ─UDS(bridge.sock)─► daemon ─WS(127.0.0.1:39917, токен+Origin)─► Расширение (вкладка портала)
|
|
@@ -14,16 +15,21 @@ Bitrix24 — в объёме прав пользователя, через бр
|
|
|
14
15
|
## Быстрый старт
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
|
-
# 1.
|
|
18
|
-
|
|
18
|
+
# 1. Настроить портал через npx — без глобальной установки (интерактивно): токен +
|
|
19
|
+
# первый портал + config.json + actions.json + расширение
|
|
20
|
+
npx -y bitrix24-mcp-bridge setup
|
|
19
21
|
|
|
20
|
-
# 2.
|
|
21
|
-
bitrix24-bridge
|
|
22
|
-
|
|
23
|
-
# 3. Зарегистрировать сервер у MCP-клиента (пример — Claude Code)
|
|
24
|
-
claude mcp add bitrix24-bridge -s user -- bitrix24-bridge
|
|
22
|
+
# 2. Зарегистрировать сервер у MCP-клиента (пример — Claude Code); каждый запуск идёт через npx
|
|
23
|
+
claude mcp add bitrix24-bridge -s user -- npx -y bitrix24-mcp-bridge
|
|
25
24
|
```
|
|
26
25
|
|
|
26
|
+
Пакет опубликован в npm registry как [`bitrix24-mcp-bridge`](https://www.npmjs.com/package/bitrix24-mcp-bridge)
|
|
27
|
+
(бинарь внутри называется `bitrix24-bridge`, но `npx bitrix24-mcp-bridge` резолвит его напрямую,
|
|
28
|
+
т.к. в `package.json` он объявлен под обоими именами). Глобальная установка (`npm i -g
|
|
29
|
+
bitrix24-mcp-bridge`) тоже работает и чуть быстрее стартует (без резолва npx при каждом
|
|
30
|
+
запуске MCP-клиента) — тогда в шаге 2 подставь `-- bitrix24-bridge` вместо `-- npx -y
|
|
31
|
+
bitrix24-mcp-bridge`.
|
|
32
|
+
|
|
27
33
|
Затем — два ручных шага, которые нельзя автоматизировать:
|
|
28
34
|
|
|
29
35
|
1. **Загрузить расширение.** `chrome://extensions` → включить **Developer mode** →
|
|
@@ -59,8 +65,9 @@ daemon после любой правки, затрагивающей конфи
|
|
|
59
65
|
|
|
60
66
|
## Инструменты
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
Типизированные инструменты — read-only; `bitrix_call` выполняет любой разрешённый каталогом
|
|
69
|
+
вызов, включая мутирующие. Каждый принимает необязательный параметр `portal` (alias; по
|
|
70
|
+
умолчанию — портал по умолчанию из `config.json`):
|
|
64
71
|
|
|
65
72
|
| Инструмент | Назначение |
|
|
66
73
|
|---|---|
|
|
@@ -119,9 +126,13 @@ Runtime-домашняя папка — `~/.bitrix24-mcp-bridge/` (или `$BITR
|
|
|
119
126
|
привилегия — живая аутентифицированная сессия Bitrix24 — физически в расширении, а не в
|
|
120
127
|
сервере. Отсюда:
|
|
121
128
|
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
- **Граница — это allowlist каталога, не режим чтения.** Мост выполняет только именованные
|
|
130
|
+
вызовы из `actions.json` — теперь среди них могут быть мутирующие. Общий локальный токен
|
|
131
|
+
(риск G7) в write-режиме означает: процесс, знающий токен и порт демона, может выполнять
|
|
132
|
+
эти действия в объёме прав пользователя. Внутри разрешённого действия значения `params`
|
|
133
|
+
не инспектируются — для мутирующего вызова это означает полный контроль агента над телом
|
|
134
|
+
запроса в рамках этого действия. Держи `actions.json` под контролем — это и есть
|
|
135
|
+
граница возможностей агента.
|
|
125
136
|
- **Токен — единственная защита loopback-WS.** Генерируйте длинный и случайный —
|
|
126
137
|
`setup` использует `crypto.randomBytes(32)`. Токен отсекает случайные подключения, но
|
|
127
138
|
не является границей против локального атакующего: любой локальный процесс, знающий
|
package/actions.example.json
CHANGED
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
"tasks.list": {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
"task.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
"projects.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
"chat.messages": {
|
|
30
|
-
"action": "im.v2.Chat.Message.list",
|
|
31
|
-
"method": "POST"
|
|
32
|
-
}
|
|
2
|
+
"tasks.list": { "action": "tasks.task.list", "method": "POST" },
|
|
3
|
+
"task.get": { "action": "tasks.task.get", "method": "POST" },
|
|
4
|
+
"task.v2.get": { "action": "tasks.v2.Task.get", "method": "POST", "bodyType": "json" },
|
|
5
|
+
"task.scrum.info": { "action": "tasks.v2.Scrum.getTaskInfo", "method": "POST", "bodyType": "json" },
|
|
6
|
+
"task.files": { "action": "tasks.v2.File.listObjects", "method": "POST", "bodyType": "json" },
|
|
7
|
+
"task.views.count": { "action": "tasks.v2.Task.View.User.count", "method": "POST", "bodyType": "json" },
|
|
8
|
+
|
|
9
|
+
"projects.list": { "action": "socialnetwork.api.workgroup.list", "method": "POST" },
|
|
10
|
+
"projects.get": { "action": "socialnetwork.api.workgroup.get", "method": "POST" },
|
|
11
|
+
|
|
12
|
+
"chats.recent": { "endpoint": "/rest/im.recent.list.json", "method": "POST", "params": { "LIMIT": 50, "SKIP_OPENLINES": "Y", "GET_ORIGINAL_TEXT": "Y", "PARSE_TEXT": "Y", "WITH_COUNTERS": "N" } },
|
|
13
|
+
"chat.load": { "action": "im.v2.Chat.load", "method": "POST", "params": { "messageLimit": 25 } },
|
|
14
|
+
"chat.messages": { "action": "im.v2.Chat.Message.list", "method": "POST" },
|
|
15
|
+
"chat.messages.tail": { "action": "im.v2.Chat.Message.tail", "method": "POST", "params": { "order[id]": "DESC", "limit": 25 } },
|
|
16
|
+
"chat.message.read": { "action": "im.v2.Chat.Message.read", "method": "POST" },
|
|
17
|
+
|
|
18
|
+
"entityselector.load": { "action": "ui.entityselector.load", "method": "POST", "bodyType": "json" },
|
|
19
|
+
"entityselector.search": { "action": "ui.entityselector.doSearch", "method": "POST", "bodyType": "json" },
|
|
20
|
+
|
|
21
|
+
"recent.load": { "action": "im.v2.Recent.load", "method": "POST" },
|
|
22
|
+
"recent.tail": { "action": "im.v2.Recent.tail", "method": "POST" },
|
|
23
|
+
"chat.dialogId": { "action": "im.v2.Chat.getDialogId", "method": "POST" },
|
|
24
|
+
"chat.read.all": { "action": "im.v2.Chat.readAll", "method": "POST" },
|
|
25
|
+
"im.user.get": { "endpoint": "/rest/im.user.get.json", "method": "POST" },
|
|
26
|
+
|
|
27
|
+
"task.subtasks": { "action": "tasks.v2.Task.Relation.Child.list", "method": "POST", "bodyType": "json" },
|
|
28
|
+
"task.related": { "action": "tasks.v2.Task.Relation.Related.list", "method": "POST", "bodyType": "json" }
|
|
33
29
|
}
|