npm-mcp
npm-mcp
Servidor del Model Context Protocol para Nginx Proxy Manager
Gestiona el enrutamiento de proxy inverso, los certificados TLS, las listas de acceso y los reenvíos de flujo de forma conversacional, con salvaguardas que asumen que tarde o temprano lo apuntarás a producción.
Contenido
Related MCP server: npm-mcp
Por qué existe
Nginx Proxy Manager tiene una API REST completa y ningún servidor MCP. Este es ese servidor, pero la parte interesante no es la fontanería, sino las restricciones.
Un proxy inverso es un punto único de fallo para todo lo que hay detrás. Un agente con acceso de escritura a uno puede tumbar servicios a los que nunca se le pidió tocar. Así que el diseño parte de ahí:
Las herramientas se generan a partir del propio documento OpenAPI de la API, no se escriben a mano. El documento está fijado en el árbol de código, y una prueba de deriva hace fallar el CI si la superficie aguas arriba cambia, en lugar de que las herramientas devuelvan 404 silenciosamente en tiempo de ejecución.
Cada resultado cruza un límite de redacción que falla en modo cerrado. Lanza una excepción ante cualquier cosa que no pueda inspeccionar, en lugar de pasarla.
Las salvaguardas se prueban mediante mutación. Cada control de seguridad tiene una prueba que demuestra que se pone en rojo cuando el control está desactivado.
Cómo funciona
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| TLas firmas de las herramientas se construyen a partir del documento fijado en el momento de la importación, por lo que
create_proxy_host expone 18 argumentos tipados con enums reales, no un
passthrough opaco de **kwargs.
Inicio rápido
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 sirve en /mcp. Una barra final redirige con 307, lo que algunos clientes
gestionan mal: no dejes que un proxy reescriba la ruta.
[!TIP] Llama primero a
get_guidance. Informa de las formas de las respuestas, la distinción entre deshabilitar y eliminar, qué pestillos están actualmente abiertos y la lista activa de dominios protegidos.
Autenticación
Dos capas, fáciles de confundir:
Dirección | Mecanismo | |
Entrante | cliente → npm-mcp |
|
Saliente | npm-mcp → NPM | Credenciales de cuenta → JWT de corta duración, renovado automáticamente. Los llamadores nunca lo ven ni lo aportan. |
NPM no emite claves API de larga duración, por eso el servidor guarda las credenciales en lugar de aceptar un token.
[!IMPORTANT]
POST /tokenstiene dos respuestas posibles: un token o un desafío de 2FA. Si la cuenta tiene 2FA activado, configuraNPM_TOTP_SECRET; de lo contrario, el servidor falla al arrancar, indicando ambos remedios, en lugar de levantarse sano y romperse en la primera llamada a una herramienta.
Catálogo de herramientas
66 herramientas = 65 operaciones de API + get_guidance.
Familia | # | Herramientas representativas |
🔀 Hosts proxy | 7 |
|
↪️ Hosts de redirección | 7 |
|
🚫 Hosts 404 | 7 |
|
🔌 Streams | 7 |
|
🔐 Listas de acceso | 5 |
|
📜 Certificados | 10 |
|
👤 Usuarios | 8 |
|
🔑 2FA de usuario | 5 |
|
⚙️ Ajustes | 3 |
|
📋 Registro de auditoría | 2 |
|
ℹ️ Meta | 4 |
|
🧭 Orientación | 1 |
|
Los nombres derivan del operationId de OpenAPI, por lo que las operaciones de listado son get_*,
no list_*.
[!WARNING] Tres operaciones no se exponen deliberadamente:
requestToken,refreshToken,loginWith2FA. Son la fontanería de autenticación del propio servidor, yrequestTokenacepta una identidad y un secreto arbitrarios: registrarla convertiría este servidor en un oráculo de prueba de credenciales contra NPM, con cada intento atribuido a la cuenta de servicio.
No existe paginación. Ni un solo endpoint acepta
limit/offset. Las herramientas los aceptan y los recortan en el lado del cliente; las descripciones de las herramientas lo indican.expandes un enum por endpoint, no un paso directo: los hosts de proxy aceptanaccess_list,owner,certificate; los certificados solo aceptanowner. Los valores fuera del enum se rechazan antes de enviar la solicitud.
Modelo de seguridad
[!CAUTION] Las escrituras están habilitadas por defecto. Este servidor puede reescribir la tabla de enrutamiento de todos los servicios detrás del proxy. Configura
NPM_READ_ONLY=1para deshabilitar todas las mutaciones.
Control | Anulación | |
| Rechaza toda herramienta mutadora, comprobado antes de cualquier lectura de salvaguarda | — |
S1 | Rechaza |
|
S2 | Cada | por llamada |
S5 | Cada mutación emite una línea de auditoría; el registro de auditoría propio de NPM es consultable | — |
S6 | Toda operación mutativa bajo |
|
S7 | Rechaza modificar, deshabilitar, eliminar o | ninguna |
S8 |
|
|
S1 coincide con CUALQUIER dominio protegido, no con TODOS. TODOS permitiría desarmar la salvaguarda a través de las propias herramientas que protege: añade un dominio no relacionado a un host y la protección se evapora.
S1 cubre
update, no solo delete/disable. De lo contrario, se elimina el nombre protegido dedomain_namesy luego se borra limpiamente: el mismo apagón.S1 coincide con el estado actual aguas arriba, nunca con el cuerpo enviado. Comprobar la solicitud permitiría que la ruta de quitar-y-actualizar pasara directamente.
Los comodines de S1 coinciden en ambas direcciones.
NPM_PROTECTED_DOMAINS=*.example.netdebe protegerapp.example.net. Una vez no coincidía con nada y suprimía la advertencia de "no protegido", porque el valor estaba establecido explícitamente.S2 se limita por método HTTP, no por prefijo de nombre. Una regla
delete_*no detectadisable_user_2fa, unDELETEque elimina el segundo factor de alguien.S6 es una regla, no una lista. Una versión enumerada omitía silenciosamente
update_user, por lo que el pestillo permanecía cerrado mientrasis_disabled: truebloqueaba a un administrador.S7 no tiene anulación. Un servidor que puede eliminar sus propias credenciales se bloquea permanentemente.
Configuración
Variable | Significado |
| URL base de la instancia de NPM |
| Correo electrónico de la cuenta |
| Contraseña de la cuenta |
Variable | Valor por defecto | Significado |
| sin configurar | Token entrante. Sin configurar ⇒ sin autenticación entrante |
|
|
|
|
| Dirección de enlace |
|
| Puerto de enlace |
Variable | Valor predeterminado | Pestillos |
|
| — ( |
| derivado de | Lista de denegación, separada por comas |
|
| S1 |
|
| S6 |
|
| S8 |
Variable | Valor predeterminado | Significado |
| sin establecer | Semilla Base32; solo si la cuenta tiene 2FA |
|
| Verificar el certificado de NPM |
|
| Tiempo de espera ascendente, segundos |
|
| Límite de respuesta antes de truncar |
|
| Indicar hacia |
|
|
Implementación
docker build -t npm-mcp:latest .
docker compose up -dEl contenedor se une a una red Docker existente junto a NPM y publica ningún puerto. NPM lo alcanza mediante DNS de contenedor y termina TLS, por lo que el token Bearer nunca cruza el cable en texto plano.
Sin clave
build:en el archivo compose. Una implementación de string compose (Portainer, por ejemplo) no incluye contexto de compilación, por lo que la imagen se construye primero y se referencia por etiqueta.El healthcheck resuelve el host de enlace en lugar de fijar
127.0.0.1. Con unNPM_MCP_HTTP_HOSTpersonalizado, la versión ingenua marca un contenedor perfectamente sano como insano para siempre. También falla bajostdio, donde no hay nada escuchando en absoluto.La autenticación de arranque se ejecuta durante la vida útil del servidor, por lo que una configuración incorrecta hace fallar el healthcheck en lugar de arrancar correctamente y romperse en el primer uso.
Pruebas
uv run pytest # 420 tests
uv run ruff check
uv run ruff format --checkAproximadamente 4.700 líneas de pruebas contra 3.300 líneas de código fuente, pero la cantidad importa menos que la forma:
🧬 Guardarraíles verificados por mutación — cada control de seguridad tiene una prueba que demuestra fallar cuando el control está deshabilitado. Escrito tras descubrir un
asyncio.Lockcuya eliminación mantenía la suite en verde.🌐 Cero acceso a la red — cada llamada ascendente está simulada con
respx. Una prueba que necesite la red es una prueba rota.🔍 Barrido A7 — las 65 herramientas se invocan contra un ascendente que devuelve secretos a cuatro niveles de profundidad, con un control negativo que verifica que el fixture realmente los contiene, para que el barrido no pase de forma vacua.
📐 Guardián de deriva de esquema — los recuentos de operaciones, las formas de las cargas útiles y el archivo de datos empaquetado se verifican todos, por lo que una actualización ascendente falla aquí en lugar de en producción.
Notas de diseño
Documento | Contenido |
Contrato del producto — decisiones D1–D13, controles S1–S8, criterios de aceptación A1–A10 | |
Las 68 operaciones con campos de cuerpo y obligatoriedad | |
Interfaces internas de los módulos | |
Dos cosas que el documento OpenAPI hace mal, medidas contra una instancia en vivo | |
Copia textual del |
This server cannot be deployed
Maintenance
Related MCP Connectors
Manage hosts, redirects, SSL, and traffic analytics from Claude and other AI assistants.
Inspect and control your Northflank projects, services, jobs, and builds from your AI assistant.
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Deploy and manage your apps, databases, storage, and scheduled jobs from your AI agent
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
- AlicenseCqualityCmaintenanceMCP server that abstracts the Nginx Proxy Manager API, enabling management of proxy hosts, redirections, streams, certificates, access lists, and users through natural language.5414 npm1AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Nginx Proxy Manager, including proxy hosts, SSL certificates, streams, and more.5 npmISC