@hubex/mcp 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/.env.example +54 -0
- package/CONNECTING.md +260 -0
- package/README.md +266 -0
- package/dist/auth.js +226 -0
- package/dist/config.js +120 -0
- package/dist/generated/manifest.js +3643 -0
- package/dist/guides/field-notes.json +27 -0
- package/dist/guides/loader.js +32 -0
- package/dist/guides/service-map.js +6 -0
- package/dist/http.js +93 -0
- package/dist/index/store.js +134 -0
- package/dist/index/types.js +1 -0
- package/dist/index.js +20 -0
- package/dist/paths.js +20 -0
- package/dist/pii/fields.js +100 -0
- package/dist/pii/mask.js +50 -0
- package/dist/pii/strategies.js +88 -0
- package/dist/schema/build-index.js +67 -0
- package/dist/schema/deref.js +87 -0
- package/dist/schema/describe.js +65 -0
- package/dist/server.js +62 -0
- package/dist/token-prompt.js +41 -0
- package/dist/tools/curated.js +151 -0
- package/dist/tools/discovery.js +187 -0
- package/dist/tools/guides.js +126 -0
- package/dist/tools/registry.js +37 -0
- package/dist/tools/request.js +170 -0
- package/dist/tools/types.js +1 -0
- package/docs/guides/assets.md +334 -0
- package/docs/guides/attributes.md +125 -0
- package/docs/guides/checklisttemplates.md +154 -0
- package/docs/guides/companies.md +57 -0
- package/docs/guides/dictionaries.md +64 -0
- package/docs/guides/lifecycle.md +263 -0
- package/docs/guides/materials.md +135 -0
- package/docs/guides/notifications.md +184 -0
- package/docs/guides/roles.md +125 -0
- package/docs/guides/sla.md +130 -0
- package/docs/guides/start.md +67 -0
- package/docs/guides/taskchecklists.md +149 -0
- package/docs/guides/taskcreate.md +260 -0
- package/docs/guides/taskedit.md +277 -0
- package/docs/guides/tasktypes.md +156 -0
- package/docs/guides/users.md +71 -0
- package/generated/index.dev.json +18776 -0
- package/generated/index.prod.json +18858 -0
- package/package.json +48 -0
- package/swagger/dev/ADM.json +27777 -0
- package/swagger/dev/AUTH.json +1739 -0
- package/swagger/dev/AUTHN.json +1250 -0
- package/swagger/dev/AUTHZ.json +1404 -0
- package/swagger/dev/CM.json +309 -0
- package/swagger/dev/COMMON.json +6543 -0
- package/swagger/dev/ES.json +28029 -0
- package/swagger/dev/EXPORT.json +4575 -0
- package/swagger/dev/IMPORT.json +1479 -0
- package/swagger/dev/LIC.json +224 -0
- package/swagger/dev/MSG.json +7883 -0
- package/swagger/dev/NEWS.json +348 -0
- package/swagger/dev/PA.json +5981 -0
- package/swagger/dev/PMP.json +3196 -0
- package/swagger/dev/PROXY.json +416 -0
- package/swagger/dev/REPORT.json +3921 -0
- package/swagger/dev/SC.json +3771 -0
- package/swagger/dev/SLA.json +2837 -0
- package/swagger/dev/TSTG.json +4981 -0
- package/swagger/dev/UI.json +4720 -0
- package/swagger/dev/WH.json +16796 -0
- package/swagger/dev/WORK.json +36024 -0
- package/swagger/dev/WSP.json +1612 -0
- package/swagger/prod/ADM.json +27777 -0
- package/swagger/prod/AUTH.json +1308 -0
- package/swagger/prod/AUTHN.json +2710 -0
- package/swagger/prod/AUTHZ.json +896 -0
- package/swagger/prod/CM.json +162 -0
- package/swagger/prod/COMMON.json +4910 -0
- package/swagger/prod/ES.json +28029 -0
- package/swagger/prod/EXPORT.json +3091 -0
- package/swagger/prod/LIC.json +123 -0
- package/swagger/prod/MSG.json +6239 -0
- package/swagger/prod/NEWS.json +295 -0
- package/swagger/prod/PA.json +5123 -0
- package/swagger/prod/PMP.json +2978 -0
- package/swagger/prod/PROXY.json +250 -0
- package/swagger/prod/REPORT.json +3729 -0
- package/swagger/prod/SC.json +3771 -0
- package/swagger/prod/SLA.json +2201 -0
- package/swagger/prod/TSTG.json +4220 -0
- package/swagger/prod/UI.json +3879 -0
- package/swagger/prod/WH.json +16730 -0
- package/swagger/prod/WORK.json +35994 -0
- package/swagger/prod/WSP.json +1468 -0
package/.env.example
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# --- HubEx MCP configuration ---
|
|
2
|
+
|
|
3
|
+
# Target environment: dev | stg | prod
|
|
4
|
+
# prod ходит на https://api.hubex.ru/fsm (без префикса), dev/stg — на https://{env}-api.hubex.ru/fsm
|
|
5
|
+
# Этой же переменной выбирается кэш swagger-схем: prod читает swagger/prod/ и
|
|
6
|
+
# generated/index.prod.json, dev и stg — swagger/dev/ и generated/index.dev.json.
|
|
7
|
+
HUBEX_ENV=dev
|
|
8
|
+
|
|
9
|
+
# Required header for every request. For the dev tenant this is 5.
|
|
10
|
+
HUBEX_APPLICATION_ID=5
|
|
11
|
+
|
|
12
|
+
# Optional: pin the tenant explicitly. If omitted, it is read from the JWT (TenantID claim).
|
|
13
|
+
# HUBEX_TENANT_ID=5
|
|
14
|
+
|
|
15
|
+
# Auth mode: token | login | service
|
|
16
|
+
HUBEX_AUTH_MODE=token
|
|
17
|
+
|
|
18
|
+
# --- mode "token" ---
|
|
19
|
+
# Ничего настраивать не нужно: сервер сам попросит access-токен при первом
|
|
20
|
+
# обращении (поле ввода в клиенте, либо инструмент hubex_set_token).
|
|
21
|
+
|
|
22
|
+
# --- mode "login" ---
|
|
23
|
+
# HUBEX_AUTH_MODE=login
|
|
24
|
+
# HUBEX_USERNAME=poweruser@hubex.ru
|
|
25
|
+
# HUBEX_PASSWORD=your-password
|
|
26
|
+
|
|
27
|
+
# --- mode "service" ---
|
|
28
|
+
# Долгоживущий интеграционный токен. HUBEX_TENANT_ID в этом режиме не нужен:
|
|
29
|
+
# токен сам определяет члена тенанта.
|
|
30
|
+
# HUBEX_AUTH_MODE=service
|
|
31
|
+
# HUBEX_SERVICE_TOKEN=ВАШ_ИНТЕГРАЦИОННЫЙ_ТОКЕН
|
|
32
|
+
|
|
33
|
+
# Какие HTTP-методы вообще доступны серверу.
|
|
34
|
+
# По умолчанию все: GET,POST,PUT,PATCH,DELETE,HEAD
|
|
35
|
+
# Запрещённые методы не регистрируются: их search_*/request_* не видны агенту.
|
|
36
|
+
# HUBEX_METHODS=GET,POST,PUT
|
|
37
|
+
|
|
38
|
+
# Эквивалент HUBEX_METHODS=GET,HEAD. При конфликте побеждает более узкое.
|
|
39
|
+
# HUBEX_READONLY=true
|
|
40
|
+
|
|
41
|
+
# Ограничить область поиска и исполнения списком сервисов.
|
|
42
|
+
# По умолчанию доступны все 22.
|
|
43
|
+
# HUBEX_SERVICES=WORK,ES,ADM
|
|
44
|
+
|
|
45
|
+
# Значения, подставляемые в тело write-запросов, если поле не задано.
|
|
46
|
+
# HUBEX_DEFAULT_REQUEST_METHOD_ID=4
|
|
47
|
+
# HUBEX_DEFAULT_TASK_TYPE_ID=1
|
|
48
|
+
# HUBEX_DEFAULT_COMPANY_ID=123
|
|
49
|
+
|
|
50
|
+
# Маскировать персональные данные (ФИО, телефоны, email, адреса, логины,
|
|
51
|
+
# токены, координаты) в ответах перед отдачей в контекст модели.
|
|
52
|
+
# По умолчанию включено. Выключается только явно — маска необратима,
|
|
53
|
+
# и агент не сможет использовать увиденное значение в следующем запросе.
|
|
54
|
+
# HUBEX_MASK_PII=false
|
package/CONNECTING.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Подключение HubEx MCP
|
|
2
|
+
|
|
3
|
+
Инструкции по подключению сервера к разным клиентам: **Claude Code**, **Claude Desktop**,
|
|
4
|
+
**Codex CLI** и **Cursor**.
|
|
5
|
+
|
|
6
|
+
## 0. Как получить сервер
|
|
7
|
+
|
|
8
|
+
Пакет называется `@hubex/mcp` и публикуется в публичный npmjs. Во всех конфигах ниже
|
|
9
|
+
используется команда `hubex-mcp` — она появляется в `PATH` после глобальной установки
|
|
10
|
+
(имя команды осталось прежним, скоуп на него не влияет).
|
|
11
|
+
|
|
12
|
+
### Вариант А — из npm (обычный путь)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g @hubex/mcp
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Проверка: `which hubex-mcp`. Обновление — `npm update -g @hubex/mcp`,
|
|
19
|
+
удаление — `npm rm -g @hubex/mcp`.
|
|
20
|
+
|
|
21
|
+
Без установки — `npx -y @hubex/mcp`; тогда в конфигах вместо `"command": "hubex-mcp"`
|
|
22
|
+
пишут `"command": "npx"` и `"args": ["-y", "@hubex/mcp"]`.
|
|
23
|
+
|
|
24
|
+
Патч-часть версии — дата сборки схем по UTC (`0.2.20260827`), так что по версии
|
|
25
|
+
установленного пакета сразу видно, насколько свежий в нём кэш swagger.
|
|
26
|
+
|
|
27
|
+
> Первый релиз выпускается вручную, и до него этот вариант вернёт 404 —
|
|
28
|
+
> пользуйтесь вариантом Б.
|
|
29
|
+
|
|
30
|
+
### Вариант Б — готовый пакет (для тех, кому его передали)
|
|
31
|
+
|
|
32
|
+
Автор присылает файл `hubex-mcp-<версия>.tgz` (имя файла без скоупа — npm склеивает
|
|
33
|
+
`@hubex/mcp` в `hubex-mcp`). Установка:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g ./hubex-mcp-0.2.0.tgz
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Дальше всё как в варианте А: в `PATH` появляется команда `hubex-mcp`, абсолютные пути
|
|
40
|
+
к `dist/index.js` не нужны. Обновление — переустановить новый `.tgz` той же командой.
|
|
41
|
+
|
|
42
|
+
### Вариант В — собрать пакет для раздачи (автор)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cd /path/to/hubexMCP
|
|
46
|
+
npm install
|
|
47
|
+
npm pack
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`npm pack` сам запускает сборку (`prepack` → `npm run build`) и кладёт рядом
|
|
51
|
+
`hubex-mcp-<версия>.tgz` — самодостаточный архив: скомпилированный `dist/`, индекс
|
|
52
|
+
эндпоинтов `generated/index.{dev,prod}.json`, кэш `swagger/{dev,prod}/` и гайды
|
|
53
|
+
`docs/guides/`.
|
|
54
|
+
Получателю нужен только Node.js ≥ 20 — ни исходников, ни репозитория.
|
|
55
|
+
|
|
56
|
+
Перед раздачей поднимите `version` в `package.json`: она видна клиенту в `serverInfo`
|
|
57
|
+
и по ней получатель понимает, что у него за сборка.
|
|
58
|
+
|
|
59
|
+
> `npm publish` уедет в публичный npmjs (`publishConfig.access: "public"`), а внутрь
|
|
60
|
+
> тарбола попадает кэш внутренних swagger-схем обоих контуров — учитывайте это перед
|
|
61
|
+
> публикацией.
|
|
62
|
+
|
|
63
|
+
### Вариант Г — из исходников (разработка сервера)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd /path/to/hubexMCP
|
|
67
|
+
npm install
|
|
68
|
+
npm run build
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Точка входа: `<путь-до-репозитория>/dist/index.js` — её указывают вместо команды
|
|
72
|
+
`hubex-mcp` в конфигах ниже (`"command": "node"`, `"args": ["<путь>/dist/index.js"]`).
|
|
73
|
+
Пересобирайте после каждого `git pull`.
|
|
74
|
+
|
|
75
|
+
### Переменные окружения
|
|
76
|
+
|
|
77
|
+
| Переменная | Обязательна | Значение |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `HUBEX_ENV` | да | `dev`, `stg` или `prod` |
|
|
80
|
+
| `HUBEX_APPLICATION_ID` | да | `5` (для dev-тенанта) |
|
|
81
|
+
| `HUBEX_AUTH_MODE` | да | `token`, `login` или `service` |
|
|
82
|
+
| `HUBEX_USERNAME` / `HUBEX_PASSWORD` | для `login` | логин/пароль (токен обновляется сам) |
|
|
83
|
+
| `HUBEX_SERVICE_TOKEN` | для `service` | долгоживущий интеграционный токен (обновляется сам) |
|
|
84
|
+
| `HUBEX_TENANT_ID` | нет | tenant явно; иначе берётся из JWT |
|
|
85
|
+
| `HUBEX_METHODS` | нет | список доступных HTTP-методов через запятую (по умолчанию — все шесть) |
|
|
86
|
+
| `HUBEX_READONLY` | нет | `true` — эквивалент `HUBEX_METHODS=GET,HEAD` |
|
|
87
|
+
| `HUBEX_SERVICES` | нет | ограничить поиск и исполнение списком сервисов (по умолчанию — все 22) |
|
|
88
|
+
| `HUBEX_DEFAULT_REQUEST_METHOD_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
89
|
+
| `HUBEX_DEFAULT_TASK_TYPE_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
90
|
+
| `HUBEX_DEFAULT_COMPANY_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
91
|
+
|
|
92
|
+
> Режим `token` переменных не требует: при первом обращении сервер попросит
|
|
93
|
+
> access-токен. Клиенты с поддержкой elicitation (Claude Code, Claude Desktop)
|
|
94
|
+
> покажут поле ввода; остальным нужно вызвать инструмент `hubex_set_token` и
|
|
95
|
+
> передать токен в него. По токену запрашивается refresh, дальше сессия
|
|
96
|
+
> продлевается сама; после перезапуска сервера токен спрашивается заново.
|
|
97
|
+
|
|
98
|
+
> Сервисный токен выпускается один раз администратором:
|
|
99
|
+
> `POST /fsm/AUTHZ/ServiceTokens` с Bearer и полномочием `ServiceTokenAdd`, тело — массив id
|
|
100
|
+
> членов тенанта. Отзыв — `DELETE /fsm/AUTHZ/ServiceTokens` с полномочием `ServiceTokenRemove`.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 1. Claude Code (CLI)
|
|
105
|
+
|
|
106
|
+
Команда `claude mcp add` со scope `user` — сервер станет доступен во **всех** ваших проектах:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
claude mcp add hubex --scope user \
|
|
110
|
+
--env HUBEX_ENV=dev \
|
|
111
|
+
--env HUBEX_APPLICATION_ID=5 \
|
|
112
|
+
--env HUBEX_AUTH_MODE=login \
|
|
113
|
+
--env HUBEX_USERNAME=poweruser@hubex.ru \
|
|
114
|
+
--env HUBEX_PASSWORD=<пароль> \
|
|
115
|
+
-- hubex-mcp
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
С сервисным токеном (`--env HUBEX_AUTH_MODE=service --env HUBEX_SERVICE_TOKEN=<токен>` вместо
|
|
119
|
+
`HUBEX_AUTH_MODE=login` + `HUBEX_USERNAME`/`HUBEX_PASSWORD`) — удобно для CI и общих окружений,
|
|
120
|
+
где заводить учётку не хочется.
|
|
121
|
+
|
|
122
|
+
Без `--scope user` конфиг попадёт в scope `local` — только для текущего каталога.
|
|
123
|
+
|
|
124
|
+
Проверка: `claude mcp list` → `hubex: ✓ connected`. Список инструментов — командой `/mcp`
|
|
125
|
+
внутри сессии (после перезапуска).
|
|
126
|
+
|
|
127
|
+
Чтобы расшарить конфиг команде через git, используйте scope `project` (создаёт `.mcp.json`
|
|
128
|
+
в корне репозитория — **без секретов**, подставляйте токен/пароль из окружения):
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
claude mcp add hubex --scope project -- hubex-mcp
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Удалить: `claude mcp remove hubex`.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 2. Claude Desktop
|
|
139
|
+
|
|
140
|
+
Файл конфигурации:
|
|
141
|
+
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS).
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"mcpServers": {
|
|
146
|
+
"hubex": {
|
|
147
|
+
"command": "hubex-mcp",
|
|
148
|
+
"env": {
|
|
149
|
+
"HUBEX_ENV": "dev",
|
|
150
|
+
"HUBEX_APPLICATION_ID": "5",
|
|
151
|
+
"HUBEX_AUTH_MODE": "login",
|
|
152
|
+
"HUBEX_USERNAME": "...",
|
|
153
|
+
"HUBEX_PASSWORD": "...",
|
|
154
|
+
"HUBEX_METHODS": "GET,HEAD,POST,PUT",
|
|
155
|
+
"HUBEX_SERVICES": "WORK,ES,ADM",
|
|
156
|
+
"HUBEX_DEFAULT_REQUEST_METHOD_ID": "4"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Этот пример разрешает всё, кроме удаления; чтобы вернуть `DELETE`, добавь его в
|
|
164
|
+
`HUBEX_METHODS` — тогда появятся `hubex_search_delete_endpoints` и `hubex_request_delete`.
|
|
165
|
+
|
|
166
|
+
Для сервисного токена замени `HUBEX_AUTH_MODE`/`HUBEX_USERNAME`/`HUBEX_PASSWORD` на:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
"HUBEX_AUTH_MODE": "service",
|
|
170
|
+
"HUBEX_SERVICE_TOKEN": "<токен>"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
После правки **полностью перезапустите** Claude Desktop. Инструменты появятся в меню 🔌.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 3. Codex CLI
|
|
178
|
+
|
|
179
|
+
Codex хранит конфиг MCP в `~/.codex/config.toml` (формат TOML, секция `mcp_servers`):
|
|
180
|
+
|
|
181
|
+
```toml
|
|
182
|
+
[mcp_servers.hubex]
|
|
183
|
+
command = "hubex-mcp"
|
|
184
|
+
args = []
|
|
185
|
+
|
|
186
|
+
[mcp_servers.hubex.env]
|
|
187
|
+
HUBEX_ENV = "dev"
|
|
188
|
+
HUBEX_APPLICATION_ID = "5"
|
|
189
|
+
HUBEX_AUTH_MODE = "login"
|
|
190
|
+
HUBEX_USERNAME = "poweruser@hubex.ru"
|
|
191
|
+
HUBEX_PASSWORD = "<пароль>"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Либо через CLI (если версия поддерживает):
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
codex mcp add hubex \
|
|
198
|
+
--env HUBEX_ENV=dev --env HUBEX_APPLICATION_ID=5 \
|
|
199
|
+
--env HUBEX_AUTH_MODE=login \
|
|
200
|
+
--env HUBEX_USERNAME=poweruser@hubex.ru --env HUBEX_PASSWORD=<пароль> \
|
|
201
|
+
-- hubex-mcp
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Для сервисного токена замени `HUBEX_AUTH_MODE = "login"` + `HUBEX_USERNAME`/`HUBEX_PASSWORD`
|
|
205
|
+
(или `--env HUBEX_AUTH_MODE=login ...`) на `HUBEX_AUTH_MODE = "service"` +
|
|
206
|
+
`HUBEX_SERVICE_TOKEN = "<токен>"`.
|
|
207
|
+
|
|
208
|
+
Проверка: `codex mcp list`.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 4. Cursor
|
|
213
|
+
|
|
214
|
+
Cursor читает MCP из JSON:
|
|
215
|
+
|
|
216
|
+
- глобально — `~/.cursor/mcp.json`;
|
|
217
|
+
- для проекта — `.cursor/mcp.json` в корне репозитория.
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"mcpServers": {
|
|
222
|
+
"hubex": {
|
|
223
|
+
"command": "hubex-mcp",
|
|
224
|
+
"env": {
|
|
225
|
+
"HUBEX_ENV": "dev",
|
|
226
|
+
"HUBEX_APPLICATION_ID": "5",
|
|
227
|
+
"HUBEX_AUTH_MODE": "login",
|
|
228
|
+
"HUBEX_USERNAME": "poweruser@hubex.ru",
|
|
229
|
+
"HUBEX_PASSWORD": "<пароль>"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Для сервисного токена замени `HUBEX_AUTH_MODE`/`HUBEX_USERNAME`/`HUBEX_PASSWORD` на:
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
"HUBEX_AUTH_MODE": "service",
|
|
240
|
+
"HUBEX_SERVICE_TOKEN": "<токен>"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Затем: **Cursor → Settings → MCP** и включите сервер `hubex` (кнопка обновить/enable).
|
|
244
|
+
Зелёный индикатор = подключено.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Проверка после подключения
|
|
249
|
+
|
|
250
|
+
Вызовите инструмент `hubex_whoami` — он вернёт окружение, tenant и срок действия токена.
|
|
251
|
+
Если видите `tokenExpired: true` или ошибки 401 — обновите токен или используйте режим
|
|
252
|
+
`login`/`service` (сервер сам получает и обновляет токен, см. раздел «Переменные окружения»).
|
|
253
|
+
|
|
254
|
+
## Безопасность
|
|
255
|
+
|
|
256
|
+
- Не коммитьте реальные токены/пароли. Файлы `.mcp.json` / `.cursor/mcp.json` с секретами
|
|
257
|
+
добавляйте в `.gitignore` или храните значения в переменных окружения.
|
|
258
|
+
- Окружение выбирается через `HUBEX_ENV` (`dev` / `stg` / `prod`); на проде базовый URL без префикса —
|
|
259
|
+
`https://api.hubex.ru/fsm`. Для прода стоит держать `HUBEX_READONLY=true`, если запись не нужна.
|
|
260
|
+
- Для полностью безопасного режима задайте `HUBEX_READONLY=true`.
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# HubEx MCP
|
|
2
|
+
|
|
3
|
+
MCP-сервер для управления **тестовыми данными** в HubEx (создание, редактирование, удаление
|
|
4
|
+
заявок, объектов, компаний, пользователей) прямо из Claude.
|
|
5
|
+
|
|
6
|
+
Окружение задаётся в `HUBEX_ENV`: `dev`, `stg` или `prod`. На проде базовый URL — без префикса
|
|
7
|
+
(`https://api.hubex.ru/fsm`); ограничить его чтением можно через `HUBEX_READONLY=true`.
|
|
8
|
+
|
|
9
|
+
## Что внутри
|
|
10
|
+
|
|
11
|
+
- **13 инструментов** (список — в разделе [«Инструменты»](#инструменты)): поиск и исполнение
|
|
12
|
+
работают через тонкий индекс, а не через по-эндпоинтную генерацию, поэтому их число не растёт
|
|
13
|
+
вместе с количеством эндпоинтов HubEx (~1100 в 22 сервисах).
|
|
14
|
+
- Единый HTTP-клиент с авторизацией (Bearer + `X-Application-ID`) и понятными сообщениями об ошибках.
|
|
15
|
+
- Два режима авторизации: готовый токен или логин/пароль (Basic → JWT через сервис AUTHN, авто-refresh).
|
|
16
|
+
- Три независимых рубежа ограничения доступа: список HTTP-методов на сервере, тумблеры инструментов
|
|
17
|
+
в MCP-клиенте, проверка метода на исполнении.
|
|
18
|
+
|
|
19
|
+
## Установка
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Инструменты
|
|
27
|
+
|
|
28
|
+
13 инструментов, число не зависит от количества эндпоинтов HubEx (~1100 в 22 сервисах).
|
|
29
|
+
|
|
30
|
+
| Инструмент | Назначение |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `hubex_whoami` | окружение, tenant, срок действия токена |
|
|
33
|
+
| `hubex_get_guide` | гайд по процессу, топики сгруппированы по областям: база — `start`, `dictionaries`; заявки — `taskcreate`, `taskedit`, `taskchecklists`; объекты и контрагенты — `assets`, `companies`, `users`, `materials`; настройка тенанта — `lifecycle`, `tasktypes`, `roles`, `notifications`, `sla`, `attributes`, `checklisttemplates` |
|
|
34
|
+
| `hubex_list_scopes` | карта сервисов; с `service` — ресурсы внутри |
|
|
35
|
+
| `hubex_search_read_endpoints` | поиск GET-эндпоинтов |
|
|
36
|
+
| `hubex_search_write_endpoints` | поиск POST/PUT/PATCH-эндпоинтов |
|
|
37
|
+
| `hubex_search_delete_endpoints` | поиск DELETE-эндпоинтов |
|
|
38
|
+
| `hubex_search_head_endpoints` | поиск HEAD-эндпоинтов |
|
|
39
|
+
| `hubex_describe_endpoint` | полная схема параметров и тела (до 5 идентификаторов за вызов) |
|
|
40
|
+
| `hubex_request_read` | выполнить GET |
|
|
41
|
+
| `hubex_request_write` | выполнить POST/PUT/PATCH |
|
|
42
|
+
| `hubex_request_delete` | выполнить DELETE (принимает `body`: часть эндпоинтов удаляет пачкой по списку) |
|
|
43
|
+
| `hubex_request_head` | выполнить HEAD |
|
|
44
|
+
| `hubex_create_test_task` | создать тестовую заявку с дефолтами и префиксом `[MCP-TEST]` |
|
|
45
|
+
|
|
46
|
+
### Как этим пользоваться
|
|
47
|
+
|
|
48
|
+
Типичный путь модели:
|
|
49
|
+
|
|
50
|
+
1. `hubex_get_guide` с нужным топиком — понять порядок вызовов.
|
|
51
|
+
2. `hubex_list_scopes` — увидеть сервисы; с `service=WORK` — ресурсы внутри.
|
|
52
|
+
3. `hubex_search_read_endpoints` со `scope`/`tag`/`query` — найти эндпоинт.
|
|
53
|
+
4. `hubex_describe_endpoint` — получить схему только для того, что будет вызвано.
|
|
54
|
+
5. `hubex_request_*` — выполнить.
|
|
55
|
+
|
|
56
|
+
Ступени необязательны: зная идентификатор из гайда, можно идти сразу к шагу 4.
|
|
57
|
+
|
|
58
|
+
### Ограничение доступных методов
|
|
59
|
+
|
|
60
|
+
Три независимых рубежа:
|
|
61
|
+
|
|
62
|
+
1. `HUBEX_METHODS` на сервере — запрещённые группы не регистрируются и не видны агенту.
|
|
63
|
+
2. Тумблеры инструментов в MCP-клиенте — можно выключить пару `search_delete` + `request_delete`.
|
|
64
|
+
3. Проверка на исполнении — `request_*` принимает только `endpointId` и отклоняет чужой метод.
|
|
65
|
+
|
|
66
|
+
Поэтому поиск и исполнение разделены по методам симметрично: выключения только
|
|
67
|
+
поискового инструмента было бы недостаточно.
|
|
68
|
+
|
|
69
|
+
## Миграция с 0.1.x
|
|
70
|
+
|
|
71
|
+
Это ломающее изменение: все инструменты v1 вида `hubex_work_tasks_list`, `hubex_es_assets_get`
|
|
72
|
+
и подобные (по одному на каждый сгенерированный эндпоинт) больше не существуют. Взамен —
|
|
73
|
+
лестница `hubex_list_scopes → hubex_search_*_endpoints → hubex_describe_endpoint → hubex_request_*`,
|
|
74
|
+
описанная выше. `hubex_whoami` и `hubex_create_test_task` не изменились. Если в сохранённых
|
|
75
|
+
промптах или конфигурации использовались v1-имена инструментов — замените их на новую лестницу.
|
|
76
|
+
|
|
77
|
+
## Конфигурация
|
|
78
|
+
|
|
79
|
+
Переменные окружения (см. `.env.example`):
|
|
80
|
+
|
|
81
|
+
| Переменная | Обязательна | Описание |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `HUBEX_ENV` | да | `dev`, `stg` или `prod` |
|
|
84
|
+
| `HUBEX_APPLICATION_ID` | да | заголовок `X-Application-ID` (для dev-тенанта — `5`) |
|
|
85
|
+
| `HUBEX_AUTH_MODE` | да | `token`, `login` или `service` |
|
|
86
|
+
| `HUBEX_USERNAME` / `HUBEX_PASSWORD` | для `login` | учётные данные |
|
|
87
|
+
| `HUBEX_SERVICE_TOKEN` | для `service` | долгоживущий интеграционный токен |
|
|
88
|
+
| `HUBEX_TENANT_ID` | нет | tenant явно; иначе берётся из JWT (`TenantID`) |
|
|
89
|
+
| `HUBEX_METHODS` | нет | список доступных HTTP-методов через запятую (по умолчанию — все шесть) |
|
|
90
|
+
| `HUBEX_READONLY` | нет | `true` — эквивалент `HUBEX_METHODS=GET,HEAD` |
|
|
91
|
+
| `HUBEX_MASK_PII` | нет | по умолчанию `true` — маскирует ПДн (ФИО, телефоны, email и т.п.) в ответах; `false` отключает маскирование |
|
|
92
|
+
| `HUBEX_SERVICES` | нет | ограничить поиск и исполнение списком сервисов (по умолчанию — все 22) |
|
|
93
|
+
| `HUBEX_DEFAULT_REQUEST_METHOD_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
94
|
+
| `HUBEX_DEFAULT_TASK_TYPE_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
95
|
+
| `HUBEX_DEFAULT_COMPANY_ID` | нет | значение по умолчанию для тела write-запросов |
|
|
96
|
+
|
|
97
|
+
Режим `token` переменных не требует: при первом обращении сервер сам попросит
|
|
98
|
+
access-токен (через MCP elicitation, а если клиент этого не умеет — через
|
|
99
|
+
инструмент `hubex_set_token`). По введённому токену запрашивается refresh, и
|
|
100
|
+
дальше сессия продлевается сама. Токены хранятся только в памяти процесса — после
|
|
101
|
+
перезапуска сервер спросит токен заново.
|
|
102
|
+
|
|
103
|
+
## Подключение
|
|
104
|
+
|
|
105
|
+
Полное руководство для **Claude Code, Claude Desktop, Codex CLI и Cursor** — в [CONNECTING.md](CONNECTING.md).
|
|
106
|
+
|
|
107
|
+
Кратко. Соберите пакет (`npm pack`) и установите его — появится команда `hubex-mcp`:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm install -g ./hubex-mcp-0.2.0.tgz
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Claude Desktop (`claude_desktop_config.json`):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"hubex": {
|
|
119
|
+
"command": "hubex-mcp",
|
|
120
|
+
"env": {
|
|
121
|
+
"HUBEX_ENV": "dev",
|
|
122
|
+
"HUBEX_APPLICATION_ID": "5",
|
|
123
|
+
"HUBEX_AUTH_MODE": "token"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Для Claude Code (во всех проектах): `claude mcp add hubex --scope user -- hubex-mcp`
|
|
131
|
+
(переменные окружения задайте через `--env` или в `.env` окружении процесса).
|
|
132
|
+
|
|
133
|
+
## Разработка
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npm run generate # перегенерировать оба индекса из swagger/{dev,prod}/*.json
|
|
137
|
+
npm run refresh-swagger # скачать swagger обоих контуров заново и перегенерировать индексы
|
|
138
|
+
npm run check-swagger # CI: обновить swagger и упасть, если индекс разошёлся
|
|
139
|
+
npm run release-swagger # обновить схемы и, при изменениях, выпустить релиз в npm
|
|
140
|
+
npm run typecheck # проверка типов (src, scripts и test)
|
|
141
|
+
npm test # unit-тесты (vitest)
|
|
142
|
+
npm run check-guides # сверить источники гайдов с первоисточниками
|
|
143
|
+
npm run dev # запуск из исходников (tsx)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`npm run check-guides -- /path/to/HubEx.Wiki [/path/to/HubEx.Frontend.AdminApp]`
|
|
147
|
+
сверяет `sources` во фронтматтере каждого гайда с первоисточником: страницы вики
|
|
148
|
+
(`admin/...`) — по полю `content_hash` самой страницы, файлы AdminApp
|
|
149
|
+
(`adminapp/...`) — по sha256 содержимого. Без второго пути источники AdminApp
|
|
150
|
+
пропускаются. Ненулевой код возврата означает, что первоисточник изменился и
|
|
151
|
+
гайд пора перечитать.
|
|
152
|
+
|
|
153
|
+
### Контуры swagger: dev и prod
|
|
154
|
+
|
|
155
|
+
Схемы хранятся раздельно, по каталогу на контур, и индекс собирается для каждого:
|
|
156
|
+
|
|
157
|
+
| Контур | Кэш схем | Индекс | Источник |
|
|
158
|
+
| ------ | -------------- | --------------------------- | ------------------------------------------------------------ |
|
|
159
|
+
| `dev` | `swagger/dev/` | `generated/index.dev.json` | `https://dev-api.hubex.ru/fsm/{SERVICE}/swagger/{версия}/swagger.json` |
|
|
160
|
+
| `prod` | `swagger/prod/` | `generated/index.prod.json` | `https://api.hubex.ru/fsm/{SERVICE}/swagger/{версия}/swagger.json` (то же, что раздаёт [doc.hubex.ru](https://doc.hubex.ru/#/)) |
|
|
161
|
+
|
|
162
|
+
Контур выбирается на старте сервера по `HUBEX_ENV`: `prod` читает prod-каталог,
|
|
163
|
+
`dev` и `stg` — dev-каталог (отдельного стенда документации у stg нет). Поиск,
|
|
164
|
+
`hubex_describe_endpoint` и валидация тел запросов работают по схемам выбранного
|
|
165
|
+
контура, так что на проде агент не увидит эндпоинтов, которых там ещё нет.
|
|
166
|
+
|
|
167
|
+
`npm run generate` всегда пересобирает оба индекса — оба каталога должны быть на месте.
|
|
168
|
+
|
|
169
|
+
Список сервисов берётся со страницы документации контура — `doc.hubex.ru` для prod
|
|
170
|
+
и `dev-doc.hubex.ru` для dev. Каталог `swagger/` источником быть не может: по нему
|
|
171
|
+
не узнать о сервисе, которого там ещё нет. Со страницы берутся только ссылки на
|
|
172
|
+
хост своего контура — dev-страница перечисляет заодно и stg.
|
|
173
|
+
|
|
174
|
+
`npm run refresh-swagger` без аргументов обновляет оба контура. Ограничения:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npm run refresh-swagger -- --catalog=prod # только prod
|
|
178
|
+
npm run refresh-swagger -- --catalog=dev WORK ES ADM # отдельные сервисы одного контура
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Список сервисов допустим только вместе с `--catalog`, а индекс после загрузки всё
|
|
182
|
+
равно строится по всему каталогу контура. Версия схем — `v1.0.0.0`, меняется через
|
|
183
|
+
`HUBEX_SWAGGER_VERSION`.
|
|
184
|
+
|
|
185
|
+
### Проверка расхождений в пайплайне
|
|
186
|
+
|
|
187
|
+
`npm run check-swagger` обновляет схемы и сравнивает результат с тем, что лежит в
|
|
188
|
+
репозитории. Сравнение идёт в два слоя, потому что индекс хранит только сигнатуры:
|
|
189
|
+
|
|
190
|
+
- **файлы схем** — по sha256: какой `swagger/<контур>/*.json` появился, пропал или
|
|
191
|
+
изменился. Этот слой ловит правки внутри схем тел запросов и ответов — новое
|
|
192
|
+
поле, изменившийся тип, — которых в индексе нет вовсе;
|
|
193
|
+
- **индекс** — какие эндпоинты появились, пропали и у каких изменилась сигнатура
|
|
194
|
+
(`summary`, `tags`, path/query-параметры, наличие и обязательность тела). Порядок
|
|
195
|
+
тегов и параметров сравнивается как множество, поэтому перестановка внутри
|
|
196
|
+
swagger расхождением не считается.
|
|
197
|
+
|
|
198
|
+
Если файл изменился, а сигнатуры нет, отчёт говорит об этом прямо — значит правка
|
|
199
|
+
внутри тела или ответа.
|
|
200
|
+
|
|
201
|
+
Коды возврата разводят дрейф и поломку — пайплайну есть на что реагировать:
|
|
202
|
+
|
|
203
|
+
| Код | Значение |
|
|
204
|
+
| --- | ---------------------------------------------------------- |
|
|
205
|
+
| `0` | расхождений нет, индексы в репозитории актуальны |
|
|
206
|
+
| `1` | схемы разошлись: появились, пропали или изменились эндпоинты |
|
|
207
|
+
| `2` | проверку выполнить не удалось: сеть, HTTP != 200, битый JSON |
|
|
208
|
+
|
|
209
|
+
Если страница документации недоступна, `refresh-swagger` предупреждает и берёт
|
|
210
|
+
список сервисов из каталога, а `check-swagger` завершается кодом `2`: запасной
|
|
211
|
+
список вернул бы слепое пятно на новый сервис, ради которого проверка и нужна.
|
|
212
|
+
|
|
213
|
+
Как и `refresh-swagger`, принимает `--catalog=dev|prod|all` (по умолчанию оба).
|
|
214
|
+
Схемы и индексы после запуска остаются **обновлёнными**, поэтому в пайплайне
|
|
215
|
+
`git diff` можно опубликовать артефактом, а локально — сразу закоммитить.
|
|
216
|
+
Загрузка атомарна: при обрыве сети рабочий каталог остаётся нетронутым, и код `2`
|
|
217
|
+
не будет спутан с реальным расхождением.
|
|
218
|
+
|
|
219
|
+
### Ежедневная сборка
|
|
220
|
+
|
|
221
|
+
Вся логика лежит в `scripts/release-swagger.ts` и запускается одной командой —
|
|
222
|
+
`npm run release-swagger`. Пайплайн `azure-pipelines-swagger.yml` только вызывает
|
|
223
|
+
её по расписанию, поэтому тот же сценарий целиком прогоняется локально:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
npm run release-swagger -- --dry-run # без коммита, push и публикации
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Скрипт обновляет схемы обоих контуров и, если что-то изменилось, прогоняет
|
|
230
|
+
typecheck, тесты и сборку, поднимает версию, коммитит, пушит и публикует пакет.
|
|
231
|
+
Работает **только в ветке `swagger-daily`**, `main` не трогает.
|
|
232
|
+
|
|
233
|
+
Релиз выпускается только из чистого рабочего дерева: свои пути (`swagger/`,
|
|
234
|
+
`generated/`, `package.json`) скрипт коммитит целиком, и чужая незакоммиченная
|
|
235
|
+
правка в них уехала бы в автоматический коммит.
|
|
236
|
+
|
|
237
|
+
CI-триггера у пайплайна нет, только расписание: ручные слияния `main` →
|
|
238
|
+
`swagger-daily` ничего не запускают, публикация происходит исключительно после
|
|
239
|
+
автоматического обновления схем. Синхронизация ветки с `main` делается руками.
|
|
240
|
+
|
|
241
|
+
Версия релиза — `0.2.YYYYMMDD`. Если при повторном дрейфе за сутки такая версия
|
|
242
|
+
уже в реестре, схемы коммитятся, а публикация пропускается: следующая уедет назавтра.
|
|
243
|
+
|
|
244
|
+
Перед первым запуском нужно:
|
|
245
|
+
|
|
246
|
+
1. создать ветку `swagger-daily` из `main` — файл пайплайна должен быть в ней;
|
|
247
|
+
2. дать Build Service право **Contribute** на репозиторий, иначе push не пройдёт;
|
|
248
|
+
3. убедиться, что на `swagger-daily` нет branch policies;
|
|
249
|
+
4. завести секретную переменную `NPM_TOKEN` с токеном публикации npm.
|
|
250
|
+
|
|
251
|
+
### Как добавить сервис
|
|
252
|
+
|
|
253
|
+
1. Передайте новый сервис команде `npm run refresh-swagger -- --catalog=<dev|prod> <SERVICE>`
|
|
254
|
+
либо положите его swagger в `swagger/<dev|prod>/<SERVICE>.json`.
|
|
255
|
+
2. `npm run generate` — индексы перестраиваются по всем файлам обоих каталогов
|
|
256
|
+
автоматически (при использовании `refresh-swagger` этот шаг уже выполнен),
|
|
257
|
+
курировать список эндпоинтов не нужно.
|
|
258
|
+
3. `npm run build`.
|
|
259
|
+
|
|
260
|
+
## Безопасность
|
|
261
|
+
|
|
262
|
+
- На проде используется отдельный кэш схем `swagger/prod/`: эндпоинты, которых на
|
|
263
|
+
проде ещё нет, агенту не видны.
|
|
264
|
+
- Все мутационные инструменты помечены «(изменяет данные)» в описании.
|
|
265
|
+
- `HUBEX_READONLY=true` полностью отключает изменение данных.
|
|
266
|
+
- Тестовые заявки из `hubex_create_test_task` помечаются префиксом `[MCP-TEST]`.
|