Skip to main content
Glama

claude-project — netmiko MCP-Server + Skill

Ein fertig kopierbares Projekt, das einem KI-Agenten schreibgeschützten Zugriff auf Router, Switches und Firewalls über SSH ermöglicht, durch das Model Context Protocol.

Es enthält zwei Komponenten und die Verbindung zwischen ihnen:

  • mcps/mcp_server_netmiko.py — ein eigenständiger MCP-Server. Zehn Tools, jeder Befehl gegen eine vom Betreiber definierte Erlaubnis-/Verbotsliste validiert, Ausgabe mit ntc-templates in JSON geparst und eine ausfallsichere Prüfspur jedes Versuchs.

  • .claude/skills/netmiko/SKILL.md — das Skill, das dem Agenten beibringt, wann er diese Tools einsetzen soll, wie die plattformspezifischen CLI-Dialekte aussehen und wie man eine Ablehnung liest.

Hier wird nichts auf ein Gerät geschrieben. Die Erlaubnisliste ist standardmäßig verweigernd — eine leere Liste erlaubt nichts — und die Verbotsseite hat immer Vorrang vor der Erlaubnisseite.

Alles, was passiert, wird in einer Prüfspur festgehalten, und netmiko.query_audit_trail macht es im Gespräch abfragbar: "alles, was auf SW-CORE-01 gemacht wurde, nach Datum", "die letzten 6 Aktionen", "welche Befehle diese Woche verweigert wurden". Da dieses Projekt keine Benutzeroberfläche hat, ist dieses Tool der einzige Weg, sie zu lesen.

Autoren und Herkunft

Dieses Projekt stammt von Ed Scrimagliaedgardo.scrimaglia@gmail.com, Octupus. Server, Skill, Konfigurationsmodell und Dokumentation sind seine Arbeit, geschrieben für den Niko-Agenten und hier als eigenständiges Projekt verpackt.

Es begann als Fork, und dieser Ursprung wird anerkannt, nicht versteckt: der Ausgangspunkt war die Arbeit von Kirk Byers, und das Projekt ist weit darüber hinausgewachsen. Was jetzt hier ist — das auf der Quelle der Wahrheit basierende Inventar, die Anmeldeinformationsauflösung, die drei Bereitstellungsvarianten, die Ausgabeseitierung, die Prüfspur, das Skill und diese Dokumentation — stammt nicht aus dem Upstream.

Die beiden Upstream-Projekte von Kirk Byers:

  • Netmiko — die Multi-Vendor-SSH-Bibliothek, die die eigentliche Kommunikation mit den Geräten übernimmt.

  • netmiko_mcp — der MCP-Server, von dem dieser abgezweigt wurde. Ein Teil davon ist weitgehend so erhalten geblieben, wie er war: der Sicherheitskern (Befehlsvalidierung, Glob-Handling, die Erlaubnis-/Verbotsasymmetrie), absichtlich als originalgetreuer Port beibehalten, damit Upstream-Patches immer noch eingespielt werden können. Das war eine technische Entscheidung, keine Einschränkung der übrigen Arbeit.

Related MCP server: Network MCP Server

Über Niko

Dieser Server wurde für Niko geschrieben, den Neural Intelligence Knowledge Orchestrator KI-Agenten, der von Ed Scrimaglia bei Octupus entwickelt wurde. Niko bedient eine Reihe von MCP-Servern — den Source-of-Truth-Server, diesen hier, Jira, E-Mails senden, Dateien erstellen und andere —, sodass ein Betreiber eine Frage in natürlicher Sprache stellen und aus der realen Umgebung beantwortet bekommen kann: die SoT für das, was wahr sein sollte, die Geräte selbst für das, was ist.

Innerhalb von Niko läuft dieselbe Datei etwas anders, und das ist wissenswert, weil es einiges im Code erklärt:

  • Server laufen über HTTP auf Loopback, ein Port pro Server, deklariert in mcps/mcp_config.json mit url / transport / local / env — dieselbe unten beschriebene Zwei-Achsen-Konfiguration, ausgedrückt in Nikos eigenem Format.

  • Die Installation erfolgt über die App, nicht durch Kopieren von Dateien: der Upload wird validiert, die Abhängigkeiten werden aus dem Code selbst aufgelöst, und eine fehlgeschlagene Installation wird zurückgesetzt, anstatt einen halben Server zurückzulassen.

Jede dieser Integrationen ist ein optionaler Import mit einem Fallback, sodass niko nie installiert sein muss. Es gibt vier, und so verhalten sie sich, wenn der Import fehlschlägt:

Import

Zeile

Eigenständiger Fallback

niko.srvclass_logging.MCPLogging

60

NIKO_AVAILABLE = False; der Server konfiguriert sein eigenes logging

niko.niko_paths.NikoPaths

68

None; Pfade kommen von den NETMIKO_MCP_*-Variablen, weshalb dieses Projekt sie explizit setzt

niko.srvclass_logging.SyncedConcurrentTimedRotatingFileHandler

436

FailClosedFileHandler — immer noch ausfallsicher, nur nicht mehr prozessübergreifend sicher

niko.srvclass_list_budget.apply_budget_to_payload

2709

eine No-Op, die die Nutzlast unverändert zurückgibt

Es geht nichts verloren, was außerhalb von Niko wichtig wäre: der nebenläufige Handler löst ein Mehrprozess-Eine-Datei-Problem, das hier nicht auftritt, und das Listenbudget kürzt lange Nutzlasten für einen Agenten, der seine eigene Kontextabrechnung hat. Eine Datei, zwei Zuhause, kein Fork.

Fedele ist Nikos Quelle der Wahrheit, weshalb die SoT-Variablen das FEDELE_-Präfix tragen, selbst wenn sie auf eine NetBox-Instanz verweisen.

Lizenz

Der eigene Code dieses Projekts ist MIT — siehe LICENSE.

Es ist eine abgeleitete Arbeit, daher gelten zwei Lizenzen und beide Dateien werden mitgeliefert:

Lizenz

Datei

Code, Dokumentation und Skill dieses Projekts

MIT

LICENSE

Aus ktbyers/netmiko_mcp portierte Teile

Apache-2.0

LICENSE-APACHE-2.0

NOTICE enthält die Namensnennung und die Erklärung der Änderungen, die Apache-2.0 §4(b) verlangt. Netmiko ist eine gewöhnliche MIT-Abhängigkeit: importiert, nicht mitgeliefert, nichts zum Weiterverteilen.


Aufbau

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

Zwei nicht verhandelbare Regeln:

  1. Das Skill lebt in .claude/skills/<name>/SKILL.md. Claude Code liest skills/netmiko.md nicht: es braucht das Verzeichnis und genau diesen Dateinamen.

  2. Der Server lebt in mcps/, nicht im Stammverzeichnis. PARENT_DIR ist das übergeordnete Verzeichnis des Ordners, der die .py enthält (mcp_server_netmiko.py:62), und dorther kommt die .env. Wenn der Server im Stammverzeichnis wäre, würde die .env eine Ebene über dem Projekt gesucht.

In Betrieb nehmen

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

Innerhalb der Sitzung: /mcp listet die 10 Tools auf, /skills bestätigt, dass das Skill geladen wurde. Erste Überprüfung, ohne das Netzwerk zu berühren:

Welche Befehlspolicy setzt der netmiko MCP durch?


Die drei Varianten

Woher das Inventar kommt und woher die Anmeldeinformationen kommen, sind zwei unabhängige Achsen. Das macht aus einem Server drei Bereitstellungen — und der Grund, warum der Server nie geändert werden muss, um zwischen ihnen zu wechseln: zwei Umgebungsvariablen entscheiden.

Inventar

Anmeldeinformationen

Was Sie brauchen

Wann verwenden

A — SoT alles

Fedele

Fedele

API-Token + Fernet-Schlüssel

Die SoT ist maßgeblich und enthält bereits die Geräte-Anmeldeinformationen

B — SoT-Inventar, lokale Anmeldeinformationen

Fedele oder NetBox

.env

API-Token

Sie haben eine SoT, aber nicht deren Anmeldeinformations-Plugin. Der übliche Ausgangspunkt

C — In sich geschlossen

lokales YAML

.env

nichts Externes

Labor, abgeschottet, Demo oder Notlaufmodus, wenn die SoT ausfällt

netmiko.get_metadata meldet, welche tatsächlich läuft — niemals aus der Konfigurationsdatei annehmen:

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

A — Fedele als Quelle der Wahrheit, inklusive Anmeldeinformationen

Der Agent fragt nach einem Gerät mit Namen; der Server löst Adresse, Plattform und Anmeldeinformationen zur Laufzeit gegen die SoT auf. Nichts über die Umgebung lebt in diesem Projekt: fügen Sie ein Gerät zur SoT hinzu, und es ist beim nächsten Aufruf erreichbar, ohne Datei bearbeiten und ohne Neustart.

// .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>

Dateien: keine sind zwingend erforderlich. commands.yml wird empfohlen — ohne sie gilt die integrierte Fallback-Policy. Es ist kein lokales Inventar beteiligt und keine NETMIKO_USERNAME / NETMIKO_PASSWORD; bei credential_source=fedele wird NETMIKO_SECRET ignoriert — das Enable-Passwort kommt ebenfalls von der SoT.

Wie die Anmeldeinformationssuche funktioniert, drei Schritte:

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

Wissenswertes, bevor Sie diese Variante wählen:

  • Der Fernet-Schlüssel ist die gesamte Sicherheitsgrenze. Er entschlüsselt Gerätepasswörter im Speicher des Servers. Behandeln Sie ihn wie die Passwörter selbst.

  • Ohne FEDELE_CREDENTIALS_KEY startet der Server trotzdem, und jedes Tool gibt denselben Startup Error zurück, der die fehlende Variable nennt. Er scheitert lautstark, nicht leise.

  • Setzen Sie den Bereichsfilter. Ohne NETMIKO_MCP_FEDELE_DEVICE_FILTER ist das Inventar die gesamte Umgebung, die die SoT kennt, was auch die gesamte Menge der Geräte ist, die der Agent erreichen kann. Der Server protokolliert eine Warnung, wenn er fehlt; der Filter akzeptiert Abfragesyntax, tag=lab&status=active.

  • Ein Gerät ohne primary_ip, ohne platform oder dessen Plattform kein Netmiko device_type ist, wird vom Inventar ausgeschlossen — SoTs inventarisieren auch Kameras, Badge-Leser und Gehäuse. Ausschlüsse werden gezählt und gemeldet, sodass der Agent nie behauptet "das sind alle Geräte" über einer Teilmenge.

  • Es gibt einen Schutzschalter: nach einem Transportfehler oder einem 5xx hört der Client für 30 s auf, die SoT aufzurufen. Ein Gruppenbefehl gegen 40 Geräte bei ausgefallener SoT scheitert einmal, nicht vierzigmal.

B — SoT für das Inventar, Anmeldeinformationen in der .env

Identisch zu A mit einer umgedrehten Variable:

"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>

Sie erhalten das dynamische Inventar — der Teil, der sich selbst bezahlt macht — ohne das Anmeldeinformations-Plugin und ohne den Fernet-Schlüssel. Ein Dienstkonto wird für jedes Gerät verwendet.

NetBox oder jede NetBox-förmige SoT

Das Inventar-Backend spricht den NetBox-REST-Dialekt, daher funktioniert NetBox selbst in dieser Variante unverändert:

Was das Backend aufruft

Was es liest

dcim/devices/

die Geräteliste, gefiltert durch den Bereichsfilter und paginiert

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

welches auch immer FEDELE_GROUP_SOURCE auswählt, wird zu den Gerätegruppen

device.primary_ip.address

der SSH-Host, Maske entfernt

device.platform.name

der Netmiko device_type, validiert gegen CLASS_MAPPER

Zeigen Sie FEDELE_URL auf die NetBox-Instanz (/api wird angehängt, wenn Sie es weglassen) und FEDELE_TOKEN auf ein NetBox-API-Token — der Client authentifiziert sich mit dem Authorization: Token …-Header, den NetBox erwartet. Die Variablen behalten das FEDELE_-Präfix; das ist ein Benennungs-Erbe, keine Produktanforderung.

Die eine Anforderung, die NetBox standardmäßig nicht erfüllt: platform.name muss exakt ein Netmiko device_type seincisco_ios, arista_eos, huawei_vrp, juniper_junos. Eine Plattform namens "Cisco IOS 15.2" ist kein device_type, daher wird jedes Gerät, das sie trägt, vom Inventar ausgeschlossen. Benennen Sie entweder die Plattformen in NetBox um oder akzeptieren Sie die Ausschlüsse, die gemeldet werden.

Anmeldeinformationen sind der Teil, den NetBox nicht abdeckt: die plugins/credentials/…-Endpunkte gehören zu Fedeles Plugin. Mit einfachem NetBox ist Variante A nicht verfügbar — bleiben Sie bei B.

C — In sich geschlossen: gar keine SoT

Alles lebt in diesem Projekt. Es wird nie ein externer Dienst kontaktiert.

// .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>

Dateien: inventory.yml ist hier erforderlich – es ist der einzige Ort, an dem die Geräte existieren. commands.yml bleibt empfohlen, nicht erforderlich. Das Inventar hat das Format von netmiko_tools – eine flache Zuordnung von Name zu Verbindungsdaten, plus Gruppenschlüssel:

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

Die mitgelieferte Datei dieses Projekts enthält Beispieldaten: 12 fiktive Geräte in den RFC-5737-Dokumentationsbereichen, 7 Gruppen und ausgewählte Plattformen, sodass jeder CLI-Dialekt, den die Zulassungsliste erwähnt, vertreten ist. Ersetzen Sie diese durch Ihre eigenen Bestände.

Dies ist die Geschmacksrichtung, mit der dieses Projekt ausgeliefert wird, und es ist auch der Degradierungsmodus: Wenn die SoT (Source of Truth) ausfällt, versetzen zwei Variablen und ein Neustart eine Bereitstellung der Geschmacksrichtung A oder B hierher. Es lohnt sich, dies zu üben, bevor Sie es brauchen.

Der Preis dafür ist, dass die Datei veraltet. scripts/export_inventory.py im übergeordneten Repository generiert sie aus der SoT neu; führen Sie es regelmäßig aus. Ein Backup-Inventar mit Adressen von vor sechs Monaten ist schlimmer als gar kein Backup, weil Sie es erst während des Betriebs merken.

Was in allen drei gleich bleibt

Die Befehlsrichtlinie, das Prüfprotokoll (Audit Trail), die Seitenausgabe und die Werkzeugoberfläche ändern sich nicht zwischen den Geschmacksrichtungen. Die agentenseitige Schnittstelle ist identisch, weshalb die Fähigkeit (Skill) keine variante pro Geschmacksrichtung benötigt.

commands.yml ist empfohlen, nicht erforderlich

Der Server läuft auch ohne sie. Wenn die Datei fehlt, verweigert er nicht alles und startet nicht mit einer Fehlermeldung: Eine eingebaute Fallback-Liste von 16 schreibgeschützten Befehlen übernimmt – show version, show ip interface brief, display version und deren Junos/VRP-Äquivalente. Das ist bewusst so gewählt. Eine leere Richtlinie würde jeden Befehl verweigern, während der Server sich selbst als gesund meldet, was für einen Operator so aussieht, als hätte „das Gerät verweigert" statt „niemand hat eine Richtlinie geschrieben". Der Fallback wird beim Start angekündigt, netmiko.get_command_policy meldet policy_source: "fallback", und jeder protokollierte Versuch trägt die Quelle.

Die Datei ist also eine Richtlinienentscheidung, kein Installationsschritt: Der Fallback ermöglicht es Ihnen, den Server beim ersten Versuch zu starten, und Sie schreiben commands.yml, wenn Sie die eigene Richtlinie des Bestands statt einer konservativen Voreinstellung wünschen. Was Sie nicht tun können, ist eine Richtlinie zu haben, die Sie nicht gewählt haben, ohne es zu wissen – der Server sagt jedes Mal, welche in Kraft ist, wenn er gefragt wird.


Die .mcp.json-Datei

.mcp.json im Projektstamm deklariert die MCP-Server für dieses Projekt. Claude Code bittet um Zustimmung, wenn es die Datei zum ersten Mal sieht, und die Datei soll eingecheckt werden: So erhält das gesamte Team denselben Server.

Für dieselbe Serverdefinition gibt es zwei weitere Gültigkeitsbereiche:

Bereich

Speicherort

Wer sieht ihn

project

.mcp.json im Projektstamm

alle, die das Projekt öffnen (nach Zustimmung)

user

~/.claude.json

jedes Projekt dieses Benutzers, auf diesem Rechner

local

~/.claude.json, projektspezifisch

nur dieser Benutzer, nur in diesem Projekt

claude mcp add --scope project netmiko -- /pfad/zu/python /pfad/zu/server.py schreibt den project-Eintrag für Sie; das manuelle Bearbeiten der JSON ist gleichwertig.

Aufbau der Datei

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

Der Servername ist nicht nur kosmetisch: Claude Code stellt jedes Werkzeug als mcp__<server-name>__<tool-name> bereit. Mit dem Namen netmiko und dem Werkzeug netmiko.get_metadata, das der Server registriert, heißt das Werkzeug, das Claude tatsächlich sieht, mcp__netmiko__netmiko.get_metadata. Führen Sie /mcp aus, um die genauen Namen zu lesen, bevor Sie sie in eine allowed-tools-Liste oder eine Berechtigungsregel eintragen.

Feldreferenz

Feld

Transport

Bedeutung

type

beide

"stdio" (Standard, wenn weggelassen), "http" oder "sse"

command

stdio

Das auszuführende Programm. Absoluter Pfad – kein Arbeitsverzeichnis voraussetzen

args

stdio

Argumentliste, jedes Element getrennt

env

stdio

Umgebung für den Kindprozess. Wird über die geerbte Umgebung gelegt

url

http / sse

Vollständige Endpunkt-URL, inklusive Pfad

headers

http / sse

Zusätzliche Anforderungsheader, typischerweise Authorization

Werte unterstützen Umgebungserweiterung: ${VAR} und ${VAR:-default}. Nützlich, um einen Token aus der eingecheckten Datei herauszuhalten:

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

Transport 1 – stdio (der in diesem Projekt verwendete)

Claude Code startet den Server als Kindprozess und kommuniziert über seine stdin/stdout per JSON-RPC. Es lauscht nichts auf einem Port, nichts ist aus dem Netzwerk erreichbar, und die Prozesslebensdauer entspricht der Sitzung. Dies ist die richtige Voreinstellung für einen Server, der SSH-Anmeldeinformationen speichert.

{
  "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"
      }
    }
  }
}

Zwei Dinge, die Probleme bereiten:

  • Keine hartcodierten Pfade, und das Arbeitsverzeichnis ist nicht verlässlich. ${CLAUDE_PROJECT_DIR:-.} sorgt dafür, dass die Datei wie besehen eingecheckt werden kann; der nächste Abschnitt erzählt die ganze Geschichte, denn die offensichtliche Lesart ist falsch.

  • Der Server darf nicht auf stdout schreiben. stdout ist der Protokollkanal, und eine einzige falsche Zeile dort unterbricht die Sitzung. Protokollierung erfolgt auf stderr plus die rotierende Datei unter LOG_FILE (5 MB × 3, erstellt mit 0600 – bei DEBUG enthält diese Datei die Geräteausgabe). Innerhalb von Niko wird dieselbe Variable von MCPLogging behandelt.

Woher ${CLAUDE_PROJECT_DIR:-.} kommt

Zwei verschiedene Dinge in einer Zeichenkette: eine Syntax und eine Variable.

Die Syntax. ${VAR} und ${VAR:-default} ist die POSIX-Parametersubstitution ("verwende VAR; wenn es nicht gesetzt oder leer ist, verwende default"), aber es ist keine Shell beteiligt – eine JSON-Datei durchläuft nie eine. Claude Code implementiert die Erweiterung selbst, wenn es die Datei liest, in command, args, env, url und headers. Es ist eine Konvention dieses Clients, nicht Teil der MCP-Spezifikation: Ein anderer Client implementiert sie möglicherweise nicht (siehe Nicht-Claude-Agenten, wo die Pfade dann literal sein müssen), und VS Code hat seine eigene Schreibweise, ${workspaceFolder}.

Die Variable. CLAUDE_PROJECT_DIR wird von Claude Code auf das Projektstammverzeichnis gesetzt, denselben Wert, den Hooks erhalten. Sie ist stabil – das Gewähren zusätzlicher Arbeitsverzeichnisse während einer Sitzung mit --add-dir verschiebt sie nicht.

Der Teil, der kontraintuitiv ist, und der Grund, warum :-. nicht nur Dekoration ist: Claude Code setzt diese Variable in der Umgebung des gestarteten Servers, nicht in seiner eigenen. Die Erweiterung erfolgt jedoch vor dem Start, in der Umgebung von Claude Code – wo die Variable nicht existiert. Ein bloßes ${CLAUDE_PROJECT_DIR} würde daher zu nichts expandieren und /config/netmiko/inventory.yml hinterlassen, einen absoluten Pfad zum Wurzelverzeichnis des Dateisystems.

In einer projektspezifischen .mcp.json ist der Standardwert also kein Fallback für einen Randfall: es ist der Wert, der jedes Mal verwendet wird. Was im Prozess ankommt, ist ./config/netmiko/inventory.yml. Die einzige Ausnahme ist eine MCP-Konfiguration, die von einem Plugin bereitgestellt wird – dort ersetzt Claude Code die Variable direkt und es wird kein Standard benötigt.

Das zwingt dem Server die Hand auf. Ein relativer Wert würde gegen das Arbeitsverzeichnis des Kindprozesses aufgelöst, und das Arbeitsverzeichnis ist die Wahl des Clients, nicht des Projekts. Daher resolve_project_path(): Jede relative Pfadeinstellung wird an PARENT_DIR verankert – dem Elternverzeichnis von mcps/, derselben Wurzel, von der auch .env stammt – wenn die Einstellungen geladen werden. Eine Sitzung, die von irgendwo gestartet wird, findet config/netmiko/, und validate_startup() benennt die absolute Datei, wenn eine fehlt. Ein ~ bedeutet immer das Home-Verzeichnis des Operators, niemals eine Datei innerhalb des Projekts.

Die Variable ist dennoch nützlich, wie in der Dokumentation vorgesehen, wenn sie innerhalb des Servers gelesen wird (os.environ["CLAUDE_PROJECT_DIR"]), wo sie gesetzt ist. Dieser Server benötigt sie nicht: PARENT_DIR leitet sich von __file__ ab und hängt daher von keinem Client ab – derselbe Grund, warum der HTTP-Transport, bei dem niemand diese Variable setzt, keinen Sonderfall benötigt.

Quelle: Claude Code – MCP, Abschnitte Add a local stdio server und Environment variable expansion in .mcp.json.

Transport 2 – HTTP (streamable HTTP)

Claude Code unterstützt ihn, ebenso wie jeder andere MCP-Client. Es ist der Transport, der verwendet werden soll, wenn der Server woanders läuft: einem anderen Host, einem Container, einem Dienst, der von mehreren Agenten gemeinsam genutzt wird, oder einem Agenten, der nicht Claude ist.

Die Serverdatei ruft immer mcp.run(transport="stdio") unter ihrer __main__-Schutzbedingung auf, sodass HTTP stattdessen über die FastMCP-CLI bedient wird – keine Codeänderung:

.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/

Die NETMIKO_MCP_*-Variablen sind nicht mehr Teil der Client-Konfiguration: Der Serverprozess wird von Ihnen gestartet, daher gehören sie zu seiner Umgebung (ein Shell-Export, eine systemd-Unit, ein environment:-Block eines Containers).

Clientseite:

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

Oder äquivalent: claude mcp add --transport http netmiko http://127.0.0.1:8123/mcp/.

--transport sse und "type": "sse" funktionieren ebenfalls; SSE ist der ältere entfernte Transport und wird für Clients beibehalten, die noch nicht auf streamable HTTP umgestiegen sind.

Sicherheit. Die FastMCP-CLI stellt dies ohne Authentifizierung bereit: Jeder, der den Port erreicht, kann show-Befehle gegen jedes Gerät im Inventar ausführen, unter Verwendung der Anmeldeinformationen in der Serverumgebung. Binden Sie für einen lokalen Test an 127.0.0.1, und stellen Sie es für alles gemeinsam Genutzte hinter einen Reverse Proxy, der TLS terminiert und den Authorization-Header überprüft. Der headers-Block oben ist das, was der Client sendet; der Proxy muss es überprüfen.

Nicht-Claude-Agenten

Das hier gezeigte mcpServers-Objekt ist die De-facto-Form: Claude Code, Claude Desktop, Cursor und Windsurf lesen alle dieselben drei Felder für stdio (command / args / env) und dieselben zwei für entfernte Verbindungen (url / headers). Das Kopieren eines Eintrags zwischen ihnen funktioniert normalerweise ohne Änderungen.

Bekannte Unterschiede, die es wert sind, vor dem Kopieren überprüft zu werden:

  • VS Code verwendet mcp.json mit einem Schlüssel "servers" auf oberster Ebene statt "mcpServers", und es verlangt, dass "type" explizit angegeben wird.

  • Einige Clients implementieren keine ${VAR}-Erweiterung; dort muss der Wert literal sein, was ein Argument für den HTTP-Transport plus einen Proxy ist, anstatt einen Token in eine eingecheckte Datei einzufügen.

  • Ein Agent ohne Konfigurationsdatei kann dennoch direkt mit dem HTTP-Endpunkt sprechen – die URL und der Authorization-Header sind der gesamte Vertrag.

Der env-Block

Die NETMIKO_MCP_*-Einträge gewinnen gegenüber jeder YAML-Konfigurationsdatei. Sie werden explizit gesetzt, weil es außerhalb von Niko keine NikoPaths gibt, sodass die Standardwerte auf ~/commands.yml und ~/.netmiko_mcp_tmp zurückfallen.

Jeder Pfad hier kann relativ zum Projektstamm angegeben werden: Der Server verankert relative Werte beim Laden der Einstellungen in PARENT_DIR, sodass das Arbeitsverzeichnis des gestarteten Prozesses nie entscheidet, wo das Inventar oder das Prüfprotokoll liegt. Ein absoluter Pfad oder ein ~ wird so übernommen, wie er geschrieben ist.

Variable

Default

Zweck

NETMIKO_MCP_INVENTORY_TYPE

netmiko_tools

yaml (lokale Datei) oder fedele (SoT)

NETMIKO_MCP_INVENTORY_FILE

(Netmiko-Tools-Suche)

Inventarpfad, wenn der Typ yaml ist

NETMIKO_MCP_CREDENTIAL_SOURCE

env

env (liest die .env) oder fedele

NETMIKO_MCP_FEDELE_GROUP_SOURCE

tags

Was eine Gruppe definiert: tags, device_roles, sites

NETMIKO_MCP_FEDELE_DEVICE_FILTER

(keine)

Bereichsfilter, tag=lab&status=active. Ohne diesen: das gesamte Inventar

NETMIKO_MCP_FEDELE_CACHE_TTL

60

SoT-Auflösungs-Cache, in Sekunden

NETMIKO_MCP_COMMAND_FILE

~/commands.yml außerhalb von Niko

Erlaubnis-/Verbotsliste

NETMIKO_MCP_ALLOW_PIPE

false

Aktiviert Pipes in Befehlen

NETMIKO_MCP_SSH_CONFIG_FILE

(keine)

OpenSSH ssh_config. Erforderlich für Jumphosts – Netmiko liest ~/.ssh/config nicht von selbst

NETMIKO_MCP_MAX_WORKERS

10

Gleichzeitige Verbindungen bei Gruppenbefehlen

NETMIKO_MCP_SAVE_OUTPUT_DIR

~/.netmiko_mcp_tmp außerhalb von Niko

Puffer für große Ausgaben

NETMIKO_MCP_SAVE_THRESHOLD

1000

Zeilenanzahl, ab der die Ausgabe gespeichert statt inline zurückgegeben wird

NETMIKO_MCP_AUDIT_LOG_FILE

(siehe übergeordnete README)

Prüfpfad (JSON, Fail-Closed). Bitten Sie den Agenten, ihn mit netmiko.query_audit_trail zu lesen

NETMIKO_MCP_CONFIG

~/.netmiko-mcp.yml

Pfad zu einer YAML-Konfigurationsdatei, die dieselben Einstellungen enthält

LOG_FILE / LOG_LEVEL

Niko.log / INFO

Betriebsprotokoll: stderr immer, plus diese rotierende Datei (5 MB × 3, 0600). LOG_LEVEL wird mit seinem Standardwert angegeben, damit der Drehknopf dort ist, wo Sie ihn suchen – setzen Sie ihn auf DEBUG und die Geräteausgabe landet im Protokoll

Anmeldedaten werden hier nicht gesetzt. NETMIKO_USERNAME, NETMIKO_PASSWORD, NETMIKO_SECRET und die FEDELE_*-Variablen werden aus <Projektstamm>/.env gelesen, sodass sie niemals in einer committeten JSON-Datei landen. Rangfolge: Was im env-Block steht, gewinnt stillschweigend gegenüber der .env – definieren Sie jede Variable genau an einer Stelle.

Jede andere Variable ist in der README des übergeordneten Repositorys dokumentiert.

Überprüfen, ob es funktioniert

claude mcp list          # netmiko: ✓ connected

Innerhalb der Sitzung listet /mcp die Tools auf und /skills bestätigt, dass die Fähigkeit geladen wurde. Fragen Sie, welche Richtlinie in Kraft ist, und netmiko.get_command_policy gibt den Namen der Datei an, die gelesen wird – oder meldet "fallback", was bedeutet, dass die Datei nie gefunden wurde und die 16 integrierten Befehle ausgeführt werden.


Autor: Ed Scrimaglia edgardo.scrimaglia@gmail.com – letzte Aktualisierung: 18.08.2026.

A
license - permissive license
A
quality
B
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 Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides AI assistants with direct access to multi-vendor network devices for tasks like configuration management, health checks, and topology discovery through 35 specialized tools. It enables natural language control over platforms including Cisco, Juniper, and Nokia using SSH, NETCONF, and SNMP protocols.
    11
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to interact with Cisco IOS-XE network devices over SSH using structured tools. Provides read and write capabilities for network management with built-in validation and security.
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables read-only querying and diagnostics of Fortigate firewalls via SSH, providing security analysis, traffic monitoring, and configuration inspection through natural language.
    MIT

View all related MCP servers

Related MCP Connectors

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

  • Read-only CVE intelligence, remediation playbooks, and agent setup guides. Not a scanner.

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

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-sot_mcp'

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