MCP-федерация
Аудитория: команды, чей сервис умеет (или хочет уметь) отдавать тулы по MCP и попасть в общий MCP-канал Aseller — тот, что подключают в Claude.
Идея
У платформы один MCP-эндпоинт для пользователя. Тулы в нём двух сортов: собственные (сгенерированы из роутов api-new) и федеративные — проксируемые в MCP-каналы сервисов экосистемы.
Платформа выступает шлюзом: раз в несколько минут обходит реестр, спрашивает у каждого сервиса список тулов, префиксует имена кодом сервиса и добавляет в общий снапшот. Когда пользователь зовёт такой тул, платформа проверяет его права и переправляет вызов вам, приложив идентичность пользователя.
Ваша сторона — обычный stateless MCP-сервер по HTTP (JSON-RPC 2.0). Никаких SDK платформы, никаких вебхуков.
Что платформа спрашивает у сервиса
Сборка списка
Раз в MCP_FEDERATION_REFRESH_SEC (по умолчанию 300 секунд) и один раз при старте платформа делает на ваш mcpUrl два запроса подряд:
// 1) POST <mcpUrl>
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2025-03-26",
"capabilities":{},
"clientInfo":{"name":"aseller-mcp-gateway","version":"1.0.0"}}}
// 2) POST <mcpUrl>
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}- Оба запроса идут без
Authorization: список тулов не считается пользовательскими данными, авторизуется сам вызов. - Если на
initializeвы вернули заголовокMcp-Session-Id, платформа пришлёт его обратно вtools/list. Требовать сессию не обязательно — stateless-сервер тоже подходит. - Ждём ответ формы
{"result":{"tools":[{"name":…,"description":…,"inputSchema":…,"annotations":…}]}}.
Вызов тула
POST <mcpUrl>
Authorization: Bearer <synth ACCESS пользователя, 60 секунд>
X-Trace-Request-Id: mcp:<kind>:<id>:<timestamp>
Content-Type: application/json
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"calc_unit_economics","arguments":{…}}}Bearer здесь — настоящий пользовательский ACCESS-токен платформы (синтетический: выпущен на этот вызов, живёт 60 секунд, под него создана эфемерная сессия, которая гасится сразу после ответа). Проверяйте его ровно так же, как любой другой — через POST /auth/validate; см. Подключение сервиса. В payload есть email — по нему линкуется ваш аккаунт.
Ответ ждём в виде MCP-результата:
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"…"}],"isError":false}}Если result не содержит массива content, платформа завернёт его целиком в один текстовый блок — работать будет, но читаемость в клиенте пострадает.
Имена тулов
Имя в общем списке — <code сервиса>_<имя тула у вас>:
| У вас | В федерации |
|---|---|
calc_unit_economics | idea_calc_calc_unit_economics |
keepa_lookup | idea_calc_keepa_lookup |
Ограничения на итоговое имя: не длиннее 64 символов и только [a-zA-Z0-9_-]. Тул с именем, которое после префикса не проходит проверку, молча пропускается — в логах платформы остаётся mcp federation: tool name invalid/too long, skipped. Учитывайте длину своего code: чем он короче, тем больше места остаётся именам.
Если два сервиса отдали одинаковое итоговое имя, побеждает тот, кого обошли раньше.
Права: кто видит ваш тул
Каждый федеративный тул получает виртуальный URL ext/<code>/<имя тула> с методом POST. Видимость и право вызова решаются обычным механизмом permissions платформы: у пользователя должен быть пермишен, в allowed_urls которого лежит
{"url":"ext/idea_calc/calc_unit_economics","httpMethod":"POST"}Полный админ платформы (роль 0 без мастера) видит и зовёт все федеративные тулы без пермишенов. Остальным права выдаёт администратор — руками их набирать не нужно, есть ручка, которая собирает пермишен из вашего же tools/list: Реестр external_tools.
Тул, на который у пользователя нет права, не просто не вызывается — он не показывается в tools/list этого пользователя.
Гарды шлюза
Платформа защищает себя от медленного или разговорчивого сервиса. Значения по умолчанию:
| Что | Сборка списка | Вызов тула |
|---|---|---|
| Таймаут | 10 с | min(mcpTimeoutMs из реестра, MCP_FEDERATION_CALL_TIMEOUT_MS) = 30 с |
| Максимум запроса | 16 КБ | MCP_FEDERATION_MAX_REQUEST_BYTES = 256 КБ |
| Максимум ответа | 2 МБ | MCP_FEDERATION_MAX_RESPONSE_BYTES = 5 МБ |
| Одновременных вызовов | — | MCP_FEDERATION_MAX_CONCURRENT = 16, очередь MCP_FEDERATION_MAX_QUEUE = 200 |
Превышение не роняет ни платформу, ни соседние сервисы — вызов возвращается пользователю как ошибка тула:
code | Значение |
|---|---|
request_failed | Не достучались: DNS, отказ соединения, таймаут, обрыв |
request_too_large | Аргументы вызова больше лимита запроса |
response_too_large | Ваш ответ больше лимита ответа — платформа обрывает чтение |
invalid_json | Ответ не разобрался как JSON |
http_error | HTTP-статус ≥ 400 без тела JSON-RPC |
overloaded | Очередь шлюза переполнена, повторите позже |
Недоступный сервис при сборке списка просто пропускается с предупреждением — снапшот собирается из тех, кто ответил, и прежние тулы этого сервиса исчезают из списка до следующей удачной сборки.
Дуал-стек
Платформа подключается и по IPv6, и по IPv4. Если ваш mcpUrl резолвится в оба, а слушаете вы только на одном — причина отказа доедет в текст ошибки целиком, не подменяясь последней попыткой. Проверяйте, что сервис слушает тот адрес, который отдаёт DNS.
Требования к вашему MCP-серверу
- HTTP POST, JSON-RPC 2.0. Один эндпоинт, принимающий
initialize,tools/list,tools/call. - Stateless или с сессией по заголовку. Платформа не хранит состояние между циклами обновления.
- Токен проверяется через
/auth/validate. Не пытайтесь разобрать подпись сами — ключ симметричный и наружу не выдаётся. - Короткие ответы. Держитесь в пределах лимитов, большие выгрузки отдавайте ссылкой, а не телом.
- Идемпотентность там, где возможно. Таймаут на стороне шлюза не означает, что ваш обработчик не доработал.
- Имена тулов стабильны. Переименование = потеря выданных прав: пермишены привязаны к
ext/<code>/<имя>.
Порядок включения
- Админ заводит строку реестра с
code,mcpUrl,mcpEnabled: true,isActive: true. - Админ открывает каталог ваших тулов —
GET /admins/tools/:guid/mcp-toolsопрашивает ваш канал живьём, так что проверить связность можно сразу, не дожидаясь пересборки снапшота. - Админ собирает пермишен на нужные тулы и выдаёт его пользователям или группе.
- В общий MCP тулы попадают в течение
MCP_FEDERATION_REFRESH_SEC(по умолчанию 5 минут) либо сразу после рестарта платформы.
Диагностика
| Симптом | Где смотреть |
|---|---|
| Тулов нет ни у кого, включая админа | Строка реестра: isActive, mcpEnabled, mcpUrl. Затем GET /admins/tools/:guid/mcp-tools — он покажет реальную причину (502 с текстом ошибки) |
| Каталог в админке есть, в MCP тулов нет | Ещё не пересобрался снапшот — подождите цикл обновления |
| Админ видит, пользователь нет | Нет пермишена с ext/<code>/<tool> |
| Часть тулов пропала | Длина имени после префикса или недопустимые символы |
Вызовы падают с request_failed | Таймаут или сеть; сверьте mcpTimeoutMs в реестре с реальным временем работы тула |