Du betrachtest gerade MCP für Pi-Hole

MCP für Pi-Hole

Mit einem lokalen MCP für Pi-Hole im Docker-Container kann Claude meinen Pi-hole im Heimnetz auslesen, ohne dass der DNS-Server ins Internet muss.

Warum dieser Weg

Für Pi-hole gibt es keinen fertigen Connector im Claude-Verzeichnis, aber mehrere Community-Server für die Pi-hole-v6-API. Ich nutze hexamatic/pihole-mcp: ein Docker-Image mit breiter API-Abdeckung (laut Projektseite 76 Tools), einem Nur-Lesen-Schalter und einem Filter für Toolsets.

Drei Vorgaben haben den Weg bestimmt:

  • Nichts ins Internet. Ein DNS-Server mit Admin-Zugang ist zu sensibel für Tunnel oder HTTPS-Weitergabe. Wer schreiben darf, kann Domains umleiten oder das Blocking abschalten. Also nur HTTP im eigenen LAN.
  • Kein zusätzlicher Installer. Docker muss installiert sein und laufen. Das Image wird beim ersten Start geladen, der Container nach jeder Sitzung wieder entfernt.
  • Sicher starten. Zuerst nur lesen, schreiben erst, wenn alles läuft.

Voraussetzung ist Pi-hole v6, denn nur dort gibt es die REST-API mit App-Passwörtern. Die Version steht im Web-UI ganz unten.

Video: MCP für Pi-Hole

Sprache: 🇩🇪|🇬🇧
☝️ Benutze YouTube Untertitel für alle Sprachen.

Warum der MCP-Server lokal und in Docker laufen muss

Claude Desktop startet den Server als lokalen Prozess und spricht über Standard-Ein- und Ausgabe (stdio) mit ihm. Das hat drei Folgen:

  • Der Rechner mit Claude Desktop braucht Docker. Er startet den Container selbst, sobald Claude ihn braucht. Eine reine Browser-Sitzung kann keinen lokalen Container starten.
  • Der Server muss im Netz des Pi-hole laufen. Der Pi-hole hat eine private Adresse wie 192.168.1.10. Aus dem Internet oder der Cloud ist er nicht erreichbar, und das soll so bleiben.
  • Es gibt keinen offenen Port. Der Server kann auch per HTTP oder SSE laufen, dann aber ohne Anmeldung, solange kein PIHOLE_HTTP_AUTH_TOKEN gesetzt ist. Die Projektseite warnt davor, diese Transporte über Loopback hinaus freizugeben. Mit stdio stellt sich die Frage nicht.

Docker bringt dazu überall dasselbe Verhalten: gleiche Config auf Windows, macOS und Linux, keine Abhängigkeiten auf dem Rechner, Update per neuem Image.

Read-only und Schreibzugriff

In meiner Config steht PIHOLE_READ_ONLY=true.

Die Datei claude_desktop_config.json liegt wahrscheinlich hier:

SystemWahrscheinlicher Pfad
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
Linux~/.config/Claude/claude_desktop_config.json

Für Linux gibt es keine offizielle Claude-Desktop-App. Bei inoffiziellen Builds liegt die Datei meist unter diesem Pfad. Am sichersten öffnest du sie in der App über Einstellungen → Entwickler → Konfiguration bearbeiten.

So schaltest du um:

  1. Schreiben erlauben: Die Zeile PIHOLE_READ_ONLY=true aus der Config entfernen oder auf false setzen, Claude Desktop neu starten.
  2. Nur Teile erlauben: PIHOLE_TOOLSETS mit einer kommagetrennten Liste setzen, zum Beispiel dashboard,domains. Beide Schalter lassen sich kombinieren, Read-only hat Vorrang.
  3. Vorher sichern: Ein Teleporter-Backup des Pi-hole anlegen. Der Export braucht einen eingebundenen Ordner (-v /pfad/auf/dem/rechner:/backups), sonst geht die Datei mit dem Container verloren.

Eine zweite Bremse sitzt im Pi-hole selbst: Laut Pi-hole-Dokumentation darf ein App-Passwort keine Konfigurationseinstellungen ändern, solange webserver.api.app_sudo auf false steht (Standard). Das ist für den Start gut. Für Konfigurationsänderungen müsstest du den Wert bewusst auf true setzen.

Nutze ein eigenes App-Passwort für den MCP-Server, nicht das Admin-Passwort. Es steht im Klartext in der lokalen Config, lässt sich aber im Pi-hole-Web-UI jederzeit widerrufen.

Leistungsumfang

Im Nur-Lesen-Modus stehen diese Bereiche zur Verfügung:

BereichWas Claude abfragen kann
StatistikZusammenfassung, Top-Clients, Top-Domains, Upstream-Antwortzeiten, Query-Typen
Query-LogSuche nach Domain, Client, Status und Zeitraum, auch in der Langzeit-Datenbank
Listen und RegelnBlocklisten, Allow- und Deny-Domains, Gruppen, Suche einer Domain über alle Listen
Konfigurationdie komplette Pi-hole-Konfiguration, nach Abschnitten
System und DiagnoseVersionen, FTL-Status, Last, Diagnosemeldungen, DNS-, FTL- und Webserver-Logs
NetzwerkGeräte, Gateway, Interfaces, Routen, DHCP-Leases
Lokales DNSA- und CNAME-Einträge
BackupTeleporter-Export

Ohne Read-only kommen laut Projektbeschreibung schreibende Tools dazu, etwa für Blocking an und aus, Domains und Listen, Gravity-Update und lokale DNS-Einträge. Mehrere Pi-holes lassen sich über nummerierte Variablen (PIHOLE_1_URL, PIHOLE_2_URL) anbinden.

Typische Fragen

  • „Zeig mir den Pi-hole-Status.“
  • „Welche Geräte fragen am meisten an?“
  • „Warum wird diese Domain blockiert?“
  • „Prüfe meine Regex-Regeln auf Fehler.“

Warum YAML hier nicht funktioniert

Pi-hole selbst läuft bei mir per docker-compose.yml. Das ist YAML, und dort gehört es auch hin. Den MCP-Server trage ich dort bewusst nicht ein:

  1. Claude Desktop liest JSON. Die Datei heißt claude_desktop_config.json. Ein YAML-Eintrag wird nicht verstanden.
  2. Ein stdio-Server ist ein Kindprozess des Clients. Claude startet ihn und hält Ein- und Ausgabe offen. Ein Compose-Dienst startet dagegen unabhängig im Hintergrund und läuft weiter, wenn Claude geschlossen ist. Claude könnte sich dann nicht mit ihm unterhalten. Darum steht in der JSON-Config docker run -i --rm: -i hält die Eingabe offen, --rm räumt den Container nach der Sitzung auf.

Compose wäre erst sinnvoll, wenn der Server als dauerhafter HTTP-Dienst laufen soll. Das erfordert Token und Absicherung und war nicht mein Ziel.

Wer den Server wie andere Dienste über eine YAML-Datei einrichten will, schreibt zum Beispiel eine config.yaml. Das Beispiel zeigt, wie es nicht funktioniert (anonymisiert):

# config.yaml (so funktioniert es nicht)
mcpServers:
  pihole:
    command: docker
    args:
      - run
      - -i
      - --rm
      - -e
      - PIHOLE_URL=http://192.168.1.10:8080
      - -e
      - PIHOLE_PASSWORD=<APP-PASSWORT>
      - -e
      - PIHOLE_READ_ONLY=true
      - ghcr.io/hexamatic/pihole-mcp:latest

Warum weder config.yaml noch docker-compose.yml mit MCP funktionieren:

  • Der Client liest nur seine eigene Datei. Claude Desktop lädt ausschließlich claude_desktop_config.json. Andere Dateien, ob config.yaml oder docker-compose.yml, werden weder gesucht noch eingelesen.
  • Der Server wird nicht über eine Datei konfiguriert. Nach der Projektseite bekommt er URL, Passwort und Schalter als Umgebungsvariablen (-e bei docker run) und Startparameter. Eine YAML-Datei würde er nicht auswerten.
  • Eine Compose-Datei startet den Container unabhängig vom Client. Sie legt fest, wie ein Dienst im Hintergrund läuft, verbindet ihn aber nicht mit Claude. Die Verbindung entsteht nur, wenn Claude den Prozess selbst startet und über stdio mit ihm spricht.

Der MCP-Eintrag gehört deshalb immer in die JSON-Datei des Clients. Alles, was der Server sonst braucht, übergibst du dort als -e-Variablen.

Typische JSON-Stolpersteine in der Claude-Config:

  • Es darf nur ein Objekt auf oberster Ebene geben. Ein zweiter Block hinter dem Dateiende führt zu „Unexpected non-whitespace character after JSON“ und die App startet ohne ihre Einstellungen.
  • Keine Kommentare und kein Komma nach dem letzten Eintrag.
  • Jeder Text steht in doppelten Anführungszeichen, auch PIHOLE_PASSWORD=... als Ganzes. Das Passwort steht nach dem = ohne weitere Anführungszeichen.

Einrichtung Schritt für Schritt

In den Beispielen läuft der Pi-hole unter http://192.168.1.10:8080. Passe Adresse und Port an dein Setup an. Voraussetzungen: Pi-hole v6, Docker Desktop und Claude Desktop auf einem Rechner, der den Pi-hole im Netz erreicht.

1. App-Passwort anlegen

Im Pi-hole-Web-UI: Settings → Web interface / API → Configure app password. Das Passwort wird nur einmal angezeigt. Kopiere es, aber gib es nicht weiter, auch nicht in einen Chat.

2. Erreichbarkeit testen

curl -I http://192.168.1.10:8080/admin/login

Unter Windows in der PowerShell curl.exe -I ... verwenden. Antwortet der Server mit 200 oder 302, stimmt die Adresse. Sonst prüfe Port, Firewall und Netz.

3. Docker prüfen und Image laden

docker ps
docker pull ghcr.io/hexamatic/pihole-mcp:latest

Der Pull ist optional. Docker lädt das Image sonst beim ersten Start.

4. Config-Datei öffnen

Am einfachsten in Claude Desktop über Einstellungen → Entwickler → Konfiguration bearbeiten. Die App legt die Datei an. Von Hand liegt sie hier:

SystemPfad
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json

Im macOS-Terminal muss der Pfad in Anführungszeichen stehen, weil er ein Leerzeichen enthält. Mache vor der Änderung eine Sicherungskopie.

5. Eintrag einfügen

Die Datei ist neu oder leer. Dann sieht die ganze Datei so aus:

{
  "mcpServers": {
    "pihole": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "PIHOLE_URL=http://192.168.1.10:8080",
        "-e", "PIHOLE_PASSWORD=<APP-PASSWORT>",
        "-e", "PIHOLE_READ_ONLY=true",
        "-e", "TZ=Europe/Berlin",
        "ghcr.io/hexamatic/pihole-mcp:latest"
      ]
    }
  }
}

Ersetze <APP-PASSWORT> samt den spitzen Klammern durch dein App-Passwort.

Die Datei hat schon Inhalt. Dann kommt mcpServers als zusätzlicher Eintrag in das bestehende Objekt, mit einem Komma davor. Hänge nie einen zweiten Block hinter das Dateiende:

{
  "preferences": {
    "sidebarMode": "chat"
  },
  "mcpServers": {
    "pihole": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "PIHOLE_URL=http://192.168.1.10:8080",
        "-e", "PIHOLE_PASSWORD=<APP-PASSWORT>",
        "-e", "PIHOLE_READ_ONLY=true",
        "-e", "TZ=Europe/Berlin",
        "ghcr.io/hexamatic/pihole-mcp:latest"
      ]
    }
  }
}

Gibt es mcpServers schon, fügst du nur den Block "pihole": { ... } mit Komma darin ein. Der Block preferencessteht hier nur als Platzhalter für deine bestehenden Einstellungen.

6. JSON prüfen

macOS und Linux:

python3 -m json.tool "$HOME/Library/Application Support/Claude/claude_desktop_config.json" > /dev/null && echo OK

Windows (PowerShell):

Get-Content "$env:APPDATA\Claude\claude_desktop_config.json" -Raw | ConvertFrom-Json | Out-Null

Bei OK beziehungsweise ohne Fehlermeldung ist die Datei gültig. Sonst zeigt die Meldung die Fehlerstelle.

7. Claude Desktop neu starten

Beende die App komplett: auf macOS mit Cmd+Q, unter Windows über das Symbol im Infobereich. Das Schließen des Fensters reicht nicht. Danach neu öffnen.

8. Testen

Frag Claude: „Zeig mir den Pi-hole-Status.“ Erwartet werden die Versionen von Core, FTL und Web, der Blocking-Status und die Zahl der Anfragen.

9. Optional: Schreibzugriff

Erst nach einigen Tagen im Nur-Lesen-Modus und mit Backup, wie im Abschnitt zu Read-only beschrieben.

Fehlersuche

SymptomUrsacheLösung
Beim Start „Unexpected non-whitespace character after JSON“Zweiter Block hinter dem Dateiende oder falsches KommaEintrag in das bestehende Objekt verschieben, danach Schritt 6
authentication failed: HTTP 401Passwort falsch, maskiert oder mit zusätzlichen AnführungszeichenNeues App-Passwort erzeugen und die Zeile prüfen
Pi-hole-Tools fehlenDocker läuft nicht oder die App wurde nicht ganz neu gestartetdocker ps prüfen, App beenden und neu starten
Keine VerbindungAdresse, Port oder FirewallSchritt 2 wiederholen, bei Docker Desktop alternativ http://host.docker.internal:8080 versuchen
Fehler zur Plattform (Apple Silicon)Image-Architektur passt nichtNach "--rm", die Einträge "--platform", "linux/amd64", ergänzen

Quellen


Spenden Bild

Link zur Unterstützung / Spende für den Kanal
Wenn meine Beiträge hilfreich sind oder dir geholfen haben, würde ich mich über eine Unterstützung sehr freuen 🙏

PayPal Link
Überweisung, Bitcoin und Lightning


#PiHole #MCP #SelfHosted #Docker #Claude

Schreibe einen Kommentar