MCP: хаб как инструменты ИИ-агента
Включается в «О системе»
MCP работает, если в «О системе» → «Экспериментальные функции» включён «MCP для ИИ-агентов» (по умолчанию выключен; выключенный отвечает 403 любому токену).
Хаб — сервер MCP (Model Context Protocol): Claude Code, Claude Desktop, Cursor и другие агенты видят nkt как набор инструментов — хосты, находки, конвейеры, сценарии, переносы, Traffic Fly, кластеры — и сами вызывают их по ходу задачи («почему упал web-2», «перенеси forgejo на web-3 и переключи маршрут»).
Адрес — POST /api/mcp (транспорт Streamable HTTP, ответ одним JSON). Для клиентов, которые запускают сервер командой, есть мост nkt mcp.
Доступ — только по API-токену
MCP работает с API-токеном, а не со входом в интерфейс. Каждый инструмент — вызов того же API хаба под тем же токеном, поэтому права агента — права токена, без отдельных правил:
- токен чтения видит только инструменты чтения (хосты, находки, службы, контейнеры, оповещения, конвейеры, задания, сценарии, переносы, кластеры, карта и статус Traffic Fly);
- токен администратора получает и действия: запуск сценария, выкладку, перенос стека, Traffic Fly, манифесты в кластеры, службы и контейнеры, бан адресов;
- токен по правам — только выбранные действия с потолками ресурсов (Токен по правам): агент видит только разрешённые инструменты, выкладка и машины — в потолках;
- предел по хостам и группам действует как в API: чужие хосты недоступны, общая карта Traffic Fly — только токену без предела;
- список адресов, срок и nkt-edge — как у любого вызова с токеном.
Действия — без подтверждения
С токеном администратора агент выполняет действия сразу, человек их не подтверждает: так задумано, чтобы агент мог довести задачу до конца. Для агента, которому вы не доверяете всё, выдайте токен чтения или токен по правам: только нужные действия, свои объекты и потолки CPU, памяти, диска и машин. Всё, что агент сделал, есть в журнале действий хаба под именем token:<имя токена>.
Встроенный ИИ хаба (разбор находок, ИИ в редакторе сценариев, ассистент) по-прежнему ничего не запускает сам: сценарий из ответа ассистента выполняется, только когда вы нажмёте «Выполнить». Без человека действия выполняет только MCP — с токеном администратора или токеном по правам (в его пределах).
Инструменты
| Инструмент | Роль | Что |
|---|---|---|
list_hosts | чтение | хосты: статус, версия, проблемы |
host_overview, host_findings, host_services, host_containers | чтение | разделы хоста (host_id; машина хаба — -1) |
list_alerts | чтение | оповещения новее номера after |
list_pipelines, get_pipeline | чтение | конвейеры и последняя выкладка; описание конвейера (секреты — @secret) |
list_pipeline_examples | чтение | готовые описания из примеров (без key — список, с key — текст) |
job_status, job_log | чтение | задание хаба и его журнал |
list_scripts, get_script | чтение | сохранённые сценарии |
list_migrations, list_clusters | чтение | учёт переносов, кластеры |
fly_map, fly_status | чтение, без предела | карта и состояние Traffic Fly |
check_script | администратор | «Проверить» для текста сценария, ничего не меняет |
run_script | администратор | запуск сценария (dry_run; dry_first — сухой прогон, при успехе выполнение; values — ответы на вопросы) |
deploy_pipeline, dry_run_pipeline | администратор | выкладка; сухой прогон сохранённого конвейера или текста описания (content) |
create_pipeline, update_pipeline, remove_pipeline | администратор | создать конвейер из описания, заменить описание (новая версия, в ответе дифф), удалить со стеком (токену по правам — действие «создание конвейеров», только compose на своих хостах и только свои) |
pipeline_power | администратор | остановить выкладку или поднять ту же версию (action: stop / start) |
create_vm, vm_power | администратор | машина на хосте из облачного образа; включить, выключить, погасить (токену по правам — свои, в потолках) |
migrate_preview, migrate_stack, migration_action | администратор | план переноса, перенос, откат / удаление старой копии |
fly_apply, fly_ops | администратор, без предела | применить карту, точечные правки целей |
manifest_diff, manifest_apply | администратор | манифест в кластеры |
device_snapshot, device_findings, device_config | чтение | хост плагина (MikroTik, Windows…): состав, находки, версии конфигурации (fresh — прочитать с устройства) |
device_action, device_exec | администратор | действие типа хоста плагина (перезагрузка, обновление…) и команда на его языке (RouterOS, PowerShell); dry_run — только сказать, что было бы |
service_action, container_action | администратор | start / stop / restart служб и контейнеров |
fail2ban_ban | администратор | бан / разбан адресов на хостах |
Плюс инструменты подключённых плагинов: <имя>_<операция> — операции чтения любому токену, остальные — с действием «плагин ИМЯ». Какие именно, с аргументами и доступом, — «Плагины» → плагин → «Для агентов» (там же «Скачать JSON» в формате tools/list).
У инструментов есть подсказки readOnlyHint и destructiveHint: клиенты, которые их учитывают, сами спросят вас перед опасным вызовом.
Задания. Длинные операции (сценарий, выкладка, перенос, Traffic Fly) возвращают job_id. С аргументом "wait": true инструмент ждёт конца задания (по умолчанию до 10 минут, timeout — до часа) и возвращает итог и хвост журнала — агенту не нужно опрашивать самому.
Пример: задание с ожиданием
Агент запускает сухой прогон сохранённого сценария и ждёт итога одним вызовом:
{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{
"name":"run_script",
"arguments":{"script_id":4,"dry_run":true,
"values":{"param:FROM":"web1","param:TO":"web2"},"wait":true,"timeout":900}}}Ответ приходит, когда задание закончилось (или вышло время — тогда "timed_out": true и job_id, чтобы спросить позже через job_status):
{"jsonrpc":"2.0","id":7,"result":{"isError":false,"content":[{"type":"text",
"text":"{\"job_id\":123,\"status\":\"succeeded\",\"succeeded\":true,\"log\":[\"…\"]}"}]}}В log — последние 200 строк журнала задания. Задание, завершившееся ошибкой, приходит с "isError": true и текстом ошибки — агент видит, что пошло не так, и может прочитать журнал целиком через job_log.
Пример работы агента
Просьба в Claude Code: «почему на web-2 падает выкладка app и что с этим делать?». Агент сам вызывает инструменты:
list_hosts— находитweb-2и егоhost_id;list_pipelines— конвейерappи его последнюю выкладку;job_log— журнал упавшего задания: «порт 8080 занят»;host_containers— кто держит 8080 на web-2;
и отвечает с причиной и исправлением. С токеном чтения на этом всё; с токеном администратора агент может сам остановить лишний контейнер (container_action) и перезапустить выкладку (deploy_pipeline с "wait": true) — без подтверждения, всё в журнале действий как token:<имя>.
Пример: агент создаёт конвейер
Просьба: «подними umami на web1 с доменом stats.example.com». Агент:
list_pipeline_examples→list_pipeline_examplesс"key":"umami"— готовое описание;- правит в нём хост, домен и
env:(пароли оставляетgenerate:— их создаст хаб); dry_run_pipelineс"content"и"wait": true— хосты, порты, образы, сайт; ошибки — правит и повторяет;create_pipeline— конвейер создан, значенияenv:ушли в зашифрованный.env, в описании —@secret;deploy_pipelineс"wait": true— итог и журнал.
Дальше правка — get_pipeline и update_pipeline (в ответе дифф, в истории версий конвейера — версия от token:<имя>), удаление — remove_pipeline.
Пример: токен по правам
Токен на основе заготовки «Агент: compose с потолками»: из действий оставлены «выкладка, откат, сухой прогон» и «создание конвейеров», конвейеры app и blog, хост web1, потолки — 2 CPU и 2048 МБ суммой, 1 CPU и 512 МБ на сервис, 10 действий в час. Агент с ним видит в tools/list инструменты чтения, deploy_pipeline, dry_run_pipeline, create_pipeline, update_pipeline и remove_pipeline — остальных действий в списке нет, а вызов их отвечает unknown or not allowed tool.
create_pipeline— только compose и только наweb1; созданный конвейер — его: выкладывать, править и удалять можно, хотя его нет в спискеapp,blog;update_pipelineдляapp(создан не им) —конвейер app создан не этим токеном;deploy_pipelineдляapp— выкладка; сервисам без своих limits хаб ставит потолок на сервис (1 CPU, 512 МБ) в копии compose-файла, которая едет на хост;стек не влез в остаток — задание заканчивается ошибкой вида
app@web1: нужно 1.50 CPU, у токена свободно 0.50 из 2.00;сервис с
privileged, сетью хоста или путём хоста вне каталога стека —сервис runner: privileged — токену с потолками нельзя (выходит за стек);конвейер не из списка — отказ с его именем, 11-е действие за час —
токен исчерпал предел действий в час (10) — повторите позже.
Ошибки приходят в ответе инструмента с "isError": true — агент видит причину и может подобрать меньшие limits сам. Сколько токен уже занял, — в окне токена («Занято»).
Claude Code
claude mcp add --transport http nkt https://hub.example.com/api/mcp \
--header "Authorization: Bearer nkt_…"Язык ответов хаба (ошибки, журналы заданий) — заголовок X-NKT-Lang: ru или en; мост nkt mcp ставит его по локали.
nkt mcp: мост stdio
Клиенты вроде Claude Desktop запускают MCP-сервер командой. Мост nkt mcp пересылает сообщения со stdin на хаб и ответы — в stdout. Адрес и токен — только из окружения (аргументы видны в списке процессов):
{
"mcpServers": {
"nkt": {
"command": "/usr/local/bin/nkt",
"args": ["mcp"],
"env": {
"NKT_HUB_URL": "https://hub.example.com",
"NKT_API_TOKEN": "nkt_…"
}
}
}
}У хаба самоподписанный сертификат — NKT_HUB_CA=/путь/к/cert.pem. Бинарник nkt подойдёт любой той же версии — машине с агентом хаб и служба не нужны.
С локальной моделью
Модель хаба для MCP не нужна: думает модель агента, хаб только даёт инструменты. С локальной моделью подойдёт любой MCP-клиент, который умеет работать с Ollama или OpenAI-совместимым адресом, — например Cline или Continue в VS Code, Goose, Open WebUI. Во многих из них MCP-сервер описывается тем же блоком mcpServers, что у Claude Desktop выше (с мостом nkt mcp), или адресом https://хаб/api/mcp с заголовком Authorization; точное место настройки — в документации клиента. Модели агента нужен вызов инструментов — те же советы по моделям, что для ассистента.
Проверка руками
Готовые команды с адресом вашего хаба — в окне токена: «О системе» → «API-токены» → токен → «Примеры MCP» (с секретом — сразу после создания токена, потом секрет не показывается).
Какие инструменты видит токен (для токена по правам — только разрешённые):
curl -s -H 'Authorization: Bearer nkt_…' -H 'Content-Type: application/json' \
https://hub.example.com/api/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Вызов инструмента:
curl -s -H 'Authorization: Bearer nkt_…' -H 'Content-Type: application/json' \
https://hub.example.com/api/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_hosts","arguments":{}}}'