Skip to main content
Glama

MCP Hub

One MCP server that gives your AI assistant the keys to your whole homelab.

Release License: MIT Python 3.11+ MCP CI

MCP Hub is a single Model Context Protocol server that sits on one machine in your network and fans out from there: SSH to every host in your fleet, Proxmox containers, Docker, Synology DSM, Cloudflare tunnels and DNS, n8n workflows, Notion, your password vault. Instead of running a dozen MCP servers and wiring each one into your client, you run one and point your assistant at it.

"Why is Jellyfin unreachable?" — and the assistant checks the container, reads the journal, notices the tunnel ingress is stale, fixes it, and tells you what it did.

⚠️ Read SECURITY.md before you deploy this. MCP Hub hands an LLM root shell access across your fleet. That is the point of it, and it is genuinely dangerous. Defaults are safe (127.0.0.1, read-only); the danger starts when you change them.

Troubleshooting demo

The repository includes a sanitized Asciinema recording of a complete, observation-first troubleshooting session: failed endpoint, systemd diagnosis, exact mutation plan, explicit confirmation, restart, and final health checks. It uses the example inventory and contains no private infrastructure data.

asciinema play docs/troubleshooting.cast

See the recording directly when Asciinema is not installed; the cast format is newline-delimited JSON and remains reviewable.

Related MCP server: homelab-mcp

Contents

Features

  • 103 tools, one endpoint, one config file.

  • Config-driven. Your network lives in hosts.yaml and .env. Nothing about your infrastructure is baked into the code.

  • Multiplexed SSH. Persistent control sockets, so fleet-wide commands take milliseconds rather than a TCP handshake each.

  • Optional integrations. Every integration is off by default and enabled with a single flag. Run it as a pure SSH fleet tool if that is all you want.

  • Pluggable secrets. Read credentials from the environment, or from a Bitwarden/Vaultwarden vault via bw serve.

  • Bearer-token authentication on top of an unguessable endpoint path.

  • Global read-only mode, on by default: one flag disables all 39 mutating tools, enforced centrally rather than tool by tool.

  • Automatic secret redaction in file reads and command output.

  • Background jobs with polling, logs, and a persistent SQLite state store.

Quick start

Requires Python 3.11+ and a Linux host with SSH access to the machines you want to manage.

git clone https://github.com/wnx82/mcp-hub.git
cd mcp-hub

python3 -m venv .venv && . .venv/bin/activate
pip install -e .

cp .env.example .env                  # then edit — see below
cp hosts.example.yaml hosts.yaml      # then edit: your fleet
chmod 600 .env hosts.yaml

python server.py

At minimum, set these two in .env:

MCP_SECRET_PATH=/$(openssl rand -hex 16)   # unguessable endpoint path
MCP_AUTH_TOKEN=$(openssl rand -hex 32)     # bearer token — the real auth

The server then listens on http://127.0.0.1:8000<MCP_SECRET_PATH>, with MCP_READ_ONLY=true. Point your MCP client at that URL and send Authorization: Bearer <MCP_AUTH_TOKEN>. Requests without the token get a 401; requests to any other path get a 404.

For a systemd deployment, sudo ./deploy/install.sh creates a dedicated mcphub user and SSH key, generates both secrets into /etc/default/mcp-hub, and installs the unit. It is idempotent and never overwrites existing config. See deploy/.

For a complete Claude Code setup, safe token handling, connection checks, a first read-only prompt, and the current Claude Desktop limitation, see Connect MCP Hub to Claude.

If you want your assistant to understand your private topology, host roles, change windows, and MCP operating rules without committing any of that data, start from PROJECT_INSTRUCTIONS.example.md and keep your customized PROJECT_INSTRUCTIONS.md local-only.

Deployment

MCP Hub supports three execution modes:

Mode

Intended use

Command

Support level

Editable package

Development and contributions

pip install -e ".[dev]" then mcp-hub

Supported for development

Direct source execution

Quick local evaluation

python server.py

Supported, operator manages the process

systemd installation

Persistent homelab deployment

sudo ./deploy/install.sh

Recommended for production

The Python package and direct execution use the current checkout and its virtualenv. They do not create a service account, SSH key, environment file, or restart policy. The systemd installer provisions those operational pieces, keeps local configuration intact when rerun, and installs Rescue outside the hub virtualenv.

Container images are not an official deployment target yet. The hub needs network access, an SSH identity, persistent state.db, and access to its local inventory; operators packaging it in a container must preserve those properties themselves.

See docs/docker-packaging.md for the current requirements and what an official image would need to guarantee before it could be recommended.

Local testing

For a contributor-focused checklist covering lint, unit tests, tool registration, generated docs, installer smoke tests, and a manual read-only run, see docs/testing-local.md.

Before opening a PR or publishing a branch, you can also run the local release readiness checks:

python3 scripts/check_repo_hygiene.py
python3 scripts/check_tool_annotations.py
python3 scripts/check_security_readiness.py

To wire the security readiness check into Git automatically on push:

./scripts/install_pre_push_hook.sh

Architecture

server.py remains the FastMCP composition root while domain code is moving incrementally into tools/. SSH command construction, Cloudflare paths and response extraction, DSM protocol metadata, inventory, and playbook builders are already isolated. tools/registry.py assigns extracted tools to a domain; that domain is included in each audit summary. New protocol logic should live in its domain module and must not import server.py.

Future integrations are prioritized in docs/integration-evaluation.md, including their least-privilege scope and promotion gates.

Rescue diagnostics

mcp-hub-rescue is a read-only local CLI designed to keep working when the main server cannot import or its virtualenv is broken. The systemd installer copies it to /opt/mcp-hub-rescue and runs it with the system Python, outside the MCP Hub process and virtualenv.

sudo mcp-hub-rescue doctor
sudo mcp-hub-rescue status
sudo mcp-hub-rescue health
sudo mcp-hub-rescue logs --lines 50
sudo mcp-hub-rescue validate-config

Results are structured JSON. Rescue never imports server.py, tools/*, MCP, or an optional integration, and this boundary is enforced by CI. The current commands only observe and diagnose; restart, repair, and rollback operations will be added separately with confirmation and last-known-good safeguards.

Configuration

All git-ignored — each has a tracked .example template:

File

Purpose

Required

.env

Ports, auth, feature flags, API tokens

yes

hosts.yaml

Fleet inventory: hostnames, users, roles, tags

yes

topology.yaml

Curated overlay: guest mapping, recycled-IP traps, do-not-touch list

no

endpoints.yaml

HTTP health probes for endpoints_health

no

A host entry is minimal by design:

hosts:
  nas:
    hostname: nas.example.lan
    user: admin
    role: storage
    tags: [nas, backup]
    mac: "aa:bb:cc:dd:ee:01"   # optional, enables wake_host()

Tags are how you address groups: fleet_exec(tag="backup", command="df -h"). For a copy-ready two-host inventory, start with docs/examples/hosts.minimal.yaml. The larger hosts.example.yaml demonstrates every supported host option.

Pair it with docs/examples/topology.guarded.yaml to map Proxmox guests, record stale-address traps, and surface infrastructure that must not be changed casually. The _do_not_touch entries are operational context for the assistant, not an enforced access-control boundary; use token profiles and host restrictions for technical enforcement.

Add docs/examples/endpoints.minimal.yaml to monitor always-on and intermittent HTTP services. Call endpoints_health() for the regular set, or endpoints_health(include_intermittent=true) to include services that may normally be powered off. Responses from 200 through 399 count as healthy; redirects are not followed.

The complete defaults, limits, integration settings, and secret-handling notes are in the environment variable reference.

Pair those tracked examples with a private, untracked PROJECT_INSTRUCTIONS.md so your assistant sees topology caveats, maintenance windows, naming conventions, and "do not touch" guidance that should not live in the repository.

Tool reference

Every tool returns the same top-level envelope:

{
  "ok": true,
  "data": {},
  "error": null,
  "duration_ms": 12,
  "host": "example",
  "request_id": "4d52b1f69b974b7784bf65dd",
  "tool": "system_info"
}

data contains the tool-specific payload. Security refusals and controlled exceptions use the same shape with ok: false, making chained calls and audit correlation predictable.

The central tool wrapper also bounds request size, calls per token, concurrent calls per target, repeated target failures, and mutation frequency. Defaults are documented in .env.example; limit refusals use the same response envelope and audit trail as every other call.

Group

Tools

Fleet & shell

list_hosts topology get_topology system_info get_system_info remote_exec local_exec fleet_exec batch_exec read_file service_ctl journal_query get_journal_entries apt_status list_package_updates ssh_reset_control wake_host dhcp_reservations endpoints_health infra_snapshot destroy_resource

Proxmox & containers

proxmox_list list_proxmox_guests proxmox_ct_status proxmox_ct_exec ct_exec ct_write_file pbs_status docker_ps list_docker_containers docker_exec

Synology DSM

dsm_health dsm_system_info dsm_storage dsm_shares dsm_packages dsm_package_control dsm_updates dsm_connections dsm_logs dsm_power dsm_file_list dsm_file_search dsm_download_list dsm_download_create dsm_download_control dsm_api dsm_relogin

Cloudflare

cloudflare_tunnels_list list_cloudflare_tunnels cloudflare_tunnel_get cloudflare_tunnel_config_get cloudflare_tunnel_config_update cloudflare_dns_list cloudflare_dns_create cloudflare_dns_delete cf_ingress_dump get_cloudflare_tunnel_ingress cloudflare_api

n8n

n8n_health n8n_list_workflows n8n_get_workflow n8n_activate_workflow n8n_deactivate_workflow n8n_list_executions n8n_get_execution n8n_call_webhook

Notion

notion_search notion_get_page notion_create_page notion_update_page notion_archive_page notion_query_database notion_get_block_children notion_append_blocks notion_append_table_row notion_delete_block notion_reload_token

Vault

vault_search vault_get_item vault_get_field vault_create_item vault_update_item vault_list_folders

LM Studio

lmstudio_status lmstudio_load lmstudio_unload

Guided diagnostics

diagnose_service diagnose_endpoint audit_host check_backup_chain

Jobs & introspection

job_run job_status job_list job_logs mcp_health get_mcp_health mcp_stats get_mcp_stats audit_export plan_mutation confirm_mutation rollback_change

The complete generated tool reference expands every group into a table with each tool's exact signature and model-facing description. CI verifies it against the registered functions.

Guided diagnostics always stop after observation. They return evidence, assessment, and suggested next steps with correction_applied: false; check_backup_chain is a freshness and storage signal, not proof that a restore will succeed.

Security

MCP Hub is a remote code execution service by design. Before exposing it:

  • Keep the default 127.0.0.1 bind, or put it behind a tunnel with access policies.

  • Set MCP_AUTH_TOKEN — the secret URL path is obscurity, not authentication.

  • Leave MCP_READ_ONLY=true until you trust what your model does with it.

  • Keep the resource-guard defaults enabled, then tune them from observed audit traffic rather than disabling them.

  • Give it a dedicated SSH key and a minimal hosts.yaml.

Full threat model, hardening guide, and vulnerability reporting: SECURITY.md.

For a local pre-publish checklist and optional Git hook that catches common secret-leak mistakes before push, see scripts/check_security_readiness.py and scripts/install_pre_push_hook.sh.

Versioning

SemVer. Pre-1.0, breaking changes bump the minor — so read the Changed and Removed notes before upgrading one. _version.py is the single source of truth; the running server reports it via mcp-hub --version, in the MCP handshake, and in mcp_health.

Every release is documented in CHANGELOG.md, with security-relevant changes called out in their own section.

Contributing

Issues and pull requests are welcome — bug reports, new integrations, and documentation fixes especially. See CONTRIBUTING.md.

License

MIT © wnx82

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
2Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

  • A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/wnx82/mcp-hub'

If you have feedback or need assistance with the MCP directory API, please join our Discord server