homelab-mcp

homelab-mcp

Lets MCP clients (Claude Code, Claude Desktop) inspect a Linux home server's health over the network: uptime, load, memory, disk, Docker containers, systemd services, journal errors, and listening ports. Read-only, bearer-token secured.

Category
访问服务器

README

homelab-mcp

A local-network MCP server that lets an MCP client (Claude Code, Claude Desktop) inspect a Linux home server's health over the network — uptime, load, memory, disk space, Docker containers, systemd services, journal errors, and listening ports.

Built with FastMCP, the official Python MCP SDK's high-level server framework.

This server is strictly read-only. No tool it exposes can modify system state, restart a service, start/stop a container, or execute an arbitrary command. It exists purely so you can ask "why is my server using so much CPU right now?" or "did that container crash again?" from a Claude client, without SSHing in yourself.

Security model

  • Bearer token auth. Every request must include Authorization: Bearer <token>. The token lives in HOMELAB_MCP_TOKEN (loaded from a .env file, never committed) and is checked with hmac.compare_digest to avoid timing attacks. Missing or wrong tokens get a 401.
  • Read-only by design. Every tool is implemented with a safe, non-mutating API (psutil, shutil.disk_usage, docker-py) or, where a subprocess is unavoidable (systemctl, journalctl), a fixed argument list with shell=True never used and any user-supplied parameter validated against a strict allowlist/regex before it touches the command line.
  • No rate limiting or lockout. This server does not throttle or lock out repeated failed auth attempts. Do not expose it on the open internet, even with the token in place. Run it behind Tailscale or WireGuard, or bind it to a LAN-only / loopback interface via HOMELAB_MCP_HOST. Treat the bearer token like a password: anyone who has it and can reach the port has full read access to your server's health data.

Setup

Requires Python 3.11+ and uv (or plain pip).

git clone https://github.com/VedantDesai11/homelab-mcp.git
cd homelab-mcp

cp .env.example .env
# edit .env: set HOMELAB_MCP_TOKEN to a strong random value, e.g.
#   python3 -c "import secrets; print(secrets.token_urlsafe(32))"

uv sync
# or: pip install -e .

Running locally

uv run homelab-mcp
# or: uv run python -m homelab_mcp.server

By default it binds 0.0.0.0:8811. Override with HOMELAB_MCP_HOST / HOMELAB_MCP_PORT in .env or the environment. The server exits immediately with a clear error if HOMELAB_MCP_TOKEN is unset.

The MCP endpoint is served at http://<host>:<port>/mcp over Streamable HTTP.

Running via systemd

For a persistent deployment on the home server itself:

  1. Copy the project to /opt/homelab-mcp (or wherever you like) and run uv sync there so /opt/homelab-mcp/.venv exists.

  2. Copy .env.example to /opt/homelab-mcp/.env and fill in a real token.

  3. Run the installer as root:

    sudo ./deploy/install.sh
    

    This creates a dedicated non-root homelab-mcp system user (if it doesn't already exist), installs deploy/homelab-mcp.service to /etc/systemd/system/, reloads systemd, and enables + starts the service (restarts automatically on failure).

    The installer also adds the service user to the systemd-journal group (so recent_journal_errors can read the journal) and, if a docker group exists on the host, to that too (so list_containers / container_logs can reach the Docker socket). If either group doesn't exist yet -- e.g. Docker isn't installed -- the installer skips it and says so; the corresponding tools will just report that data source as unavailable rather than failing the whole server.

Connecting Claude Code / Claude Desktop

Add an MCP server entry pointing at the running instance, with the bearer token as a header. For example, in Claude Code's MCP config:

{
  "mcpServers": {
    "homelab": {
      "url": "http://your-server-hostname:8811/mcp",
      "headers": {
        "Authorization": "Bearer <your HOMELAB_MCP_TOKEN>"
      }
    }
  }
}

If you're on Tailscale, use the server's Tailscale hostname/IP so the connection never leaves your tailnet.

Tools

Tool Description
system_status() Uptime, load average (1/5/15m), memory used/total, CPU count and utilization.
disk_usage(path="/") Total/used/free/percent disk space for a given mount path.
list_containers() Name, image, status, and port mappings for all Docker containers (running and stopped).
container_logs(name, lines=100) Tail of logs for one named Docker container.
list_services() All systemd service units with their load/active/sub state.
service_status(unit) Detailed systemctl status output for one systemd service unit.
recent_journal_errors(since="1h", priority="err") Recent journal entries at or above a given syslog priority.
network_connections() Listening TCP/UDP sockets: local address, port, and owning process where permitted.

What it looks like in practice

Once connected, the MCP client picks whichever tools are relevant to your question and calls them directly -- no manual tool selection needed.

Claude Code connected to homelab-mcp, calling tools and answering a health-check question

Here's the same session as text, from Claude Code:

You: Use the homelab MCP server to check system status, disk usage, list systemd services, and check for recent journal errors.

Claude: I'll check system status, disk usage, services, and recent errors on the homelab server.

Called homelab 4 times

System status — healthy. Uptime ~28.6 days, load average near 0, memory 20.7% used (1.6GB/8GB), CPU idle.

Disk (/) — 354GB/501GB used, 70.7% full, 121GB free. Not critical, but worth watching.

Services — 188 systemd units. Two failed: fwupd.service (firmware update daemon) and fwupd-refresh.service (fwupd metadata refresh). Everything else notable (docker, jellyfin, pihole-FTL, ssh, openvpn, NetworkManager) is active/running fine.

Journal errors — retrieved cleanly (once the service user was added to the systemd-journal group by the installer -- see below).

Want me to look closer at the fwupd failures via service_status?

Four tool calls (system_status, disk_usage, list_services, recent_journal_errors), one natural-language question, zero SSH sessions.

Gotcha we hit getting here: on the first run, recent_journal_errors failed with a permissions error -- the dedicated homelab-mcp service user isn't in the adm/systemd-journal groups by default, so journalctl denied access even though the process itself was running fine. deploy/install.sh now adds the service user to systemd-journal automatically (see Running via systemd above), so a fresh install via the installer shouldn't hit this. If you set the service up by hand instead, run:

sudo usermod -aG systemd-journal homelab-mcp
sudo systemctl restart homelab-mcp

Development

uv sync --group dev
uv run pytest

Tests mock psutil, docker-py, and subprocess so the suite never touches the real system, a real Docker daemon, or spawns real subprocesses.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选