{
  "markdown": "<div align=\"center\">\n\n<img src=\"assets/logo.svg\" width=\"120\" alt=\"pihole-mcp\">\n\n# pihole-mcp\n\nA production-grade [MCP](https://modelcontextprotocol.io/) server for [Pi-hole](https://pi-hole.net/) v6.\n\n**76+ tools** | **9 prompts** | **5 resources** | Multi-instance + sync | Single Go binary | 6.4 MB download (slim: 3.8 MB)\n\n[![CI](https://github.com/hexamatic/pihole-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/hexamatic/pihole-mcp/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/hexamatic/pihole-mcp/graph/badge.svg)](https://codecov.io/gh/hexamatic/pihole-mcp)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/hexamatic/pihole-mcp/badge)](https://scorecard.dev/viewer/?uri=github.com/hexamatic/pihole-mcp)\n[![Go Reference](https://pkg.go.dev/badge/github.com/hexamatic/pihole-mcp.svg)](https://pkg.go.dev/github.com/hexamatic/pihole-mcp)\n[![Licence: MIT](https://img.shields.io/badge/licence-MIT-blue.svg)](LICENSE)\n\n</div>\n\nGives AI assistants full control over your Pi-hole instance — DNS blocking, domain management, query analysis, statistics, network devices, DHCP, and system administration. Compatible with the Pi-hole v6 REST API.\n\n## Quick Start\n\nMost MCP clients use the same configuration format. Add this to your client's config:\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\nThen install the binary via one of the methods below.\n\n## Installation\n\n### MCP Registry\n\npihole-mcp is listed in the [official MCP Registry](https://registry.modelcontextprotocol.io/) as:\n\n```\nio.github.hexamatic/pihole-mcp\n```\n\nClients that support registry install can add it by that name and will prompt for\n`PIHOLE_URL` and `PIHOLE_PASSWORD`. The listing points at the `ghcr.io` image, so the\nclient needs a working Docker.\n\n### Homebrew\n\n```bash\nbrew install hexamatic/tap/pihole-mcp\n```\n\nInstalls on both macOS and Linux (Homebrew on Linux). On macOS the cask clears the\nquarantine attribute during install, so the binary runs without a Gatekeeper prompt.\n\n### Scoop (Windows)\n\n```powershell\nscoop bucket add hexamatic https://github.com/hexamatic/scoop-bucket\nscoop install pihole-mcp\n```\n\n### Go Install\n\n```bash\ngo install github.com/hexamatic/pihole-mcp/cmd/pihole-mcp@latest\n```\n\n### Docker\n\n```bash\ndocker pull ghcr.io/hexamatic/pihole-mcp:latest\n```\n\n### Linux Packages\n\n`.deb` and `.rpm` packages for Debian-based (Ubuntu, Raspberry Pi OS) and RPM-based (Fedora, RHEL) distributions are available on the [Releases](https://github.com/hexamatic/pihole-mcp/releases) page.\n\n```bash\n# Debian / Ubuntu / Raspberry Pi OS\nsudo dpkg -i pihole-mcp_X.Y.Z_linux_amd64.deb\n\n# Fedora / RHEL / CentOS\nsudo rpm -i pihole-mcp_X.Y.Z_linux_amd64.rpm\n```\n\n### Binary Download\n\nPre-built binaries for Linux, macOS, and Windows (amd64 and arm64) are available on the [Releases](https://github.com/hexamatic/pihole-mcp/releases) page.\n\nReleases are checksummed, signed with keyless cosign, and ship SPDX SBOMs and SLSA build provenance — see [SECURITY.md](SECURITY.md#verifying-release-artefacts) for the verification commands.\n\n## Configuration\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `PIHOLE_URL` | Yes | — | Pi-hole base URL (e.g. `http://192.168.1.2`) |\n| `PIHOLE_PASSWORD` | Yes | — | Admin password or [application password](https://docs.pi-hole.net/api/auth/) |\n| `PIHOLE_REQUEST_TIMEOUT` | No | `30s` | HTTP request timeout |\n| `PIHOLE_MAX_RETRIES` | No | `3` | Retries after a failed Pi-hole API call. `0` disables. |\n| `PIHOLE_RETRY_MAX_DELAY` | No | `8s` | Upper bound on a single backoff wait. |\n| `PIHOLE_RATE_LIMIT` | No | `120` | Per-session requests-per-minute cap on the HTTP/SSE transports. `0` disables. |\n| `PIHOLE_ALLOWED_ORIGINS` | No | `localhost,127.0.0.1,[::1]` | Comma-separated Origin/Host allowlist for HTTP/SSE transports. The literal `*` disables enforcement (unsafe). |\n| `PIHOLE_TLS_SKIP_VERIFY` | No | `false` | Disable TLS certificate verification for Pi-hole connections. Only for instances serving self-signed certificates — prefer a trusted certificate where possible. |\n| `TZ` | No | System timezone (UTC in Docker) | IANA timezone for rendered timestamps (e.g. `Australia/Adelaide`). Timezone data is embedded in the binary, so this works in the Docker image out of the box. |\n| `OTEL_EXPORTER_OTLP_ENDPOINT` | No | — | OpenTelemetry collector endpoint. Setting it enables tracing; ignored in slim builds. |\n\nApplication passwords are recommended for automation — they bypass TOTP 2FA and can be revoked independently.\n\n`PIHOLE_RATE_LIMIT` and `PIHOLE_ALLOWED_ORIGINS` only apply to the `http` and `sse` transports; stdio is a single-process, single-user channel by definition and isn't gated.\n\n### Multiple instances\n\nTo manage more than one Pi-hole, configure numbered instances instead of `PIHOLE_URL`/`PIHOLE_PASSWORD`:\n\n| Variable | Required | Description |\n|----------|----------|-------------|\n| `PIHOLE_1_URL`, `PIHOLE_2_URL`, … | Yes | Base URL of each instance (contiguous from 1) |\n| `PIHOLE_1_PASSWORD`, `PIHOLE_2_PASSWORD`, … | Yes | Password for the matching instance |\n| `PIHOLE_1_NAME`, `PIHOLE_2_NAME`, … | No | Friendly name (default `instance-1`, `instance-2`, …) |\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_1_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_1_PASSWORD\": \"primary-password\",\n        \"PIHOLE_1_NAME\": \"downstairs\",\n        \"PIHOLE_2_URL\": \"http://192.168.1.3\",\n        \"PIHOLE_2_PASSWORD\": \"secondary-password\",\n        \"PIHOLE_2_NAME\": \"upstairs\"\n      }\n    }\n  }\n}\n```\n\nEvery tool then accepts an optional `instance` argument, and every result is labelled with the instance it came from. Omit the argument to target the first instance; pass a name to target a specific one; pass `instance=all` on a read-only tool (e.g. `pihole_padd`, `pihole_stats_summary`) to query every instance concurrently and get back a single structured aggregate (per-instance results plus a success/failure summary — one slow or unreachable instance no longer fails the whole call). State-changing tools require a single named instance. `PIHOLE_URL` and `PIHOLE_1_URL` are mutually exclusive.\n\n### Keeping instances in sync\n\nWhen you run more than one Pi-hole, two extra tools appear for keeping them aligned:\n\n- **`pihole_instance_diff`** — compare two instances and see exactly what differs across adlists/allowlists, allow/deny rules (exact and regex), groups, clients, local DNS A/AAAA records, and CNAME records. It is read-only and writes nothing.\n- **`pihole_instance_sync`** — push a source instance's configuration onto a target. It is deliberately cautious:\n  - **One direction only.** You name the `source` of truth and the `target`; only the target is ever written to.\n  - **Dry-run first.** It returns a plan and a `confirm_token` by default; nothing changes until you re-run with `mode=apply` and that token. If the configuration drifts between planning and applying, the token no longer matches and the apply is refused.\n  - **Add/update by default.** Entries on the target but not the source are left alone unless you pass `prune=true`.\n  - **Backed up.** A teleporter backup of the target is taken before any change (disable with `snapshot=false`).\n  - **Safe by omission.** Host-specific and identity settings — DHCP, interface bindings, passwords, TLS certificates, sessions, 2FA — are never synced. Group *membership* associations are not synced either, because Pi-hole group IDs are local to each instance.\n\nExample: preview what the `upstairs` Pi-hole is missing relative to `downstairs`, then apply it.\n\n```text\npihole_instance_diff   { \"source\": \"downstairs\", \"target\": \"upstairs\" }\npihole_instance_sync   { \"source\": \"downstairs\", \"target\": \"upstairs\" }            → returns a plan + confirm_token\npihole_instance_sync   { \"source\": \"downstairs\", \"target\": \"upstairs\",\n                         \"mode\": \"apply\", \"confirm_token\": \"<token from the plan>\" }\n```\n\n## Client Setup\n\nThe Quick Start config above works for most clients. Expand the section below for client-specific instructions.\n\n<details>\n<summary><strong>Claude Desktop</strong></summary>\n\nAdd to your Claude Desktop configuration file:\n\n| OS | Path |\n|----|------|\n| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n| Windows | `%APPDATA%\\Claude\\claude_desktop_config.json` |\n| Linux | `~/.config/Claude/claude_desktop_config.json` |\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\nRestart Claude Desktop after saving.\n\n</details>\n\n<details>\n<summary><strong>Claude Code</strong></summary>\n\n```bash\nclaude mcp add pihole \\\n  -e PIHOLE_URL=http://192.168.1.2 \\\n  -e PIHOLE_PASSWORD=your-password \\\n  -- pihole-mcp\n```\n\nVerify with:\n\n```bash\nclaude mcp list\n```\n\n</details>\n\n<details>\n<summary><strong>VS Code (GitHub Copilot)</strong></summary>\n\nAdd to `.vscode/mcp.json` in your workspace:\n\n```json\n{\n  \"servers\": {\n    \"pihole\": {\n      \"type\": \"stdio\",\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\nOr add via the command palette: `MCP: Add Server`.\n\n> **Note:** VS Code uses `\"servers\"` as the top-level key (not `\"mcpServers\"`), and requires `\"type\": \"stdio\"`.\n\n</details>\n\n<details>\n<summary><strong>Cursor</strong></summary>\n\nAdd to `~/.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><strong>Windsurf</strong></summary>\n\nAdd to `~/.codeium/windsurf/mcp_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><strong>Cline</strong></summary>\n\nOpen Cline settings > MCP Servers > Configure, and add:\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"pihole-mcp\",\n      \"env\": {\n        \"PIHOLE_URL\": \"http://192.168.1.2\",\n        \"PIHOLE_PASSWORD\": \"your-password\"\n      }\n    }\n  }\n}\n```\n\n</details>\n\n<details>\n<summary><strong>Docker (any client)</strong></summary>\n\nFor clients that support Docker-based MCP servers:\n\n```json\n{\n  \"mcpServers\": {\n    \"pihole\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n        \"-e\", \"PIHOLE_URL=http://192.168.1.2\",\n        \"-e\", \"PIHOLE_PASSWORD=your-password\",\n        \"-e\", \"TZ=Australia/Adelaide\",\n        \"ghcr.io/hexamatic/pihole-mcp:latest\"]\n    }\n  }\n}\n```\n\nUseful when you don't have Go installed or want to run the server on a remote host.\n\n</details>\n\n## Tools\n\nA single Pi-hole exposes 76 tools. Configuring more than one adds `pihole_instance_diff` and `pihole_instance_sync`, for 78 — they are registered only when there is a second instance to compare against, so a single-Pi-hole setup isn't shown tools it cannot use.\n\nThe tables below are a summary; the full generated reference with every parameter is in [docs/TOOLS.md](docs/TOOLS.md).\n\n### Dashboard\n| Tool | Description |\n|------|-------------|\n| `pihole_padd` | One-call snapshot: queries, blocking, top domain/client, cache, versions, host health |\n\n### DNS Control\n| Tool | Description |\n|------|-------------|\n| `pihole_dns_get_blocking` | Get current DNS blocking status and timer |\n| `pihole_dns_set_blocking` | Enable/disable blocking with optional timer |\n\n### Statistics\n| Tool | Description |\n|------|-------------|\n| `pihole_stats_summary` | Queries, blocking rate, clients, gravity size |\n| `pihole_stats_top_domains` | Top queried or blocked domains |\n| `pihole_stats_top_clients` | Most active clients by query count |\n| `pihole_stats_upstreams` | Upstream DNS server performance |\n| `pihole_stats_query_types` | Query type distribution (A, AAAA, MX, etc.) |\n| `pihole_stats_recent_blocked` | Recently blocked domains |\n| `pihole_stats_database` | Long-term database statistics |\n\n### Domain Management\n| Tool | Description |\n|------|-------------|\n| `pihole_domains_list` | List allow/deny domains |\n| `pihole_domains_add` | Add domains (bulk supported) |\n| `pihole_domains_update` | Update domain entry |\n| `pihole_domains_delete` | Remove a domain |\n| `pihole_domains_batch_delete` | Remove multiple domains |\n\n### Groups, Clients, Lists\n| Tool | Description |\n|------|-------------|\n| `pihole_groups_list/add/update/delete/batch_delete` | Manage groups |\n| `pihole_clients_list/suggestions/add/update/delete` | Manage clients |\n| `pihole_lists_list/add/update/delete/batch_delete` | Manage blocklists/allowlists |\n\n### Query Log\n| Tool | Description |\n|------|-------------|\n| `pihole_queries_search` | Search queries with 12 filters + cursor pagination |\n| `pihole_queries_suggestions` | Available filter values |\n\n### System\n| Tool | Description |\n|------|-------------|\n| `pihole_info_system` | Host, CPU, memory, disk, load, temperature |\n| `pihole_info_version` | Pi-hole component versions |\n| `pihole_info_database` | Database size and query count |\n| `pihole_info_messages` | FTL diagnostic messages |\n| `pihole_info_dismiss_message` | Dismiss a diagnostic message by ID |\n| `pihole_search_domains` | Cross-list domain search |\n| `pihole_config_get/set` | Read/modify Pi-hole configuration |\n| `pihole_config_get_value/add_value/remove_value` | Granular dotted-path config access |\n| `pihole_config_properties` | List read-only config keys (Pi-hole v6.6.1+) |\n\n### Actions and Network\n| Tool | Description |\n|------|-------------|\n| `pihole_action_gravity_update` | Re-download blocklists |\n| `pihole_action_restart_dns` | Restart FTL DNS resolver |\n| `pihole_action_flush_logs/network` | Flush logs or network table |\n| `pihole_network_devices/gateway/info` | Network device discovery |\n| `pihole_dhcp_leases/delete_lease` | DHCP lease management |\n| `pihole_logs_dns/ftl/webserver` | Log retrieval |\n| `pihole_teleporter_export/import` | Configuration backup and restore |\n| `pihole_history_graph/clients` | Activity history |\n\n### Multi-instance (only with more than one Pi-hole configured)\n| Tool | Description |\n|------|-------------|\n| `pihole_instance_diff` | Compare configuration between two instances |\n| `pihole_instance_sync` | Reconcile a target instance towards a source (dry-run plan, then confirmed apply) |\n\n### Response Options\n\nMost tools accept optional parameters for controlling output:\n\n- **`detail`** (`minimal` | `normal` | `full`) — Controls response depth. Default: `normal`. Use `minimal` for one-line summaries, `full` for complete API data.\n- **`format`** (`text` | `csv`) — Output format for tabular data. Default: `text`. CSV saves ~29% tokens. Available on `pihole_domains_list`, `pihole_lists_list`, `pihole_clients_list`, `pihole_queries_search`, `pihole_network_devices`, `pihole_stats_top_domains`, `pihole_stats_top_clients`, `pihole_stats_upstreams`, `pihole_stats_query_types`, `pihole_stats_recent_blocked`, `pihole_stats_database_top_domains`, `pihole_stats_database_top_clients`, `pihole_stats_database_upstreams`, `pihole_dhcp_leases`, and `pihole_config_properties`.\n\n## Prompts\n\nPre-built multi-step workflows for common tasks:\n\n| Prompt | Description |\n|--------|-------------|\n| `diagnose_slow_dns` | Analyse upstream performance and identify bottlenecks |\n| `investigate_domain` | Check why a domain is blocked/allowed across all lists |\n| `review_top_blocked` | Identify false positives in top blocked domains |\n| `audit_network` | Discover unknown devices and unconfigured clients |\n| `optimise_blocklists` | Suggest list consolidation and cleanup |\n| `daily_report` | Comprehensive daily Pi-hole health summary |\n| `security_audit` | Review active sessions and auth config for unauthorised access |\n| `weekly_trends` | Compare DNS statistics week over week |\n| `upstream_health` | Deep performance analysis of upstream resolvers |\n\n## Resources\n\nRead-only context an MCP client can pull in without calling a tool:\n\n| URI | Description |\n|-----|-------------|\n| `pihole://status` | Blocking status, version, health |\n| `pihole://summary` | Query statistics |\n| `pihole://clients/{client}` | Configuration and groups for one client |\n| `pihole://domains/{type}/{kind}` | Domains on a list, e.g. `deny/exact` |\n| `pihole://lists/{address}` | Details of one blocklist or allowlist |\n\nWith more than one Pi-hole configured, each instance is also addressable directly — `pihole://instances` lists them, and `pihole://<instance>/status` and `pihole://<instance>/summary` read a named one. The unprefixed URIs above always read the first-declared instance.\n\n## Advanced Configuration\n\n### Transport\n\nBy default, pihole-mcp uses stdio (standard for MCP). HTTP and SSE transports are also available:\n\n```bash\n# Default stdio (for Claude Desktop, Cursor, etc.)\npihole-mcp\n\n# HTTP transport (for web-based MCP clients)\npihole-mcp -transport http -address localhost:8080\n\n# SSE transport (deprecated — see below)\npihole-mcp -transport sse -address localhost:8080\n```\n\n> **SSE is deprecated.** The MCP specification superseded the HTTP+SSE transport with Streamable HTTP in the 2025-03-26 revision. `-transport sse` is kept for older clients and still receives security fixes, but new deployments should use `-transport http`. It will be removed once the clients that need it have moved on.\n\n### Security (HTTP and SSE transports)\n\nThe `http` and `sse` transports apply two security middlewares to every request, in line with the MCP 2025-11-25 spec's DNS-rebinding protection guidance. stdio is unaffected (single-process, single-user).\n\n- **Origin and Host validation.** Both headers must resolve to a host in `PIHOLE_ALLOWED_ORIGINS` (default loopback only). Missing `Origin` is allowed for non-browser MCP clients. Mismatches return HTTP 403. To expose pihole-mcp on a LAN, extend the allowlist:\n\n  ```bash\n  export PIHOLE_ALLOWED_ORIGINS=\"localhost,127.0.0.1,[::1],pihole-mcp.lan\"\n  ```\n\n  The literal `*` disables enforcement entirely — only use it if you're behind a reverse proxy doing its own access control.\n\n- **Per-session rate limiting.** A token bucket keyed by `Mcp-Session-Id` (fallback to client IP) caps requests at `PIHOLE_RATE_LIMIT` per minute (default `120`, burst `max(120/4, 30)`). Throttled requests return HTTP 429 with `Retry-After: 1`. `0` disables.\n\n  ```bash\n  # Tighter limit for a small fleet\n  export PIHOLE_RATE_LIMIT=60\n\n  # Disable (only when running behind a proxy with its own rate limit)\n  export PIHOLE_RATE_LIMIT=0\n  ```\n\n### OpenTelemetry\n\nTracing is opt-in. Set `OTEL_EXPORTER_OTLP_ENDPOINT` to enable:\n\n```bash\nexport OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318\npihole-mcp\n```\n\nAll tool calls are automatically traced with tool name, duration, and error status.\n\nIf you don't need tracing, the slim build strips the OpenTelemetry SDK, gRPC, protobuf and grpc-gateway dependencies entirely — a little over 40% smaller:\n\n| linux/amd64, v0.6.0 | Binary | Download (`.tar.gz`) | Docker image |\n|---|---|---|---|\n| Default | 16.4 MB | 6.1 MB | 18.2 MB |\n| Slim | 9.2 MB | 3.6 MB | 11.8 MB |\n\n```bash\njust build-slim\n# or\ngo build -tags slim -o bin/pihole-mcp-slim ./cmd/pihole-mcp\n\n# Docker\ndocker pull ghcr.io/hexamatic/pihole-mcp:latest-slim\n```\n\nThe slim binary is functionally identical apart from `OTEL_EXPORTER_OTLP_ENDPOINT` being ignored.\n\n## Troubleshooting\n\n### \"Pi-hole rejected the login: its API session pool is full\"\n\nPi-hole allows a limited number of concurrent API sessions — `webserver.api.max_sessions`, **16 by default** — and every client that logs in takes a seat: the web interface, PADD, Home Assistant, any other integration, and pihole-mcp. When they are all taken, Pi-hole answers `429` and refuses further logins, including from its own web interface.\n\npihole-mcp releases its seat on shutdown, but a session left behind by a process that was killed rather than stopped will hold one until it expires. Three ways out, in order of preference:\n\n1. **Free a seat.** Ask for the session list (`pihole_auth_sessions`) and revoke one that is idle (`pihole_auth_revoke_session`).\n2. **Raise the cap.** On a machine with a handful of integrations, 16 is low:\n   ```bash\n   pihole-FTL --config webserver.api.max_sessions 32\n   ```\n3. **Wait.** Seats release themselves after `webserver.session.timeout` — 30 minutes by default.\n\nRetrying will not help, so pihole-mcp does not: it reports the problem instead of silently stalling.\n\n### Authentication fails with a correct password\n\nPi-hole rate-limits repeated failed logins, and the limiter does not distinguish between \"wrong password\" and \"the password you just fixed\". Wait a few seconds and try again. If it persists, confirm you are using the admin password or an [application password](https://docs.pi-hole.net/api/auth/) — not the web interface's TOTP code.\n\n### Docker: \"connection refused\" reaching Pi-hole\n\n`localhost` inside a container is the container, not the host. Point `PIHOLE_URL` at the host's LAN address (`http://192.168.1.2`), at `host.docker.internal` on Docker Desktop, or put both containers on the same Docker network and use the Pi-hole container's name.\n\n### Timestamps are shown in UTC\n\nEvery timestamp in tool output carries an explicit zone marker (e.g. `19 Jul 2026, 9:41 AM UTC`), so responses are unambiguous whatever the zone. Which zone is used depends on where the server runs: native binaries use the system timezone, while the Docker image defaults to UTC. To get local times from the container, set `TZ` on the *pihole-mcp* container (not just the Pi-hole one) — timezone data is embedded in the binary, so no extra packages or volume mounts are needed:\n\n```yaml\nenvironment:\n  - TZ=Australia/Adelaide\n```\n\nAn unrecognised `TZ` value logs a warning at startup and falls back to UTC rather than refusing to start.\n\n### \"x509: certificate signed by unknown authority\"\n\nYour Pi-hole is serving HTTPS with a self-signed certificate, which fails standard TLS verification. The right fix is a trusted certificate on the Pi-hole (for example via its built-in domain settings or a reverse proxy with Let's Encrypt). If that isn't practical, set `PIHOLE_TLS_SKIP_VERIFY=true` to disable verification — connections are still encrypted, but the server's identity is no longer checked, so only use this on a network you control.\n\n### Occasional dropped connections\n\nPi-hole's embedded web server closes connections under load. pihole-mcp retries these automatically with backoff; if you see failures anyway, raise `PIHOLE_MAX_RETRIES` (default `3`).\n\n## Development\n\n```bash\n# Prerequisites: Go 1.26+, Docker, mise, just\n\n# One-command setup\njust setup\n\n# Start local Pi-hole (http://localhost:8081, password: test)\njust dev-up\n\n# Run quality checks (format + lint + test)\njust check\n\n# Run integration tests against local Pi-hole\njust integration\n\n# Build binary\njust build\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for full development guidelines.\n\n---\n\n[Pi-hole](https://pi-hole.net/) is a registered trademark of Pi-hole LLC. This project is independently maintained and is not affiliated with, endorsed by, or sponsored by Pi-hole LLC.\n\n## Licence\n\n[MIT](LICENSE)\n",
  "bytes": 23567,
  "sha": "b9cf4397e3cf72009ce2f555cae0ebef165c24e63e4b2085a119c45b0e26c0ef",
  "repo_slug": "hexamatic/pihole-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_hexamatic_pihole_mcp_61957865/readme"
}