{"id":49416464,"url":"https://github.com/chris2ao/pihole-mcp","last_synced_at":"2026-04-29T03:10:41.109Z","repository":{"id":352327717,"uuid":"1214730512","full_name":"chris2ao/pihole-mcp","owner":"chris2ao","description":"Consolidated Pi-hole v6 MCP server (FastMCP + httpx). Unifies tools from three upstream Pi-hole MCPs.","archived":false,"fork":false,"pushed_at":"2026-04-19T01:23:33.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-19T03:28:06.506Z","etag":null,"topics":["ad-blocking","anthropic","claude-code","dns","fastmcp","home-automation","httpx","mcp","model-context-protocol","pihole","pihole-v6","pydantic","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chris2ao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T01:05:32.000Z","updated_at":"2026-04-19T01:23:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chris2ao/pihole-mcp","commit_stats":null,"previous_names":["chris2ao/pihole-mcp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/chris2ao/pihole-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris2ao%2Fpihole-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris2ao%2Fpihole-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris2ao%2Fpihole-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris2ao%2Fpihole-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chris2ao","download_url":"https://codeload.github.com/chris2ao/pihole-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chris2ao%2Fpihole-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32408546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T02:37:21.628Z","status":"ssl_error","status_checked_at":"2026-04-29T02:36:50.947Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ad-blocking","anthropic","claude-code","dns","fastmcp","home-automation","httpx","mcp","model-context-protocol","pihole","pihole-v6","pydantic","python"],"created_at":"2026-04-29T03:10:40.004Z","updated_at":"2026-04-29T03:10:41.101Z","avatar_url":"https://github.com/chris2ao.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pihole-mcp\n\n[![test](https://github.com/chris2ao/pihole-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/chris2ao/pihole-mcp/actions/workflows/test.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Python](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)\n[![MCP](https://img.shields.io/badge/MCP-compatible-6E56CF.svg)](https://modelcontextprotocol.io/)\n[![Pi-hole v6](https://img.shields.io/badge/Pi--hole-v6-96060C.svg)](https://docs.pi-hole.net/)\n\nUnified 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).\n\n## Tools (28)\n\nStats (8): `get_stats`, `get_top_blocked`, `get_top_permitted`, `get_top_clients`, `get_query_types`, `get_forward_destinations`, `get_recent_blocked`, `get_history`\n\nQueries (2): `get_query_log` (rich filters: time range, domain, client, upstream, cursor), `get_query_suggestions`\n\nBlocking (3): `get_blocking_status`, `enable_blocking`, `disable_blocking` (with optional timer)\n\nDomain lists (6): `get_whitelist`, `get_blacklist`, `add_to_whitelist`, `add_to_blacklist`, `remove_from_whitelist`, `remove_from_blacklist`\n\nLocal DNS (5): `list_local_dns`, `add_local_a_record`, `remove_local_a_record`, `add_local_cname_record`, `remove_local_cname_record`\n\nMaintenance (4): `update_gravity`, `flush_cache`, `flush_logs`, `get_tail_log`\n\nPlus `server_info`.\n\nSee `docs/plans/consolidated-tool-map.md` for per-tool endpoint mapping.\n\n## Auth\n\nPi-hole v6 uses session-based auth. This server handles it automatically:\n\n1. `POST /api/auth` with `{\"password\": \"\u003capp-password\u003e\"}` returns a session SID.\n2. All subsequent calls include `X-FTL-SID: \u003csid\u003e`.\n3. On 401 or near-expiry, the client re-authenticates and retries once.\n4. On shutdown, `DELETE /api/auth` releases the session.\n\n**App password** is created in the Pi-hole Web UI: Settings \u003e Web Interface \u003e \"Application password\" \u003e Generate. This is separate from the main admin web password and is the correct credential for API clients.\n\n## Install\n\n```bash\ncd /Users/chris2ao/GitProjects/chris2ao-pihole-mcp\nuv sync\ncp .env.example .env   # fill in PIHOLE_URL and PIHOLE_PASSWORD\nuv run pytest\n```\n\nOr via the wrapper (production use with Claude Code):\n\n```bash\n~/.claude/scripts/pihole-wrapper.sh\n```\n\n## Register with Claude Code\n\nIn `~/.claude.json`, add to `mcpServers`:\n\n```json\n\"pihole\": {\n  \"command\": \"/Users/chris2ao/.claude/scripts/pihole-wrapper.sh\",\n  \"args\": []\n}\n```\n\nThe wrapper sources `~/.claude/secrets/secrets.env` for `PIHOLE_URL` and `PIHOLE_PASSWORD`, then invokes `uv run`.\n\n## Development\n\n- Run tests: `uv run pytest`\n- Coverage: `uv run pytest --cov --cov-report=term`\n- Python: 3.12+\n\n## Relation to chris2ao-unifi-mcp\n\nSame stack (FastMCP, httpx, Pydantic-settings, hatchling, uv). Simpler than unifi-mcp because Pi-hole is a single product (no dynamic product loading or discovery). If you extend this for multi-Pi-hole or for the gap items (adlist/gravity CRUD, groups, DHCP, Teleporter), follow the unifi-mcp module-per-capability pattern.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris2ao%2Fpihole-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchris2ao%2Fpihole-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchris2ao%2Fpihole-mcp/lists"}