# Homelab MCP Server Guide

The homelab MCP (Model Context Protocol) server gives Claude Code live access to homelab infrastructure. Instead of copying logs or running curl commands manually, Claude can query and act on real systems directly in the conversation.

## What is MCP?

MCP is a standard that lets Claude connect to external tools and services as "plugins". Each MCP server exposes a set of tools. When Claude is connected to the homelab MCP server, it can call those tools mid-conversation to get live data or take actions.

**Flow:** You ask Claude something → Claude calls an MCP tool → Tool hits a real API → Claude answers with live data.

## Server Location

```
scripts/homelab-mcp/server.py
```

Single Python file using [FastMCP](https://github.com/jlowin/fastmcp). No database, no daemon, no background threads — it only runs while Claude Code is active.

## Tool Reference

### Portainer

| Tool | Description |
|------|-------------|
| `list_endpoints` | List all Portainer environments (atlantis, calypso, nuc, homelab, rpi5) |
| `list_stacks(endpoint?)` | List stacks, optionally filtered by endpoint |
| `get_stack(name_or_id)` | Detailed info for a specific stack |
| `redeploy_stack(name_or_id)` | Trigger GitOps redeploy (pull from Gitea + redeploy) |
| `list_containers(endpoint, all?, filter?)` | List containers on an endpoint |
| `get_container_logs(name, endpoint?, tail?)` | Fetch container logs |
| `restart_container(name, endpoint?)` | Restart a container |
| `start_container(name, endpoint?)` | Start a stopped container |
| `stop_container(name, endpoint?)` | Stop a running container |
| `list_stack_containers(name_or_id)` | List containers belonging to a stack |
| `check_portainer` | Health check + stack count summary |

### Gitea

| Tool | Description |
|------|-------------|
| `gitea_list_repos(owner?, limit?)` | List repositories |
| `gitea_list_issues(repo, state?, limit?)` | List issues (open/closed/all) |
| `gitea_create_issue(repo, title, body?)` | Create a new issue |
| `gitea_list_branches(repo)` | List branches |

Repo names can be `vish/homelab` or just `homelab` (defaults to `vish` org).

### Prometheus

| Tool | Description |
|------|-------------|
| `prometheus_query(query)` | Run an instant PromQL query |
| `prometheus_targets` | List all scrape targets and health status |

**Example queries:**
- `up` — which targets are up
- `node_memory_MemAvailable_bytes` — available memory on all nodes
- `rate(node_cpu_seconds_total[5m])` — CPU usage rate

### Grafana

| Tool | Description |
|------|-------------|
| `grafana_list_dashboards` | List all dashboards with UIDs |
| `grafana_list_alerts` | List all alert rules |

### Sonarr / Radarr

| Tool | Description |
|------|-------------|
| `sonarr_list_series(filter?)` | List all series (optional name filter) |
| `sonarr_queue` | Show active download queue |
| `radarr_list_movies(filter?)` | List all movies (optional name filter) |
| `radarr_queue` | Show active download queue |

### SABnzbd

| Tool | Description |
|------|-------------|
| `sabnzbd_queue` | Show download queue with progress |
| `sabnzbd_pause` | Pause all downloads |
| `sabnzbd_resume` | Resume downloads |

**Note:** SABnzbd is on Atlantis at port 8080 (internal).

### SSH

| Tool | Description |
|------|-------------|
| `ssh_exec(host, command, timeout?)` | Run a command on a homelab host via SSH |

**Allowed hosts:** `atlantis`, `calypso`, `setillo`, `setillo-root`, `nuc`, `homelab-vm`, `rpi5`

Requires SSH key auth to be configured in `~/.ssh/config`. Uses `BatchMode=yes` (no password prompts).

### Filesystem

| Tool | Description |
|------|-------------|
| `fs_read(path)` | Read a file (max 1MB) |
| `fs_write(path, content)` | Write a file |
| `fs_list(path?)` | List directory contents |

**Allowed roots:** `/home/homelab`, `/tmp`

### Health / Utilities

| Tool | Description |
|------|-------------|
| `check_url(url, expected_status?)` | HTTP health check with latency |
| `send_notification(message, title?, topic?, priority?, tags?)` | Send ntfy push notification |
| `list_homelab_services(host_filter?)` | Find compose files in repo |
| `get_compose_file(service_path)` | Read a compose file from repo |

## Configuration

All credentials are hardcoded in `server.py` except SABnzbd's API key which is loaded from the environment.

### Service URLs

| Service | URL | Auth |
|---------|-----|------|
| Portainer | `https://192.168.0.200:9443` | API token (X-API-Key) |
| Gitea | `http://192.168.0.250:3052` | Token in Authorization header |
| Prometheus | `http://192.168.0.210:9090` | None |
| Grafana | `http://192.168.0.210:3300` | HTTP basic (admin) |
| Sonarr | `http://192.168.0.200:8989` | X-Api-Key header |
| Radarr | `http://192.168.0.200:7878` | X-Api-Key header |
| SABnzbd | `http://192.168.0.200:8080` | API key in query param |

## How Claude Code Connects

The MCP server is registered in Claude Code's project settings:

```json
// .claude/settings.local.json
{
  "mcpServers": {
    "homelab": {
      "command": "python3",
      "args": ["scripts/homelab-mcp/server.py"]
    }
  }
}
```

When you open Claude Code in this repo directory, the MCP server starts automatically. You can verify it's working by asking Claude to list endpoints or check Portainer.

## Resource Usage

The server is a single Python process that starts on-demand. It consumes:
- **Memory:** ~30–50MB while running
- **CPU:** Near zero (only active during tool calls)
- **Network:** Minimal — one API call per tool invocation

No background polling, no persistent connections.

## Adding New Tools

1. Add a helper function (e.g. `_myservice(...)`) at the top of `server.py`
2. Add config constants in the Configuration section
3. Decorate tool functions with `@mcp.tool()`
4. Add a section to this doc

The FastMCP framework auto-generates the tool schema from the function signature and docstring. Args are described in the docstring `Args:` block.

## Related Docs

- `docs/admin/PORTAINER_API_GUIDE.md` — Portainer API reference
- `docs/services/individual/gitea.md` — Gitea setup
- `docs/services/individual/grafana.md` — Grafana dashboards
- `docs/services/individual/prometheus.md` — Prometheus setup
- `docs/services/individual/sonarr.md` — Sonarr configuration
- `docs/services/individual/radarr.md` — Radarr configuration
- `docs/services/individual/sabnzbd.md` — SABnzbd configuration
