Content
# Pi-hole Read-Only MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) server that exposes read-only Pi-hole v6 statistics to Claude (or any MCP client). Every tool call opens a fresh Pi-hole session, performs exactly one API request, then immediately deletes the session — no tokens are cached or logged.
---
## Prerequisites
- Python 3.11+ on the Ubuntu host (`openclaw-pc`, user `dumaki`)
- Pi-hole v6 running at `http://100.103.118.39`
- The existing `/etc/sherman-executor/.env` already on the machine
---
## 1. Add credentials to the .env file
The server reads `PIHOLE_PASSWORD` from `/etc/sherman-executor/.env`. Add (or confirm) this line:
```bash
sudo bash -c 'echo "PIHOLE_PASSWORD=your_pihole_web_password_here" >> /etc/sherman-executor/.env'
```
> The password is the same one you use to log in to the Pi-hole web UI.
---
## 2. Install the server
```bash
# Copy files to a stable location
sudo mkdir -p /opt/pihole-mcp
sudo cp server.py start.sh requirements.txt /opt/pihole-mcp/
sudo chmod +x /opt/pihole-mcp/start.sh
# Install dependencies (system-wide or in a venv)
sudo pip3 install -r /opt/pihole-mcp/requirements.txt
```
Or with a venv (recommended):
```bash
python3 -m venv /opt/pihole-mcp/.venv
/opt/pihole-mcp/.venv/bin/pip install -r /opt/pihole-mcp/requirements.txt
# Then update start.sh: replace `exec python3` with `exec /opt/pihole-mcp/.venv/bin/python3`
```
---
## 3. Register in OpenClaw MCP config
Add an entry to your OpenClaw MCP server configuration (typically `~/.config/openclaw/mcp_servers.json` or the path shown in `openclaw config`):
```json
{
"pihole": {
"command": "/bin/bash",
"args": ["/opt/pihole-mcp/start.sh"],
"description": "Read-only Pi-hole v6 statistics"
}
}
```
Restart OpenClaw (or reload MCP servers) after saving.
---
## 4. Test each tool with curl
First obtain a session token manually (replace `YOUR_PASSWORD`):
```bash
TOKEN=$(curl -s -X POST http://100.103.118.39/api/auth \
-H 'Content-Type: application/json' \
-d '{"password":"YOUR_PASSWORD"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['session']['sid'])")
echo "Token: $TOKEN"
```
### pihole_get_summary
```bash
curl -s http://100.103.118.39/api/stats/summary \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
### pihole_get_top_blocked
```bash
curl -s "http://100.103.118.39/api/stats/top_domains?blocked=true&count=10" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
### pihole_get_top_clients
```bash
curl -s "http://100.103.118.39/api/stats/top_clients?count=10" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
### pihole_get_recent_blocked
```bash
curl -s "http://100.103.118.39/api/queries?blocked=true&limit=20" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
### pihole_search_domain
```bash
curl -s "http://100.103.118.39/api/search/ads.example.com" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
### pihole_get_query_log (with optional filters)
```bash
# All recent queries
curl -s "http://100.103.118.39/api/queries?limit=50" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
# Blocked only, from a specific client
curl -s "http://100.103.118.39/api/queries?blocked=true&client=192.168.1.5&limit=25" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
# Domain substring filter
curl -s "http://100.103.118.39/api/queries?domain=doubleclick&limit=25" \
-H "X-FTL-SID: $TOKEN" | python3 -m json.tool
```
After testing, delete the session:
```bash
curl -s -X DELETE "http://100.103.118.39/api/auth/$TOKEN"
```
---
## Security notes
- The server **never caches** session tokens between tool calls.
- The server **never logs** the password or token (only error-level messages with no credential content).
- Every tool function has an explicit `_assert_allowed()` guard that rejects any non-GET, non-auth operation before it reaches the network.
- The `.env` file is read fresh on each call, so rotating the password takes effect immediately without restarting the server.
---
## Environment variables
| Variable | Default | Description |
|---|---|---|
| `PIHOLE_PASSWORD` | *(required)* | Pi-hole web password, read from `/etc/sherman-executor/.env` |
| `PIHOLE_BASE_URL` | `http://100.103.118.39` | Override the Pi-hole host URL |