10 KiB
Homelab MCP Server
Last updated: 2026-03-21
The homelab MCP (Model Context Protocol) server exposes tools that allow AI assistants (OpenCode/Claude) to interact directly with homelab infrastructure. It runs as a stdio subprocess started by OpenCode on session init.
Location & Config
| Item | Path |
|---|---|
| Server source | scripts/homelab-mcp/server.py |
| OpenCode config | ~/.config/opencode/opencode.json |
| Runtime | Python 3, fastmcp library |
| Transport | stdio (started per-session by OpenCode) |
Changes to server.py take effect on the next OpenCode session (the server is restarted each session).
Tool Categories
1. Portainer — Docker orchestration
Manages containers and stacks across all 5 Portainer endpoints.
| Tool | What it does |
|---|---|
check_portainer |
Health check — version and stack count |
list_endpoints |
List all endpoints (Atlantis, Calypso, NUC, Homelab VM, RPi5) |
list_stacks |
List all stacks, optionally filtered by endpoint |
get_stack |
Get details of a specific stack by name or ID |
redeploy_stack |
Trigger GitOps redeploy (pull from Git + redeploy) |
list_containers |
List running containers on an endpoint |
get_container_logs |
Fetch recent logs from a container |
restart_container |
Restart a container |
start_container |
Start a stopped container |
stop_container |
Stop a running container |
list_stack_containers |
List all containers belonging to a stack |
Endpoints: atlantis (id=2), calypso (id=443397), nuc (id=443398), homelab (id=443399), rpi5 (id=443395)
2. Gitea — Source control
Interacts with the self-hosted Gitea instance at git.vish.gg.
| Tool | What it does |
|---|---|
gitea_list_repos |
List all repos in the org |
gitea_list_issues |
List open/closed issues for a repo |
gitea_create_issue |
Create a new issue |
gitea_list_branches |
List branches for a repo |
Default org: vish — repo names can be homelab or vish/homelab
3. AdGuard — Split-horizon DNS
Manages DNS rewrite rules on the Calypso AdGuard instance (192.168.0.250:9080).
Critical context: the wildcard *.vish.gg → 100.85.21.51 (matrix-ubuntu Tailscale IP) requires specific overrides for services that internal hosts need to reach directly (e.g. pt.vish.gg, sso.vish.gg, git.vish.gg all need → 192.168.0.154).
| Tool | What it does |
|---|---|
adguard_list_rewrites |
List all DNS overrides |
adguard_add_rewrite |
Add a new domain → IP override |
adguard_delete_rewrite |
Remove a DNS override |
4. NPM — Nginx Proxy Manager
Manages reverse proxy hosts and SSL certs on matrix-ubuntu (192.168.0.154:81).
Critical cert rule: Never reuse an existing npm-N ID. Always use the next available number when adding new certs.
| Tool | What it does |
|---|---|
npm_list_proxy_hosts |
List all proxy hosts with domain, forward target, cert ID |
npm_list_certs |
List all SSL certs with type and expiry |
npm_get_proxy_host |
Get full details of a proxy host including advanced nginx config |
npm_update_cert |
Swap the SSL cert on a proxy host |
Cert reference:
| ID | Domain | Type |
|---|---|---|
| npm-1 | *.vish.gg + vish.gg |
Cloudflare Origin (proxied only) |
| npm-6 | mx.vish.gg |
Let's Encrypt |
| npm-7 | livekit.mx.vish.gg |
Let's Encrypt |
| npm-8 | *.vish.gg CF Origin |
Cloudflare Origin (all proxied *.vish.gg) |
| npm-9 | *.thevish.io |
Let's Encrypt |
| npm-10 | *.crista.love |
Let's Encrypt |
| npm-11 | pt.vish.gg |
Let's Encrypt |
| npm-12 | sso.vish.gg |
Let's Encrypt |
5. Headscale — Tailnet management
Manages nodes and pre-auth keys via SSH to Calypso → docker exec headscale.
| Tool | What it does |
|---|---|
headscale_list_nodes |
List all tailnet nodes with IPs and online status |
headscale_create_preauth_key |
Generate a new node auth key (with expiry/reusable/ephemeral options) |
headscale_delete_node |
Remove a node from the tailnet |
headscale_rename_node |
Rename a node's given name |
Login server: https://headscale.vish.gg:8443
New node command: tailscale up --login-server=https://headscale.vish.gg:8443 --authkey=<key> --accept-routes=false
6. Authentik — SSO identity provider
Manages OAuth2/OIDC apps, providers, and users at sso.vish.gg.
| Tool | What it does |
|---|---|
authentik_list_applications |
List all SSO apps with slug, provider, launch URL |
authentik_list_providers |
List all OAuth2/proxy providers with PK and type |
authentik_list_users |
List all users with email and active status |
authentik_update_app_launch_url |
Update the dashboard tile URL for an app |
authentik_set_provider_cookie_domain |
Set cookie domain on a proxy provider (must be vish.gg to avoid redirect loops) |
Critical: All Forward Auth proxy providers must have cookie_domain: vish.gg or they cause ERR_TOO_MANY_REDIRECTS.
7. Cloudflare — DNS management
Manages DNS records for the vish.gg zone.
| Tool | What it does |
|---|---|
cloudflare_list_dns_records |
List all DNS records, optionally filtered by name |
cloudflare_create_dns_record |
Create a new A/CNAME/TXT record |
cloudflare_delete_dns_record |
Delete a DNS record by ID |
cloudflare_update_dns_record |
Update an existing record's content or proxied status |
Proxied (orange cloud): Most *.vish.gg services
Unproxied (DNS-only): mx.vish.gg, headscale.vish.gg, livekit.mx.vish.gg, pt.vish.gg, sso.vish.gg, derp*.vish.gg
8. Uptime Kuma — Monitoring
Manages monitors and groups via SSH to Pi-5 → SQLite DB manipulation.
Always call kuma_restart after adding or modifying monitors — Kuma caches config in memory.
| Tool | What it does |
|---|---|
kuma_list_monitors |
List all monitors with type, status, URL/hostname, group |
kuma_list_groups |
List all group monitors with IDs (for use as parent_id) |
kuma_add_monitor |
Add a new http/port/ping/group monitor |
kuma_set_parent |
Assign a monitor to a group |
kuma_restart |
Restart Kuma container to apply DB changes |
Monitor group hierarchy:
Homelab (3) → Atlantis (4), Calypso (49), Concord_NUC (44),
Raspberry Pi 5 (91), Guava (73), Setillo (58),
Proxmox_NUC (71), Seattle (111),
Matrix-Ubuntu (115), Moon (114)
9. Prometheus — Metrics queries
Queries the Prometheus instance at 192.168.0.210:9090.
| Tool | What it does |
|---|---|
prometheus_query |
Run a PromQL instant query |
prometheus_targets |
List all scrape targets and their health |
10. Grafana — Dashboards & alerts
Inspects dashboards and alert rules at 192.168.0.210:3300.
| Tool | What it does |
|---|---|
grafana_list_dashboards |
List all dashboards with folder |
grafana_list_alerts |
List all alert rules and current state |
11. Media — Sonarr / Radarr / SABnzbd
Manages the media download stack on Atlantis.
| Tool | What it does |
|---|---|
sonarr_list_series |
List TV series, optionally filtered by title |
sonarr_queue |
Show current Sonarr download queue |
radarr_list_movies |
List movies, optionally filtered by title |
radarr_queue |
Show current Radarr download queue |
sabnzbd_queue |
Show SABnzbd download queue with progress |
sabnzbd_pause |
Pause the SABnzbd queue |
sabnzbd_resume |
Resume the SABnzbd queue |
12. SSH — Remote command execution
Runs shell commands on homelab hosts via SSH.
| Tool | What it does |
|---|---|
ssh_exec |
Run a command on a named host |
Known hosts: atlantis, calypso, setillo, setillo-root, nuc, homelab-vm, rpi5, pi-5, matrix-ubuntu, moon, olares, guava, pve, seattle-tailscale, gl-mt3000
13. Filesystem — Local file access
Read/write files on the homelab-vm filesystem.
| Tool | What it does |
|---|---|
fs_read |
Read a file (allowed: /home/homelab, /tmp) |
fs_write |
Write a file (allowed: /home/homelab, /tmp) |
fs_list |
List directory contents |
14. Repo — Homelab repository inspection
Inspects the homelab Git repository at /home/homelab/organized/repos/homelab.
| Tool | What it does |
|---|---|
list_homelab_services |
List all compose files, optionally filtered by host |
get_compose_file |
Read a compose file by partial path or name (searches docker-compose.yml/yaml and standalone *.yaml/*.yml stacks) |
15. Notifications — ntfy push
Sends push notifications via the self-hosted ntfy instance.
| Tool | What it does |
|---|---|
send_notification |
Send a push notification to ntfy topic |
Default topic: homelab-alerts
Priorities: urgent, high, default, low, min
16. Health checks
| Tool | What it does |
|---|---|
check_url |
HTTP health check against a URL with expected status code |
Bug Fixes Applied (2026-03-21)
| Bug | Symptom | Fix |
|---|---|---|
list_homelab_services |
AttributeError: 'str' object has no attribute 'parts' — crashed every call |
Changed str(f).parts → f.parts |
get_compose_file |
Couldn't find standalone stack files like homarr.yaml, whisparr.yaml |
Extended search to all *.yaml/*.yml, prefers docker-compose.* when both match |
check_portainer |
Type error on stacks.get() — stacks is a list not a dict |
Added isinstance guards |
gitea_create_issue |
Type error on data['number'] — subscript on dict | list union |
Added isinstance(data, dict) guard |
Adding New Tools
- Add helper function (e.g.
_myservice(...)) to the helpers section - Add
@mcp.tool()decorated function with a clear docstring - Update the
instructions=string inmcp = FastMCP(...)with the new category - Add
pragma: allowlist secretto any token/key constants - Commit and push — changes take effect next OpenCode session
Related docs
docs/admin/ai-integrations.md— AI/LLM integrations overviewdocs/troubleshooting/matrix-ssl-authentik-incident-2026-03-19.md— NPM cert referencedocs/services/individual/uptime-kuma.md— Kuma monitor group reference