Skip to main content
Glama

npm-mcp

Сервер Model Context Protocol для Nginx Proxy Manager

Управляйте reverse-proxy маршрутизацией, TLS-сертификатами, списками доступа и stream-пересылкой в диалоговом режиме — с защитными механизмами, которые предполагают, что вы в конечном итоге направите его на продакшен.

Python FastMCP NPM Tests Tools Ruff


Содержание


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

Необязательный Authorization: Bearer … через NPM_MCP_BEARER_TOKEN, сравнивается с помощью hmac.compare_digest. Не задан ⇒ аутентификации нет вообще.

Исходящая

npm-mcp → NPM

Учётные данные аккаунта → кратковременный JWT, обновляется автоматически. Вызывающие его никогда не видят и не предоставляют.

NPM не выдаёт долгоживущих API-ключей, поэтому сервер хранит учётные данные, а не принимает токен.

[!IMPORTANT] У POST /tokens два возможных ответа: токен или 2FA-вызов. Если в аккаунте включена 2FA, задайте NPM_TOTP_SECRET — в противном случае сервер завершится с ошибкой при запуске, указав оба способа решения, вместо того чтобы подняться здоровым и сломаться на первом вызове инструмента.


Каталог инструментов

66 инструментов = 65 операций API + get_guidance.

Семейство

#

Представительные инструменты

🔀 Proxy-хосты

7

get_proxy_hosts · create_proxy_host · update_proxy_host · delete_proxy_host · enable_proxy_host · disable_proxy_host

↪️ Хосты-редиректы

7

*_redirection_host

🚫 Хосты 404

7

create_404_host · *_dead_host

🔌 Streams

7

*_stream

🔐 Списки доступа

5

get_access_lists · create_access_list · update_access_list · delete_access_list

📜 Сертификаты

10

get_certificates · create_certificate · renew_certificate · upload_certificate · validate_certificates · download_certificate · test_http_reach · get_dns_providers

👤 Пользователи

8

get_users · create_user · update_user · update_user_auth · update_user_permissions · login_as_user

🔑 2FA пользователей

5

setup_user_2fa · enable_user_2fa · disable_user_2fa · get_user_2fa_status · regen_user_2fa_codes

⚙️ Настройки

3

get_settings · update_setting

📋 Журнал аудита

2

get_audit_logs · get_audit_log

ℹ️ Мета

4

health · check_version · reports_hosts · schema

🧭 Руководство

1

get_guidance

Названия происходят из operationId в OpenAPI, поэтому операции списка называются get_*, а не list_*.

[!WARNING] Три операции намеренно не предоставляются: requestToken, refreshToken, loginWith2FA. Это собственная аутентификационная обвязка сервера, а requestToken принимает произвольную идентичность и секрет — регистрация превратила бы этот сервер в оракул для проверки учётных данных против NPM, при этом каждая попытка приписывалась бы служебному аккаунту.

  • Пагинации не существует. Ни одна конечная точка не принимает limit/offset. Инструменты принимают их и обрезают на стороне клиента; в описаниях инструментов об этом сказано.

  • expand — это перечисление для каждой конечной точки, а не сквозной параметр — proxy-хосты принимают access_list,owner,certificate; сертификаты принимают только owner. Значения вне перечисления отклоняются до отправки запроса.


Модель безопасности

[!CAUTION] Запись включена по умолчанию. Этот сервер может переписать таблицу маршрутизации для каждого сервиса за прокси. Установите NPM_READ_ONLY=1, чтобы отключить все изменения.

Контроль

Переопределение

NPM_READ_ONLY

Отклоняет каждый изменяющий инструмент, проверяется до любого чтения защитных механизмов

S1

Отказывает в delete / disable / update для защищённых хостов, а также для сертификатов и списков доступа, от которых эти хосты зависят

NPM_ALLOW_SELF_MUTATION

S2

Каждый DELETE требует confirm: true; без него инструмент возвращает то, что было бы затронуто, и ничего не записывает

при каждом вызове

S5

Каждое изменение порождает одну строку аудита; собственный журнал аудита NPM доступен для запросов

S6

Каждая изменяющая операция в /users или /settings защёлкнута

NPM_ALLOW_ACCOUNT_MUTATION

S7

Отказывается изменять, отключать, удалять или выполнять login_as для собственного аккаунта

нет

S8

download_certificate возвращает приватные ключи TLS, поэтому защёлкнут

NPM_ALLOW_CERT_EXPORT

  • S1 сопоставляет ЛЮБОЙ защищённый домен, а не ВСЕ. ВСЕ позволило бы обезвредить защитный механизм через инструменты, которые он защищает: добавьте один посторонний домен к хосту — и защита испарится.

  • S1 покрывает update, а не только delete/disable. Иначе вы удаляете защищённое имя из domain_names, а затем чисто удаляете — тот же самый простой.

  • S1 сопоставляется с текущим состоянием вышестоящей системы, никогда с отправленным телом. Проверка запроса позволила бы пути «удалить-затем-обновить» пройти напрямую.

  • Подстановочные знаки S1 сопоставляются в обоих направлениях. NPM_PROTECTED_DOMAINS=*.example.net должен защищать app.example.net. Однажды он не сопоставлял ничего и подавлял предупреждение «не защищено», потому что значение было явно задано.

  • S2 ограничивается HTTP-методом, а не префиксом имени. Правило delete_* пропускает disable_user_2faDELETE, который снимает второй фактор у человека.

  • S6 — это правило, а не список. Перечисляемая версия молча пропускала update_user, поэтому защёлка оставалась закрытой, пока is_disabled: true блокировал администратора.

  • У S7 нет переопределения. Сервер, который может удалить собственные учётные данные, навсегда блокирует сам себя.


Конфигурация

Переменная

Значение

NPM_URL

Базовый URL экземпляра NPM

NPM_IDENTITY

Email аккаунта

NPM_SECRET

Пароль аккаунта

Переменная

По умолчанию

Значение

NPM_MCP_BEARER_TOKEN

не задан

Входящий токен. Не задан ⇒ нет входящей аутентификации

NPM_MCP_TRANSPORT

streamable-http

stdio | streamable-http

NPM_MCP_HTTP_HOST

0.0.0.0

Адрес привязки

NPM_MCP_HTTP_PORT

8000

Порт привязки

Переменная

По умолчанию

Снятие ограничений

NPM_READ_ONLY

0

— (1 блокирует все записи)

NPM_PROTECTED_DOMAINS

производное от NPM_URL

S1 денylist, через запятую

NPM_ALLOW_SELF_MUTATION

0

S1

NPM_ALLOW_ACCOUNT_MUTATION

0

S6

NPM_ALLOW_CERT_EXPORT

0

S8

Переменная

По умолчанию

Значение

NPM_TOTP_SECRET

не задано

Base32-сид; только если у аккаунта включена 2FA

NPM_TLS_VERIFY

1

Проверять сертификат NPM

NPM_TIMEOUT

30

Таймаут вышестоящего сервиса, секунды

NPM_MAX_RESPONSE_CHARS

50000

Лимит ответа до усечения

NPM_GUIDANCE_GATE

1

Подсказка к get_guidance при ранних мутациях

LOG_LEVEL

INFO


Развёртывание

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 инструментов вызываются против вышестоящего сервиса, возвращающего секреты на четырёх уровнях вложенности, с отрицательным контролем, подтверждающим, что фикстура действительно их содержит, чтобы проход не мог пройти впустую.

  • 📐 Защита от дрейфа схемы — количество операций, формы полезной нагрузки и упакованный файл данных — всё проверяется, так что обновление вышестоящего сервиса падает здесь, а не в продакшене.


Заметки по дизайну

Документ

Содержимое

spec.md

Контракт продукта — решения D1–D13, контроли S1–S8, критерии приёмки A1–A10

docs/api-surface.md

Все 68 операций с полями тела и обязательностью

docs/module-contract.md

Внутренние интерфейсы модулей

docs/findings.md

Две вещи, которые OpenAPI-документ описывает неверно, проверенные на живом экземпляре

npm_mcp/data/npm-openapi.json

Дословная копия /api/schema экземпляра — внутри пакета, потому что это зависимость времени выполнения, а не документация

A
license - permissive license
Not graded
quality - not tested
C
maintenance

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

  • A
    license
    B
    quality
    C
    maintenance
    Enables 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.
    50
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to manage Nginx Proxy Manager instances through natural language, covering 28 tools for proxy hosts, certificates, streams, and more.
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables natural language management of FastPanel 2 servers, including creating sites, databases, SSL certificates, and hardening nginx configurations.
    32
    2
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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