Skip to content
Conduit

mcp server

homelab-mcp

MCP server for Proxmox homelab — 65+ tools across 17 domains. Manage VMs, Docker, media stack, monitoring, storage, and networking from AI assistants.

Nainounen/homelab-mcpcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "nainounen-homelab-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "homelab-mcp"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 25, 2026

homelab-mcp

CI npm version License: MIT Node: >=20

MCP server that gives AI assistants full control of a Proxmox homelab — manage VMs and containers, deploy Docker projects, monitor services, control the media stack, and check storage health, all from conversation.

Tools cover infrastructure, media automation, monitoring, storage, and network services. The modular architecture lets contributors add integrations without changing the MCP server core.

AI Setup

No manual config needed. The server includes an AI-native setup wizard. Just connect it to your MCP client and say:

"Set up my homelab" or "Configure the MCP server"

The setup wizard scans your configuration, guides you through each setting interactively, saves your answers, and verifies connectivity — all through conversation. Credentials are never exposed to the AI; the wizard masks passwords, API keys, and tokens before returning any results.

Quick start

Prerequisites

  • Node.js 20+
  • A Proxmox VE host reachable over the network
  • A devbox (any SSH-accessible Linux host running Docker)
  • (Optional) Media services: Plex, Radarr, Sonarr, SABnzbd, Overseerr, Prowlarr
  • (Optional) Monitoring: Prometheus, Grafana, Uptime Kuma

Install

From npm (recommended):

npm install -g homelab-mcp
# Or locally in your project:
npm install homelab-mcp

From source (for contributors):

git clone https://github.com/Nainounen/homelab-mcp.git
cd homelab-mcp
npm install
npm run build

Docker (optional)

A Dockerfile is provided for containerized deployments:

npm run build
cp .env.example .env   # edit with your credentials
docker compose up -d

For most users, running directly with Node.js (no Docker) is simpler — the MCP server communicates over stdio.

Connect to your MCP client

Add to your MCP client's config file. For Claude Code, that's ~/.claude/claude_mcp_config.json:

{
  "mcpServers": {
    "homelab": {
      "command": "npx",
      "args": ["homelab-mcp"],
      "cwd": "/path/to/your/homelab-config"
    }
  }
}

Place your .env file in the cwd directory (copy .env.example from this repo as a starting point). No secrets go in the MCP config — the server loads .env from its working directory.

Then just say "set up my homelab" — the AI-native setup wizard will guide you through the rest.

Configuration

All settings live in .env. See .env.example for the full template. The server starts with the services you configure — any service whose env vars are missing is skipped with a warning.

Required (server won't start without these)

VariableDescription
PROXMOX_HOST, PROXMOX_PORT, PROXMOX_USER, PROXMOX_NODEProxmox API access
PROXMOX_PASSWORD or PROXMOX_KEY_PATHProxmox auth
DEVBOX_HOST, DEVBOX_USERDevbox SSH access
DEVBOX_PASSWORD or DEVBOX_KEY_PATHDevbox SSH auth
RADARR_URL, RADARR_API_KEYRadarr API
SONARR_URL, SONARR_API_KEYSonarr API
PROWLARR_URL, PROWLARR_API_KEYProwlarr API
SABNZBD_URL, SABNZBD_API_KEYSABnzbd API
OVERSEERR_URL, OVERSEERR_API_KEYOverseerr API

Optional (skipped with a warning if missing)

VariableService
QNAP_HOST, QNAP_USER, QNAP_PASSWORD or QNAP_KEY_PATHQNAP NAS
PLEX_URL, PLEX_TOKENPlex
TAUTULLI_URL, TAUTULLI_API_KEYTautulli analytics
BAZARR_URL, BAZARR_API_KEYBazarr subtitles
ADGUARD_URL, ADGUARD_USER, ADGUARD_PASSWORDAdGuard Home
PBS_URL, PBS_TOKEN_ID, PBS_TOKEN_SECRETProxmox Backup Server
LIDARR_URL, LIDARR_API_KEYLidarr music
READARR_URL, READARR_API_KEYReadarr books
UPTIME_KUMA_URL, UPTIME_KUMA_USER, UPTIME_KUMA_PASSWORDUptime Kuma
PROMETHEUS_URLPrometheus API
GRAFANA_URL, GRAFANA_TOKENGrafana API
TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_IDTelegram notifications

Security settings

VariableDefaultDescription
SSH_STRICT_HOST_KEYfalseSet to true to enable known_hosts verification
PROXMOX_TLS_VERIFYfalseSet to true to validate Proxmox TLS certificates
PBS_TLS_VERIFYfalseSet to true to validate PBS TLS certificates

Tuning

VariableDefaultDescription
MAX_OUTPUT_CHARS30000Max characters per tool result before truncation (0 disables)
HTTP_RETRIES3Retries for transient HTTP failures (0 disables)
DEVBOX_CMD_TIMEOUT30000Devbox SSH command timeout in ms
PROXMOX_CMD_TIMEOUT60000Proxmox SSH command timeout in ms

Tools reference

Infrastructure

ToolDescription
proxmox_list_nodesList Proxmox nodes with CPU, RAM, uptime
proxmox_list_vmsList all VMs and LXC containers
proxmox_start_vmStart a VM or container
proxmox_stop_vmStop a VM or container
proxmox_restart_vmRestart a VM or container
proxmox_get_metricsDetailed metrics for one VM/CT
proxmox_get_node_metricsNode-level CPU, RAM, disk, load
proxmox_create_ctCreate a new Debian 12 LXC container
proxmox_get_logsTail task log for a VM/CT
proxmox_execRun a shell command on Proxmox host (dangerous commands blocked)

Devbox & Docker

ToolDescription
devbox_execRun a shell command on the devbox (dangerous commands blocked)
devbox_read_fileRead a file (max 100 KB)
devbox_write_fileWrite a file, auto-creates parent dirs (max 1 MB)
devbox_list_dirList directory contents
devbox_docker_psShow running Docker containers
devbox_docker_composeRun compose up/down/restart/pull/logs
devbox_gitGit status, pull, log, or clone a repo
devbox_project_deployDeploy: git pull → compose pull → compose up → status
devbox_project_statusHealth check for a deployed project
devbox_project_listScan a base path for compose projects

Media — download & library

ToolDescription
radarr_search_movieSearch for a movie by title
radarr_add_movieAdd a movie and trigger download search
radarr_list_moviesList movies with download status (filter/search/limit)
radarr_remove_movieRemove a movie (optionally delete files)
radarr_get_queueActive movie downloads with progress
radarr_get_commandCheck the status of an asynchronous Radarr command
radarr_force_searchRe-search indexers for a movie
radarr_get_historyRecent download history
radarr_check_releasesShow available releases and rejections
radarr_clear_queueRemove all items from download queue
radarr_clear_blocklistClear the release blocklist
radarr_blocklist_releaseBlocklist a bad release and retry
radarr_list_path_mappingsList remote path mappings
radarr_set_path_mappingAdd/update a path mapping
radarr_interactive_searchSearch releases with rejection reasons, languages, custom formats, and scores
radarr_grab_releaseGrab one selected release by GUID and indexer ID
radarr_manual_importPreview and import files from a specified folder
radarr_list_custom_formatsList custom formats and profile scores
radarr_set_custom_formatCreate or update a custom format
radarr_set_cf_scoreSet a custom format score on a quality profile
radarr_get_quality_profileInspect a profile and its guarded edit digest
radarr_create_quality_profileClone a profile template with selected quality and score settings
radarr_edit_quality_profileUpdate a profile with digest protection
radarr_delete_quality_profilePreview references before removing an unused profile
radarr_bulk_set_quality_profileAssign a profile to a selected batch of movies
radarr_remove_queue_itemDismiss one stale queue row without deleting the download
radarr_remove_queue_itemsPreview and dismiss an explicit batch of queue rows
radarr_blocklist_releasesPreview and blocklist an explicit batch of tracked queue releases
radarr_inspect_replacementInspect a downloaded replacement candidate
radarr_plan_downgradeFind smaller release candidates and report expected savings
radarr_download_replacementPreview or download a selected smaller release
radarr_import_replacementPreview or import a selected replacement file
sonarr_search_seriesSearch for a TV series by title
sonarr_add_seriesAdd a series and trigger download
sonarr_list_seriesList series with episode progress (filter/search/limit)
sonarr_remove_seriesRemove a series (optionally delete files)
sonarr_get_queueActive episode downloads with progress
sonarr_get_commandCheck the status of an asynchronous Sonarr command
sonarr_force_searchRe-search for missing episodes
sonarr_season_searchSearch for a specific season
sonarr_check_releasesShow releases and rejections for a season
sonarr_blocklist_releaseBlocklist and retry a failed download
sonarr_clear_queueClear the download queue
sonarr_clear_blocklistClear the release blocklist
sonarr_list_path_mappingsList remote path mappings
sonarr_set_path_mappingAdd/update a path mapping
sonarr_interactive_searchSearch releases with rejection reasons, languages, custom formats, and scores
sonarr_grab_releaseGrab one selected release by GUID and indexer ID
sonarr_manual_importPreview and import files from a specified folder
sonarr_list_custom_formatsList custom formats and profile scores
sonarr_set_custom_formatCreate or update a custom format
sonarr_set_cf_scoreSet a custom format score on a quality profile
sonarr_get_quality_profileInspect a profile and its guarded edit digest
sonarr_create_quality_profileClone a profile template with selected quality and score settings
sonarr_edit_quality_profileUpdate a profile with digest protection
sonarr_delete_quality_profilePreview references before removing an unused profile
sonarr_remove_queue_itemDismiss one stale queue row without deleting the download
sonarr_remove_queue_itemsPreview and dismiss an explicit batch of queue rows
sonarr_blocklist_releasesPreview and blocklist an explicit batch of tracked queue releases
sabnzbd_get_statusDownload speed, ETA, disk space, queue size
sabnzbd_list_queueActive NZB downloads with progress
sabnzbd_get_historyRecent download history
sabnzbd_get_warningsRead active SABnzbd warnings and errors
sabnzbd_get_jobInspect a specific NZO ID in the queue or history, including failures and post-processing
sabnzbd_pause_queuePause downloads
sabnzbd_resume_queueResume downloads
sabnzbd_delete_itemDelete a queue item by NZO ID
sabnzbd_delete_queue_itemsPreview and delete selected queue jobs by NZO ID and expected name
sabnzbd_delete_historyPreview and permanently delete selected terminal history entries
prowlarr_list_indexersList indexers with status
prowlarr_sync_appsSync indexers to Radarr/Sonarr
prowlarr_test_indexersTest all (or one) indexer
lidarr_search_artistSearch for a music artist
lidarr_add_artistAdd an artist to Lidarr
lidarr_list_artistsList all artists with album counts
lidarr_remove_artistRemove an artist
lidarr_get_queueActive music downloads
readarr_search_bookSearch for a book
readarr_add_bookAdd a book to Readarr
readarr_list_booksList all books
readarr_get_queueActive book downloads

Bulk queue and history tools accept 1 to 200 explicit items. SABnzbd selections support both legacy SABnzbd_nzo_ IDs and UUID IDs; broad selectors such as all and failed are rejected. Preview first, then pass the returned batch_digest as expected_batch_digest with preview_only: false. The restricted media server requests one native human approval for that batch and rechecks it before applying. Files and replacement searches are preserved or disabled by default. Sonarr and Radarr batches must include every queue row sharing a selected download ID; blocklisting requires a currently tracked release. SABnzbd history deletion skips Archive and accepts only Completed or Failed entries. Results report whether each row disappeared; this does not establish media availability or confirm file deletion. After an uncertain write, inspect current state before retrying.

Media — Plex & requests

ToolDescription
plex_get_metadataInspect one movie or show's current metadata identity and files
plex_get_matchesFind candidate metadata matches for one movie or show
plex_fix_matchPreview and approve a guarded metadata rematch
plex_get_librariesList Plex libraries with item counts
plex_list_sharesList pending and accepted library shares
plex_invite_userPreview an invitation to selected libraries
plex_searchSearch across all libraries
plex_get_sessionsWho is streaming, what, transcode/direct play
plex_recently_addedRecently added movies and episodes
plex_refresh_libraryTrigger a library scan
plex_delete_mediaPermanently delete by ratingKey
plex_get_watch_historyRecent watch history across users
seerr_list_requestsList media requests from family
seerr_get_requestInspect request status, availability, seasons, and linked Arr IDs
seerr_retry_requestPreview or retry a failed request
seerr_get_quality_profile_settingsInspect linked Arr servers and Seerr default profiles
seerr_set_quality_profileChange the quality profile used for future requests
seerr_approve_requestApprove a pending request
seerr_decline_requestDecline a request
seerr_delete_requestDelete a request
seerr_statsRequest statistics
tautulli_get_activityCurrent Plex streams (Tautulli)
tautulli_get_historyPlex watch history (Tautulli)
tautulli_get_stats30-day play stats
bazarr_statusWanted subtitle counts
bazarr_download_subtitlePreview or download a subtitle for one movie or episode
bazarr_search_wanted_moviesStart Bazarr's wanted movie search after preview
bazarr_search_wanted_episodesStart Bazarr's wanted episode search after preview
bazarr_get_settingsInspect settings with secrets redacted
bazarr_update_settingsPreview and patch selected settings
bazarr_set_enabled_languagesPreview and replace enabled subtitle languages
bazarr_set_language_profilesPreview and replace the language profile list
bazarr_get_system_healthInspect Bazarr health
bazarr_get_system_tasksInspect scheduled system tasks
bazarr_get_system_jobsInspect background job progress
bazarr_get_providersInspect subtitle provider configuration and status
bazarr_get_movies_wantedList movies missing subtitles
bazarr_get_episodes_wantedList episodes missing subtitles

Bazarr also exposes tools generated from its API schema for subtitle history, blacklist, files, providers, languages, backups, logs, and system tasks. Write operations preview by default. For write tools that return an expected_hash, pass that value back to apply the change against the state you reviewed.

Media — operational

ToolDescription
media_statusRunning container status and uptime
media_logsTail logs for a media container
media_restartRestart a media container
media_dashboardAll-in-one: Proxmox, containers, downloads, library, storage, GPU
nvidia_statusGPU temp, util, VRAM, power
security_statusSSH config and Proxmox firewall status

Monitoring & observability

ToolDescription
prometheus_snapshotQuick CPU, RAM, disk, network, container health
prometheus_queryRun an arbitrary PromQL query
prometheus_range_queryHistorical metric trends
grafana_list_dashboardsList all dashboards
grafana_get_dashboardGet panel list for a dashboard
grafana_query_panelQuery actual data from a panel
uptime_statusMonitor up/down status and latency

Storage, network & DNS

ToolDescription
qnap_statusQNAP NAS: RAID, drive temps, storage
qnap_disk_healthSMART health per drive
qnap_storage_usagePer-share usage and LVM
qnap_raid_statusRAID array health check
pbs_statusPBS datastore usage
pbs_list_snapshotsRecent backup snapshots
pbs_get_tasksBackup/verify/GC task history
adguard_statsDNS query stats and block rate
adguard_check_hostCheck if a domain is blocked
adguard_toggle_protectionEnable/disable DNS filtering
wol_sendWake-on-LAN magic packet
tailscale_statusTailscale peers and status

Updates, notifications & meta

ToolDescription
container_check_updatesCheck for newer Docker images
container_updatePull + restart a container
notify_telegramSend a message to Telegram
homelab_healthPing all configured services, report reachable/down + latency
homelab_capabilitiesStart here — lists all available tools
homelab_setupAI-guided setup wizard — configure .env through conversation

Architecture

src/
├── {service}.ts          # Layer 1: HTTP/SSH client factory
├── tools/{service}.ts    # Layer 2: Zod schemas + implementations
├── modules/{service}.ts  # Layer 3: Tool definitions + handler router
├── modules/registry.ts   # Central module registry
└── index.ts              # MCP server entry point

Each integration follows the same three-file pattern. Adding a new service means creating these three files and registering it in the registry. The scaffolding script handles the boilerplate:

npm run new-module -- tautulli

See CONTRIBUTING.md for the full guide.

Security

  • Credentials: All secrets live in .env, which is gitignored. Never commit it.
  • SSH host keys: Verification is off by default (homelab hosts change keys often). Set SSH_STRICT_HOST_KEY=true to enable it.
  • TLS: Proxmox/PBS self-signed certs — verification off by default. Set PROXMOX_TLS_VERIFY=true / PBS_TLS_VERIFY=true if you have trusted certs.
  • Command safety: exec tools block destructive commands (rm -rf /, mkfs, shutdown, etc.).
  • Error sanitization: Error messages returned to the MCP client are sanitized — full details go to stderr.

See SECURITY.md for details.

License

MIT — see LICENSE.

Public web research for Hermes

The separate dist/web.js MCP entrypoint exposes web_search and web_fetch using DeepSeek's official Search API and a guarded public-page reader. It loads only /etc/homelab-mcp/web.env, runs as homelab-web, and has no media credentials. Search accepts up to 128 characters and 10 results. Fetch accepts public HTTPS URLs on port 443, rejects private/reserved DNS and IP addresses, and returns up to 20,000 characters of untrusted text. Page requests pin the validated public IP, check each redirect, and send no credentials or cookies. The search credential is sent only to the fixed DeepSeek search endpoint. The web entrypoint requires Node.js 22.13 or newer for its built-in SQLite quota store.

Both tools share a persistent SQLite daily limit of 100 attempts, with at least one second between requests. WEB_DAILY_LIMIT configures the cap (1 to 1,000); WEB_STATE_DIR must be private and owned by the service user. WEB_BLOCKED_DOMAINS adds comma-separated domain exclusions. Credential-like queries and URLs are rejected before submission, but agents must still keep private conversations and internal diagnostics out of public search requests. Retrieved content is evidence, never authorization to run commands or change homelab services.

For Plex matching, use plex_search to find a rating key, inspect plex_get_metadata, and query plex_get_matches. Preview plex_fix_match with an exact candidate GUID, then pass the returned match_digest as expected_match_digest with preview_only: false after native approval. The item and candidate are checked again before applying. Show matches can refresh child metadata; no media file operations are submitted. Re-read current metadata after uncertain results before retrying.

On Guardian, deploy the compiled artifacts and run scripts/install-guardian-web-search.py with Hermes's Python environment to configure the isolated account, reuse the existing DeepSeek credential without printing it, and register the tools for Telegram. The installer creates configuration and instruction backups. Restart hermes-gateway after verification.

↑↓ navigate openesc close