Synapse встраивает FastMCP (пакет mcp) — тот же контейнер API, тот же процесс uvicorn. Эндпоинты /mcp-protocol/ (конвенция хендбука, 10-platform/mcp.md — слэш в конце значим для реверс-прокси) и /mcp (исторический alias), транспорт streamable-http (stateless).
Зачем: ИИ-агент (Claude Code и совместимые) управляет Synapse целиком — выдаёт API-ключи клиентам (сервисам-источникам), регистрирует типы, ведёт правила маршрутизации, смотрит поток событий и доставок, меняет настройки — без ручной работы в админке. Правка 2026-10-03; персональные ключи 2026-10-04.
/mcp монтируется всегда; гейт (McpTokenGuard, app/mcp/server.py) принимает два вида Bearer-ключей:
mcp_... — основной путь. Каждый пользователь выпускает себе ключ на SPA-странице /mcp-keys (или POST /api/v1/me/mcp_tokens, plaintext в ответе ровно один раз; в БД — sha256-хэш + хвост). Одновременно активно до 10 ключей. Ключ действует ролью владельца на момент выпуска (снейпшот system_role в строке; call-home по sub без токена gnexus-auth невозможен — после смены роли выпустите ключ заново, старый отзовите):
admin/superadmin — весь каталог тулов (35);user — только личный набор: me, my_events_list, my_push_subscriptions_list, my_push_subscription_delete; любой админ-тул отвечает {"error": 403, "detail": "…"}. Админ видит ключи всех на /mcp-keys (или GET /api/v1/admin/mcp_tokens) и может отозвать любой (POST /api/v1/admin/mcp_tokens/{id}/revoke). SSO-логаут MCP-токены не трогает — это самостоятельные креды, как ключи источников. Блокировка пользователя (вебхуки gnexus-auth user.blocked/deleted/archived → флаг в user_prefs) гасит все его личные ключи: гард отвечает тем же 401, что и при неверном токене.MCP_TOKEN из .env — суперадмин-бэкдор: сохраняет совместимость с существующими сценариями агентов. Опционален (пусто — работают только персональные ключи); держать в .env + gnexus-creds. Генерация: openssl rand -hex 32.Регистрация в Claude Code:
claude mcp add --transport http synapse http://localhost:8013/mcp \ --header "Authorization: Bearer mcp_<персональный ключ>"
app/api/admin_routes.py)/личные (me_routes.py) напрямую — та же pydantic-валидация, те же коды ошибок и тексты. Автор запросов — реальный владелец ключа (роль — снейпшот выпуска; статический токен = superadmin)._admin_run (app/mcp/tools.py) пропускает admin/superadmin, для user-ключа возвращает данные {"error": 403}.{"error": 409, "detail": "…"} — агент читает причину и может её исправить (например restore архивной записи).McpTokenGuard, app/mcp/server.py): резолвит Authorization: Bearer (стат. токен или mcp_* в БД) на каждом запросе, 401 (www-authenticate: Bearer) при промахе; не BaseHTTPMiddleware — SSE-стримы не ломает. Обновляет last_used_at токена.| Группа | Тулы |
|---|---|
| Состояние | system_status (БД + Celery ping + SSO) · stats_get (счётчики по статусам, живые справочники) |
| Источники | sources_list (query, include_archived) · source_create · source_archive · source_restore |
| Ключи | keys_list · key_issue (plaintext один раз в token) · key_revoke |
| Типы | types_list (source_id, query, include_archived) · type_register · type_archive · type_restore |
| Цели | targets_list (channel, enabled, include_archived) · target_create · target_patch · target_archive · target_restore |
| Правила | rules_list (enabled, include_archived) · rule_create · rule_patch · rule_archive · rule_restore |
| Поток | events_list (status, source_name) · event_get · deliveries_list (status, channel) |
| Push | push_subscriptions_list (user_id) · push_subscription_delete (жёстко — устройства пользователей) |
| Настройки | settings_get (секреты write-only: value=null, факт в set) · settings_put (правила docs/06: "" — не менять, null — сброс; настройка push-канала — рецепт VAPID в docs/06 «Как задать VAPID», выполняется shell'ом в контейнере) |
| Контроль | send_test_event (source_name, subject, action, payload, priority) — полный маршрут в воркере |
| Личный (любая роль) | me (sub/email/роль ключа) · my_events_list · my_push_subscriptions_list · my_push_subscription_delete |
DELETE не удаляет — ставит deleted_at (архив). Действует на sources, notification_types, channel_targets, routing_rules. Пуш-подписки — исключение: устройства пользователей удаляются физически (push-нотификации не переживают несуществующую подписку).
Что это значит:
include_archived=true покажет архив (deleted_at в объектах; в UI-списках поле всегда null).skipped с причиной «цель в архиве» (аудит, видно в deliveries).POST /api/v1/admin/{sources|types|targets|rules}/{id}/restore → 200 с объектом; конфликт имени с живой записью → 409. Restore типа требует живого источника (409).REST-эквивалент доступен и из админ-API (те же эндпоинты), UI-клиент SPA ничего не заметил (204-ответы прежние).
Выдать ключ клиенту:
1. source_create(name="bugtrail", description="Трекер ошибок…") 2. key_issue(source_id=<id>, name="основной") → token: "syn_…" — передать клиенту один раз 3. type_register(source_id, subject="issue", action="created") 4. Третьесторонний сервис шлёт POST /api/v1/events с Bearer syn_…
Проверить правило:
1. rule_create(name="critical → Navi rei", actions=[{"channel":"s2s","target_id":3}],
conditions={"priority_min":"critical"})
2. send_test_event(source_name="monitoring", subject="container", action="down",
payload={"container":"api"}, priority="critical")
3. events_list(source_name="monitoring") → доставed в цель
settings_get их не отдаёт).send_test_event и просмотр потока требуют живого воркера (Celery) — system_status покажет./mcp-protocol/ (и alias /mcp) не публикуем.