pihole-mcp
Provides tools for interacting with Pi-hole v6/FTL via its REST API, including status and statistics, query logs, allow/deny entries, subscription lists, groups, clients, local DNS records, CNAME aliases, DHCP reservations, configuration management, and maintenance actions.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
pihole-mcp
MCP server for Pi-hole v6 (FTL), over its REST API. Runs in a hardened Docker container and exposes ~50 tools: status/stats, query log, allow/deny entries, subscribe lists, groups, clients, local DNS records, CNAME aliases, DHCP reservations, config, and maintenance actions.
Built from scratch rather than adopting a community server (the existing ones
were small and unaudited), with a focus on verified behavior: several things
the official docs describe do not match FTL 6.x, and were learned by reading
FTL's C source. Those findings are encoded in server.py and listed below.
Files
file | role |
| the MCP server (stdio) |
| python:3.14-slim, non-root, no version-specific data baked in |
| hardened stdio launcher (OpenCode-style |
| live end-to-end test: real MCP handshake + tool round-trips |
| the OpenAPI fragments as served by FTL 6.8 ( |
Related MCP server: Pi-hole MCP Server
Setup
Create an app password in the Pi-hole web UI (Settings → API / Web Interface). Store the plaintext at
~/.config/opencode/pihole.password(or pointPIHOLE_PASSWORD_FILEelsewhere), mode 600.Enable config writes if you want them: FTL refuses config changes from app-password sessions unless
webserver.api.app_sudois true (Settings → Advanced, orPATCH /api/configfrom a web-password session). Reads and list management work without it.Build and test:
docker build -t pihole-mcp:1.0.0 . PIHOLE_URL=http://<your-pihole> python3 test_smoke.pyRegister with your MCP client as a stdio/local server running
pihole-mcp-container.sh. Useful env for the launcher:PIHOLE_URL(defaulthttp://pi.hole),PIHOLE_READ_ONLY=1(all mutating tools refuse; reads keep working).
Auth model (FTL 6.x, verified against src/api/auth.c)
POST /api/auth {"password": <app-password>}→ session id.Carry it in the
X-FTL-SIDheader on every call. The header path skips the CSRF requirement that cookie auth imposes (cookie auth needs the token inX-CSRF-TOKEN-- the spec examples'X-CRSFis not read by FTL).Sessions idle out (default 30 min) and die when the password rotates; the server re-logs in once per 401 automatically.
The app-password session shows as
app: trueinGET /api/auth/sessions, separate from interactive web sessions.
Gotchas encoded in server.py
The domain block list is
denyin the URL space (/domains/deny/exact) even though the UI says "block". Adlists do useblock.GET /api/authreports a session valid without checking CSRF -- useless as an auth probe; only a real endpoint is an honest check.Local DNS records, CNAME aliases, and DHCP reservations are not dedicated endpoints: they are config string-arrays (
dns.hosts,dns.cnameRecords,dhcp.hosts) managed viaPUT/DELETE /config/{element}/{array}/{item}.dns.hostsapplies live; the other two carry FTL's restart flag.POST /domains/{type}/{kind}wants group ids; the tools resolve group names for you (list_groupsto discover).PUTon a config array item answers 201,DELETEanswers 204.Credential/2FA config keys (
webserver.api.pwhash,app_pwhash,totp_secret, ...) are refused byset_config/api_rawby design -- a chat misfire must not be able to lock the web UI.FTL hands real password hashes (
pwhash,app_pwhash) to any authenticated session in the config tree; every response this server returns passes through a redactor so those never enter the model's context.
Safety
PIHOLE_READ_ONLY=1makes every mutating tool refuse.api_rawreaches any endpoint except/auth*and teleporter (bulk config import is too sharp a knife for chat).The generic array-item tool refuses
webserver.*.The container:
--read-only,--cap-drop ALL,--security-opt no-new-privileges, pids/memory limits.The app password is never an env var or CLI arg (docker inspect leaks env): the launcher stages it on tmpfs and bind-mounts it read-only at
/run/secrets/pihole.password, removing it on exit.
Refreshing the spec snapshot
spec/ is what our FTL 6.8 serves at /api/docs/specs/*.yaml. If a tool
starts returning 400s after an FTL upgrade, re-download it and diff.
License
MIT. The spec/ directory contains the API documentation as distributed by
Pi-hole FTLDNS (c) Pi-hole LLC.
This server cannot be deployed
Maintenance
Related MCP Connectors
Query and update Teable records, manage tables, and access the Teable API with AI agents.
29 DNS, SEO, SSL, security, WHOIS & mail tools for AI agents. Pay per call (x402) or card API key.
Agent utility API: 28+ free endpoints (hash, QR, DNS, scrape, JWT...) run by an autonomous AI agent.
Read-only search of 2,189 AI agent tools (MCP servers, x402 APIs) with daily automated trust scores.
Related MCP Servers
- AlicenseAqualityDmaintenanceConnects AI assistants to Pi-hole network-wide ad blocker, enabling monitoring of DNS traffic statistics, controlling blocking settings, managing whitelist/blacklist domains, viewing query logs, and performing maintenance tasks through natural language.16120 npm8MIT
- FlicenseNot gradedqualityDmaintenanceEnables control of Pi-hole v6 ad blocking, allowing users to toggle DNS blocking status and retrieve real-time statistics like query counts and blocked domains. It provides a structured interface for monitoring and managing network-level ad filtering through the Pi-hole REST API.-
- AlicenseAqualityDmaintenanceEnables management of Pi-hole DNS servers through natural language commands, including enabling/disabling blocking, viewing statistics, and configuration.5MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to control Pi-hole DNS filtering, including domain management, query analysis, and system administration, with support for multiple Pi-hole instances and synchronization.11MIT