# Handoff 2026-08-28 — Portainer 2.40 → 2.42.0 Bump + portainer-mcp (uvx, projektebene) > **Vorgeschichte:** Direktive vom 2026-08-28 (User): "wenn du künftig das ganze containermanagement machst, > brauchst du einen MCP für Portainer". Vorgänger-Direktive vom 2026-08-28 selbst (gestern Session): > ⛔ NICHT installieren. → **revidiert** in derselben Diskussion, weil die wiederholten curl-Aufrufe > in der Inventur-Session gezeigt haben, dass ein MCP-Layer hier operativ hilft. ## Was diese Session geliefert hat ### 1. Portainer-Server 2.40.0 → 2.42.0 (auf pve LXC 400, Container `portainer`) **Vorab-Korrektur (war falsch im Handoff 2026-08-28):** README schrieb 2.42.6 als Ziel, PyPI hat ein 2.42.6-Wheel, aber Docker-Hub hat **nur 2.42.0** als letzten 2.42.x-Tag für `portainer/portainer-ce`. Bump-Ziel deshalb **2.42.0** statt 2.42.6. **Ablauf:** 1. Pre-Upgrade-Snapshot: - `docker commit portainer portainer/portainer-ce:2.40.0-preupgrade-20260828` (186 MB) - Settings+Endpoints+Stacks-JSON-Dump (40 KB, 31 Stacks, 4 Endpoints) - Volume `/var/lib/docker/volumes/portainer_data/_data` ist **persistent**, bleibt beim Image-Swap unangetastet. - Runflags aus `docker inspect` ins Runbook übernommen. 2. `docker pull portainer/portainer-ce:2.42.0` 3. `docker stop portainer && docker rm portainer && docker run -d` mit identischen Flags. 4. Post-Upgrade-Verifikation: - HTTP 200 auf `/`, TLS self-signed OK - `api/status` → `Version: 2.42.0`, **gleiche InstanceID** wie vorher - **API-Token weiter gültig** (`api/settings` → 200), kein Re-Auth - Alle 4 Endpoints + 31 Stacks abrufbar **Sicherheitsabstände für den Bump:** - Container läuft, alle Endpoints erreichbar (status=1) - Edge-Agents auf den 4 Hosts (DS923, macmini, nas-fm, pve) sind **eigene Container**, Portainer-Container-Restart berührt sie nicht. ### 2. portainer-mcp — installiert als projektspezifischer uvx-stdio **Quelle:** `mcp-portainer` von PyPI (offiziell, von Portainer, generiert aus OpenAPI-Spec). Wegen "Match minor to minor"-Policy (PyPI/README) war der Bump **Pflicht**, sonst kein offizieller MCP. **Installation:** - `uvx --from "mcp-portainer~=2.42.0" mcp-portainer` — Wheel lokal aufgelöst, 193 Tools - `bf-infra/.mcp.json` (gitignored): ```jsonc { "mcpServers": { "portainer": { "command": "uvx", "args": ["--from", "mcp-portainer~=2.42.0", "mcp-portainer"], "env": { "PORTAINER_URL": "https://10.40.20.126:9443", "PORTAINER_API_KEY": "${env:PORTAINER_API_KEY}", "PORTAINER_TLS_VERIFY": "0" } } } } ``` - Token via `~/.secrets/exports.zsh` (`PORTAINER_API_KEY`) — kein Klartext im Repo - **`PORTAINER_TLS_VERIFY=0`** weil self-signed Cert auf pve-LXC - **Nur projektebene**, **kein** Eintrag in `~/.claude.json` oder `~/.config/opencode/opencode.jsonc` - **`.mcp.json` aus Repo entfernt** (`git rm --cached`) — `mcp/INVENTORY.md` zeigt das **Tool-Gate:** jeder erste Read in einer Session erfordert `get_guidance()` (vom Server erzwungen). Erst danach funktionieren `EndpointList`, `StackList`, `StackInspect` etc. ### 3. Abnahme (drei Calls gegen die echte API) ``` EndpointList mit select-Projektion: [ { "Id":2, "Name":"pve", "Type":1, "Status":1 }, { "Id":14, "Name":"nas-bf (ds923+)", "Type":2, "Status":1 }, { "Id":20, "Name":"macmini", "Type":2, "Status":1 }, { "Id":21, "Name":"nas-fm (ds415+)", "Type":2, "Status":1 } ] StackList (plattformweit, mit select): 31 Stacks (pve=4, DS923=20, macmini=4, nas-fm=3) StackInspect(202) mit select: { "id":202, "name":"pve-mcp", "endpointId":14, "status":1, "entryPoint":"docker-compose.yml", "projectPath":"/data/compose/202" } ``` **MCP ersetzt jetzt:** `curl "$PORTAINER_URL/api/..."` aus Bash. Vorher 4-5 Aufrufe pro Inventur-/Deploy-Schritt; jetzt ein Tool-Call mit `select`-JMESPath-Projektion. ### 4. Bestands-Update (`mcp/INVENTORY.md`) - Zeile `portainer-mcp`: ⛔ → 🟢, mit Stand 2026-08-28, 193 Tools, Tool-Gate vermerkt - Header ergänzt: "MCP-Hosts künftig nur WARP/lokal" (User-Direktive) - `mcp/portainer/README.md`: **überholt** (steht noch auf "Portainer-Bump zuerst" — jetzt erledigt) → TODO für eigene Session: README auf neuen Stand bringen. ## Lehren aus dieser Session ### Versions-Korrektur **PyPI ≠ Docker-Hub für dieselbe Software.** PyPI `mcp-portainer` hatte 2.42.0-2.42.6 als Wheels (alle 6 Patch-Versionen), aber das Docker-Image `portainer/portainer-ce:2.42.x` stoppte bei 2.42.0 — vermutlich weil Portainer die Docker-Patch-Serie anders versioniert. **Vor jedem Versions-Claim den jeweils anderen Pfad gegenprüfen.** ### Werkzeug-Namen lernen `list_endpoints` war geraten. Tatsächlich heißt das Tool `EndpointList` (PascalCase), und es braucht zwingend `get_guidance()` vor dem ersten Read. **Bei unbekanntem MCP zuerst `tools/list` und ein einzelner Probe-Call, dann den echten Read.** Sonst verschwendet man drei Tool-Calls an Authentifizierungsfehler wie ich es hier gemacht habe. ### uvx-stdio vs Container-MCP Für ein **einzelnes Projekt** mit Performance-Bedenken ist uvx-stdio klar besser als Container: - kein zusätzlicher Host (DS923-Belastung entfällt) - keine macvlan-IP nötig (kein neuer Port-Range-Konflikt) - Tool-Calls direkt aus dem Claude/opencode-Prozess, kein Round-Trip - **Nachteil:** Token im Memory des Claude-Prozesses lebt so lange wie die Session. Bei Container-Lösung wäre der Token nur im MCP-Container. → Sicherheitsbedenken gegen Performance — die Direktive des Users ist hier explizit "Performance > Security weil LAN-only". ### `git rm --cached` für gitignored-Configs Eine bereits getrackte Datei (hier `.mcp.json` aus Commit 3426366) wird durch nachträgliches `.gitignore`-Pattern **nicht** ausgegraut — `git rm --cached` ist nötig, sonst bleibt sie im Index. Beim nächsten Commit verschwindet sie sauber. ## Commit-Plan (für die nächste Session oder als Quick-Commit) ``` git add .gitignore mcp/INVENTORY.md docs/portainer-upgrade-20260828/ git commit -m "Portainer 2.40 → 2.42.0 Bump + portainer-mcp (uvx projektebene) - Portainer-Server: 2.40.0 → 2.42.0 auf pve LXC 400, Pre-Upgrade-Snapshot (docker commit :2.40.0-preupgrade-20260828 + JSON-Dump 31 Stacks/4 Endpoints) - .mcp.json aus Repo (war aus Commit 3426366 getrackt, jetzt gitignored) - mcp/INVENTORY.md: portainer-mcp ⛔→🟢, Header um MCP-WARP-Direktive ergänzt - docs/portainer-upgrade-20260828/: Rollback-Runbook + Pre-Upgrade-State.json Hinweis: PyPI hat mcp-portainer bis 2.42.6, Docker-Hub nur bis 2.42.0 — README im mcp/portainer/ ist auf 2.42.6 formuliert und sollte angepasst werden. ``` ## TODO (offene Punkte, NICHT Teil dieser Session) 1. **`mcp/portainer/README.md`** ist überholt (steht noch auf 2.42.6-Bump, jetzt erledigt). Eigene 5-Minuten-Session, README auf den neuen Stand bringen. 2. **Cleanup nach 7 Tagen Bump-Stabilität:** `docker rmi portainer/portainer-ce:2.40.0-preupgrade-20260828` 3. **Shelly-mcp-Deployment** (das war Session B vor dem Portainer-Thema): shelly-mcp-Image ist gebaut, Stack-YML liegt auf DS923, Stack-Deploy steht aus. **Sofort zurück zu Session B**, weil die `.mcp.json` jetzt **auch** das shelly-mcp-Deployment erleichtert (kein wiederholtes curl-Poren).