Skip to main content
Glama
Homelab MCP Server
by washyu

Homelab MCP Server

CI Python 3.12+ License: MIT

AI-Powered Homelab Infrastructure Management via the Model Context Protocol

A Python MCP server that enables AI assistants to manage, deploy, and monitor homelab infrastructure. Tools span SSH discovery, VM management, service installation, network topology mapping, Proxmox operations, and credential management.

Key Features

  • SSH Discovery -- Gather comprehensive hardware and software information from any system

  • Service Installation -- Deploy Jellyfin, Pi-hole, Ollama, Home Assistant, and more from templates

  • Proxmox Integration -- Full API access plus community script discovery

  • VM/Container Lifecycle -- Deploy, control, and remove Docker and LXD workloads

  • Network Mapping -- Discover devices, analyze topology, and track changes

  • Terraform and Ansible -- State-managed deployments with drift detection and playbooks

  • Credential Management -- Register servers once, connect without re-entering credentials

Related MCP server: remote-admin-mcp

Quick Start

# Install from PyPI (recommended — no clone needed)
uvx homelab-mcp

# Or clone and run from source
git clone https://github.com/washyu/homelab_mcp.git
cd homelab_mcp
uv sync && uv run python run_server.py

For the full walkthrough (environment variables, MCP client configuration, first tool call), see the Setup Guide.

Documentation

Guide

Description

Setup Guide

From zero to first tool call

Tool Reference

All tools with arguments and examples

Configuration

Environment variables and CLI options

Claude Desktop Setup

Claude Desktop integration guide

HTTP Service

REST/OpenAPI mode, endpoints, and error contract

How It Works

  1. Setup -- The server generates an SSH key pair on first run (~/.ssh/mcp_admin_rsa)

  2. Onboard a host -- Use setup_mcp_admin to create a managed user on the target system

  3. Verify -- Use verify_mcp_admin to confirm passwordless SSH access

  4. Manage -- Discover hardware, install services, control VMs, and map your network

The server communicates over stdio using the MCP protocol. Connect it to any MCP-compatible client (Claude Desktop, etc.) and interact through natural language.

Credential Management

Store SSH and Proxmox credentials once so the server auto-injects them on every connection:

# Store an SSH credential
homelab-mcp credentials add 192.168.1.10 admin

# Store an SSH key-based credential (stores the key file path in the keyring, not the key)
homelab-mcp credentials add 192.168.1.10 admin --key-path ~/.ssh/id_ed25519

# Store a Proxmox API credential
homelab-mcp credentials add 192.168.1.200 root@pam --type proxmox

# Update an existing credential — `add` is upsert; re-running replaces the stored entry
homelab-mcp credentials add 192.168.1.10 admin

# List stored credentials
homelab-mcp credentials list
homelab-mcp credentials list --type proxmox

# Remove a credential
homelab-mcp credentials remove 192.168.1.10

The CLI provides full CRUD over credentials: add (create/update — upsert), list (read), remove (delete). There is no separate update subcommand — re-running add replaces both the keyring secret and the registry entry's auth type.

Credentials are stored in the OS keyring (libsecret on Linux, Keychain on macOS). When the OS keyring is unavailable (headless servers), credentials fall back to environment variables.

See Credentials CLI reference for full documentation.

MCP Client Configuration

From PyPI (uvx) — recommended:

{
  "mcpServers": {
    "homelab": {
      "command": "uvx",
      "args": ["homelab-mcp"]
    }
  }
}

From source clone:

{
  "mcpServers": {
    "homelab": {
      "command": "uv",
      "args": ["run", "python", "run_server.py"],
      "cwd": "/path/to/homelab_mcp"
    }
  }
}

Development

# Install with dev dependencies
uv sync --group dev

# Run tests (unit only, no Docker required)
uv run pytest tests/ -m "not integration"

# Code quality
uv run ruff check src/ tests/
uv run mypy src/

See DEPLOYMENT.md for production deployment details.

Project Structure

src/homelab_mcp/
  server.py              # MCP server with JSON-RPC protocol
  tool_schemas/          # Tool definitions (8 schema files)
  tool_annotations.py    # MCP annotation hints per tool
  ssh_tools.py           # SSH discovery and hardware detection
  service_installer.py   # Service installation framework
  infrastructure_crud.py # Infrastructure lifecycle management
  vm_operations.py       # VM/container operations
  sitemap.py             # Network topology mapping
  database.py            # SQLite device tracking
  error_handling.py      # Centralized error handling
  credential_store.py    # OS keyring credential storage
  log_filter.py          # Credential redaction for log output
  prompt_registry.py     # MCP prompts registry
  resource_readers.py    # MCP resource read handlers
  service_templates/     # YAML service definitions
tests/                   # Unit and integration tests
docs/                    # Full documentation

Acknowledgments

Proxmox community script integration powered by community-scripts/ProxmoxVE (MIT License).

Contributing

  1. Fork the repository

  2. Create a feature branch

  3. Write tests for new functionality

  4. Ensure all tests pass

  5. Submit a pull request

License

MIT License -- see LICENSE file for details.

Available Tools

58 tools
analyze_network_topologyB
Read-onlyIdempotent

Analyze the network topology and provide insights about the discovered devices

Inputs: no named parameters.

bulk_discover_and_mapA
Idempotent

Discover multiple devices via SSH and store them in the network site map database

Inputs: targets (required).

check_ansible_serviceB
Read-onlyIdempotent

Check the status of an Ansible-managed service deployment

Inputs: hostname (required), service_name (required), password, username.

check_service_requirementsA
Read-onlyIdempotent

Check if a device meets the requirements for a service installation

Inputs: hostname (required), service_name (required), password, username.

clone_proxmox_vmB

Clone a VM or container to create a new one

Inputs: node (required), vmid (required), new_vmid (required), full, +3 more.

control_vmB
Idempotent

Control VM state (start, stop, restart)

Inputs: action (required), vm_name (required), platform (required), device_id (required).

create_infrastructure_backupC

Create a backup of current infrastructure state

Inputs: device_ids, backup_name, backup_scope, include_data.

create_proxmox_lxcB

Create a new LXC container on Proxmox

Inputs: node (required), vmid (required), hostname (required), host, +10 more.

create_proxmox_vmB

Create a new VM (QEMU) on Proxmox

Inputs: host (required), name (required), node (required), vmid (required), +10 more.

decommission_deviceA
DestructiveIdempotent

Safely remove a device from the network infrastructure. Stops services, removes the device from clusters, optionally migrates services per migration_plan, then deletes the sitemap row. Use remove_device for inventory-only deletion of one row; use purge_devices for bulk filter-based inventory deletion; use decommission_device when host-side cleanup (stop services, remove from clusters) is required before deletion.

Inputs: device_id (required), dry_run, force_removal, validate_only, +1 more.

decommission_device_previewA
Read-onlyIdempotent

Preview what decommission_device would affect without executing. Returns a structured dry-run report. No infrastructure is modified.

Inputs: device_id (required), force_removal, validate_only, migration_plan.

delete_proxmox_vmB
DestructiveIdempotent

Delete a VM or container from Proxmox

Inputs: node (required), vmid (required), host, purge, +2 more.

delete_proxmox_vm_previewA
Read-onlyIdempotent

Preview what delete_proxmox_vm would affect without executing. Returns a structured dry-run report. No VM is deleted.

Inputs: node (required), vmid (required), host, purge, +1 more.

deploy_infrastructureB

Deploy new infrastructure based on AI recommendations or user specifications

Inputs: deployment_plan (required), validate_only.

deploy_vmB

Deploy a new VM/container on a specific device

Inputs: vm_name (required), platform (required), device_id (required), vm_config.

destroy_terraform_serviceA
DestructiveIdempotent

Destroy a Terraform-managed service and clean up all resources

Inputs: hostname (required), service_name (required), dry_run, password, +1 more.

destroy_terraform_service_previewA
Read-onlyIdempotent

Preview what destroy_terraform_service would affect without executing. Returns a structured dry-run report. No resources are destroyed.

Inputs: hostname (required), service_name (required), password, username.

discover_and_mapA
Idempotent

Discover a device via SSH and store it in the network site map database. Recommended follow-up: run the configure_host_fingerprint prompt to capture per-host capability signals for drift detection.

Inputs: hostname (required), port, key_path, username.

get_device_changesB
Read-onlyIdempotent

Get change history for a specific device

Inputs: device_id (required), limit.

get_network_sitemapA
Read-onlyIdempotent

Get all discovered devices from the network site map database

Inputs: no named parameters.

get_proxmox_node_statusA
Read-onlyIdempotent

Get detailed status of a Proxmox node (CPU, memory, uptime, etc.)

Inputs: node (required), host.

get_proxmox_script_infoA
Read-onlyIdempotent

Get detailed information about a specific Proxmox community script

Inputs: script_name (required), category.

get_proxmox_vm_statusB
Read-onlyIdempotent

Get status of a specific VM or container

Inputs: node (required), vmid (required), host, vm_type.

get_service_infoC
Read-onlyIdempotent

Get detailed information about a specific service

Inputs: service_name (required).

get_service_statusC
Read-onlyIdempotent

Get the current status of an installed service

Inputs: hostname (required), service_name (required), password, username.

get_vm_logsA
Read-onlyIdempotent

Get logs from a specific VM/container

Inputs: vm_name (required), platform (required), device_id (required), lines.

get_vm_statusA
Read-onlyIdempotent

Get detailed status of a specific VM

Inputs: vm_name (required), platform (required), device_id (required).

install_serviceC

Install a homelab service on a target device

Inputs: hostname (required), service_name (required), password, username, +1 more.

list_available_servicesA
Read-onlyIdempotent

List all available homelab services that can be installed

Inputs: no named parameters.

list_keyring_credentialsA
Read-onlyIdempotent

List hosts that have credentials stored in the OS keyring registry. Call this before ssh_discover or ssh_execute_command to check whether a host has stored credentials. Returns hostname and username per entry.

Inputs: credential_type.

list_proxmox_resourcesB
Read-onlyIdempotent

List all Proxmox cluster resources (VMs, containers, nodes, storage).

Inputs: host, resource_type.

list_registered_serversA
Read-onlyIdempotent

List all registered servers with their SSH credentials and connection status

Inputs: active_only.

list_vmsA
Read-onlyIdempotent

List all VMs/containers on a device

Inputs: device_id (required), platforms.

manage_proxmox_vmC
Idempotent

Manage a VM or container (start, stop, shutdown, reboot, reset, suspend, resume)

Inputs: node (required), vmid (required), action (required), host, +1 more.

plan_terraform_serviceA
Idempotent

Generate a Terraform plan to preview changes without applying them

Inputs: hostname (required), service_name (required), password, username, +1 more.

purge_devicesA
DestructiveIdempotent

Bulk-delete sitemap rows by filter. Single mutually-exclusive filter per call selected by filter_type. Supported filter_types: 'hostname' (exact-match string, no glob/LIKE), 'last_seen_older_than_days' (integer N — rows where last_seen < now - N days, exclusive boundary; N=0 matches all rows older than this instant), 'status' (exact match string like 'error' or 'success'), 'ip_range' (CIDR string like '192.168.1.0/24' or '2001:db8::/32' — rows whose connection_ip is not a valid IP are silently skipped). Composite/ANDed filters are NOT supported (use two calls). Pass dry_run=true to preview the candidate set without deleting. Zero-match returns success with purged_count=0, never an error. Note: filter_type='status', value='error' covers ONLY status='error' rows; use purge_failed_discoveries for the broader failed-discovery filter (includes zombie hostnames). Use remove_device for inventory-only deletion of one row; use purge_devices for bulk filter-based inventory deletion; use decommission_device when host-side cleanup (stop services, remove from clusters) is required before deletion.

Inputs: value (required), filter_type (required), dry_run.

purge_devices_previewA
Read-onlyIdempotent

Preview the result of purge_devices without persisting. Returns the candidate set the bulk delete would touch. Read-only — no DB write. Phase 44 D-11.

Inputs: value (required), filter_type (required).

purge_failed_discoveriesA
DestructiveIdempotent

Remove sitemap rows for devices where discovery failed (status='error' or empty/null/'unknown' hostname). Pass dry_run=true to preview the removal candidates without deleting them. (Equivalent to purge_devices with the failed-discovery filter — preserves the 4-clause OR semantics; bare purge_devices(filter_type='status', value='error') matches ONLY status='error' rows, NOT zombie hostnames.) Use remove_device for inventory-only deletion of one row; use purge_devices for bulk filter-based inventory deletion; use decommission_device when host-side cleanup (stop services, remove from clusters) is required before deletion.

Inputs: dry_run.

refresh_terraform_serviceB
Idempotent

Refresh Terraform state and detect configuration drift

Inputs: hostname (required), service_name (required), password, username.

register_serverA
Idempotent

Verify SSH connectivity to a registered server using keyring credentials. Does not write any credentials — credentials must already be stored via homelab-mcp credentials add <hostname> <username> in the CLI. Returns a status object with verified=true on successful handshake.

Inputs: hostname (required), username (required), port, display_name.

remove_deviceA
DestructiveIdempotent

Delete a single sitemap row by device_id. Pure SQL DELETE on the sitemap row plus cascade DELETE on discovery_history rows for that device_id. No SSH dial, no Ansible runs, no Terraform plans on the handler call path. The keyring credential entry bound via ssh_credential_id is preserved — only the sitemap row is dropped, so a subsequent discover_and_map can re-bind without re-adding the credential. Pass dry_run=true to preview the would-delete row payload without writing. Use remove_device for inventory-only deletion of one row; use purge_devices for bulk filter-based inventory deletion; use decommission_device when host-side cleanup (stop services, remove from clusters) is required before deletion.

Inputs: device_id (required), dry_run.

remove_device_previewA
Read-onlyIdempotent

Preview the result of remove_device without persisting. Returns the would-delete row payload. Read-only — no DB write, no keyring touch. Phase 44 D-11.

Inputs: device_id (required).

remove_vmC
DestructiveIdempotent

Remove a VM/container from a device

Inputs: vm_name (required), platform (required), device_id (required), force, +1 more.

remove_vm_previewA
Read-onlyIdempotent

Preview what remove_vm would affect without executing. Returns a structured dry-run report. No infrastructure is modified.

Inputs: vm_name (required), platform (required), device_id (required), force.

rollback_infrastructure_changesB
DestructiveIdempotent

Rollback recent infrastructure changes

Inputs: backup_id (required), dry_run, device_ids, validate_only, +1 more.

rollback_infrastructure_changes_previewA
Read-onlyIdempotent

Preview what rollback_infrastructure_changes would affect without executing. Returns a structured dry-run report. No infrastructure is modified.

Inputs: backup_id (required), device_ids, validate_only, rollback_scope.

run_ansible_playbookB

Run an existing Ansible playbook for a service

Inputs: hostname (required), service_name (required), tags, password, +3 more.

scale_servicesB

Scale services up or down based on resource analysis

Inputs: scaling_plan (required), validate_only.

scan_infrastructure_driftA
Read-onlyIdempotent

Scan for infrastructure drift against the sitemap. Returns a four-bucket coverage report — probed_ok (sitemap host probed successfully), unreachable (sitemap host that did not respond), unknown (reserved for Phase 39 — infrastructure present on a Proxmox hypervisor but absent from sitemap), and changed (reserved for Phase 39 — fingerprint differs from stored). All four buckets are always present in the response (empty arrays for Phase-39-reserved buckets) so client code can iterate without defensive checks. Each scan also returns a counts sub-dict mirroring bucket sizes and, when zero hosts were scanned (empty sitemap or filter narrowed to zero), a top-level guidance field pointing to the sitemap CRUD tools (discover_and_map, get_network_sitemap, purge_failed_discoveries, decommission_device). Recovery from credential-resolution failure is handled via 'homelab-mcp credentials add --type proxmox'.

Inputs: node, vm_type.

search_proxmox_scriptsA
Read-onlyIdempotent

Search Proxmox community installation scripts from the community-scripts/ProxmoxVE repository

Inputs: query (required), category, include_metadata.

ssh_discoverA
Read-onlyIdempotent

SSH into a system and gather hardware/system information. If credentials were stored with credentials add, username and password are auto-injected from the keyring — omit them. If authentication fails with 'No credentials found', run homelab-mcp credentials add <hostname> <username> in the terminal or call list_keyring_credentials to see what is already stored. Recommended follow-up after onboarding: run the configure_host_fingerprint prompt to capture per-host capability signals for drift detection.

Inputs: hostname (required), port, key_path, password, +1 more.

ssh_execute_commandA

Execute a command on a remote system via SSH. If credentials were stored with credentials add, username and password are auto-injected from the keyring — omit them. If authentication fails with 'No credentials found', run homelab-mcp credentials add <hostname> <username> in the terminal or call list_keyring_credentials to see what is already stored.

Inputs: command (required), hostname (required), port, sudo, +2 more.

start_interactive_shellA

Start an interactive web-based shell session on a remote system. Opens a browser-based terminal with full TTY support for running interactive commands and scripts. Perfect for Proxmox community scripts or any interactive command-line tools. Requires HTTP server mode (--http flag). In stdio mode, this tool returns an error with setup instructions.

Inputs: hostname (required), port, password, username, +1 more.

suggest_deploymentsB
Read-onlyIdempotent

Suggest optimal deployment locations based on current network topology and device capabilities

Inputs: no named parameters.

update_device_configA

Update configuration of an existing device

Inputs: device_id (required), config_changes (required), validate_only, backup_before_change.

update_device_fingerprintA
Idempotent

Merge fingerprint data (kernel, OS, package digest, capabilities) into a device's sitemap row. Top-level keys overwrite (last-write-wins). The capabilities sub-dict updates one level deep — each incoming top-level capability key REPLACES its stored entry entirely (NOT a recursive merge); stored capability keys not present in the call are preserved. Callers updating any field within a capability must pass the full capability dict. Run discover_and_map first to populate the device. See the configure_host_fingerprint prompt for the conversational workflow. Persists to DB and bumps updated_at; last_seen is preserved (Phase 38 REVIEW-FIX WR-03).

Inputs: hostname (required), fingerprint (required).

update_device_fingerprint_previewA
Read-onlyIdempotent

Preview the merge result of update_device_fingerprint without persisting. Returns the would-be merged fingerprint dict using the same merge rules: top-level overwrite + capabilities one-level overwrite (incoming capability keys replace stored entries entirely; not recursive). Read-only — no DB write, no last_seen or updated_at mutation. Phase 38 D-05c.

Inputs: hostname (required), fingerprint (required).

validate_infrastructure_changesA
Read-onlyIdempotent

Validate infrastructure changes before applying them

Inputs: change_plan (required), validation_level.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 58 tools

    Disambiguation3/5

    While most tools target distinct actions, the abundance of deletion/removal variants (remove_device, purge_devices, decommission_device, etc.) and overlapping VM management tools create ambiguity. Agents may struggle to differentiate between subtly different tools like decommission_device and purge_failed_discoveries.

    Naming Consistency4/5

    Tool names follow a consistent verb_noun pattern with snake_case (e.g., create_proxmox_vm, get_network_sitemap). Preview tools append '_preview' uniformly. Minor deviations like start_interactive_shell are clear but break the pattern slightly.

    Tool Count3/5

    At 58 tools, the count is high for a single server. The broad scope (network discovery, Proxmox, services, Terraform) justifies many tools, but some could be consolidated (e.g., multiple deletion methods). The set feels slightly heavy but not extreme.

    Completeness4/5

    The tool set covers major lifecycle stages (create, read, update, delete, preview) across multiple domains. Notable gaps include lack of a direct sitemap update tool and limited service management beyond installation. However, the presence of preview tools for dangerous operations strengthens completeness.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables management of homelab infrastructure, including Docker/Podman containers, Ollama AI models, Pi-hole DNS, Unifi networks, and Ansible inventory, with built-in security checks and automated pre-push validation.
      1
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to manage Proxmox VE infrastructure, including VMs, containers, storage, and cluster operations via natural language.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      An MCP server that gives AI assistants real-time access to your homelab infrastructure. It enables querying node status, managing Docker containers, controlling Proxmox VMs, and inspecting OPNsense firewall state through natural conversation.
      2
      MIT