nautobot-mcp
nautobot-mcp
Un servidor MCP para Nautobot, diseñado para instancias cuya API es demasiado grande para enumerar: Nautobot 3.2 incluye 1,673 operaciones REST en 477 rutas, y cada aplicación instalada añade más. Este servidor expone 15 herramientas basadas en esquemas en lugar de una herramienta por endpoint, de modo que toda la API — tanto el núcleo como los plugins — es accesible sin saturar el contexto de un agente.
Qué lo hace funcionar
Un paso de compilación, no análisis en tiempo de ejecución. El documento OpenAPI de Nautobot tiene 18 MB y su introspección de GraphQL otros 10 MB. Un script de compilación los fusiona en un índice SQLite de ~1.1 MB con una tabla de búsqueda FTS5. El servidor lo abre en modo solo lectura y responde a las consultas en microsegundos; el arranque no depende del tamaño de la API.
Claves foráneas recuperadas de GraphQL. OpenAPI por sí solo no puede describir las relaciones de Nautobot: cada campo relacionado se serializa como un objeto opaco idéntico:
// dcim.device: device_type, role, status and location are indistinguishable here
"device_type": { "id": {...}, "object_type": {"pattern": "^[a-z]+\\.[a-z]+$"}, "url": {...} }El sistema de tipos de GraphQL nombra los objetivos directamente (device_type → DeviceTypeType), por lo que ambos se unen mediante el nombre del componente OpenAPI para recuperar 441 aristas FK tipadas. Ese grafo es lo que hace posible la planificación de dependencias.
Filtros comprimidos. dcim.device expone 250 parámetros de filtro, que en realidad son ~74 campos base multiplicados por una familia de sufijos de búsqueda (__ic, __n, __isnull, __gte, …). El índice almacena los campos base junto con sus conjuntos de sufijos y describe el vocabulario una sola vez.
Related MCP server: mcp-graphql
Instalación
uv venv && uv pip install -e ".[dev]"
cp .env.example .env # then set NAUTOBOT_URL and NAUTOBOT_TOKEN
cp .mcp.json.example .mcp.json # optional: for stdio-based clients
python -m nautobot_mcp.schema.build --probeO evite la clonación por completo y ejecútelo en un contenedor; consulte Docker.
El paso de compilación obtiene los esquemas y escribe var/index.sqlite. Vuelva a ejecutarlo después de instalar o actualizar una aplicación de Nautobot, o llame a la herramienta nautobot_refresh_schema.
Configuración
Variable | Default | Propósito |
| — | URL base, p. ej. |
| — | Token de API |
|
| Puerta maestra para crear/actualizar/eliminar |
|
| Verificación TLS |
|
| Tiempo de espera por solicitud (segundos) |
|
| Dónde viven las fuentes de esquema y el índice |
|
| Límite máximo para la paginación de |
Controles solo para contenedor, leídos por el punto de entrada en lugar del servidor:
Variable | Default | Propósito |
|
| Transporte que sirve el contenedor ( |
|
| Dirección de enlace para transportes HTTP |
|
| Puerto de enlace para transportes HTTP |
|
| Construir un índice de esquema faltante al inicio en lugar de negarse a ejecutarse |
Registro con un cliente
{
"mcpServers": {
"nautobot": {
"command": "/path/to/nautobot-mcp/.venv/bin/python",
"args": ["-m", "nautobot_mcp"],
"env": {
"NAUTOBOT_URL": "http://nautobot.example.com:8080",
"NAUTOBOT_TOKEN": "...",
"NAUTOBOT_CACHE_DIR": "/path/to/nautobot-mcp/var"
}
}
}
}También hay transportes HTTP disponibles: python -m nautobot_mcp --transport streamable-http --port 8000.
Docker
cp .env.example .env # then set NAUTOBOT_URL and NAUTOBOT_TOKEN
docker compose up -d # or: make docker-upEl primer inicio construye el índice de esquema contra su instancia y lo almacena en el volumen index; los inicios posteriores lo reutilizan. El servidor escucha en 127.0.0.1:8000/mcp.
El índice no está incluido en la imagen, y no puede estarlo: se fusiona a partir de los esquemas de una instancia específica de Nautobot, incluidas las aplicaciones que esa instancia tenga instaladas. Vuelva a construirlo después de instalar o actualizar una aplicación — make docker-index, o la herramienta nautobot_refresh_schema, que escribe en el mismo volumen.
make docker-index # rebuild the index in place
make docker-logs # follow the server log
make docker-down # stop; VOLUMES=1 also drops the index
docker compose run --rm server index --offline # rebuild from cached sources onlyRegistro del contenedor con un cliente
Sobre HTTP, apunte el cliente al puerto publicado:
{
"mcpServers": {
"nautobot": { "url": "http://127.0.0.1:8000/mcp" }
}
}O deje que el cliente inicie un contenedor por sesión sobre stdio, reutilizando el mismo volumen de índice:
{
"mcpServers": {
"nautobot": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"--env-file", "/path/to/nautobot-mcp/.env",
"-e", "MCP_TRANSPORT=stdio",
"-v", "nautobot-mcp_index:/data",
"nautobot-mcp:latest"
]
}
}
}Cualquier cosa pasada después del nombre de la imagen va directamente a python -m nautobot_mcp, así que docker run ... nautobot-mcp:latest --transport sse --host 0.0.0.0 --port 8000 también funciona.
Qué asume el archivo compose
El puerto se publica solo en loopback. La sección Seguridad se aplica en su totalidad: este es un proxy no autenticado que posee un token con sus permisos, por lo que alcanzarlo desde otro host significa poner autenticación delante, no ampliar el mapeo de puertos.
Las escrituras permanecen desactivadas a menos que
NAUTOBOT_ALLOW_WRITE=trueesté en su.env.El contenedor está endurecido por defecto — no root (uid 1000), sistema de archivos raíz de solo lectura, todas las capacidades eliminadas,
no-new-privileges. La única ruta escribible es el volumen/data, que es donde pertenecen el índice y sus fuentes en caché.La salud es una conexión TCP, no una solicitud MCP: una solicitud sin sesión a
/mcphace que el administrador de sesiones asigne un transporte que nada reutiliza, por lo que sondear el protocolo cada 30 s filtraría una sesión por sonda..envse lee literalmente por compose. Mantenga los comentarios en su propia línea; un# comentarioal final no se elimina de manera confiable de un valor.
Herramientas
Herramienta | Propósito |
| Encontrar modelos por nombre, descripción o nombre de campo |
| Campos, campos obligatorios, destinos FK, filtros, acciones |
| Espacios de nombres de aplicaciones (núcleo y plugins), versiones, estado del índice |
| Requisitos previos ordenados para crear un objeto |
| Nombre humano → UUID, limitado al modelo que lo referencia |
| Leer cualquier modelo, reducido o proyectado |
| Escrituras controladas |
| Consultas GraphQL arbitrarias |
| Introspección, un tipo a la vez |
| Endpoints no CRUD ( |
| Cualquier endpoint REST — plugins, operaciones masivas, acciones personalizadas |
| Volver a obtener esquemas y reconstruir el índice |
Las referencias a modelos son tolerantes: dcim.device, device, devices, Device, /dcim/devices/ y DeviceType se resuelven todos, y los errores tipográficos reciben sugerencias (dvice → "¿Quiso decir: dcim.device?").
Planificación de dependencias
Crear un Device en una instancia vacía significa crear primero otros cuatro objetos. nautobot_plan_create("dcim.device") recorre el grafo FK, comprueba en la instancia en vivo qué ya existe y los devuelve en orden:
dcim.manufacturer → dcim.devicetype → dcim.locationtype → dcim.location → extras.role → dcim.deviceTambién maneja el alcance de content-type de Nautobot. Role, Status y Tag solo se pueden asignar a modelos listados en sus content_types. Una cuenta global es la pregunta equivocada: una instancia puede tener 20 Roles mientras ninguno se aplica a un Device:
{
"model": "extras.role",
"action": "create", // not "use_existing", despite 20 existing
"content_type_scoped": true,
"by_referrer": { "dcim.device": { "valid_count": 0 } },
"note": "No extras.role is assignable to dcim.device yet. Create one with
content_types including ['dcim.device'] ..."
}Qué modelos se limitan de esta manera se descubre, no está codificado: content_types significa "qué puede vivir aquí" en LocationType y "quién puede referenciarme" en Role. El planificador intenta la consulta con alcance y trata un 400 como prueba de que el alcance no se aplica, por lo que los modelos de plugins se comportan correctamente sin código adicional.
Escrituras
Las escrituras están desactivadas hasta que NAUTOBOT_ALLOW_WRITE=true. Incluso entonces, las mutaciones son de dos pasos: la primera llamada devuelve una vista previa y un confirm_token, y la llamada se repite con ese token para aplicarla. Los tokens se derivan del payload, por lo que uno emitido para un cuerpo no puede reproducirse contra otro. nautobot_update muestra una vista previa de un diff a nivel de campo; nautobot_delete muestra una vista previa del objeto y de todo lo que lo referencia.
Seguridad
Este servidor es un proxy privilegiado no autenticado hacia Nautobot. Posee un token de API y no realiza autenticación propia: cualquier cliente que pueda alcanzarlo actúa con los permisos completos de ese token, sin poseerlo jamás.
Los valores predeterminados son deliberadamente seguros: --host se enlaza a 127.0.0.1 y NAUTOBOT_ALLOW_WRITE es false. La configuración arriesgada es combinar un enlace no loopback con escrituras habilitadas, lo que otorga creación/actualización/eliminación no autenticadas sobre su fuente de verdad a cualquier cosa que pueda enrutar al puerto.
El flujo de confirmación de token es una protección contra accidentes, no un control de acceso: cualquier cliente puede leer el token de la respuesta de vista previa y confirmar inmediatamente.
Si el servidor debe ser accesible desde otros hosts, ponga autenticación delante (un proxy inverso con mTLS, una puerta de enlace compatible con OAuth o un túnel SSH) y asígnele un token de Nautobot limitado solo a lo que el agente necesite. Consulte SECURITY.md.
Capacidad de respuesta
Un cliente HTTP/2 agrupado se comparte entre las herramientas; el planificador distribuye las comprobaciones de existencia de forma concurrente.
Las respuestas se reducen antes de llegar al agente. Nautobot no tiene soporte para campos dispersos (
?fields=se rechaza como filtro desconocido), por lo queurl,natural_slug,notes_url, marcas de tiempo y bloques de campos personalizados vacíos se eliminan en el lado del cliente, y los objetos relacionados anidados se reducen a identidad. Pasefields=[...]para proyectar, ofull=truepara optar por no hacerlo.
Extensión
Cada conjunto de herramientas es un módulo que expone register(server, ctx), listado en tools/__init__.py::TOOLSETS. El registro está envuelto para que cada herramienta devuelva un error estructurado en lugar de lanzar una excepción: una excepción no capturada llegaría al agente como un "Error ejecutando la herramienta X" opaco.
Los endpoints de plugins no necesitan código: aparecen en /api/swagger.json, por lo que reconstruir el índice los hace disponibles para todas las herramientas.
Pruebas
pytest82 pruebas se ejecutan contra fixtures extraídos del esquema en vivo, con HTTP simulado mediante respx. Fijan las trampas encontradas al construir esto: la colisión de slug que mapea virtualization.vminterface sobre InterfaceType de DCIM, el alcance de content_types que produce silenciosamente planes inutilizables, y la heurística FK que resuelve DynamicGroupMembership.group al auth.Group de Django en lugar de extras.DynamicGroup.
Configuración del agente
AGENT.md contiene un prompt de sistema listo para usar y una descripción de registro para un agente que maneja este servidor, incluido el protocolo de escritura y la regla de alcance de content-type que más comúnmente causa que una creación falle.
Contribuciones
Las issues y las pull requests son bienvenidas. pytest debe pasar y ruff check / ruff format --check deben estar limpios; CI lo exige en Python 3.11-3.13. La suite no necesita instancia de Nautobot ni red: se ejecuta contra fixtures de esquema en tests/fixtures con HTTP simulado por respx.
Licencia
Apache 2.0 - consulte LICENSE.
Estructura
src/nautobot_mcp/
schema/build.py fuses OpenAPI + GraphQL + content types into the index
schema/index.py read-only query layer (lookup, FTS search, graph)
client.py pooled async HTTP, slimming, error normalisation
depgraph.py creation planning and reference resolution
safety.py write gate, confirm tokens, diffs
tools/ one module per toolset, registered through a guard
server.py MCP server assemblyThis server cannot be deployed
Maintenance
Related MCP Connectors
MCP facade over the Nebelus Construction API. ~48 tools give full agent build parity: create/update/probe agents, edit graphs, attach knowledge and vector stores, wire connectors, set governance policies and locked guardrails, enable grounding-trace, and read deployment wiring. Purpose-built for regulated industries: data residency is enforced per region (EU / GCC-KSA), with PII controls and an audit trail. Agents are created as drafts — no deploy tool is exposed over MCP by design; publishing happens in the Nebelus console.
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
Build and run agents and automations across hundreds of apps using natural language.
- mcp-serverOAuthcom.make
Give your AI agents the tools to build, manage, and run automation workflows.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables comprehensive interaction with NetBox infrastructure management through both read and write operations. Supports full CRUD operations for devices, IP addresses, sites, racks, and other NetBox objects through natural language commands.917Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to interact with GraphQL APIs through schema introspection and query execution.676 npm1MIT
- AlicenseAqualityDmaintenanceEnables AI agents to connect to any GraphQL endpoint, introspect schemas, and execute queries or mutations through auto-generated tools.2235 npmMIT
- AlicenseBqualityAmaintenanceGives AI assistants read (and optionally write) access to a NetBox instance, covering DCIM, IPAM, circuits, virtualization, tenancy, and more.10021 npm1MIT