remnawave-mcp
remnawave-mcp
MCP-сервер для API панели Remnawave.
Опубликовано в области
@folexz: имяremnawave-mcpбез области на npm принадлежит несвязанному проекту, который нацелен на Remnawave 2.7.4 и не работает с 2.8.0+.
npx -y @folexz/remnawave-mcp # configured via REMNAWAVE_BASE_URL + REMNAWAVE_API_TOKEN_READ/_WRITEОн покрывает все 205 операций в 28 контроллерах API Remnawave v3.3.2 — пользователи,
узлы, хосты, конфигурационные профили, отряды, подписки, плагины узлов, инфраструктурный
биллинг, системная статистика — сгенерировано из собственного OpenAPI-документа панели,
а не написано вручную. Укажите более новую спецификацию в npm run build-spec — и набор
инструментов последует за ней.
Возможности
Управляется спецификацией и самообновляется.
npm run update-specзагружает новейший OpenAPI-документ из собственной опубликованной копии Remnawave и пересобирает каталог; схема ввода каждого инструмента берётся напрямую из параметров операции и тела запроса. Ничего об API не написано вручную, а при пересборке выводится diff с указанием каждой добавленной, удалённой или переименованной операции, так что обновление версии не может незаметно удалить инструмент.Ограниченная стоимость контекста. 205 типизированных инструментов стоили бы ~39k токенов
tools/listна каждый запрос. Профиль по умолчанию предоставляет 5 инструментов (~1.4k токенов) и при этом охватывает все операции — см. Почему не 205 инструментов.Двухтокенная аутентификация с минимальными привилегиями. Токен чтения и опциональный токен записи.
GETиспользует токен чтения;POST/PATCH/PUT/DELETE— токен записи. Без токена записи изменяющие инструменты вообще не регистрируются — сервер физически доступен только для чтения.Защитные механизмы для живой панели. Мутации сериализуются с минимальным интервалом и повторяются с экспоненциальной задержкой, потому что каждая запись конфигурации заставляет панель отправлять конфигурацию на все узлы и перезапускать Xray. Массовые операции и операции удаления дополнительно требуют
confirm: true.Встроенные примечания к полям. Приведённые ниже подводные камни прикреплены к затрагиваемым операциям, поэтому они появляются в описании инструмента и в выводе
remnawave_describe_operation.Никаких запросов, которые не могут завершиться успехом. 16 конечных точек (auth, passkeys, управление API-токенами) обслуживаются только для вошедшего в систему администраторского JWT и отклоняют API-токены. Они обнаруживаются из спецификации и отклоняются локально с объяснением, а не отправляются.
Запасные выходы.
remnawave_request_read/remnawave_request_writeдостигают любого пути, включая недокументированные маршруты и синтаксис запросов, который OpenAPI не может выразить.
Related MCP server: mcp-remnawave
Требования
Node.js ≥ 18
Панель Remnawave (3.x), доступная по HTTPS
API-токен из панели: Настройки → API-токены. Remnawave 3.x поддерживает токены с областями — создайте один с правами на чтение и, если нужны изменения, второй с правами на запись.
Установка
Быстрый путь — npx — см. Регистрация в Claude Code. Для
запуска из исходников:
git clone https://github.com/folexz/remnawave-mcp.git
cd remnawave-mcp
npm install
npm run buildКонфигурация
Вся конфигурация задаётся переменными окружения, предоставляемыми вашим MCP-хостом. Файлы не читаются.
Переменная | Обязательно | По умолчанию | Описание |
| да | — | Адрес панели, например |
| да | — | Токен чтения. Псевдоним: |
| нет | — | Токен записи. Опустите для работы только на чтение. |
| нет |
|
|
| нет | — | Разделённые запятыми слаги контроллеров; переопределяет выбор типизированных инструментов профиля. |
| нет |
| Схемы ввода больше этого размера сворачиваются в |
| нет |
| Минимальный интервал между двумя мутациями. |
| нет |
| Повторные попытки при транспортных сбоях, 429 и 5xx. |
| нет |
| Тайм-аут на запрос. |
| нет |
|
|
| нет |
|
|
Регистрация в Claude Code
Только чтение (рекомендуемый вариант по умолчанию):
claude mcp add remnawave --scope user \
--env REMNAWAVE_BASE_URL=https://panel.example.com \
--env REMNAWAVE_API_TOKEN_READ=your_read_token \
-- npx -y @folexz/remnawave-mcp@latestС включёнными мутациями и типизированными инструментами для повседневных контроллеров:
claude mcp add remnawave --scope user \
--env REMNAWAVE_BASE_URL=https://panel.example.com \
--env REMNAWAVE_API_TOKEN_READ=your_read_token \
--env REMNAWAVE_API_TOKEN_WRITE=your_write_token \
--env REMNAWAVE_TOOL_PROFILE=core \
-- npx -y @folexz/remnawave-mcp@latest@latest заставляет npx разрешать самую новую опубликованную версию при каждом запуске.
Чтобы запустить локальную сборку, замените команду на
node /absolute/path/to/remnawave-mcp/dist/index.js.
Регистрация в Claude Desktop / других MCP-клиентах
{
"mcpServers": {
"remnawave": {
"command": "npx",
"args": ["-y", "@folexz/remnawave-mcp@latest"],
"env": {
"REMNAWAVE_BASE_URL": "https://panel.example.com",
"REMNAWAVE_API_TOKEN_READ": "your_read_token"
}
}
}
}Почему не 205 инструментов
tools/list повторно отправляется модели на каждый запрос, поэтому его сериализованный
размер — постоянный налог на контекст. Измерено на этой спецификации
(npx tsx scripts/tool-stats.ts):
Профиль | Инструменты (чтение+запись) |
| ≈ токенов | Инструменты (только чтение) | ≈ токенов |
| 5 | 5.6 KB | ~1.4k | 4 | ~1.2k |
| 91 | 71 KB | ~17.8k | 38 | ~5.9k |
| 210 | 156 KB | ~39k | 92 | ~13.9k |
DTO Remnawave — причина, по которой full так дорог: один разыменованный объект хоста
сам по себе занимает ~30 КБ JSON Schema, потому что он включает все варианты входящих
и безопасности.
Поэтому сервер не выбирает между «один инструмент на операцию» и «один грубый диспетчер» — он поставляет оба варианта и позволяет профилю решать, сколько рекламировать:
Каталожные инструменты (всегда включены, 3 инструмента).
remnawave_list_operationsпросматривает и ищет в каталоге и возвращает одну компактную строку на операцию;remnawave_describe_operationвозвращает полную JSON Schema плюс примечания к полям для одной операции;remnawave_callвыполняет любую из 205 по имени. Обычный цикл — список → описание → вызов, и он стоит те же 1.4k токенов независимо от размера API. Это та же идея ленивой загрузки, которую использует агентский каркас, когда откладывает схемы инструментов.Типизированные инструменты (выбираются профилем). Один сгенерированный инструмент на операцию для контроллеров, с которыми вы реально работаете —
coreпокрывает пользователей, узлы, хосты, конфигурационные профили, внутренние отряды, систему и два контроллера массовых действий;fullпокрывает всё;minimal— ничего. Схемы, превышающиеREMNAWAVE_MAX_SCHEMA_BYTES, сохраняют свои поля верхнего уровня и отбрасывают вложенность, со ссылкой наremnawave_describe_operationдля полной версии.Запасные выходы (2 инструмента). Сырой GET и сырая запись для всего, что пропускает спецификация.
Каждый маршрут проходит через один и тот же исполнитель, поэтому шлюз записи, шлюз подтверждения разрушительных операций, шаблонизация путей и обработка запросов ведут себя одинаково, какой бы интерфейс вы ни использовали.
Выбирайте профиль по вкусу: minimal, если у вас подключено много MCP-серверов, core,
если хотите иметь повседневные операции в одном вызове, full, если контекст не проблема.
Примечания к полям — поведение, не документированное в спецификации
Все они были проверены на живой панели 3.3.2 и прикреплены к затрагиваемым операциям в описаниях инструментов.
PATCH /api/config-profiles— это замена, а не частичное обновление. Тело —{uuid, config}, иconfigдолжен быть полным, корректным конфигом Xray. Фрагмент завершается ошибкойA061: Config doesn't have inbounds. Правильная последовательность:GET /api/config-profiles/{uuid}→ отредактируйте возвращённый объектconfigна месте →PATCHвсего целиком.Панель не отвечает на
127.0.0.1:3000, даже с самого хоста панели и даже несмотря на то, чтоdocker-proxyслушает там (curlвозвращает код выхода 52, пустой ответ). Всегда используйте публичный HTTPS-адрес с Bearer-токеном.Каждый ответ обёрнут в
{"response": ...}. Этот сервер разворачивает его, поэтому вывод инструмента — это сам полезный груз.Хост привязывается к профилю через вложенный
inbound.configProfileUuid(плюсinbound.configProfileInboundUuid), а не через верхнеуровневыйconfigProfileUuid. Проверено на живых хостах: вложенный присутствует, верхнеуровневый отсутствует.Серия
PATCH-запросов выведет панель из строя. Каждая запись конфигурации отправляется на каждый узел и перезапускает там Xray; несколько подряд — и собственный TLS-слушатель панели перестаёт отвечать. Клиент сериализует мутации (REMNAWAVE_WRITE_MIN_INTERVAL_MS, по умолчанию 1500 мс) и повторяет транспортные сбои с экспоненциальной задержкой и джиттером. Не обходите это, запуская массовые обновления параллельно.POST /api/subscription-templatesсоздаёт только пустой шаблон. Содержимое загружается отдельнымPATCH /api/subscription-templates. JSON и YAML тела нельзя обновить в одном вызове.serverDescriptionна хосте ограничено 30 символами (подтвержденоmaxLengthв спецификации). Это также то, что заставляет хост Hysteria2 правильно отображаться в Happ вместо сырого JSON.Шестнадцать конечных точек доступны только для администраторского JWT — все контроллеры
authиpasskeys, а также управление API-токенами (GET/POST /api/tokens,DELETE /api/tokens/{uuid},GET /api/tokens/scopes). Панель отвечает на API-токен там 401/403. Этот сервер обнаруживает их из спецификации и отказывает локально;REMNAWAVE_ALLOW_ADMIN_JWT_OPS=1снимает ограничение, если настроенный вами токен действительно является администраторским JWT.GET /api/users/streamотвечает JSON, разделённым переводами строк, а не одним документом. Он разбирается в массив записей пользователей, а не возвращается как кусок текста.PATCH /api/hostsдействительно является настоящим частичным обновлением — одного{uuid, serverDescription}достаточно. Только конфигурационные профили имеют семантику полной замены. Проверено вживую.Ошибки возвращаются как
{message, errorCode};errorCode(например,A061) включается в текст ошибки этого сервера.
Покрытие инструментов
Каждый контроллер доступен через remnawave_call и запасные выходы. Столбец typed
показывает, какие получают отдельные инструменты при REMNAWAVE_TOOL_PROFILE=core.
Controller slug | Операции | Типизированы в |
| 17 | да |
| 18 | — |
| 15 | да |
| 12 | — |
| 12 | да |
| 12 | да |
| 10 | да |
| 9 | да |
| 8 | — |
| 7 | — |
| 7 | — |
| 7 | — |
| 7 | да |
| 7 | — |
| 7 | — |
| 7 | — |
| 6 | — |
| 5 | — |
| 5 | — |
| 5 | — |
| 4 | — |
| 4 | да |
| 4 | — |
| 3 | — |
| 2 | — |
| 2 | — |
| 2 | — |
| 1 | — |
Итого | 205 |
Запустите remnawave_list_operations на живом сервере, чтобы получить точный актуальный набор.
Примеры
Просмотр и вызов без типизированных инструментов:
// 1. What is there?
{ "tool": "remnawave_list_operations", "arguments": { "controller": "nodes" } }
// 2. What does it take?
{ "tool": "remnawave_describe_operation",
"arguments": { "operation": "remnawave_post_nodes_uuid_actions_restart" } }
// 3. Do it.
{ "tool": "remnawave_call",
"arguments": { "operation": "remnawave_post_nodes_uuid_actions_restart",
"params": { "uuid": "…" } } }params, body и query могут также приходить в виде JSON-текста — "params": "{\"uuid\":\"…\"}" —
потому что некоторые MCP-клиенты передают аргументы нетипизированных инструментов дословно, не разбирая их.
Строка разбирается за вас; строка, не являющаяся JSON, отклоняется с соответствующим сообщением.
Безопасное редактирование профиля конфигурации (ловушка A061):
// Read the whole profile first — PATCH replaces the config wholesale.
{ "tool": "remnawave_call",
"arguments": { "operation": "remnawave_get_config_profiles_uuid", "params": { "uuid": "…" } } }
// Send the full, edited config back.
{ "tool": "remnawave_call",
"arguments": { "operation": "remnawave_patch_config_profiles",
"params": { "body": { "uuid": "…", "config": { /* complete Xray config */ } } } } }Синтаксис запросов, который спецификация не может выразить:
{ "tool": "remnawave_request_read",
"arguments": { "path": "/api/users",
"query": { "size": 25, "start": 0,
"filters[0][id]": "status", "filters[0][value]": "ACTIVE" } } }Тестирование
npm run build
npm test # 50 unit tests + the offline smoke suite
npm run test:unit # unit tests aloneМодульные тесты покрывают части, которые отказывают тихо: разворачивание $ref через рекурсивные
DTO Remnawave, вывод имён инструментов (бюджет длины, детерминизм, обнаружение коллизий), diff каталога,
оба шлюза записи, шлюз admin-JWT, схлопывание схем и разбор NDJSON.
Проверки только на чтение против реальной панели
Когда панель доступна, а в окружении есть read-токен, smoke-скрипт также выполняет живые вызовы только на чтение (никогда не мутации):
REMNAWAVE_BASE_URL=https://panel.example.com \
REMNAWAVE_API_TOKEN_READ="$REMNAWAVE_API_TOKEN" \
npm run smokeЗапускайте его там, где токен уже живёт (например, на хосте панели), чтобы секрет никуда не путешествовал. Скрипт печатает формы — типы, имена ключей, длины массивов — и никогда значения полезной нагрузки, так что его вывод можно безопасно вставлять в issue.
Проверки защитных ограждений намеренно указывают на http://127.0.0.1:9, чтобы шлюз, который когда-либо
откажет в открытом виде, не смог дотянуться до реальной панели.
Проверка пути записи
Чтения не могут доказать, что маршрутизация токенов, троттлинг, шлюз подтверждения и семантика частичного
PATCH действительно работают. scripts/write-check.mjs доказывает это на объектах, к которым никто
не привязан, и возвращает на место единственный предсуществующий объект, которого касается:
REMNAWAVE_BASE_URL=https://panel.example.com \
REMNAWAVE_API_TOKEN_READ="$T" REMNAWAVE_API_TOKEN_WRITE="$T" \
node scripts/write-check.mjs --i-understand-this-mutates [--host-uuid <uuid>]Он создаёт внутренний отряд без входящих подключений и без участников и снова удаляет его, затем
перезаписывает serverDescription на одном хосте и восстанавливает исходное значение. Он отказывается
запускаться без флага подтверждения и сообщает о ненулевом коде выхода, если что-то осталось.
Против живой панели 3.3.2 он подтвердил: шлюз подтверждения срабатывает на реальном DELETE; частичный
PATCH /api/hosts работает; панель отклоняет serverDescription из 31 символа; исходное значение
(включая null) проходит туда и обратно; а последовательные мутации были разнесены на 1525 и 1524 мс
при настроенном минимуме в 1500 мс.
Локальный просмотр
REMNAWAVE_BASE_URL=https://panel.example.com REMNAWAVE_API_TOKEN_READ=xxx npm run inspectОбновление спецификации API
Всё об API берётся из одного файла, так что отслеживание нового релиза Remnawave — это одна команда:
npm run update-spec # fetch the newest spec + rebuild the catalogue
npm run update-spec -- --strict # additionally fail if any operation disappeared or was renamed
npm run build && npm test # compile and verifyОткуда берётся спецификация
https://cdn.remna.st/docs/openapi.json — публикуется собственным workflow Build&Push OpenAPI Specs
Remnawave на каждом теге апстрима, так что всегда описывает новейший релиз. Переопределите с помощью
--url <u> или REMNAWAVE_SPEC_URL, чтобы закрепить другой источник.
Экземпляр панели не является пригодным источником: документация отключена, если развёртывание
не включает её, и даже тогда Swagger смонтирован на /backend-tools/swagger, который обычный обратный
прокси не маршрутизирует. Проверка живой панели 3.3.2 вернула 404 на каждом обычном пути спецификации.
Загрузка записывается на диск только после того, как она разбирается как документ OpenAPI с непустым
paths, так что страница ошибки или captive-портал не могут затереть рабочую спецификацию.
Что проверить после
build-spec сравнивает новый каталог с предыдущим и печатает каждое изменение:
build-spec: Remnawave API v3.4.0 -> 211 operations, 28 controllers, 315 KB
methods: DELETE=22 GET=90 PATCH=19 POST=78 PUT=2 admin-JWT-only: 16
diff: API version 3.3.2 -> 3.4.0
REMOVED — tools that will disappear (1):
remnawave_get_old_thing (GET /api/old-thing)
added (7):
...REMOVED / RENAMED — ломающие изменения для тех, чьи промпты или скрипты называют эти инструменты.
--strictпревращает их в ненулевой код выхода — это флаг, который должна использовать автоматизация.added — безопасно; новые операции сразу доступны через
remnawave_callи получают типизированные инструменты, если их контроллер в активном профиле.schema changed — стоит взглянуть на операции, которые вы реально используете.
Затем npm test повторно проверяет, что каталог на диске совпадает со свежей сборкой, что все имена
инструментов уникальны и укладываются в бюджет 64 символов, и что защитные ограждения по-прежнему держатся.
Автоматизация
npm run update-spec -- --strict # exits non-zero on a breaking catalogue change
npm test
npm version minor --no-git-tag-version
git commit -am "chore: Remnawave API 3.4.0" && git push
git tag "v$(node -p "require('./package.json').version")" && git push --tagsОтправленный тег запускает workflow релиза, который перепубликует пакет в npm. Клиенты, зарегистрированные
с @folexz/remnawave-mcp@latest, подхватят новую версию при следующем запуске.
Релиз (для мейнтейнеров)
Первая публикация — обязательно вручную
npm не может настроить доверенного издателя для пакета, которого ещё не существует: настройка живёт на странице настроек самого пакета. Это известное, всё ещё открытое ограничение (npm/cli#8544), и оно применимо и к scoped-пакетам. Поэтому версию 0.1.0 нужно публиковать с машины, где выполнен вход:
npm whoami # must print the account that owns the @folexz scope
npm publish --access public--access public обязателен: scoped-пакеты по умолчанию ограничены.
Затем переключитесь на релизы без токенов
Как только пакет существует, на npmjs.com → @folexz/remnawave-mcp → Settings → Trusted Publisher
добавьте издателя GitHub Actions с репозиторием folexz/remnawave-mcp и workflow release.yml.
repository.url в package.json должен точно совпадать с репозиторием GitHub — так и есть.
После этого .github/workflows/release.yml публикует по любому отправленному тегу vX.Y.Z через OIDC —
без токена, без секрета, с автоматически прикреплённой provenance:
npm version patch --no-git-tag-version
git commit -am "chore: v0.1.1"
git push
git tag v0.1.1 && git push origin v0.1.1Workflow переустанавливает зависимости из lockfile, пересобирает, запускает модульные тесты и офлайн
smoke-набор и быстро падает, если тег не совпадает с package.json.
Клиенты, зарегистрированные с @folexz/remnawave-mcp@latest, подхватят новую версию при следующем
запуске.
Заметки по безопасности
Токены читаются только из окружения и никогда не логируются. Логи идут в stderr; stdout — это канал MCP JSON-RPC.
Предпочитайте настраивать только
REMNAWAVE_API_TOKEN_READ. Мутирующих инструментов не существует без write-токена, так что скомпрометированный или запутавшийся клиент не сможет изменить панель.Эндпоинты подписок возвращают рабочие конфигурации клиентов. Относитесь к их выводу как к секрету.
Никогда не коммитьте реальные токены.
.envв gitignore;.env.exampleпоказывает форму.
Известные ограничения
Валидация тела делегирована панели. Этот сервер проверяет только наличие обязательных аргументов и обязательного
body; он не проверяет внутреннюю форму тела на соответствие схеме. Это намеренно — панель уже валидирует каждое поле и отвечает точнымmessage+errorCode(например,A061), а дублирование этого локально означало бы поставку валидатора JSON Schema плюс вторую, неизбежно расходящуюся, копию правил. Цена в том, что о некорректном теле вы узнаёте ценой одного round trip.Запасные люки обходят шлюзы отдельных операций.
remnawave_request_writeсырой по замыслу: он по-прежнему требует write-токен и по-прежнему проходит через троттлинг и логику повторов, но не применяет разрушительный шлюзconfirmили проверку admin-JWT, потому что у него нет операции, по которой их можно найти. Предпочитайтеremnawave_call, если вам не нужен маршрут, который спецификация не описывает.Инструменты настолько актуальны, насколько актуальна поставляемая спецификация (v3.3.2). Панель на другой минорной версии может открывать маршруты, которые она не описывает; для этого и нужны запасные люки. См. Обновление спецификации API.
Эндпоинты admin-JWT закрыты шлюзом, а не реализованы. Этот сервер носит API-токены; он не выполняет вход администратора, не держит сессию и не обновляет JWT. Если вы предоставите admin JWT в качестве токена и установите
REMNAWAVE_ALLOW_ADMIN_JWT_OPS=1, эти 16 эндпоинтов станут вызываемыми, но истечение и продление — ваша проблема.Эндпоинт метрик Prometheus с basic-auth не является частью этой спецификации и не открыт.
write-check.mjsмутирует. Это инструмент мейнтейнера, исключённый изnpm test, и отказывается запускаться без явного флага подтверждения.
Лицензия
MIT — см. LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Managed MCP gateway with OAuth, per-agent permissions, shared accounts and activity logs.
EU cloud as MCP tools: VPS, databases, caches, storage, containers and more. Takes an API token.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Unified gateway exposing 150+ tools across all NexGenData MCP servers via one endpoint.
Related MCP Servers
- AlicenseCqualityBmaintenanceWraps the Remnawave API to provide per-operation MCP tools with mutation safety and data redaction, enabling secure interaction with Remnawave panel.100MIT
- AlicenseCqualityAmaintenanceEnables MCP clients like Claude Code, Claude Desktop, or Cursor to read and manage Remnawave 3.x VPN panel resources — users, nodes, hosts, config profiles, squads, subscription templates, billing, and HWID devices — through the panel's REST API, with contract-driven tool schemas, numeric user IDs, multi-panel config lookup, and an optional readonly mode.2045 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables managing and observing Technitium DNS Server through MCP, including read-only or read-write tool surfaces, scoped bearer authentication, audit logging, and confirmation gates for destructive operations.MIT
- AlicenseCqualityBmaintenanceEnables managing a Remnawave VPN panel from MCP clients, providing tools for users, nodes, subscriptions, statistics, billing, and system operations, plus resources and prompts for common admin tasks.1905 npmMIT