homelab-codex-ws/kb/runbooks/ha-mcp-install.md
oskar 3292ab54e2 feat(kb): SPLIT service+runbook — 10 serwisow -> 20 dokumentow
Wzorzec mechaniczny: sekcje deploy/verify/install/testy wycinane do
kb/runbooks/<serwis>-*.md, reszta zostaje dokumentem type: service.
Wzajemne `links` w obie strony. Tresc sekcji nietknieta — przenoszone
doslownie, dodany wylacznie naglowek H1 nowego runbooka.

kb-query, paperless-worker, planner-agent, ha-diag-agent, ollama-piha,
narty27, home-assistant, ha-mcp, job-gmail-header-backfill, job-mail-body-ingest.

Weryfikacja: dla kazdego pliku multizbior niepustych linii
(main + runbook) == oryginal z HEAD. Zero zgubionych, zero dodanych.

Recon szacowal 13 splitow service+runbook; faktycznie 2-typowych jest 10,
pozostale 5 (paperless, nextcloud, gokapi, fleet-prometheus, deploy-runner)
sa 3-typowe i ida osobno jako splity wielotypowe.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 16:53:57 +02:00

3.4 KiB

okf type visibility status updated links
0.1 runbook private active 2026-07-30
../services/ha-mcp.md

ha-mcp — instalacja i rejestracja

Install

The mcp SDK (and its pydantic/anyio/httpx dependency tree) is not packaged for Debian and is not needed by anything else in this repo, so it goes into a venv rather than into the system Python:

python3 -m venv --system-site-packages services/ha-mcp/.venv
services/ha-mcp/.venv/bin/pip install mcp pytest

--system-site-packages is deliberate: requests, PyYAML and websocket-client are already installed system-wide and used by scripts/ha/lib/*; the venv reuses those exact versions instead of shadowing them with a second copy. .venv/ is already covered by the repo .gitignore.

pip install --break-system-packages mcp also works and is one line shorter, but it writes into the system interpreter that runs every deploy script on this workstation — a venv keeps a 40-package dependency tree out of that blast radius for a tool only Claude Code uses. Use the venv.

run.sh prefers services/ha-mcp/.venv/bin/python and falls back to the system python3; if neither can import mcp it exits with one actionable line on stderr rather than a traceback.

Registration in Claude Code

.mcp.json in the repo root (project scope — shared with anyone who checks out this repo):

{
  "mcpServers": {
    "ha": {
      "command": "./services/ha-mcp/run.sh",
      "args": [],
      "env": {}
    }
  }
}

The command path is relative, so it resolves in any checkout (main or task worktree) as long as Claude Code is started from the repo root. Start CC there; on first run it asks whether to trust the project's MCP servers. Check with /mcp — the server appears as ha, its tools as mcp__ha__<tool>. Which repo the server reads is derived from its own location; override with the HA_MCP_REPO environment variable if you ever need to point one checkout at another's config.

Standalone

./services/ha-mcp/run.sh                      # stdio server — speaks JSON-RPC on stdout
services/ha-mcp/tests/run.sh                  # offline test suite (no HA, no token)
services/ha-mcp/.venv/bin/python services/ha-mcp/tests/smoke_live.py [instance] [entity_id]

smoke_live.py is the only thing here that touches the network (GET only). A one-off tool call without a client is easiest through the package:

PYTHONPATH=services/ha-mcp/src services/ha-mcp/.venv/bin/python -c "
from ha_mcp import tools; from ha_mcp.backend import LiveBackend
from ha_mcp.config import get_instance, repo_root
n, c = get_instance('ken', repo_root()); print(tools.instance_status(LiveBackend(n, c, repo_root())))"

Tests

services/ha-mcp/tests/run.sh          # 42 tests, offline

Offline in the same sense as scripts/ha/tests/*: no network, no HA instance, no token. Small hand-made fixtures under tests/fixtures/ (shaped like real /api/states and WebSocket registry payloads) cover the tool logic; the repo's own config/ken/automations/ and newest fixtures/ken-states-*.yaml cover the repo-backed and at-scale paths (ranking over ~1650 real entities behaves differently from ranking over ten).

Live smoke (read-only, run against ken on 2026-07-30): instance_status → HA 2026.7.2, 1647 entities, 377 unavailable, 115 automations, 13 areas; get_state("sensor.thsalon_temperature")24.5 °C.