# forge-tools-lexicomai MCP-сервер для **обслуживания продуктов Lexicom AI** на серверах компании. Даёт AI-ассистенту (агенту) инструменты: посмотреть статус продукта, его конфигурацию и лицензию, логи, здоровье, диагностику и список доступных версий в репозитории. Позволяет администратору быстро разбираться с развёрнутыми сервисами и сокращать рутину. > **Что такое MCP-сервер коротко.** MCP — стандартный протокол подключения > AI-ассистентов к инструментам. Этот сервер — небольшая отдельная программа: > она читает запросы от ассистента, выполняет действия (по SSH на боевые > машины) и возвращает результат. Ассистент вызывает его инструменты по > имени — например «покажи статус продукта ups». --- ## Что умеет (текущая версия) | Инструмент | Что делает | |---|---| | `products_list` | Сводка по всем машинам: продукт → машина, состояние, порт, лицензия, версия | | `service_status` | Краткий статус конкретного продукта (unit, порт, состояние, лицензия) | | `repo_catalog` | Список доступных версий продукта в репозитории (ветки release/beta) | | `base_status` | Полнота базовой среды `/opt/pve` на машине | | `service_config_get` | Top-level ключи `config.json` продукта (+ наличие примера схемы) | | `license_get` | Содержимое `license.json` (service, срок, ключ) | | `license_verify` | Проверка лицензии: поля + живой ответ `/license/check` продукта | | `service_logs` | Хвост журнала продукта (опц. фильтр) | | `service_health` | Живой статус + `/openapi.json` (жив/версия) + `/license/check` | | `service_diagnose` | Чек-лист: юнит, порт, лицензия, база `/opt/pve` | | `errors_search` | Поиск ошибок в журнале продукта за окно времени | ### Изменения (только при `read_only=false` + `allow_mutate` + одобрение) | Инструмент | Что делает | |---|---| | `service_install` | Установка продукта (асинхронно, возвращает id); по умолчанию последняя версия | | `service_update` | Обновление до последней версии в ветке (backup инсталлятором) | | `service_uninstall` | Удаление продукта | | `base_ensure` | Создание минимальной базы `/opt/pve` (идемпотентно) | | `service_config_set` | Изменение ключей `config.json` (точечный путь) + рестарт | | `license_apply` | Запись `license.json` + проверка через `/license/check` | | `service_restart` | Перезапуск службы продукта | | `service_install_status` | Прогресс установки по id | Установка идёт асинхронно (возвращает `id`, прогресс — `service_install_status`), чтобы не блокировать агента. Для GPU-продуктов (crs, spr) автоматически подхватывается ускоритель (cu13) через `nvidia-smi`. ## Поддерживаемые продукты `acs, ams, cls, crs, llm, qas, res, sbs, see, ses, ses-sip, smc, spr, tts, ups, vds` Не поддерживаются: `vllm` (open-source), `spr5` (легаси), `ses-sip-gateway-api` (вспомогательные). ## Как сервер узнаёт о продуктах Ничего не «зашито» в код. Все данные берутся из живой системы: - **порт, движок (uvicorn/gunicorn/python/bwrap) и venv** — из действующего systemd-юнита (`ExecStart`) продукта; - **живость и версия** — по `GET /openapi.json` (продукты на FastAPI его отдают); - **лицензия** — из `license.json` + живой проверки `GET /license/check`; - **версии в репозитории** — по web-API SFTPGo (каталог `/repos/<продукт>/<ветка>`). Поэтому добавлять/обновлять продукты можно без правки кода — только в конфиге указать, какие продукты на какой машине. ## Сборка ```bash go build -o forge-tools-lexicomai . ./forge-tools-lexicomai --health # → ok (проверка, что сервер живой) go test -race ./... ``` Зависимости минимальны: общая библиотека `forge-toolkit` + официальный Go-SDK MCP. Собранный бинарь `forge-tools-lexicomai` в репозиторий не коммитится (в `.gitignore`). ## Подключение сервера Сервер запускается как **stdio-процесс** (читает/пишет MCP-протокол через стандартные ввод/вывод). В конфиге MCP-хоста указывается команда запуска и флаг `-config`: ```json { "command": "/opt/lexicomai/forge-tools-lexicomai", "args": ["-config", "/etc/lexicomai/lexicomai.json"] } ``` То же самое подходит для любого MCP-клиента. ## Конфигурация Файл `lexicomai.json`. Реальные адреса, ключи и пароли в репозиторий **не попадают** — подставляются переменными окружения `${VAR}` (или берутся из локального файла, который не коммитится). ```jsonc { "targets": [ { "alias": "prod", "ssh": { "host": "${LEXICOMAI_HOST}", "user": "${LEXICOMAI_USER}", "key": "${LEXICOMAI_SSH_KEY}", "port": 22 }, "products": ["ups", "spr", "cls"], "allow_mutate": false } ], "default": "prod", "read_only": true, "timeout_seconds": 15, "max_output_bytes": 4194304, "repo": { "base": "https://cloud.connect2ai.net", "user": "${SFTPGO_USER}", "pass": "${SFTPGO_PASS}" } } ``` | Поле | Смысл | |---|---| | `targets[]` | Управляемые машины: `alias` (имя), `ssh` (host/user/key/port), `products` (что на ней живёт), `allow_mutate` (разрешены ли изменения) | | `default` | Машина по умолчанию | | `read_only` | Полный запрет мутаций (по умолчанию `true`) | | `timeout_seconds` | Таймаут одного SSH-вызова/пробы | | `max_output_bytes` | Ограничение размера результата | | `repo` | Доступ к репозиторию дистрибутивов (web-клиент SFTPGo) | Требования: у машины должен быть SSH-доступ по ключу (пользователь с `sudo -n`); `products[]` объявляет продукты на машине. ## Безопасность - По умолчанию — **только чтение**; мутации включаются явно (`read_only=false` + `allow_mutate` на конкретной машине) и дополнительно требуют одобрения. - Никаких адресов/подсетей/ключей в коде — всё из конфига/окружения. - Команды на машине выполняются через `sudo -n`; пользовательский ввод экранируется; ключ лицензии в выводе маскируется. - Инструменты ограничены по времени (таймаут) и размеру результата. ## Проверено - `go build`, `go vet`, `go test -race` — зелёные; `gofmt` — чисто. - Ручная проверка MCP (T1): `initialize` → сервер отвечает именем `lexicomai`, `tools/list` возвращает инструменты с корректными обязательными параметрами. ## Статус - **M1 (готово):** каркас + read-only инструменты. - **M3–M5 (готово):** установка/обновление/удаление, изменение конфигурации, применение лицензий, база `/opt/pve`, управление службой — для всех поддерживаемых продуктов. Написано по архитектуре остальных MCP-серверов компании. Live-проверка на боевых машинах — только на стейджинге.