mcp server
pihole-mcp
Consolidated Pi-hole v6 MCP server (FastMCP + httpx). Unifies tools from three upstream Pi-hole MCPs.
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
{
"mcpServers": {
"chris2ao-pihole-mcp": {
"command": "uvx",
"args": [
"chris2ao-pihole-mcp"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 26, 2026pihole-mcp
Unified Pi-hole v6 MCP server. Consolidates the useful tools from three upstream MCPs (aplaceforallmystuff/mcp-pihole, sbarbett/pihole-mcp-server, cwdcwd/mcp-server-pihole) into one Python server that matches the chris2ao-unifi-mcp stack (FastMCP + httpx + Pydantic v2).
Tools (72)
Stats (9): get_stats, get_top_blocked, get_top_permitted, get_top_clients, get_query_types, get_forward_destinations, get_recent_blocked, get_history, get_client_history. Pass from_ts and until_ts to any of them (except get_recent_blocked) to query the long-term database for any time range.
Queries (2): get_query_log (filters: time range, domain, client IP or name, upstream, query type, status, reply, DNSSEC, paging, disk for the long-term database), get_query_suggestions
Search (1): search_domain explains why a domain is blocked or allowed (matching lists, regexes, adlists, groups)
Blocking (3): get_blocking_status, enable_blocking, disable_blocking (with optional timer)
Domain lists (10): list_domains, add_domain, update_domain, remove_domain (allow/deny, exact/regex, groups, comments), plus the legacy exact-match get_whitelist, get_blacklist, add_to_whitelist, add_to_blacklist, remove_from_whitelist, remove_from_blacklist
Adlists (4): list_adlists, add_adlist, update_adlist, remove_adlist
Groups and clients (9): list_groups, add_group, update_group, remove_group, list_clients, get_client_suggestions, add_client, update_client, remove_client
Local DNS (5): list_local_dns, add_local_a_record, remove_local_a_record, add_local_cname_record, remove_local_cname_record
System info (10): get_version, get_system_info, get_host_info, get_sensors, get_ftl_info, get_database_info, get_metrics, get_messages, delete_message, get_padd
Network and DHCP (7): list_network_devices, delete_network_device, get_gateway, get_routes, get_interfaces, list_dhcp_leases, remove_dhcp_lease
Settings (4): get_config, update_config, add_config_item, remove_config_item
Maintenance (8): update_gravity, flush_cache, restart_dns, flush_logs, flush_arp, flush_network, get_tail_log, export_teleporter
Plus server_info.
Safety
- Disruptive or destructive tools return a preview and change nothing unless called with
confirm=true:update_config,add_config_item,remove_config_item,restart_dns,flush_arp,flush_network,remove_adlist,remove_group,delete_network_device,remove_dhcp_lease. get_configredacts password hashes and the TOTP secret. The settings tools refuse any change underwebserver.api(authentication settings).export_teleporterwrites the backup zip to a directory you name and never overwrites a file. The archive includes the password hash, so store it securely. Teleporter import is deliberately not exposed.
Auth
Pi-hole v6 uses session-based auth. This server handles it automatically:
POST /api/authwith{"password": "<app-password>"}returns a session SID.- All subsequent calls include
X-FTL-SID: <sid>. - On 401 or near-expiry, the client re-authenticates and retries once.
- On shutdown,
DELETE /api/authreleases the session.
App password is created in the Pi-hole Web UI: Settings > Web Interface > "Application password" > Generate. This is separate from the main admin web password and is the correct credential for API clients. App passwords also bypass two-factor (TOTP) login, which this server does not implement.
Install
cd /Users/chris2ao/GitProjects/chris2ao-pihole-mcp
uv sync
cp .env.example .env # fill in PIHOLE_URL and PIHOLE_PASSWORD
uv run pytest
Or via the wrapper (production use with Claude Code):
~/.claude/scripts/pihole-wrapper.sh
Register with Claude Code
In ~/.claude.json, add to mcpServers:
"pihole": {
"command": "/Users/chris2ao/.claude/scripts/pihole-wrapper.sh",
"args": []
}
The wrapper sources ~/.claude/secrets/secrets.env for PIHOLE_URL and PIHOLE_PASSWORD, then invokes uv run.
Development
- Run tests:
uv run pytest - Coverage:
uv run pytest --cov --cov-report=term - Python: 3.12+
Relation to chris2ao-unifi-mcp
Same stack (FastMCP, httpx, Pydantic-settings, hatchling, uv) and the same module-per-capability layout under src/pihole_mcp/tools/. Simpler than unifi-mcp because Pi-hole is a single product (no dynamic product loading or discovery).
See CHANGELOG.md for release notes.