npm-mcp
npm-mcp
Сервер Model Context Protocol для Nginx Proxy Manager
Управляйте reverse-proxy маршрутизацией, TLS-сертификатами, списками доступа и stream-пересылкой в диалоговом режиме — с защитными механизмами, которые предполагают, что вы в конечном итоге направите его на продакшен.
Содержание
Related MCP server: npm-mcp
Зачем это существует
У Nginx Proxy Manager есть полноценный REST API и нет MCP-сервера. Этот сервер — именно он, но интересна не техническая часть, а ограничения.
Reverse proxy — это единая точка отказа для всего, что за ним стоит. Агент с правом записи может вывести из строя сервисы, к которым его не просили прикасаться. Поэтому дизайн исходит из этого:
Инструменты генерируются из собственного OpenAPI-документа API, а не пишутся вручную. Документ закреплён в репозитории, и drift-тест проваливает CI, если вышестоящая поверхность меняется — вместо того чтобы инструменты молча возвращали 404 во время выполнения.
Каждый результат проходит через одну границу редактирования, которая закрывается по умолчанию. Она вызывает исключение на всём, что не может проверить, вместо того чтобы пропускать это дальше.
Защитные механизмы проходят mutation-тестирование. Для каждого контроля безопасности есть тест, который, как доказано, становится красным, когда контроль отключён.
Как это работает
flowchart LR
C["MCP Client"] -->|"Bearer (optional)"| S
subgraph S["npm-mcp"]
direction TB
A["Bearer verifier<br/><i>hmac.compare_digest</i>"] --> G["Guardrails<br/><i>S1 · S2 · S6 · S7 · S8</i>"]
G --> T["66 generated tools"]
T --> R["serialize_result()<br/><i>redact + cap</i>"]
end
S -->|"JWT, auto-refreshed"| N["Nginx Proxy Manager"]
P["npm-openapi.json<br/><i>pinned, in-package</i>"] -.->|generates| TСигнатуры инструментов строятся из закреплённого документа во время импорта, поэтому
create_proxy_host предоставляет 18 типизированных аргументов с настоящими перечислениями —
а не непрозрачный проход через **kwargs.
Быстрый старт
uv sync
cp .env.example .env # then fill in NPM_URL / NPM_IDENTITY / NPM_SECRET
uv run npm-mcp{
"mcpServers": {
"npm": {
"command": "uv",
"args": ["run", "npm-mcp"],
"env": {
"NPM_URL": "https://nginx-proxy-manager.example.net",
"NPM_IDENTITY": "npm-mcp@example.net",
"NPM_SECRET": "…",
"NPM_MCP_TRANSPORT": "stdio"
}
}
}
}{
"mcpServers": {
"npm": {
"type": "http",
"url": "https://npm-mcp.example.net/mcp",
"headers": { "Authorization": "Bearer <NPM_MCP_BEARER_TOKEN>" }
}
}
}FastMCP обслуживает запросы по адресу /mcp. Завершающий слэш вызывает 307-редирект,
который некоторые клиенты обрабатывают некорректно — не позволяйте прокси переписывать путь.
[!TIP] Сначала вызовите
get_guidance. Он сообщает о формах ответов, различии между отключением и удалением, о том, какие защёлки в данный момент открыты, и о действующем списке защищённых доменов.
Аутентификация
Два уровня, которые легко перепутать:
Направление | Механизм | |
Входящая | клиент → npm-mcp | Необязательный |
Исходящая | npm-mcp → NPM | Учётные данные аккаунта → кратковременный JWT, обновляется автоматически. Вызывающие его никогда не видят и не предоставляют. |
NPM не выдаёт долгоживущих API-ключей, поэтому сервер хранит учётные данные, а не принимает токен.
[!IMPORTANT] У
POST /tokensдва возможных ответа: токен или 2FA-вызов. Если в аккаунте включена 2FA, задайтеNPM_TOTP_SECRET— в противном случае сервер завершится с ошибкой при запуске, указав оба способа решения, вместо того чтобы подняться здоровым и сломаться на первом вызове инструмента.
Каталог инструментов
66 инструментов = 65 операций API + get_guidance.
Семейство | # | Представительные инструменты |
🔀 Proxy-хосты | 7 |
|
↪️ Хосты-редиректы | 7 |
|
🚫 Хосты 404 | 7 |
|
🔌 Streams | 7 |
|
🔐 Списки доступа | 5 |
|
📜 Сертификаты | 10 |
|
👤 Пользователи | 8 |
|
🔑 2FA пользователей | 5 |
|
⚙️ Настройки | 3 |
|
📋 Журнал аудита | 2 |
|
ℹ️ Мета | 4 |
|
🧭 Руководство | 1 |
|
Названия происходят из operationId в OpenAPI, поэтому операции списка называются get_*,
а не list_*.
[!WARNING] Три операции намеренно не предоставляются:
requestToken,refreshToken,loginWith2FA. Это собственная аутентификационная обвязка сервера, аrequestTokenпринимает произвольную идентичность и секрет — регистрация превратила бы этот сервер в оракул для проверки учётных данных против NPM, при этом каждая попытка приписывалась бы служебному аккаунту.
Пагинации не существует. Ни одна конечная точка не принимает
limit/offset. Инструменты принимают их и обрезают на стороне клиента; в описаниях инструментов об этом сказано.expand— это перечисление для каждой конечной точки, а не сквозной параметр — proxy-хосты принимаютaccess_list,owner,certificate; сертификаты принимают толькоowner. Значения вне перечисления отклоняются до отправки запроса.
Модель безопасности
[!CAUTION] Запись включена по умолчанию. Этот сервер может переписать таблицу маршрутизации для каждого сервиса за прокси. Установите
NPM_READ_ONLY=1, чтобы отключить все изменения.
Контроль | Переопределение | |
| Отклоняет каждый изменяющий инструмент, проверяется до любого чтения защитных механизмов | — |
S1 | Отказывает в |
|
S2 | Каждый | при каждом вызове |
S5 | Каждое изменение порождает одну строку аудита; собственный журнал аудита NPM доступен для запросов | — |
S6 | Каждая изменяющая операция в |
|
S7 | Отказывается изменять, отключать, удалять или выполнять | нет |
S8 |
|
|
S1 сопоставляет ЛЮБОЙ защищённый домен, а не ВСЕ. ВСЕ позволило бы обезвредить защитный механизм через инструменты, которые он защищает: добавьте один посторонний домен к хосту — и защита испарится.
S1 покрывает
update, а не только delete/disable. Иначе вы удаляете защищённое имя изdomain_names, а затем чисто удаляете — тот же самый простой.S1 сопоставляется с текущим состоянием вышестоящей системы, никогда с отправленным телом. Проверка запроса позволила бы пути «удалить-затем-обновить» пройти напрямую.
Подстановочные знаки S1 сопоставляются в обоих направлениях.
NPM_PROTECTED_DOMAINS=*.example.netдолжен защищатьapp.example.net. Однажды он не сопоставлял ничего и подавлял предупреждение «не защищено», потому что значение было явно задано.S2 ограничивается HTTP-методом, а не префиксом имени. Правило
delete_*пропускаетdisable_user_2fa—DELETE, который снимает второй фактор у человека.S6 — это правило, а не список. Перечисляемая версия молча пропускала
update_user, поэтому защёлка оставалась закрытой, покаis_disabled: trueблокировал администратора.У S7 нет переопределения. Сервер, который может удалить собственные учётные данные, навсегда блокирует сам себя.
Конфигурация
Переменная | Значение |
| Базовый URL экземпляра NPM |
| Email аккаунта |
| Пароль аккаунта |
Переменная | По умолчанию | Значение |
| не задан | Входящий токен. Не задан ⇒ нет входящей аутентификации |
|
|
|
|
| Адрес привязки |
|
| Порт привязки |
Переменная | По умолчанию | Снятие ограничений |
|
| — ( |
| производное от | S1 денylist, через запятую |
|
| S1 |
|
| S6 |
|
| S8 |
Переменная | По умолчанию | Значение |
| не задано | Base32-сид; только если у аккаунта включена 2FA |
|
| Проверять сертификат NPM |
|
| Таймаут вышестоящего сервиса, секунды |
|
| Лимит ответа до усечения |
|
| Подсказка к |
|
|
Развёртывание
docker build -t npm-mcp:latest .
docker compose up -dКонтейнер подключается к существующей Docker-сети вместе с NPM и не публикует никаких портов. NPM обращается к нему по DNS-имени контейнера и завершает TLS, поэтому Bearer-токен никогда не передаётся по сети в открытом виде.
Никакого ключа
build:в compose-файле. Развёртывание из compose-строки (например, Portainer) не передаёт контекст сборки, поэтому образ сначала собирается, а затем указывается по тегу.Healthcheck резолвит хост привязки вместо жёстко заданного
127.0.0.1. С нестандартнымNPM_MCP_HTTP_HOSTнаивная версия навсегда помечает полностью здоровый контейнер как нездоровый. Он также срабатывает вхолостую приstdio, где вообще ничего не слушает.Аутентификационный прогрев выполняется в течение жизни сервера, поэтому неверная конфигурация приводит к провалу healthcheck, а не к зелёному статусу с последующей поломкой при первом использовании.
Тестирование
uv run pytest # 420 tests
uv run ruff check
uv run ruff format --checkПримерно 4 700 строк тестов на 3 300 строк исходного кода, но количество важнее формы:
🧬 Мутационно-проверенные предохранители — для каждого элемента контроля безопасности есть тест, который, как доказано, падает при отключении этого контроля. Написано после обнаружения
asyncio.Lock, удаление которого оставляло набор тестов зелёным.🌐 Нулевой доступ к сети — каждый вызов вышестоящего сервиса замокан через
respx. Тест, которому нужна сеть, — это сломанный тест.🔍 Проход A7 — все 65 инструментов вызываются против вышестоящего сервиса, возвращающего секреты на четырёх уровнях вложенности, с отрицательным контролем, подтверждающим, что фикстура действительно их содержит, чтобы проход не мог пройти впустую.
📐 Защита от дрейфа схемы — количество операций, формы полезной нагрузки и упакованный файл данных — всё проверяется, так что обновление вышестоящего сервиса падает здесь, а не в продакшене.
Заметки по дизайну
Документ | Содержимое |
Контракт продукта — решения D1–D13, контроли S1–S8, критерии приёмки A1–A10 | |
Все 68 операций с полями тела и обязательностью | |
Внутренние интерфейсы модулей | |
Две вещи, которые OpenAPI-документ описывает неверно, проверенные на живом экземпляре | |
Дословная копия |
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityCmaintenanceEnables management of Nginx Proxy Manager instances for configuring proxy hosts, requesting Let's Encrypt SSL certificates, and managing access lists. It allows users to control their web proxy infrastructure through natural language commands in MCP-compatible environments.503MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Nginx Proxy Manager instances through natural language, covering 28 tools for proxy hosts, certificates, streams, and more.MIT
- AlicenseCqualityDmaintenanceMCP server that abstracts the Nginx Proxy Manager API, enabling management of proxy hosts, redirections, streams, certificates, access lists, and users through natural language.54171AGPL 3.0
- AlicenseAqualityAmaintenanceEnables natural language management of FastPanel 2 servers, including creating sites, databases, SSL certificates, and hardening nginx configurations.322MIT
Related MCP Connectors
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/omichelbraga/nginx-proxy-manager-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server