Реестр external_tools
Аудитория: фронтенд админки Aseller и администраторы платформы.
Всё, что раньше заливалось SQL-скриптом — sso-поля, mcp-канал, права на федеративные тулы — заводится этими ручками. SQL для заведения сервиса больше не нужен.
Все пути — от базового URL платформы, с префиксом /api/v1. Каждая ручка требует Authorization: Bearer <ACCESS админа>; не-админ получает 409 Only admin can call this method, а пользователь без права на URL — 403 ещё на уровне permissions.
Модель
Одна строка external_tools = один сервис экосистемы. Она обслуживает три роли сразу, и какие поля заполнены — те роли и включены:
| Роль строки | Включающие поля |
|---|---|
| Плитка микрофронта в Host UI | allowedRoles (непустой), mfName, mfRemoteEntry, mfExposedModule, permissionKey |
| SSO-клиент | code, ssoEnabled, ssoRedirectUris, serviceSecretHash |
| MCP-канал для федерации | code, mcpEnabled, mcpUrl, mcpTimeoutMs |
Чисто сервисная строка (SSO + MCP, без плитки) заводится с allowedRoles: [] — такая запись не показывается в /mf-registry и в интерфейсе не появляется.
Поля
| Поле | Тип | Назначение |
|---|---|---|
title * | string ≤128 | Название. Обязательное |
toolUrl * | string ≤2048 | URL инструмента. Обязательное |
allowedRoles * | string[] | Роли, которым показывать плитку. Для сервисной строки — [] |
code | string ≤64 | Slug сервиса: префикс имён федеративных тулов, идентификатор SSO-клиента. Уникален |
isActive | boolean | Главный рубильник: строка участвует в реестре кредов и в федерации |
ssoEnabled | boolean | POST /sso/grant выдаёт код только при true |
ssoRedirectUris | string[] | null | Allowlist адресов возврата. Сравнение префиксное, каждый элемент обязан начинаться с http:// или https://. null очищает |
serviceSecretHash | string | null | sha256 сервисного секрета, 64 hex-символа. null очищает |
mcpUrl | string | null | Endpoint MCP-канала сервиса. null очищает |
mcpEnabled | boolean | Включает сервис в сборку федеративного снапшота |
mcpTimeoutMs | integer 1000…120000 | Таймаут федеративного вызова. Эффективный = min(это, MCP_FEDERATION_CALL_TIMEOUT_MS) |
permissionKey | string ≤128 | Ключ пермишена плитки. Пермишен создаётся автоматически при заведении строки. Уникален |
mfName, mfRemoteEntry, mfExposedModule | string | Module Federation: контейнер, remoteEntry.js, exposed-модуль |
backendBaseUrl, swaggerUrl, standaloneUrl, guideUrl | string ≤2048 | Служебные ссылки сервиса |
images | string[] | Иллюстрации карточки |
comment | string ≤2048 | Комментарий администратора |
* — обязательные при создании.
Секрет платформе не передаётся
В serviceSecretHash кладётся хеш: printf %s "$SECRET" | sha256sum. Сам секрет считает и хранит команда сервиса. В GET возвращается тот же хеш — по нему админ сверяет, тот ли секрет прописан на стороне сервиса, но восстановить секрет из него нельзя.
Ручки реестра
Создать сервис
POST /api/v1/admins/tools
Content-Type: application/json
{
"title": "Калькулятор юнит-экономики",
"toolUrl": "https://calc.aseller.cat",
"allowedRoles": [],
"code": "idea_calc",
"isActive": true,
"ssoEnabled": true,
"ssoRedirectUris": ["https://calc.aseller.cat/sso/callback"],
"serviceSecretHash": "3b1f…64 hex",
"mcpEnabled": true,
"mcpUrl": "https://calc.aseller.cat/mcp",
"mcpTimeoutMs": 30000
}201 → {"_id": "d559628a-…"}. Дубль code или permissionKey → 409 Tool with the same code already exists.
Если передан permissionKey, под него автоматически создаётся пермишен (для плитки микрофронта) — отдельно заводить не нужно.
Изменить
PATCH /api/v1/admins/tools/:guid
{ "mcpUrl": "https://calc.aseller.cat/mcp/v2", "mcpTimeoutMs": 45000 }204. Любое подмножество полей — обязательных при правке нет. null в ssoRedirectUris, serviceSecretHash, mcpUrl очищает поле.
Прочитать
GET /api/v1/admins/tools?limit=15&offset=0&sortField=title&sortType=ASC&filters=[title][$contains]=калькул
GET /api/v1/admins/tools/:guidСписок — {"count": 42, "rows": [ … ]}, одна строка — объект целиком, вместе с toolPlaces, sso- и mcp-полями. Фильтры — стандартный синтаксис платформы ($eq, $contains, $null, $any, or[0][…]).
Удалить
DELETE /api/v1/admins/tools/:guid204. Связанный пермишен плитки не удаляется — переводится в status = 100.
Места отображения
Только для плиток микрофронтов; на SSO и MCP не влияют.
POST /api/v1/admins/tools/places { toolId, showPlace, windowHeight, windowWidth, multipleProductData, … }
PATCH /api/v1/admins/tools/places/:guid
DELETE /api/v1/admins/tools/places/:guidПрава на тулы
Федеративный тул виден пользователю, если у того есть пермишен с allowed_url вида {"url":"ext/<code>/<tool>","httpMethod":"POST"}. Набирать эти строки руками не нужно — есть две ручки.
Каталог тулов сервиса
GET /api/v1/admins/tools/:guid/mcp-toolsПлатформа опрашивает MCP-канал сервиса живьём (initialize + tools/list) и возвращает его тулы:
{
"serviceCode": "idea_calc",
"mcpUrl": "https://calc.aseller.cat/mcp",
"count": 2,
"tools": [
{
"name": "idea_calc_calc_profit_forecast",
"remoteName": "calc_profit_forecast",
"description": "Прогноз прибыли",
"permissionUrl": "ext/idea_calc/calc_profit_forecast",
"httpMethod": "POST"
},
{
"name": "idea_calc_calc_unit_economics",
"remoteName": "calc_unit_economics",
"description": "Юнит-экономика",
"permissionUrl": "ext/idea_calc/calc_unit_economics",
"httpMethod": "POST"
}
]
}Живой опрос, а не кэш: у только что заведённого сервиса федеративный снапшот ещё пуст, а список в интерфейсе нужен сразу. Побочная польза — это готовая проверка связности с сервисом.
Ошибки: 400 — у строки нет code или mcpUrl; 404 — строки нет; 502 — канал не ответил, в тексте причина (MCP channel of "idea_calc" is unavailable: …).
Собрать пермишен
POST /api/v1/admins/tools/:guid/mcp-permission
Content-Type: application/json
{}Пустое тело — весь каталог сервиса одним пермишеном с ключом EXT_<CODE>_TOOLS:
{
"guid": "dbe463a2-…",
"key": "EXT_IDEA_CALC_TOOLS",
"created": true,
"tools": ["calc_profit_forecast", "calc_unit_economics"],
"allowedUrls": [
"{\"url\":\"ext/idea_calc/calc_profit_forecast\",\"httpMethod\":\"POST\"}",
"{\"url\":\"ext/idea_calc/calc_unit_economics\",\"httpMethod\":\"POST\"}"
]
}Полное тело:
| Поле | Тип | По умолчанию |
|---|---|---|
key | string ≤128 | EXT_<CODE>_TOOLS |
title | string ≤255 | Тулы сервиса <название> |
description | string ≤255 | Федеративные MCP-тулы сервиса <code> |
role | 0, 10, 20, 30, 35, 40, 45, 60 | 10 (клиент) |
hierarchy | integer 0…200 | 0 |
status | 0 | 100 | 0 (100 — публичный, выдаётся всем) |
tools | string[] из remoteName | пусто = весь каталог |
mode | replace | append | replace |
replace заменяет список url у пермишена целиком, append дописывает недостающие, не трогая остальные. Повторный вызов с тем же key обновляет существующий пермишен — в ответе "created": false, дубликаты не плодятся.
Ошибки: 400 Unknown tools for "<code>": … — в tools имя, которого сервис не отдаёт (в тексте перечислены все неизвестные); 400 Service "<code>" exposes no tools — каталог пуст; 502 — канал недоступен.
Дальше — обычная выдача прав
Получившийся пермишен назначается пользователю или группе штатно, как любой другой. Полному админу (роль 0 без мастера) федеративные тулы доступны без пермишенов.
Если пермишен нужно собрать вручную (например, смешать тулы двух сервисов в один ключ) — это обычный POST /api/v1/permissions со своим allowedUrls:
{
"key": "EXT_MIXED_TOOLS",
"title": "Расчёты и хаб",
"description": "Тулы калькулятора и platform_hub",
"role": 10,
"allowedUrls": [
{"url": "ext/idea_calc/calc_unit_economics", "httpMethod": "POST"},
{"url": "ext/platform_hub/read_ds_execute", "httpMethod": "POST"}
]
}Что стоит сделать в интерфейсе
Минимум, который закрывает ручную работу администратора:
- Карточка сервиса — форма по таблице полей выше. Отдельной вкладкой sso-блок (
ssoEnabled, списокssoRedirectUrisс добавлением строк, поле хеша с подсказкой проsha256sum) и mcp-блок (mcpEnabled,mcpUrl,mcpTimeoutMs). - Кнопка «Загрузить тулы» на карточке — зовёт
GET …/mcp-tools, показывает список с описаниями. Ошибку502показывать текстом как есть: там реальная причина, с которой идут к команде сервиса. - Выбор галочками поверх этого списка + кнопка «Выдать» →
POST …/mcp-permissionсtools. Кнопка «Выдать все» — тот же запрос с пустым телом. - В экране пермишена — вместо ручного ввода строк
ext/…показывать те же чекбоксы, сгруппированные по сервисам.
Пока интерфейса нет, администратор закрывает задачу двумя запросами: создать строку и выдать весь список одним пермишеном.
Когда правка вступает в силу
| Что меняли | Через сколько действует |
|---|---|
Секрет, ssoRedirectUris, isActive, ssoEnabled | Сразу: кэш реестра сервисных кредов сбрасывается на POST/PATCH/DELETE этих ручек (иначе жил бы 60 секунд) |
| Пермишены на тулы | При следующем запросе пользователя |
| Появление тулов в общем MCP | До MCP_FEDERATION_REFRESH_SEC (по умолчанию 300 с) или сразу после рестарта платформы. Каталог в админке при этом уже актуален |