Skip to main content
Glama

claude-project — servidor MCP netmiko + skill

Un proyecto listo para copiar que proporciona a un agente de IA acceso de solo lectura a routers, switches y firewalls a través de SSH, mediante el Model Context Protocol.

Incluye dos piezas y la conexión entre ellas:

  • mcps/mcp_server_netmiko.py — un servidor MCP autónomo. Nueve herramientas, cada comando validado contra una lista de permitidos/denegados definida por el operador, salida parseada a JSON con ntc-templates, y un registro de auditoría de cierre forzado de cada intento.

  • .claude/skills/netmiko/SKILL.md — la skill que enseña al agente cuándo recurrir a esas herramientas, cómo son los dialectos CLI por plataforma y cómo leer una denegación.

Nada de esto escribe en un dispositivo. La lista de permitidos es denegación por defecto — una vacía no permite nada — y el lado de denegación siempre prevalece sobre el lado de permitidos.

Autores y procedencia

Este proyecto es obra de Ed Scrimagliaedgardo.scrimaglia@gmail.com, Octupus. El servidor, la skill, el modelo de configuración y la documentación son su trabajo, escritos para el agente Niko y empaquetados aquí como un proyecto independiente.

Surgió de un fork, y ese origen se reconoce en lugar de ocultarse: el punto de partida fue el trabajo de Kirk Byers, y el proyecto creció mucho más allá de él. Lo que está aquí ahora — el inventario respaldado por la fuente de verdad, la resolución de credenciales, los tres sabores de despliegue, la paginación de salida, el registro de auditoría, la skill y esta documentación — no proviene del upstream.

Los dos proyectos upstream de Kirk Byers:

  • Netmiko — la biblioteca SSH multi-vendor que realiza la comunicación real con los dispositivos.

  • netmiko_mcp — el servidor MCP del que se bifurcó este. Una parte de él sobrevive en gran medida como estaba: el núcleo de seguridad (validación de comandos, manejo de globs, la asimetría permitir/denegar), mantenido como un puerto fiel a propósito para que los parches upstream aún puedan ser diferenciados. Eso fue una decisión de ingeniería, no un límite para el resto del trabajo.

Acerca de Niko

Este servidor fue escrito para Niko, el agente de IA Neural Intelligence Knowledge Orchestrator construido por Ed Scrimaglia en Octupus. Niko presenta un conjunto de servidores MCP — el servidor de fuente de verdad, este, Jira, enviar correos electrónicos, crear archivos y otros — para que un operador pueda hacer una pregunta en lenguaje natural y obtener respuesta desde el ámbito inmobiliario: la Fuente de Verdad para lo que debería ser verdad, los dispositivos mismos para lo que es.

Dentro de Niko, el mismo archivo se ejecuta de manera ligeramente diferente, y eso vale la pena saberlo porque explica algunas cosas en el código:

  • Los servidores se ejecutan sobre HTTP en loopback, un puerto cada uno, declarados en mcps/mcp_config.json con url / transport / local / env — la misma configuración de dos ejes descrita a continuación, expresada en el formato propio de Niko.

  • La instalación se realiza a través de la aplicación, no copiando archivos: la carga se valida, las dependencias se resuelven a partir del propio código, y una instalación fallida retrocede en lugar de dejar medio servidor atrás.

Cada una de esas integraciones es una importación opcional con un fallback, así que niko nunca tiene que estar instalado. Hay cuatro, y esto es lo que cada una degrada cuando falla la importación:

Importación

Línea

Fallback independiente

niko.srvclass_logging.MCPLogging

60

NIKO_AVAILABLE = False; el servidor configura su propio logging

niko.niko_paths.NikoPaths

68

None; las rutas provienen de las variables NETMIKO_MCP_*, que es por lo que este proyecto las establece explícitamente

niko.srvclass_logging.SyncedConcurrentTimedRotatingFileHandler

436

FailClosedFileHandler — aún de cierre forzado, pero no seguro para múltiples procesos

niko.srvclass_list_budget.apply_budget_to_payload

2709

un no-op que devuelve el payload sin cambios

No se pierde nada que importe fuera de Niko: el manejador concurrente resuelve un problema de varios procesos y un archivo que no surge aquí, y el presupuesto de lista trimitiza cargas útiles largas para un agente que tiene su propio registro de contexto. Un archivo, dos hogares, sin fork.

Fedele es la fuente de verdad de Niko, por lo que las variables de la Fuente de Verdad llevan el prefijo FEDELE_ incluso cuando apuntan a una instancia de NetBox.

Licencia

El código propio de este proyecto es MIT — consulte LICENSE.

Es un trabajo derivado, por lo que se aplican dos licencias y ambos archivos se incluyen con él:

Licencia

Archivo

Código, documentación y skill de este proyecto

MIT

LICENSE

Partes portadas de ktbyers/netmiko_mcp

Apache-2.0

LICENSE-APACHE-2.0

NOTICE lleva la atribución y la declaración de modificaciones que Apache-2.0 §4(b) requiere. Netmiko es una dependencia MIT ordinaria: importada, no vendida, nada que redistribuir.


Diseño

claude-project/
├── .mcp.json                     # declares the server (project scope)
├── .env.example                  # → copy to .env with the SSH credentials
├── .claude/skills/netmiko/
│   └── SKILL.md                  # one directory per skill, file named SKILL.md
├── mcps/
│   └── mcp_server_netmiko.py     # NOT at the root: the server reads ../.env
├── config/netmiko/
│   ├── commands.yml              # allow/deny list — without it, a 16-command fallback applies
│   └── inventory.yml             # inventory in netmiko_tools format
├── logs/                         # netmiko-mcp.log + netmiko-audit.jsonl
├── mcpr/netmiko/                 # created on demand (0700): large outputs
├── LICENSE  LICENSE-APACHE-2.0  NOTICE
└── pyproject.toml

Dos reglas que no son negociables:

  1. La skill reside en .claude/skills/<nombre>/SKILL.md. Claude Code no lee skills/netmiko.md: necesita el directorio y ese nombre de archivo exacto.

  2. El servidor reside en mcps/, no en la raíz. PARENT_DIR es el padre del directorio que contiene el .py (mcp_server_netmiko.py:62), y ahí es de donde proviene el .env. Con el servidor en la raíz, el .env se buscaría un nivel por encima del proyecto.

Poniéndolo en marcha

uv venv --python 3.12
uv pip install -r <(uv pip compile pyproject.toml)   # or: uv sync
cp .env.example .env && $EDITOR .env                 # SSH credentials
# .mcp.json needs no editing: its paths are project-relative
claude                                               # approve the project server

Dentro de la sesión: /mcp lista las 9 herramientas, /skills confirma que la skill se cargó. Primera verificación, sin tocar la red:

¿qué política de comandos está aplicando el MCP de netmiko?


Los tres sabores

De dónde proviene el inventario y de dónde provienen las credenciales son dos ejes independientes. Eso es lo que hace tres despliegues a partir de un solo servidor — y la razón por la que el servidor nunca tiene que ser modificado para moverse entre ellos: dos variables de entorno lo deciden.

Inventario

Credenciales

Qué necesitas

Cuándo usarlo

A — SoT todo

Fedele

Fedele

Token de API + clave Fernet

La SoT es autoritativa y ya contiene las credenciales del dispositivo

B — SoT inventario, credenciales locales

Fedele o NetBox

.env

Token de API

Tienes una SoT pero no su plugin de credenciales. El punto de partida habitual

C — Autónomo

YAML local

.env

nada externo

Laboratorio, aislado, una demo, o modo degradado cuando la SoT está caída

netmiko.get_metadata informa cuál se está ejecutando realmente — nunca asumas por el archivo de configuración:

{
  "inventory": {"backend": "fedele", "scope_filter": {"tag": "lab"}, "available": true},
  "credential_source": "env",
  "device_types_in_inventory": ["cisco_ios", "huawei_vrp", "…"]
}

A — Fedele como fuente de verdad, credenciales incluidas

El agente solicita un dispositivo por nombre; el servidor resuelve la dirección, plataforma y credenciales contra la SoT en el momento de la llamada. Nada del inventario vive en este proyecto: añade un dispositivo a la SoT y será accesible en la siguiente llamada, sin archivo que editar ni reinicio.

// .mcp.json → env
"NETMIKO_MCP_INVENTORY_TYPE": "fedele",
"NETMIKO_MCP_CREDENTIAL_SOURCE": "fedele",
"NETMIKO_MCP_FEDELE_GROUP_SOURCE": "tags",        // tags | device_roles | sites
"NETMIKO_MCP_FEDELE_DEVICE_FILTER": "tag=lab",    // the scope filter — read the warning
"NETMIKO_MCP_FEDELE_CACHE_TTL": "60"
# .env
FEDELE_URL=https://fedele.example.com
FEDELE_TOKEN=<API token>
FEDELE_CREDENTIALS_KEY=<Fernet key of the fedele_credentials plugin>

Archivos: ninguno es obligatorio. commands.yml es recomendado — sin él se aplica la política de fallback incorporada. No hay inventario local involucrado, y no hay NETMIKO_USERNAME / NETMIKO_PASSWORD; con credential_source=fedele, NETMIKO_SECRET es ignorado — la contraseña de enable también proviene de la SoT.

Cómo funciona la búsqueda de credenciales, tres saltos:

GET dcim/devices/?name=<name>                          → device.id
GET plugins/credentials/devicecredentials/?device=<id> → credential id
GET plugins/credentials/networkcredentials/<id>/       → username + encrypted password
                                                          decrypted locally with the Fernet key

Cosas que vale la pena saber antes de elegir este sabor:

  • La clave Fernet es todo el límite de seguridad. Descifra las contraseñas de los dispositivos en la memoria del servidor. Trátala como las propias contraseñas.

  • Sin FEDELE_CREDENTIALS_KEY el servidor aún arranca, y cada herramienta devuelve el mismo Startup Error nombrando la variable faltante. Falla ruidosamente, no silenciosamente.

  • Establece el filtro de alcance. Sin NETMIKO_MCP_FEDELE_DEVICE_FILTER el inventario es todo el inventario que la SoT conoce, que también es todo el conjunto de dispositivos a los que el agente puede acceder. El servidor registra una advertencia cuando falta; el filtro admite sintaxis de consulta, tag=lab&status=active.

  • Un dispositivo sin primary_ip, sin platform, o cuya plataforma no es un device_type de Netmiko queda excluido del inventario — las SoT también inventarian cámaras, lectores de tarjetas y chasis. Las exclusiones se cuentan y reportan, para que el agente nunca afirme "estos son todos los dispositivos" sobre un subconjunto.

  • Hay un interruptor de circuito: después de un error de transporte o un 5xx el cliente deja de llamar a la SoT durante 30 s. Un comando de grupo contra 40 dispositivos con la SoT caída falla una vez, no cuarenta veces.

B — SoT para el inventario, credenciales en el .env

Idéntico a A con una variable invertida:

"NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
# .env
FEDELE_URL=https://sot.example.com
FEDELE_TOKEN=<API token>
NETMIKO_USERNAME=<service account>
NETMIKO_PASSWORD=<password>
NETMIKO_SECRET=<enable password, if any device asks for it>

Obtienes el inventario dinámico — la parte que se amortiza sola — sin el plugin de credenciales ni la clave Fernet. Se usa una única cuenta de servicio para todos los dispositivos.

NetBox, o cualquier SoT con forma de NetBox

El backend de inventario habla el dialecto REST de NetBox, por lo que NetBox mismo funciona en este sabor, sin modificaciones:

Lo que el backend llama

Lo que lee

dcim/devices/

la lista de dispositivos, filtrada por el filtro de alcance y paginada

extras/tags/, dcim/device-roles/, dcim/sites/

el que FEDELE_GROUP_SOURCE selecciona se convierte en los grupos de dispositivos

device.primary_ip.address

el host SSH, máscara eliminada

device.platform.name

el device_type de Netmiko, validado contra CLASS_MAPPER

Apunta FEDELE_URL a la instancia de NetBox (/api se añade si lo omites) y FEDELE_TOKEN a un token de API de NetBox — el cliente se autentica con el encabezado Authorization: Token … que NetBox espera. Las variables mantienen el prefijo FEDELE_; eso es un legado de nomenclatura, no un requisito del producto.

El único requisito que NetBox no cumple por defecto: platform.name debe ser exactamente un device_type de Netmikocisco_ios, arista_eos, huawei_vrp, juniper_junos. Una plataforma llamada "Cisco IOS 15.2" no es un device_type, por lo que todo dispositivo que la lleve queda excluido del inventario. O renombra las plataformas en NetBox o acepta las exclusiones, que se reportan.

Las credenciales son la parte que NetBox no cubre: los endpoints plugins/credentials/… pertenecen al plugin de Fedele. Con NetBox simple, el sabor A no está disponible — quédate en B.

C — Autónomo: sin SoT en absoluto

Todo vive en este proyecto. No se contacta ningún servicio externo, nunca.

// .mcp.json → env
"NETMIKO_MCP_INVENTORY_TYPE": "yaml",
"NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
"NETMIKO_MCP_INVENTORY_FILE": "/abs/path/claude-project/config/netmiko/inventory.yml"
# .env
NETMIKO_USERNAME=<service account>
NETMIKO_PASSWORD=<password>
NETMIKO_SECRET=<enable password, if any device asks for it>

Archivos: inventory.yml es obligatorio aquí — es el único lugar donde existen los dispositivos. commands.yml sigue siendo recomendado, no obligatorio. El inventario tiene el formato netmiko_tools — un mapeo plano de nombre a datos de conexión, más claves de grupo:

CORE-RTR-01:
  device_type: cisco_xr        # must be a Netmiko device_type, verbatim
  host: 192.0.2.11

CORE-SW-01:
  device_type: arista_eos
  host: 192.0.2.21

core:                          # a group is a list of device names
- CORE-RTR-01
- CORE-SW-01

Esta es la configuración con la que se envía este proyecto, y también es el modo degradado: si el SoT falla, dos variables y un reinicio mueven aquí un despliegue de sabor A o sabor B. Vale la pena ensayarlo antes de necesitarlo.

El costo es que el archivo se vuelve obsoleto. scripts/export_inventory.py en el repositorio principal lo regenera desde el SoT; ejecútalo periódicamente. Un inventario de respaldo con direcciones de hace seis meses es peor que no tener respaldo, porque te das cuenta durante la operación.

Lo que permanece igual en los tres

La política de comandos, el registro de auditoría, la paginación de salida y la superficie de herramientas no cambian entre sabores. El contrato orientado al agente es idéntico, por lo que la habilidad no necesita una variante por sabor.

commands.yml es recomendado, no obligatorio

El servidor funciona sin él. Si el archivo falta, no deniega todo y no se niega a iniciar: un fallback incorporado de 16 comandos de solo lectura toma el control — show version, show ip interface brief, display version y sus equivalentes en Junos/VRP. Eso es intencional. Una política vacía denegaría cada comando mientras el servidor se reporta como saludable, lo que un operador interpretaría como "el dispositivo se negó" en lugar de "nadie escribió una política". El fallback se anuncia al inicio, netmiko.get_command_policy reporta policy_source: "fallback", y cada intento auditado lleva la fuente.

Por lo tanto, el archivo es una decisión de política, no un paso de instalación: el fallback te permite ejecutar el servidor en el primer intento, y escribes commands.yml cuando quieres la política propia del dominio en lugar de un valor predeterminado conservador. Lo que no puedes hacer es tener una política que no elegiste y no saberlo — el servidor dice cuál está en vigor, cada vez que se le pregunta.


El archivo .mcp.json

.mcp.json en la raíz del proyecto declara los servidores MCP para este proyecto. Claude Code solicita aprobación la primera vez que ve el archivo, y el archivo está destinado a ser confirmado: es cómo todo el equipo obtiene el mismo servidor.

Existen otros dos ámbitos para la misma definición de servidor:

Ámbito

Dónde reside

Quién lo ve

project

.mcp.json en la raíz del proyecto

cualquiera que abra el proyecto (después de aprobarlo)

user

~/.claude.json

cada proyecto de ese usuario, en esa máquina

local

~/.claude.json, indexado por ruta del proyecto

solo ese usuario, solo en ese proyecto

claude mcp add --scope project netmiko -- /path/to/python /path/to/server.py escribe la entrada project por ti; editar el JSON manualmente es equivalente.

Forma del archivo

{
  "mcpServers": {           // ← the top-level key. Not "servers", not "mcp".
    "netmiko": {            // ← the server name; it becomes the tool prefix
      ...                   //    mcp__netmiko__<tool>
    }
  }
}

El nombre del servidor no es cosmético: Claude Code expone cada herramienta como mcp__<nombre-servidor>__<nombre-herramienta>. Con el nombre netmiko y la herramienta netmiko.get_metadata que el servidor registra, la herramienta que Claude realmente ve es mcp__netmiko__netmiko.get_metadata. Ejecuta /mcp para leer los nombres exactos antes de escribirlos en una lista de allowed-tools o una regla de permiso.

Referencia de campos

Campo

Transporte

Significado

type

ambos

"stdio" (predeterminado si se omite), "http" o "sse"

command

stdio

el ejecutable a iniciar. Ruta absoluta — no asumas un cwd

args

stdio

lista de argumentos, cada elemento separado

env

stdio

entorno para el proceso hijo. Se fusiona sobre el heredado

url

http / sse

URL completa del endpoint, incluida la ruta

headers

http / sse

encabezados de solicitud adicionales, típicamente Authorization

Los valores admiten expansión de variables de entorno: ${VAR} y ${VAR:-default}. Útil para mantener un token fuera del archivo confirmado:

"headers": { "Authorization": "Bearer ${NETMIKO_MCP_TOKEN}" }

Transporte 1 — stdio (el que usa este proyecto)

Claude Code inicia el servidor como un proceso hijo y se comunica mediante JSON-RPC a través de su stdin/stdout. Nada escucha en un puerto, nada es accesible desde la red y la vida útil del proceso es la de la sesión. Este es el valor predeterminado correcto para un servidor que contiene credenciales SSH.

{
  "mcpServers": {
    "netmiko": {
      "type": "stdio",
      "command": "${CLAUDE_PROJECT_DIR:-.}/.venv/bin/python",
      "args": ["${CLAUDE_PROJECT_DIR:-.}/mcps/mcp_server_netmiko.py"],
      "env": {
        "NETMIKO_MCP_INVENTORY_TYPE": "yaml",
        "NETMIKO_MCP_INVENTORY_FILE": "${CLAUDE_PROJECT_DIR:-.}/config/netmiko/inventory.yml",
        "NETMIKO_MCP_COMMAND_FILE": "${CLAUDE_PROJECT_DIR:-.}/config/netmiko/commands.yml",
        "NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
        "NETMIKO_MCP_SAVE_OUTPUT_DIR": "${CLAUDE_PROJECT_DIR:-.}/mcpr/netmiko",
        "NETMIKO_MCP_AUDIT_LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/logs/netmiko-audit.jsonl",
        "LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/logs/netmiko-mcp.log",
        "LOG_LEVEL": "INFO"
      }
    }
  }
}

Dos cosas que causan problemas:

  • Sin rutas codificadas, y el directorio de trabajo no es algo en lo que confiar. ${CLAUDE_PROJECT_DIR:-.} es lo que mantiene el archivo confirmable tal cual; la siguiente sección cuenta toda la historia, porque la lectura obvia es incorrecta.

  • El servidor no debe escribir en stdout. stdout es el canal del protocolo, y una línea errante allí rompe la sesión. El registro va a stderr más el archivo rotativo en LOG_FILE (5 MB × 3, creado 0600 — en DEBUG este archivo lleva la salida del dispositivo). Dentro de Niko la misma variable es manejada por MCPLogging.

De dónde viene ${CLAUDE_PROJECT_DIR:-.}

Dos cosas separadas en una cadena: una sintaxis y una variable.

La sintaxis. ${VAR} y ${VAR:-default} es sustitución de parámetros POSIX ("usa VAR; si no está definida o está vacía, usa default"), pero no interviene ningún shell — un archivo JSON nunca pasa por uno. Claude Code implementa la expansión por sí mismo cuando lee el archivo, en command, args, env, url y headers. Es una convención de ese cliente, no parte de la especificación MCP: otro cliente puede no implementarla (ver Agentes que no son Claude, donde las rutas deben ser literales), y VS Code tiene su propia ortografía, ${workspaceFolder}.

La variable. CLAUDE_PROJECT_DIR es establecida por Claude Code en la raíz del proyecto, el mismo valor que reciben los hooks. Es estable — otorgar directorios de trabajo adicionales a mitad de sesión con --add-dir no la mueve.

La parte que es contraintuitiva, y la razón por la que :-. no es decoración: Claude Code establece esa variable en el entorno del servidor que inicia, no en el suyo propio. La expansión, sin embargo, ocurre antes del inicio, contra el entorno de Claude Code — donde la variable no existe. Un ${CLAUDE_PROJECT_DIR} desnudo se expandiría a nada y dejaría /config/netmiko/inventory.yml, una ruta absoluta a la raíz del sistema de archivos.

Por lo tanto, en un .mcp.json de ámbito de proyecto, el valor predeterminado no es un respaldo para un caso extremo: es el valor que se usa, cada vez. Lo que llega al proceso es ./config/netmiko/inventory.yml. La única excepción es una configuración MCP enviada por un plugin — allí Claude Code sustituye la variable directamente y no se necesita valor predeterminado.

Eso es lo que fuerza la mano del servidor. Un valor relativo se resolvería contra el cwd del proceso hijo, y el cwd es elección del cliente, no del proyecto. Por lo tanto, resolve_project_path(): cada configuración de ruta relativa se ancla a PARENT_DIR — el padre de mcps/, la misma raíz de la que proviene .env — cuando se cargan las configuraciones. Una sesión iniciada desde cualquier lugar encuentra config/netmiko/, y validate_startup() nombra el archivo absoluto cuando falta uno. Un ~ sigue significando el directorio personal del operador, nunca un archivo dentro del proyecto.

La variable sigue siendo útil como lo indica la documentación, leída desde dentro del servidor (os.environ["CLAUDE_PROJECT_DIR"]), donde está establecida. Este servidor no la necesita: PARENT_DIR se deriva de __file__ y por lo tanto no depende de ningún cliente — la misma razón por la que el transporte HTTP, donde nadie establece esa variable, no necesita un caso especial.

Fuente: Claude Code — MCP, secciones Add a local stdio server y Environment variable expansion in .mcp.json.

Transporte 2 — HTTP (HTTP transmisible)

Claude Code lo soporta, y también cualquier otro cliente MCP. Es el transporte a usar cuando el servidor se ejecuta en otro lugar: otro host, un contenedor, un servicio compartido por varios agentes, o un agente que no es Claude.

El archivo del servidor siempre llama a mcp.run(transport="stdio") bajo su guarda __main__, por lo que HTTP se sirve mediante la CLI de FastMCP — sin cambios de código:

.venv/bin/fastmcp run mcps/mcp_server_netmiko.py \
  --transport http --host 127.0.0.1 --port 8123
# endpoint: http://127.0.0.1:8123/mcp/

Las variables NETMIKO_MCP_* ya no forman parte de la configuración del cliente: el proceso del servidor es iniciado por ti, por lo que pertenecen a su entorno (una exportación de shell, una unidad systemd, un bloque environment: de un contenedor).

Lado del cliente:

{
  "mcpServers": {
    "netmiko": {
      "type": "http",
      "url": "http://127.0.0.1:8123/mcp/",
      "headers": {
        "Authorization": "Bearer ${NETMIKO_MCP_TOKEN}"
      }
    }
  }
}

O, equivalentemente, claude mcp add --transport http netmiko http://127.0.0.1:8123/mcp/.

--transport sse y "type": "sse" también funcionan; SSE es el transporte remoto más antiguo y se mantiene para clientes que no han migrado a HTTP transmisible.

Seguridad. La CLI de FastMCP sirve esto sin autenticación: quien alcance el puerto puede ejecutar comandos show contra cada dispositivo en el inventario, usando las credenciales en el entorno del servidor. Enlaza a 127.0.0.1 para una prueba local, y para cualquier cosa compartida ponlo detrás de un proxy inverso que termine TLS y verifique el encabezado Authorization. El bloque headers de arriba es lo que envía el cliente; el proxy es lo que debe verificarlo.

Agentes que no son Claude

El objeto mcpServers mostrado aquí es la forma de facto: Claude Code, Claude Desktop, Cursor y Windsurf leen los mismos tres campos para stdio (command / args / env) y los mismos dos para remoto (url / headers). Copiar una entrada entre ellos normalmente funciona tal cual.

Diferencias conocidas que vale la pena verificar antes de copiar:

  • VS Code usa mcp.json con una clave "servers" de nivel superior en lugar de "mcpServers", y quiere que "type" se indique explícitamente.

  • Algunos clientes no implementan la expansión ${VAR}; allí el valor debe ser literal, lo cual es un argumento para el transporte HTTP más un proxy en lugar de un token pegado en un archivo confirmado.

  • Un agente sin ningún archivo de configuración aún puede comunicarse directamente con el endpoint HTTP — la URL y el encabezado Authorization son todo el contrato.

El bloque env

Las entradas NETMIKO_MCP_* tienen prioridad sobre cualquier archivo de configuración YAML. Se establecen explícitamente porque fuera de Niko no hay NikoPaths, por lo que los valores predeterminados caen en ~/commands.yml y ~/.netmiko_mcp_tmp.

Cada ruta aquí puede escribirse relativa a la raíz del proyecto: el servidor ancla los valores relativos a PARENT_DIR cuando se cargan las configuraciones, por lo que el cwd del proceso iniciado nunca decide dónde reside el inventario o el registro de auditoría. Una ruta absoluta o un ~ se toma tal cual.

Variable

Default

Propósito

NETMIKO_MCP_INVENTORY_TYPE

netmiko_tools

yaml (archivo local) o fedele (SoT)

NETMIKO_MCP_INVENTORY_FILE

(búsqueda de netmiko-tools)

ruta del inventario cuando el tipo es yaml

NETMIKO_MCP_CREDENTIAL_SOURCE

env

env (lee el .env) o fedele

NETMIKO_MCP_FEDELE_GROUP_SOURCE

tags

qué define un grupo: tags, device_roles, sites

NETMIKO_MCP_FEDELE_DEVICE_FILTER

(ninguno)

filtro de alcance, tag=lab&status=active. Sin él: todo el inventario

NETMIKO_MCP_FEDELE_CACHE_TTL

60

tiempo de vida de la caché de resolución de SoT, en segundos

NETMIKO_MCP_COMMAND_FILE

~/commands.yml fuera de Niko

lista de permitidos/denegados

NETMIKO_MCP_ALLOW_PIPE

false

habilita tuberías en los comandos

NETMIKO_MCP_SSH_CONFIG_FILE

(ninguno)

ssh_config de OpenSSH. Requerido para jumphosts — Netmiko no lee ~/.ssh/config por sí mismo

NETMIKO_MCP_MAX_WORKERS

10

conexiones concurrentes en comandos de grupo

NETMIKO_MCP_SAVE_OUTPUT_DIR

~/.netmiko_mcp_tmp fuera de Niko

búfer para salidas grandes

NETMIKO_MCP_SAVE_THRESHOLD

1000

número de líneas a partir del cual la salida se guarda en lugar de devolverse en línea

NETMIKO_MCP_AUDIT_LOG_FILE

(ver el README principal)

registro de auditoría (JSON, fail-closed)

NETMIKO_MCP_CONFIG

~/.netmiko-mcp.yml

ruta a un archivo de configuración YAML que contiene estos mismos ajustes

LOG_FILE / LOG_LEVEL

Niko.log / INFO

registro operativo: stderr siempre, más este archivo rotativo (5 MB × 3, 0600). LOG_LEVEL se indica con su valor predeterminado para que el control esté donde lo buscas — ajústalo a DEBUG y la salida del dispositivo aparecerá en el registro

Las credenciales no se configuran aquí. NETMIKO_USERNAME, NETMIKO_PASSWORD, NETMIKO_SECRET y las variables FEDELE_* se leen desde <project-root>/.env, para que nunca terminen en un archivo JSON confirmado. Precedencia: lo que está en el bloque env tiene prioridad sobre el .env, en silencio — define cada variable en un solo lugar.

Cualquier otra variable está documentada en el README del repositorio principal.

Verificar que funciona

claude mcp list          # netmiko: ✓ connected

Dentro de la sesión, /mcp lista las herramientas y /skills confirma que la habilidad se ha cargado. Pregunta qué política está en vigor y netmiko.get_command_policy nombra el archivo que está leyendo — o informa "fallback", lo que significa que nunca encontró el archivo y se está ejecutando con los 16 comandos integrados.


Autor: Ed Scrimaglia edgardo.scrimaglia@gmail.com — última actualización: 2026-08-18.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.

  • Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.

  • Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.

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/escrimaglia/netmiko-mcp-claude'

If you have feedback or need assistance with the MCP directory API, please join our Discord server