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: Advanced Hasura GraphQL MCP Server
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 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 Servers
- AlicenseAqualityDmaintenanceEnables 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.916Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with Hasura GraphQL endpoints to discover schema structures and execute queries or mutations. It provides specialized tools for table introspection, data previewing, and performing data aggregations through natural language.
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to interact with any GraphQL API by introspecting the schema and exposing queries and mutations as MCP tools, with built-in pagination, semantic search, and framework adapters.13MIT
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to interact with GraphQL APIs through schema introspection and query execution.1,5161MIT
Related MCP Connectors
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
SaaS intelligence for AI agents. 5 unified tools cover 1,000+ services with 91-96% token savings.
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
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/shamalawy/nautobot-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server