Files
bf-infra/mcp/shelly/BUILD.md
Christoph Emsenhuber 27863c1f2e shelly-mcp: Build-Materialien (Dockerfile + Anleitung)
Vorbereitung für Session B (Deploy auf DS923). Datei-Set reicht für
Image-Build ohne weitere Quellen aus dem Repo:

- Dockerfile: python:3.12-slim, mountbares /config ohne .env-COPY
- requirements.txt: mcp[cli]>=1.0, starlette>=0.36 (StreamableHTTP)
- BUILD.md: rsync → docker build → Portainer-Container-Deploy
- .gitignore: .env (Schema-Vorlage lokal) + __pycache__ ausklammern

Die Live-Instanz .env und der Container selbst werden in Session B
gebaut, nicht hier. Kein Secret in Git.
2026-08-28 19:08:43 +02:00

2.9 KiB

shelly-mcp — Build-Anleitung (DS923, lokal)

Source-Tree (im Repo, gepflegt)

  • mcp/shelly/Dockerfile — Multi-stage-frei, python:3.12-slim, COPY requirements.txt + server.py + discover.py
  • mcp/shelly/requirements.txt — mcp[cli]>=1.0, starlette>=0.36
  • mcp/shelly/server.py — FastMCP, StreamableHTTP /mcp + /health + /
  • mcp/shelly/discover.py — Read-only-Sweep (CLI-Argument, nicht Env)

Secrets

  • SSoT: ~/.secrets/credentials.env + ~/.secrets/exports.zsh
  • Niemals ins Image brennen. Dockerfile macht kein COPY .env.
  • Im Stack: docs/nas-vlan20/stacks/shelly-mcp.yml (gitignored) trägt die Werte als environment: — folgt der Konvention der anderen DS923-Stacks.

Build (auf der DS923, einmalig)

# 1. Build-Verzeichnis auf der DS923 anlegen (außerhalb des Compose-Stacks)
ssh adm.christoph@10.40.20.10 "sudo -i mkdir -p /data/compose/shelly-mcp-build"

# 2. Source rsyncen (vom Mac)
rsync -avz --delete \
  mcp/shelly/Dockerfile \
  mcp/shelly/requirements.txt \
  mcp/shelly/server.py \
  mcp/shelly/discover.py \
  adm.christoph@10.40.20.10:/data/compose/shelly-mcp-build/

# 3. Image bauen
ssh adm.christoph@10.40.20.10 "sudo -i docker build -t bf/shelly-mcp:0.1 /data/compose/shelly-mcp-build"

# 4. Stack deployen (Portainer → Stacks → Add stack → Repository upload
#    ODER Portainer-API CreateStack mit Git-Repository-Pfad)
ssh adm.christoph@10.40.20.10 "sudo -i cd /data/compose && docker stack deploy -c shelly-mcp.yml shelly-mcp"
# (Hinweis: der pve-mcp-Stack wurde via Portainer-UI deployed, nicht docker-stack.
#  Vorzugsweise Portainer-API CreateStack mit GitRepo-Ref auf docs/nas-vlan20/stacks/shelly-mcp.yml.)

# 5. IP am DHCP-Server (crs326-core, dhcp-v20) als statische Reservierung eintragen
#    MAC wird nach dem ersten Boot sichtbar (docker inspect shelly-mcp | jq '.[0].NetworkSettings.Networks.vlan20.MacAddress')
#    Reservierung in Nautobot/RouterOS: dhcp-server lease add ... server=dhcp-v20

Abnahme

# Health-Endpoint
curl http://10.40.20.180:3030/health

# MCP-Discovery (StreamableHTTP erwartet initialize)
curl -X POST http://10.40.20.180:3030/mcp \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"0.0"}}}'
# → serverInfo.name = "shelly-mcp"

# Live-Sweep aus dem Container heraus
docker exec shelly-mcp python3 discover.py 10.40.30.180-250
# → erwartet 23 Shellys (s. Handoff 2026-08-28)

# MCP-Client-Konfiguration (in ~/.claude.json + ~/.config/opencode/opencode.jsonc):
# {
#   "shelly-mcp": {
#     "url": "http://10.40.20.180:3030/mcp",
#     "enabled": true,
#     "headers": {}   # falls Bearer gewünscht: "Authorization": "Bearer ${SHELLY_MCP_BEARER}"
#   }
# }

Rollback

docker rm -f shelly-mcp
docker rmi bf/shelly-mcp:0.1