juniper-junos-mcp
juniper-junos-mcp
Un servidor MCP que expone dispositivos Juniper Junos —en particular firewalls SRX— como herramientas que un cliente LLM puede invocar. Lecturas operativas con nombre, más una ruta de cambio de configuración que previsualiza el diff del propio dispositivo, confirma tras un temporizador de reversión, verifica que el equipo sigue respondiendo, y solo entonces confirma.
Habla MCP sobre HTTP Streamable, por lo que se ejecuta como su propio servicio en la red en lugar de como un subproceso local de un solo cliente. El transporte al dispositivo es NETCONF sobre SSH, a través de junos-eznc.
Construido para universal-network-director, un gestor de red multi-fabricante basado en chat con una puerta de aprobación humana en cada escritura, pero es un servidor MCP independiente y funciona con cualquier cliente MCP.
No está afiliado, respaldado ni soportado por Juniper Networks. "Juniper", "Junos" y "SRX" son marcas comerciales de sus respectivos propietarios y se utilizan aquí únicamente para describir con qué se comunica este software.
El modelo de seguridad
La configuración de un router no es un conjunto de llamadas API estrechas, por lo que esto no pretende serlo. Dos cosas hacen que los cambios de configuración sean supervivibles, y ninguna es el modelo:
1. El diff proviene del dispositivo, no del modelo
preview_config_change carga tus líneas set en una configuración candidata y devuelve la salida show | compare del propio dispositivo. Eso es el router diciéndote qué cambiaría realmente, dado su estado actual — no el relato del modelo sobre lo que pretendía. Apruebas eso.
write_apply_previewed_config entonces toma solo un id de previsualización. No puede confirmar nada que no haya sido previsualizado, y la previsualización se revalida contra el dispositivo antes de confirmar: si la configuración en ejecución se movió por debajo, la aplicación falla de forma segura en lugar de confirmar un diff obsoleto. Las previsualizaciones caducan (JUNOSGW_PREVIEW_TTL, por defecto 30 minutos), y una caducada falla con "previsualización desconocida o caducada" para que vuelvas a previsualizar contra el estado actual.
2. Un cambio que corta la gestión se revierte solo
La aplicación es commit confirmed <n>: entra en vigor de inmediato, pero Junos la revierte automáticamente a menos que llegue una confirmación de confirmación dentro de n minutos (1–60, por defecto 5). Este servidor entonces se reconecta en una nueva sesión para verificar que el dispositivo sigue respondiendo, y envía la confirmación de confirmación solo si lo hace. Si te bloqueas, el equipo deshace el cambio por sí solo.
Lo que esto no protege
Las lecturas están acotadas por construcción — cada lectura operativa ejecuta un comando que este servidor eligió, por lo que el modelo selecciona una herramienta, nunca un comando. Los cambios de configuración no están acotados de esa manera: el modelo escribe las líneas set. Lo que protege ese lado es el diff proveniente del dispositivo y la reversión automática, no la superficie de la herramienta. Lee el diff.
Lee esto antes de apuntarlo a producción
Dos de las quince herramientas cambian el estado, y este servidor no pregunta antes de ejecutarlas. No hay un paso de confirmación aquí — el prefijo write_ es una convención para que tu cliente las controle.
Herramienta | Qué hace | Riesgo |
| Derriba una SA IPsec por índice, forzando renegociación | El tráfico por ese túnel se detiene hasta que se restablece. No cambia ninguna configuración. |
| Confirma un cambio previamente previsualizado | Lo que sea que dijera el diff. Detrás de |
Observa la asimetría que codifica el prefijo: write_ significa "un humano debe aprobar esto", no "esto edita la configuración". write_clear_ipsec_sa no edita nada y está controlado porque el tráfico se detiene cuando se ejecuta. Junos mismo traza la línea entre configuración y estado operativo; la puerta de aprobación la traza alrededor de las consecuencias.
No hay deliberadamente una herramienta de comandos de forma libre. Cada lectura operativa tiene su comando fijado aquí, por lo que no hay sintaxis adivinada ni aprobación gastada en un comando que nunca iba a funcionar. Una operación sin nombre obtiene "No tengo herramienta para eso" — que es la señal de qué construir a continuación, no un vacío que cubrir con un shell.
Limita la cuenta del dispositivo a solo lectura a menos que pretendas específicamente que las escrituras funcionen. Ese control reside en el dispositivo, no en este código, y es el que se mantiene independientemente de lo que decida cualquier modelo o cliente.
El endpoint MCP no tiene autenticación
Este servidor expone sus herramientas a cualquiera que pueda alcanzar su puerto. No hay token, autenticación de cliente ni TLS en el lado MCP.
MCP_HOST por defecto es 127.0.0.1 por esa razón. La imagen del contenedor establece 0.0.0.0 porque tiene que hacerlo, lo que significa que publicar el puerto del contenedor pone una ruta no autenticada a tus firewalls en esa interfaz. Mantenlo en una red interna con el cliente, o termina TLS y autenticación delante de él.
Inventario de dispositivos
Las credenciales de los dispositivos residen en un archivo JSON montado como solo lectura dentro del contenedor — nunca horneado en la imagen, nunca confirmado. Contiene credenciales SSH en texto plano, así que haz chmod 600 y propietario del uid con el que se ejecuta el contenedor.
{
"srx-edge": {
"ip": "192.0.2.10",
"port": 22,
"username": "automation",
"auth": { "type": "password", "password": "..." }
},
"srx-branch": {
"ip": "192.0.2.11",
"username": "automation",
"auth": { "type": "ssh_key", "private_key_path": "/app/config/id_ed25519" }
}
}port por defecto es 22. auth.type es password o ssh_key; un "password": "..." plano en el nivel superior también se acepta para compatibilidad con el formato que esto heredó. Las claves del objeto son los nombres que list_devices devuelve y toda otra herramienta toma como device — ninguna credencial se expone nunca a través de un resultado de herramienta.
Uid del contenedor. La imagen crea una entrada passwd uid-1000 deliberadamente. OpenSSH se niega a ejecutarse cuando el uid que llama no tiene entrada en
/etc/passwd, y el síntoma es un engañoso "EOF reading from transport" en lugar de algo que nombre la causa real.
Ejecutarlo
docker build -t juniper-junos-mcp .
docker run --rm \
-v "$PWD/secrets/devices.json:/app/config/devices.json:ro" \
--user 1000:1000 \
-p 127.0.0.1:8003:8003 \
juniper-junos-mcpVariable | Por defecto | Significado |
|
| Ruta del inventario de dispositivos |
|
| Segundos que una previsualización sigue siendo aplicable |
|
| Dirección de enlace (la imagen establece |
|
| Puerto de enlace |
Pruebas
docker run --rm juniper-junos-mcp python test_arg_validation.pyComprobaciones de validación de argumentos fuera de línea — sin contacto con el dispositivo, sin necesidad de credenciales.
Referencia de herramientas
TOOLS.md tiene la referencia herramienta por herramienta: argumentos, qué devuelve cada una y cuáles necesitan aprobación.
Licencia
Apache-2.0. Ver LICENSE.
This server cannot be installed
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 Connectors
Crypto transaction firewall and risk tools for MCP agents.
Tailscale device, route, DNS, key, user, and ACL management over MCP and CLI.
Remote MCP for Copilot CLI switch gate MCP, structured receipts, audit logs, and reviewer-ready evid
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/anderson-jason573/juniper-junos-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server