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_TOKENgesetzt 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:
| System | Wahrscheinlicher 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:
- Schreiben erlauben: Die Zeile
PIHOLE_READ_ONLY=trueaus der Config entfernen oder auffalsesetzen, Claude Desktop neu starten. - Nur Teile erlauben:
PIHOLE_TOOLSETSmit einer kommagetrennten Liste setzen, zum Beispieldashboard,domains. Beide Schalter lassen sich kombinieren, Read-only hat Vorrang. - 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:
| Bereich | Was Claude abfragen kann |
|---|---|
| Statistik | Zusammenfassung, Top-Clients, Top-Domains, Upstream-Antwortzeiten, Query-Typen |
| Query-Log | Suche nach Domain, Client, Status und Zeitraum, auch in der Langzeit-Datenbank |
| Listen und Regeln | Blocklisten, Allow- und Deny-Domains, Gruppen, Suche einer Domain über alle Listen |
| Konfiguration | die komplette Pi-hole-Konfiguration, nach Abschnitten |
| System und Diagnose | Versionen, FTL-Status, Last, Diagnosemeldungen, DNS-, FTL- und Webserver-Logs |
| Netzwerk | Geräte, Gateway, Interfaces, Routen, DHCP-Leases |
| Lokales DNS | A- und CNAME-Einträge |
| Backup | Teleporter-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:
- Claude Desktop liest JSON. Die Datei heißt
claude_desktop_config.json. Ein YAML-Eintrag wird nicht verstanden. - 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:-ihält die Eingabe offen,--rmrä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, obconfig.yamloderdocker-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 (
-ebeidocker 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:
| System | Pfad |
|---|---|
| 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
| Symptom | Ursache | Lösung |
|---|---|---|
| Beim Start „Unexpected non-whitespace character after JSON“ | Zweiter Block hinter dem Dateiende oder falsches Komma | Eintrag in das bestehende Objekt verschieben, danach Schritt 6 |
authentication failed: HTTP 401 | Passwort falsch, maskiert oder mit zusätzlichen Anführungszeichen | Neues App-Passwort erzeugen und die Zeile prüfen |
| Pi-hole-Tools fehlen | Docker läuft nicht oder die App wurde nicht ganz neu gestartet | docker ps prüfen, App beenden und neu starten |
| Keine Verbindung | Adresse, Port oder Firewall | Schritt 2 wiederholen, bei Docker Desktop alternativ http://host.docker.internal:8080 versuchen |
| Fehler zur Plattform (Apple Silicon) | Image-Architektur passt nicht | Nach "--rm", die Einträge "--platform", "linux/amd64", ergänzen |
Quellen
- hexamatic/pihole-mcp, Projektseite mit Konfiguration und Tools
- Pihole-mcp von lloydmcl, Pi-hole Forum
- Python MCP Server for Pi-hole von sbarbett, Pi-hole Forum

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 🙏
#PiHole #MCP #SelfHosted #Docker #Claude