# 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) ```bash # 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 ```bash # 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 ```bash docker rm -f shelly-mcp docker rmi bf/shelly-mcp:0.1 ```