{"id":42184692,"url":"https://github.com/mtgibbs/pi-cluster-mcp","last_synced_at":"2026-02-06T21:04:14.568Z","repository":{"id":334765151,"uuid":"1142641127","full_name":"mtgibbs/pi-cluster-mcp","owner":"mtgibbs","description":"Connect Claude to your homelab safely. This MCP server provides structured tools for K3s cluster operations, Pi-hole DNS management, and Jellyfin/Immich control, built with a security-first architecture.","archived":false,"fork":false,"pushed_at":"2026-01-29T05:30:14.000Z","size":321,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-29T16:10:08.600Z","etag":null,"topics":["homelab-automation","mcp","mcp-server","model-context-protocol","raspberry-pi"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mtgibbs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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-01-26T17:10:26.000Z","updated_at":"2026-01-29T05:27:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mtgibbs/pi-cluster-mcp","commit_stats":null,"previous_names":["mtgibbs/pi-cluster-mcp"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/mtgibbs/pi-cluster-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgibbs%2Fpi-cluster-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgibbs%2Fpi-cluster-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgibbs%2Fpi-cluster-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgibbs%2Fpi-cluster-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mtgibbs","download_url":"https://codeload.github.com/mtgibbs/pi-cluster-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mtgibbs%2Fpi-cluster-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28993724,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T22:01:47.507Z","status":"ssl_error","status_checked_at":"2026-02-01T21:58:37.335Z","response_time":56,"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":["homelab-automation","mcp","mcp-server","model-context-protocol","raspberry-pi"],"created_at":"2026-01-26T22:21:39.336Z","updated_at":"2026-02-06T21:04:14.563Z","avatar_url":"https://github.com/mtgibbs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Homelab MCP Server\n\nA [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server designed for managing a Kubernetes-based homelab (specifically a Raspberry Pi K3s cluster). \n\nThis server provides a safe, structured interface for LLMs (like Claude) to interact with your cluster, media services, and network infrastructure without giving them raw `kubectl` access or unrestricted SSH capabilities.\n\n## 🚀 Features\n\n### Kubernetes Operations\n- **Health Checks:** Monitor nodes, resource usage, and problem pods.\n- **Resource Inspection:** List and describe deployments, statefulsets, daemonsets, pods, services, and configmaps with full spec details.\n- **Storage:** Inspect PersistentVolumeClaims with status, capacity, and storage class info.\n- **Safe Restarts:** Trigger rolling restarts for whitelisted deployments (e.g., Jellyfin, Pi-hole, media stack).\n- **Backups:** Check CronJob status, inspect detailed job specs, retrieve job pod logs, and manually trigger backup jobs.\n- **GitOps:** Monitor Flux Kustomizations/HelmReleases and trigger reconciliation.\n- **Secrets:** View External Secrets sync status and force refreshes (1Password integration).\n\n### Network \u0026 DNS (Pi-hole/Unbound)\n- **Status:** Check health of DNS services.\n- **Diagnostics:** View blocked query stats, top blocked domains, and recent query logs.\n- **Testing:** Run `dig` commands from within the cluster to verify resolution.\n- **Management:** View whitelist and trigger Gravity updates.\n\n### Media Services (Jellyfin/Immich)\n- **Health:** Monitor pod status for media applications.\n- **Stats:** detailed library statistics and active session monitoring.\n- **Management:** Search media libraries and trigger metadata refreshes for specific items.\n\n### Network Diagnostics\n- **Node Networking:** Inspect interfaces, addresses, routes, and routing rules on any cluster node.\n- **Firewall Rules:** Dump iptables/ip6tables rules by table and chain.\n- **Connection Tracking:** View conntrack entries with source/destination filtering.\n- **Ingress Testing:** Curl ingress URLs from within the cluster with detailed timing.\n- **Connectivity Testing:** Ping and TCP port checks between nodes and targets.\n- **Pod Logs:** Retrieve pod logs with container, time range, and line count filtering.\n\n### Infrastructure\n- **Certificates:** Monitor cert-manager certificate expiry and readiness.\n- **NAS Integration:** Securely touch specific paths on a Synology NAS (via SSH) to trigger file system events.\n- **Tailscale:** Monitor VPN connector status.\n\n## 🔒 Security Model\n\nThis project is built with a \"defense in depth\" approach:\n\n1.  **Least Privilege:** Runs with a dedicated ServiceAccount.\n    -   **Read-Only:** Most resources (Pods, Events, Flux, Certs).\n    -   **Scoped Action:** `patch` is strictly limited to whitelisted deployments and Flux resources.\n    -   **Scoped Exec:** `pod/exec` is strictly limited to `jellyfin`, `pihole`, and `mcp-homelab` (debug-agent) namespaces via specific Roles.\n2.  **Input Validation:** Strict validation on all tool inputs (especially for file paths and resource names).\n3.  **Authentication:** Requires `X-API-Key` header for all requests.\n4.  **Network:** Designed to run behind an Ingress accessible only via Tailscale.\n\n## 🛠️ Configuration\n\n### Environment Variables\n\n| Variable | Description | Required |\n|----------|-------------|----------|\n| `MCP_API_KEY` | Secret key for authenticating requests | Yes |\n| `MCP_TRANSPORT` | `stdio` (default) or `sse` | No |\n| `NAS_HOST` | Hostname/IP of Synology NAS | Yes (for NAS tools) |\n| `NAS_USER` | SSH Username for NAS | Yes (for NAS tools) |\n| `NAS_PRIVATE_KEY` | SSH Private Key for NAS | Yes (for NAS tools) |\n| `NAS_ALLOWED_PATHS`| Comma-separated list of allowed path prefixes | No (defaults to strict subset) |\n| `JELLYFIN_URL` | Internal URL for Jellyfin | No (default: cluster svc) |\n| `JELLYFIN_API_KEY` | API Key for Jellyfin operations | Yes (for Media tools) |\n| `IMMICH_API_KEY` | API Key for Immich stats | Yes (for Media tools) |\n| `BAZARR_URL` | Internal URL for Bazarr | No (default: cluster svc) |\n| `BAZARR_API_KEY` | API Key for Bazarr operations | Yes (for Subtitle tools) |\n| `SONARR_URL` | Internal URL for Sonarr | No (default: cluster svc) |\n| `SONARR_API_KEY` | API Key for Sonarr operations | Yes (for TV tools) |\n| `RADARR_URL` | Internal URL for Radarr | No (default: cluster svc) |\n| `RADARR_API_KEY` | API Key for Radarr operations | Yes (for Movie tools) |\n| `SABNZBD_URL` | Internal URL for SABnzbd | No (default: cluster svc) |\n| `SABNZBD_API_KEY` | API Key for SABnzbd operations | Yes (for Download tools) |\n\n## 📦 Deployment\n\n### Local Development (Stdio)\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Run in stdio mode (for testing with Claude Desktop/CLI)\nnpm run dev\n```\n\n### Kubernetes (Production)\n\nThe server is designed to be deployed as a Pod in your cluster.\n\n1.  **Build Docker Image:**\n    ```bash\n    docker build -t ghcr.io/username/homelab-mcp:latest .\n    ```\n\n2.  **Deploy Manifests:**\n    See the `k8s/` directory for example manifests, including:\n    -   `deployment.yaml`\n    -   `service.yaml`\n    -   `ingress.yaml` (configured for Tailscale/Cert-manager)\n    -   `clusterrole.yaml` (Scoped RBAC permissions)\n\n## 🧩 Available Tools\n\n| Category | Tools |\n|----------|-------|\n| **Cluster** | `get_cluster_health`, `restart_deployment` |\n| **DNS** | `get_dns_status`, `test_dns_query`, `update_pihole_gravity`, `get_pihole_whitelist`, `get_pihole_queries` |\n| **GitOps** | `get_flux_status`, `reconcile_flux` |\n| **Media** | `get_media_status`, `fix_jellyfin_metadata` |\n| **Subtitles** | `get_subtitle_status`, `get_subtitle_history`, `search_subtitles` |\n| **TV (Sonarr)** | `get_sonarr_queue`, `get_sonarr_history`, `search_sonarr_episode` |\n| **Movies (Radarr)** | `get_radarr_queue`, `get_radarr_history`, `search_radarr_movie` |\n| **Downloads (SABnzbd)** | `get_sabnzbd_queue`, `get_sabnzbd_history`, `retry_sabnzbd_download`, `pause_resume_sabnzbd` |\n| **Arr Shared** | `get_quality_profile`, `reject_and_search` |\n| **Backups** | `get_backup_status`, `trigger_backup`, `get_cronjob_details`, `get_job_logs` |\n| **Secrets** | `get_secrets_status`, `refresh_secret` |\n| **Storage** | `get_pvcs` |\n| **Resources** | `describe_resource` |\n| **System** | `get_certificate_status`, `get_ingress_status`, `touch_nas_path` |\n| **Networking** | `get_node_networking`, `get_iptables_rules`, `get_conntrack_entries`, `curl_ingress`, `test_pod_connectivity` |\n| **Logs** | `get_pod_logs` |","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtgibbs%2Fpi-cluster-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmtgibbs%2Fpi-cluster-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmtgibbs%2Fpi-cluster-mcp/lists"}