Juniper Junos MCP Server
Un servidor MCP para interactuar con dispositivos de red Juniper Junos utilizando LLMs.
Documentación
junos-mcp-server
Un servidor de Model Context Protocol (MCP) para dispositivos Juniper Junos que habilita interacciones de LLM con equipos de red.
Tabla de Contenidos
- junos-mcp-server
- Tabla de Contenidos
- Aviso de Seguridad Importante
- Aviso de Configuración Importante
- Primeros Pasos
- Iniciar Junos MCP Server
- Configuración
- Uso de Docker
- Configuración de Dispositivos Junos
- Integración con VSCode + GitHub Copilot
- Autenticación para Acceso al Servidor MCP
- GuardRails para Commit de Configuración
- GuardRails para Ejecutar Comandos Operativos
- Uso del Servidor MCP con Juniper Cloud-Native Router (JCNR)
- Guía para Desarrolladores
Aviso de Seguridad Importante
Advertencia: Este servidor habilita acceso de LLM a su infraestructura de red. Revise cuidadosamente estas consideraciones de seguridad.
Requisitos de Seguridad
-
Cumplimiento de Políticas Corporativas: Solo use este servidor si la política de su empresa permite enviar datos de dispositivos Junos a servicios de LLM.
-
Seguridad del Servidor: Siempre asegure su servidor Junos MCP antes de implementarlo en entornos de producción.
-
Autenticación: No use autenticación por contraseña para implementaciones de producción. Recomendamos encarecidamente usar autenticación basada en claves SSH para mayor seguridad.
-
Estrategia de Implementación: Hasta que su servidor MCP esté adecuadamente asegurado, solo implemente localmente para fines de prueba. No implemente servidores remotos en producción sin las medidas de seguridad adecuadas.
Mejores Prácticas de Seguridad
- Use autenticación por clave SSH en lugar de contraseñas
- Implemente controles de acceso a red adecuados
- Monitoree y registre todas las actividades del servidor MCP
- Auditorías de seguridad y actualizaciones regulares
- Siga las políticas de seguridad de su organización
Aviso de Configuración Importante
Advertencia: El servidor Junos MCP admite cambios de configuración, pero asegúrese de usar esta funcionalidad solo cuando desee que las configuraciones generadas por LLM se carguen y confirmen en su router Junos.
Siempre revise la configuración generada por el LLM y solo permita la ejecución de la herramienta si es la configuración correcta para su caso de uso.
Primeros Pasos
Obtenga el código.
git clone https://github.com/Juniper/junos-mcp-server.git
cd junos-mcp-server
pip install -r requirements.txt
Ejecutar con uv
Si está usando uv, puede ejecutar el servidor directamente:
uv run python jmcp.py -f devices.json -t stdio
Iniciar Junos MCP Server
python3.11 jmcp.py --help
Junos MCP Server
options:
-h, --help show this help message and exit
-f DEVICE_MAPPING, --device-mapping DEVICE_MAPPING
the name of the JSON file containing the device mapping
-H HOST, --host HOST Junos MCP Server host
-t TRANSPORT, --transport TRANSPORT
Junos MCP Server transport
-p PORT, --port PORT Junos MCP Server port
El servidor Junos MCP admite transporte streamable-http y stdio. No use --host con transporte stdio.
Variables de Entorno
JUNOS_TIMEOUT: Tiempo de espera de comando en segundos para operaciones CLI de Junos.JMCP_POOL_IDLE_TIMEOUT: Tiempo de espera de inactividad en segundos para conexiones SSH/NETCONF agrupadas.- Las sesiones SSH se reutilizan entre llamadas de herramientas mediante un grupo de conexiones; un hilo de limpieza en segundo plano (que se ejecuta una vez por minuto) cierra conexiones inactivas más allá de este tiempo de espera.
- Predeterminado:
300. Los valores no válidos se registran y se vuelve al valor predeterminado.
Configuración
Configuración para Claude Desktop (transporte stdio)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "python3",
"args": ["jmcp.py", "-f", "devices.json", "-t", "stdio"]
}
}
}
Configuración para Claude Desktop (usando uv)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "uv",
"args": ["run", "python", "jmcp.py", "-f", "devices.json", "-t", "stdio"]
}
}
}
Nota: Proporcione la ruta absoluta para jmcp.py y el archivo devices.json.
Configuración para Claude Desktop (contenedor Docker)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "/usr/local/bin/docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"devices.json:/app/config/devices.json",
"-v",
"vsrx_keypair.pem:/app/config/vsrx_keypair.pem",
"junos-mcp-server:latest"
]
}
}
}
Uso de Docker
Construir Contenedor Docker
docker build -t junos-mcp-server:latest .
Ejecutar con Configuración Predeterminada
De forma predeterminada, el contenedor Docker se ejecuta con transporte stdio:
docker run --rm -it -v /path/to/your/devices.json:/app/config/devices.json
junos-mcp-server:latest
Esto usa el comando predeterminado: python jmcp.py -f /app/config/devices.json -t stdio
Sobrescribir Argumentos Predeterminados
Puede sobrescribir cualquier argumento especificando el comando completo:
Para transporte stdio:
docker run --rm -it -v /path/to/your/devices.json:/app/config/devices.json
junos-mcp-server:latest python jmcp.py -f /app/config/devices.json -t stdio
Para transporte streamable-http:
Seguridad: el transporte streamable-http se niega a iniciar sin un archivo
.tokensválido. Genere uno conpython jmcp_token_manager.py generate --id <token-id>y móntelo en el contenedor como se muestra a continuación. Consulte Autenticación para más detalles, o pase--allow-unauthenticated-httppara desarrollo local solo de bucle de retorno.
docker run --rm -it \
-v /path/to/your/devices.json:/app/config/devices.json \
-v /path/to/.tokens:/app/.tokens \
-p 30030:30030 \
junos-mcp-server:latest \
python jmcp.py -f /app/config/devices.json -t streamable-http -H 0.0.0.0
Para streamable-http con puerto personalizado:
docker run --rm -it \
-v /path/to/your/devices.json:/app/config/devices.json \
-v /path/to/.tokens:/app/.tokens \
-p 8080:8080 \
junos-mcp-server:latest \
python jmcp.py -f /app/config/devices.json -t streamable-http -p 8080 -H 0.0.0.0
Nota:
- Siempre monte su archivo de configuración de dispositivos usando
-v /ruta/a/su/ devices.json:/app/config/devices.json - Para transporte streamable-http, exponga el puerto usando
-p puerto_host:puerto_contenedor - Monte cualquier archivo de clave privada SSH si usa autenticación basada en claves (por ejemplo,
-v /ruta/a/clave.pem:/app/config/clave.pem)
Construya el contenedor docker para Junos MCP Server
docker build -t junos-mcp-server:latest .
Nota: Monte su archivo de configuración devices.json y monte cualquier otro archivo, en
mi caso estoy usando un archivo pem para autenticación de clave privada ssh, así que también estoy
montando vsrx_keypair.pem
Configuración de Dispositivos Junos
El servidor Junos MCP admite autenticación basada en password así como autenticación basada en SSH key
(Consulte las configuraciones de los primeros 2 routers [router-1, router-2]).
{
"router-1": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"auth": {
"type": "password",
"password": "pwd"
}
},
"router-2": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"auth": {
"type": "ssh_key",
"private_key_path": "/path/to/private/key.pem"
}
},
"router-3": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"ssh_config": "~/.ssh/config_dc",
"auth": {
"type": "ssh_key",
"private_key_path": "/path/to/private/key.pem"
}
},
"router-4": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"ssh_config": "/home/user/.ssh/config_jumphost",
"auth": {
"type": "password",
"password": "pwd"
}
}
}
El servidor Junos MCP también proporciona soporte para ProxyCommand. (Consulte las configuraciones de los últimos 2 routers
[router-3, router-4]), lo que le permite acceder a un dispositivo de destino
a través de un host intermediario que admite netcat. Esto es útil cuando
solo puede iniciar sesión en el dispositivo de destino a través del host intermedio (jumphost).
Este es un ejemplo de un archivo de configuración SSH que se está usando .ssh/config_jumphost:
# Jumphost VM Connection
Host jumphost-vm
HostName 10.2.11.200
User root
# Used for MCP server
IdentityFile /home/user/.ssh/id_rsa_claude
IdentitiesOnly yes
StrictHostKeyChecking no
# cRPD Devices (via jump host)
Host dt-crpd1 dtwin-crpd1 digital-twin-crpd1 clab-digital-twin-eop6-pe1
HostName 172.20.20.11
User claude
IdentityFile c
# ProxyJump jumphost-vm # Not working with JunOS MCP
ProxyCommand ssh -l root jumphost-vm nc %h 22 2>/dev/null
StrictHostKeyChecking no
Nota #1: El valor de Port debe ser un entero (típicamente 22 para SSH).
Nota #2: IdentityFile recomendación use la ruta completa (por ejemplo /home/usuario/.ssh /id_rsa_claude rather than ~/.ssh/id_rsa_claude).
Integración con VSCode + GitHub Copilot
Iniciar Su Servidor
python3.11 jmcp.py -f devices.json
[06/11/25 08:26:11] INFO Starting MCP server 'jmcp-server' with transport
'streamable-http' on http://127.0.0.1:30030/mcp
INFO: Started server process [33512]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:30030 (Press CTRL+C to quit)
Apuntar a Esta URL en Su Configuración de VSCode
{
"mcp": {
"servers": {
"my-junos-mcp-server": {
"url": "http://127.0.0.1:30030/mcp/"
}
}
}
}
Nota: Puede usar Cmd+Shift+P de VSCode para configurar el servidor MCP.
Autenticación para Acceso al Servidor MCP
El servidor Junos MCP admite autenticación basada en tokens para acceso seguro de clientes cuando se usa transporte streamable-http. Esto evita el acceso no autorizado a su infraestructura de red.
Comportamiento de Autenticación
- Transporte stdio (Claude Desktop): No se requiere autenticación - seguro por diseño ya que se ejecuta localmente
- Transporte streamable-http (VSCode, clientes web): Autenticación basada en tokens disponible
Gestión de Tokens
El servidor incluye una herramienta CLI dedicada de gestión de tokens:
jmcp_token_manager.py
De forma predeterminada, tanto el servidor como el gestor de tokens usan el archivo .tokens junto a
jmcp.py, independientemente del directorio de trabajo actual. En sistemas POSIX, el
gestor de tokens crea el archivo con permisos solo para el propietario (0600) y repara
esos permisos cada vez que escribe un archivo existente.
Generar un Nuevo Token
# Basic token generation
python jmcp_token_manager.py generate --id "vscode-dev"
# With description
python jmcp_token_manager.py generate --id "vscode-dev" --description "VSCode
development environment"
# Use a custom token file location
python jmcp_token_manager.py --tokens-file /secure/path/tokens.json generate --id "vscode-dev"
# Example output:
Generated new token:
ID: vscode-dev
Token: jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8
Description: VSCode development environment
Save this token securely - it won't be shown again!
Listar Todos los Tokens
python jmcp_token_manager.py list
# Example output:
ID Description Created
-------------------------------------------------------------------------------------
vscode-dev VSCode development environment
2025-01-28T10:30:00Z
prod-client Production client access
2025-01-28T09:15:00Z
Mostrar Valor del Token (Recuperación)
python jmcp_token_manager.py show --id "vscode-dev"
# Example output:
Token ID: vscode-dev
Token: jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8
Description: VSCode development environment
Created: 2025-01-28T10:30:00Z
Revocar un Token
python jmcp_token_manager.py revoke --id "vscode-dev"
# Example output:
Token 'vscode-dev' has been revoked
Estado de Autenticación del Servidor
Para el transporte streamable-http el servidor falla de forma segura: se niega a
iniciar a menos que esté presente un archivo .tokens válido y no vacío. La única forma de
iniciar sin tokens es el indicador explícito --allow-unauthenticated-http,
que a su vez está restringido a enlaces de bucle de retorno (127.0.0.1, ::1,
localhost).
Para usar una ubicación personalizada, pase la misma ruta al servidor:
python jmcp.py -f devices.json -t streamable-http --tokens-file /secure/path/tokens.json
Con tokens configurados:
python jmcp.py -f devices.json -t streamable-http
INFO - Token-based authentication enabled
INFO - Clients must send 'Authorization: Bearer <token>' header
INFO - Use jmcp_token_manager.py to manage tokens
INFO - Streamable HTTP server started on http://127.0.0.1:30030
Sin tokens configurados (predeterminado - se niega a iniciar):
python jmcp.py -f devices.json -t streamable-http
ERROR - Refusing to start streamable-http transport without authentication: .tokens file not found
ERROR - Generate a token with: python jmcp_token_manager.py generate --id <token-id>
ERROR - Or, for local development on loopback only, re-run with --allow-unauthenticated-http
Modo no autenticado explícito (solo bucle de retorno, solo desarrollo):
python jmcp.py -f devices.json -t streamable-http --allow-unauthenticated-http
WARNING - *** Streamable HTTP authentication is DISABLED (--allow-unauthenticated-http). .tokens file not found. Server is open to any client that can reach 127.0.0.1:30030 and can commit configuration to mapped devices. Use only for local development. ***
INFO - Streamable HTTP server started on http://127.0.0.1:30030
Combinar --allow-unauthenticated-http con un enlace que no sea de bucle de retorno (por
ejemplo -H 0.0.0.0) se rechaza al inicio.
Configuración del Cliente con Autenticación
Configuración de VSCode con Token
{
"mcp": {
"servers": {
"my-junos-mcp-server": {
"url": "http://127.0.0.1:30030/mcp/",
"headers": {
"Authorization": "Bearer
jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8"
}
}
}
}
}
Pruebas con curl
# Test authentication with valid token
curl -X POST "http://127.0.0.1:30030/mcp/" \
-H "Authorization: Bearer jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Test without token (should fail with 401)
curl -X POST "http://127.0.0.1:30030/mcp/" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
Nota: MCP streamable-http requiere el encabezado Accept: application/json, tex /event-stream.
Docker con Autenticación
Al usar Docker, monte el archivo .tokens para habilitar la autenticación:
# Generate token first (outside container)
python jmcp_token_manager.py generate --id "docker-client"
# Run container with token file mounted
docker run --rm -it \
-v /path/to/devices.json:/app/config/devices.json \
-v /path/to/.tokens:/app/.tokens \
-p 30030:30030 \
junos-mcp-server:latest \
python jmcp.py -f /app/config/devices.json -t streamable-http -H 0.0.0.0
Mejores Prácticas de Seguridad
-
Seguridad de Tokens:
- Almacene los tokens de forma segura (gestores de contraseñas, variables de entorno)
- Use IDs de token descriptivos para una gestión fácil
- Rote los tokens regularmente revocando los antiguos y generando nuevos
- Nunca confirme tokens en el control de versiones
-
Control de Acceso:
- Genere tokens separados para diferentes clientes/entornos
- Revoque los tokens inmediatamente cuando ya no sean necesarios
- Monitoree los registros del servidor para detectar intentos de acceso no autorizado
-
Seguridad de Red:
- Ejecute el servidor streamable-http detrás de un proxy inverso con HTTPS en producción
- Use reglas de firewall para restringir el acceso al puerto del servidor MCP
- Considere acceso VPN para clientes remotos
Formato del Archivo de Tokens
El archivo .tokens almacena tokens en formato JSON:
{
"vscode-dev": {
"token": "jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8",
"description": "VSCode development environment",
"created": "2025-01-28T10:30:00Z"
},
"prod-client": {
"token": "jmcp_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2",
"description": "Production client access",
"created": "2025-01-28T09:15:00Z"
}
}
Importante: Mantenga este archivo seguro y no lo confirme en el control de versiones.
GuardRails para Commit de Configuración
La herramienta load_and_commit_config ahora incluye una verificación de guardrail previa al commit que valida la configuración candidata enviada contra patrones en block.cfg antes de que se intenten acciones de commit en el dispositivo.
Cómo funciona
- Cada línea que no sea comentario en
block.cfgse trata como un patrón bloqueado. - La coincidencia de patrones se realiza contra líneas de configuración normalizadas del
config_textenviado. - Los patrones admiten tokens de expresiones regulares (por ejemplo, para coincidir con nombres de usuario dinámicos).
- Los tokens de palabras clave literales también coinciden con abreviaturas CLI de Junos no vacías, por lo que
set sys root-authcoincide conset system root-authentication. - Si alguna línea coincide, la solicitud se rechaza y no se carga ni confirma ninguna configuración.
Ejemplo block.cfg
# Blocked configuration prefixes/patterns for load_and_commit_config
set system root-authentication
set system login user ([^ ]+) authentication
Esto protege áreas de configuración comunes de alto riesgo (por ejemplo, autenticación raíz o cambios no gestionados de credenciales de usuarios locales) de ser confirmadas por automatización.
GuardRails para Ejecutar Comandos Operativos
Las herramientas execute_junos_command y execute_junos_command_batch ahora incluyen guardrails de comandos usando block.cmd.
Cómo funciona
- Cada línea que no sea un comentario en
block.cmdse trata como un patrón de comando regex. - Los comandos enviados se normalizan y verifican antes de la ejecución.
- Los tokens de palabras clave literales coinciden tanto con su forma completa como con abreviaturas no vacías de la CLI de Junos; los patrones regex siguen siendo compatibles.
- Si un comando coincide con un patrón bloqueado, se rechaza la ejecución.
- Para la ejecución por lotes, el comando bloqueado se rechaza antes de enviarse a los routers.
Ejemplo block.cmd
# Blocked operational command prefixes/patterns for execute_junos_command
request system reboot
request system halt
request system power-cycle
request system power-off
request system zeroize
Esto bloquea comandos disruptivos (acciones de clase reboot/power/zeroize) mientras que aún permite comandos operativos de solo lectura como show.
Uso del servidor MCP con Juniper Cloud-Native Router (JCNR)
JCNR es un router nativo de la nube que se ejecuta en varios entornos de nube. Se puede usar este servidor MCP con JCNR también siguiendo los pasos que se indican a continuación. Consulte la documentación de JCNR para obtener más detalles sobre la configuración.
- Configure el acceso SSH en JCNR en un puerto deseado distinto del 22. Esto es necesario porque JCNR se ejecuta como un contenedor en un sistema operativo compartido. No se recomienda ejecutar SSH en el puerto predeterminado. Por defecto, SSH está habilitado en el puerto 24. Pero es preferible cambiarlo al puerto deseado según sus necesidades de red.
- Habilite el método de autenticación para SSH. JCNR admite autenticación basada en clave SSH y contraseña.
- Habilite Netconf sobre SSH. Esto está habilitado por defecto.
set system services netconf ssh
set system services ssh port 3030
set system services ssh root-login allow
set system root-authentication encrypted-password
"$6$3vvMI$RNemhmu9izWXzO46msh38frIg4VoeFNJWJZugxgnU.NQso3OQ00QWOIZmzNePD.MWjDOD
BBEYut/W7kfADdV." (or)
set system root-authentication load-key-file <public key>
Guía para desarrolladores
Esta sección explica la arquitectura del servidor MCP de Junos y cómo extenderlo con nuevas herramientas.
Descripción general de la arquitectura
El servidor MCP de Junos utiliza el Protocolo de Contexto de Modelo (MCP) para permitir que los LLM interactúen con dispositivos de red de Juniper. La arquitectura del servidor consta de:
- Núcleo del servidor MCP (
jmcp.py): Maneja la comunicación del protocolo MCP - Manejadores de herramientas: Funciones individuales que implementan operaciones de red específicas
- Registro de herramientas: Asigna nombres de herramientas a sus funciones de manejo
- Capa de transporte: Admite stdio (Claude Desktop) y streamable-http (VSCode)
Cómo funcionan las herramientas
Cada herramienta en el servidor MCP sigue este flujo:
Agregar una nueva herramienta
Agregar una nueva herramienta es un proceso simple de 3 pasos:
Paso 1: Crear una función de manejo
Cree una función de manejo asíncrona en jmcp.py (antes del
diccionario TOOL_HANDLERS):
async def handle_my_new_tool(arguments: dict) -> list[types.ContentBlock]:
"""Handler for my_new_tool - describe what it does"""
# Extract arguments
router_name = arguments.get("router_name", "")
my_param = arguments.get("my_param", "default_value")
# Validate router exists
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
# Your tool logic here
log.debug(f"Executing my_new_tool on router {router_name}")
result = _run_junos_cli_command(router_name, f"show {my_param}")
return [types.TextContent(type="text", text=result)]
Paso 2: Registrar el manejador
Agregue su manejador al diccionario TOOL_HANDLERS (alrededor de la línea 330):
TOOL_HANDLERS = {
"execute_junos_command": handle_execute_junos_command,
"get_junos_config": handle_get_junos_config,
"junos_config_diff": handle_junos_config_diff,
"gather_device_facts": handle_gather_device_facts,
"get_router_list": handle_get_router_list,
"load_and_commit_config": handle_load_and_commit_config,
"my_new_tool": handle_my_new_tool, # Add your tool here
}
Paso 3: Definir los metadatos de la herramienta
Agregue la definición de la herramienta al método list_tools() (alrededor de la línea 410):
types.Tool(
name="my_new_tool",
description="Brief description of what your tool does",
inputSchema={
"type": "object",
"properties": {
"router_name": {"type": "string", "description": "The name of the
router"},
"my_param": {"type": "string", "description": "Description of
parameter"}
},
"required": ["router_name"] # List required parameters
}
)
Ejemplo: Crear una herramienta de vecinos BGP
Aquí hay un ejemplo completo de cómo agregar una herramienta para mostrar vecinos BGP:
# Step 1: Handler function
async def handle_show_bgp_neighbors(arguments: dict) -> list[types.ContentBloc
]:
"""Handler for show_bgp_neighbors tool"""
router_name = arguments.get("router_name", "")
neighbor_address = arguments.get("neighbor_address", "")
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
log.debug(f"Getting BGP neighbors from router {router_name}")
if neighbor_address:
cmd = f"show bgp neighbor {neighbor_address}"
else:
cmd = "show bgp summary"
result = _run_junos_cli_command(router_name, cmd)
return [types.TextContent(type="text", text=result)]
# Step 2: Add to TOOL_HANDLERS
TOOL_HANDLERS = {
# ... existing tools ...
"show_bgp_neighbors": handle_show_bgp_neighbors,
}
# Step 3: Add to list_tools()
types.Tool(
name="show_bgp_neighbors",
description="Show BGP neighbor information",
inputSchema={
"type": "object",
"properties": {
"router_name": {"type": "string", "description": "The name of the
router"},
"neighbor_address": {"type": "string", "description": "Optional:
specific neighbor IP"}
},
"required": ["router_name"]
}
)
Mejores prácticas para el desarrollo de herramientas
- Manejo de errores: Siempre maneje los errores de conexión y las entradas no válidas con elegancia
- Registro: Use el registrador global
logpara depuración - Validación: Verifique si el router existe antes de intentar operaciones
- Documentación: Escriba descripciones claras para herramientas y parámetros
- Tiempos de espera: Soporte tiempos de espera configurables para operaciones de larga duración
- Formato de retorno: Siempre devuelva
list[types.ContentBlock]con contenido de texto - Parámetro de contexto: Use el parámetro
context: Contextpara enviar progreso y mensajes de registro al cliente
Uso de PyEZ para operaciones avanzadas
Para operaciones más allá de los comandos CLI, use PyEZ directamente:
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
# Example: Using PyEZ tables
async def handle_get_interfaces(arguments: dict) -> list[types.ContentBlock]:
router_name = arguments.get("router_name", "")
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
device_info = devices[router_name]
try:
connect_params = prepare_connection_params(device_info, router_name)
with Device(**connect_params) as junos_device:
# Use PyEZ tables or other utilities
interfaces = junos_device.rpc.get_interface_information()
# Process interfaces...
result = "Interface information..."
except Exception as e:
result = f"Error: {e}"
return [types.TextContent(type="text", text=result)]
Prueba de sus herramientas
- Pruebas unitarias: Pruebe las funciones de manejo con argumentos simulados
- Pruebas de integración: Pruebe con dispositivos Junos reales o vSRX
- Casos de error: Pruebe con routers no válidos, fallas de red, etc.
Ejemplo de prueba:
# Test the handler directly
result = await handle_my_new_tool({
"router_name": "router-1",
"my_param": "test"
})
print(result[0].text)
Consejos de depuración
- Habilite el registro de depuración para ver la ejecución detallada:
logging.basicConfig(level=logging.DEBUG)
- Use el transporte stdio para una depuración más fácil:
python jmcp.py -f devices.json -t stdio
- Pruebe comandos individuales manualmente:
result = _run_junos_cli_command("router-1", "show version")
print(result)