nautobot-mcp
nautobot-mcp
Ein MCP-Server für Nautobot, gebaut für Instanzen, deren API zu groß zum Aufzählen ist: Nautobot 3.2 bringt 1.673 REST-Operationen über 477 Pfade mit, und jede installierte App fügt weitere hinzu. Dieser Server stellt 15 schema-getriebene Tools bereit statt eines Tools pro Endpunkt, sodass die gesamte API – Kern und Plugins gleichermaßen – erreichbar ist, ohne den Kontext eines Agents zu überfluten.
Was ihn funktionieren lässt
Ein Build-Schritt, kein Runtime-Parsing. Das OpenAPI-Dokument von Nautobot ist 18 MB groß und die GraphQL-Introspection weitere 10 MB. Ein Build-Skript verschmilzt beide zu einem ~1,1 MB großen SQLite-Index mit einer FTS5-Suchtabelle. Der Server öffnet ihn schreibgeschützt und beantwortet Lookups in Mikrosekunden; der Start hängt nicht von der Größe der API ab.
Fremdschlüssel aus GraphQL rekonstruiert. OpenAPI allein kann die Beziehungen von Nautobot nicht beschreiben – jedes verknüpfte Feld serialisiert als identisches opakes Objekt:
// dcim.device: device_type, role, status and location are indistinguishable here
"device_type": { "id": {...}, "object_type": {"pattern": "^[a-z]+\\.[a-z]+$"}, "url": {...} }Das Typsystem von GraphQL benennt die Ziele direkt (device_type → DeviceTypeType), also
werden beide über den OpenAPI-Komponentennamen verbunden, um 441 typisierte
FK-Kanten zu rekonstruieren. Dieser Graph ist es, der die Abhängigkeitsplanung möglich
macht.
Filter komprimiert. dcim.device stellt 250 Filterparameter bereit, die in
Wirklichkeit ~74 Basisfelder mal einer Familie von Lookup-Suffixen sind (__ic, __n,
__isnull, __gte, …). Der Index speichert Basisfelder plus deren Suffixmengen und
beschreibt das Vokabular einmal.
Related MCP server: Advanced Hasura GraphQL MCP Server
Installation
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 --probeOder überspringen Sie den Checkout ganz und führen Sie ihn in einem Container aus – siehe Docker.
Der Build-Schritt holt die Schemas und schreibt var/index.sqlite. Führen Sie ihn nach
der Installation oder dem Upgrade einer Nautobot-App erneut aus – oder rufen Sie das
Tool nautobot_refresh_schema auf.
Konfiguration
Variable | Standard | Zweck |
| — | Basis-URL, z. B. |
| — | API-Token |
|
| Master-Schalter für Create/Update/Delete |
|
| TLS-Verifizierung |
|
| Timeout pro Anfrage (Sekunden) |
|
| Wo Schemaquellen und der Index liegen |
|
| Obergrenze für die |
Nur für Container geltende Stellschrauben, die vom Entrypoint statt vom Server gelesen werden:
Variable | Standard | Zweck |
|
| Transport, den der Container bedient ( |
|
| Bind-Adresse für HTTP-Transports |
|
| Bind-Port für HTTP-Transports |
|
| Fehlenden Schema-Index beim Start aufbauen statt die Ausführung zu verweigern |
Bei einem Client registrieren
{
"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"
}
}
}
}HTTP-Transports sind ebenfalls verfügbar: 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-upDer erste Start baut den Schema-Index gegen Ihre Instanz und speichert ihn auf dem
index-Volume; spätere Starts verwenden ihn erneut. Der Server lauscht auf 127.0.0.1:8000/mcp.
Der Index ist nicht ins Image eingebacken und kann es auch nicht sein: Er wird aus den
Schemas einer bestimmten Nautobot-Instanz verschmolzen, einschließlich aller Apps, die
diese Instanz installiert hat. Bauen Sie ihn nach der Installation oder dem Upgrade einer
App neu auf – make docker-index oder das Tool nautobot_refresh_schema, das in dasselbe
Volume schreibt.
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 onlyDen Container bei einem Client registrieren
Über HTTP zeigen Sie den Client auf den veröffentlichten Port:
{
"mcpServers": {
"nautobot": { "url": "http://127.0.0.1:8000/mcp" }
}
}Oder lassen Sie den Client pro Sitzung einen Container über stdio spawnen und dabei dasselbe Index-Volume wiederverwenden:
{
"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"
]
}
}
}Alles, was nach dem Image-Namen übergeben wird, geht direkt an python -m nautobot_mcp,
also funktioniert auch docker run ... nautobot-mcp:latest --transport sse --host 0.0.0.0 --port 8000.
Was die Compose-Datei voraussetzt
Der Port wird nur auf Loopback veröffentlicht. Abschnitt Sicherheit gilt in vollem Umfang: Dies ist ein unauthentifizierter Proxy, der ein Token mit Ihren Berechtigungen hält. Wenn er also von einem anderen Host erreichbar sein soll, muss Authentifizierung davor geschaltet werden, nicht die Port-Zuordnung erweitert werden.
Schreibzugriffe bleiben aus, außer
NAUTOBOT_ALLOW_WRITE=truesteht in Ihrer.env.Der Container ist standardmäßig gehärtet – nicht-root (uid 1000), read-only Root-Dateisystem, alle Capabilities entfernt,
no-new-privileges. Der einzige beschreibbare Pfad ist das/data-Volume, auf dem der Index und seine gecachten Quellen liegen.Health ist ein TCP-Connect, keine MCP-Anfrage: Eine Anfrage ohne Session an
/mcpveranlasst den Session-Manager, einen Transport zu allozieren, den nichts aufräumt. Das Protokoll alle 30s zu sondieren würde also eine Session pro Sondierung leaken..envwird von Compose wörtlich gelesen. Halten Sie Kommentare auf einer eigenen Zeile; ein nachgestellter# commentwird nicht zuverlässig von einem Wert getrennt.
Tools
Tool | Zweck |
| Modelle nach Name, Beschreibung oder Feldname finden |
| Felder, Pflichtfelder, FK-Ziele, Filter, Aktionen |
| App-Namespaces (Kern und Plugin), Versionen, Indexzustand |
| Geordnete Voraussetzungen zum Erstellen eines Objekts |
| Menschenlesbarer Name → UUID, auf das referenzierende Modell begrenzt |
| Beliebiges Modell lesen, verschlankt oder projiziert |
| Gesteuerte Schreibzugriffe |
| Beliebige GraphQL-Abfragen |
| Introspection, ein Typ nach dem anderen |
| Nicht-CRUD-Endpunkte ( |
| Beliebiger REST-Endpunkt – Plugins, Bulk-Operationen, benutzerdefinierte Aktionen |
| Schemas neu holen und den Index neu aufbauen |
Modellreferenzen sind nachsichtig: dcim.device, device, devices, Device,
/dcim/devices/ und DeviceType lösen alle auf, und Tippfehler erhalten Vorschläge
(dvice → "Meinten Sie: dcim.device?").
Abhängigkeitsplanung
Das Erstellen eines Device auf einer leeren Instanz bedeutet, zuerst vier andere Objekte
zu erstellen. nautobot_plan_create("dcim.device") durchläuft den FK-Graphen, prüft die
Live-Instanz auf bereits Vorhandenes und gibt sie in Reihenfolge zurück:
dcim.manufacturer → dcim.devicetype → dcim.locationtype → dcim.location → extras.role → dcim.deviceEs behandelt auch die Content-Type-Scoping von Nautobot. Role, Status und Tag
sind nur Modellen zuweisbar, die in ihren content_types aufgeführt sind. Eine globale
Zählung ist die falsche Frage – eine Instanz kann 20 Rollen enthalten, während keine
auf ein Device zutrifft:
{
"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'] ..."
}Welche Modelle auf diese Weise gescoped werden, wird entdeckt, nicht hartkodiert:
content_types bedeutet "was hier leben darf" bei LocationType und "wer mich
referenzieren darf" bei Role. Der Planer versucht die gescopte Abfrage und behandelt
eine 400 als Beweis, dass Scoping nicht zutrifft – Plugin-Modelle verhalten sich also
ohne zusätzlichen Code korrekt.
Schreibzugriffe
Schreibzugriffe sind aus, bis NAUTOBOT_ALLOW_WRITE=true gesetzt ist. Selbst dann sind
Mutationen zweistufig: Der erste Aufruf gibt eine Vorschau und einen confirm_token
zurück, und der Aufruf wird mit diesem Token wiederholt, um ihn anzuwenden. Tokens werden
aus der Payload abgeleitet, sodass ein für einen Body ausgestelltes Token nicht gegen
einen anderen wiederverwendet werden kann. nautobot_update zeigt eine Vorschau eines
Diffs auf Feldebene; nautobot_delete zeigt eine Vorschau des Objekts und von allem, was
darauf referenziert.
Sicherheit
Dieser Server ist ein unauthentifizierter privilegierter Proxy zu Nautobot. Er hält ein API-Token und führt keine eigene Authentifizierung durch: Jeder Client, der ihn erreichen kann, handelt mit den vollen Berechtigungen dieses Tokens, ohne jemals das Token zu besitzen.
Die Standardwerte sind bewusst sicher – --host bindet 127.0.0.1 und
NAUTOBOT_ALLOW_WRITE ist false. Die riskante Konfiguration ist die Kombination aus
einem Nicht-Loopback-Bind mit aktivierten Schreibzugriffen, was unauthentifiziertes
Create/Update/Delete über Ihre Quelle der Wahrheit für alles gewährt, was den Port
erreichen kann.
Der Confirm-Token-Ablauf ist eine Unfallschutzmaßnahme, keine Zugriffskontrolle – jeder Client kann das Token aus der Vorschauantwort lesen und sofort bestätigen.
Wenn der Server von anderen Hosts erreichbar sein muss, setzen Sie Authentifizierung davor (einen Reverse-Proxy mit mTLS, ein OAuth-fähiges Gateway oder einen SSH-Tunnel) und geben Sie ihm ein Nautobot-Token, das nur auf das beschränkt ist, was der Agent benötigt. Siehe SECURITY.md.
Reaktionsfähigkeit
Ein gepoolter HTTP/2-Client wird von allen Tools gemeinsam genutzt; der Planer führt Existenzprüfungen parallel aus.
Antworten werden verschlankt, bevor sie den Agent erreichen. Nautobot hat keine Unterstützung für spärliche Feldsets (
?fields=wird als unbekannter Filter abgelehnt), also werdenurl,natural_slug,notes_url, Zeitstempel und leere Custom-Field-Blöcke clientseitig entfernt, und verschachtelte verknüpfte Objekte werden auf Identität reduziert. Übergeben Siefields=[...]zum Projizieren oderfull=truezum Opt-out.
Erweiterung
Jedes Toolset ist ein Modul, das register(server, ctx) exponiert und in
tools/__init__.py::TOOLSETS aufgeführt ist. Die Registrierung ist so umhüllt, dass jedes
Tool einen strukturierten Fehler zurückgibt statt zu werfen – eine unbehandelte Ausnahme
würde den Agent als undurchsichtigen "Fehler beim Ausführen von Tool X" erreichen.
Plugin-Endpunkte benötigen keinen Code: Sie erscheinen in /api/swagger.json, also macht
das Neuaufbauen des Index sie für jedes Tool verfügbar.
Tests
pytest82 Tests laufen gegen Fixtures, die aus dem Live-Schema geschnitten sind, mit per respx
gemocktem HTTP. Sie fixieren die Fallstricke, die beim Bauen gefunden wurden: die
Slug-Kollision, die virtualization.vminterface auf DCIMs InterfaceType abbildet, das
content_types-Scoping, das stillschweigend unbrauchbare Pläne erzeugt, und die
FK-Heuristik, die DynamicGroupMembership.group zu Djangos auth.Group auflöst statt zu
extras.DynamicGroup.
Agent-Konfiguration
AGENT.md enthält einen gebrauchsfertigen System-Prompt und eine Registry-Beschreibung für einen Agent, der diesen Server steuert, einschließlich des Schreibprotokolls und der Content-Type-Scoping-Regel, die am häufigsten dazu führt, dass ein Create fehlschlägt.
Mitwirken
Issues und Pull Requests sind willkommen. pytest muss bestehen und ruff check /
ruff format --check müssen sauber sein; CI erzwingt beides über Python 3.11-3.13. Die
Suite benötigt keine Nautobot-Instanz und kein Netzwerk – sie läuft gegen Schema-Fixtures
in tests/fixtures mit per respx gemocktem HTTP.
Lizenz
Apache 2.0 – siehe LICENSE.
Aufbau
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