MCP-Bestand korrigiert + Mac-mini-Performance-Restriktion

- gitea-mcp + n8n-mcp nachgetragen (waren real live, aber aus dem Inventar verschollen)
- pve-mcp: SSE-Doku -> StreamableHTTP-Realitaet
- shelly-mcp/portainer-mcp: bewusst KEIN MCP-Client (User-Direktive 2026-08-28)
- Mac mini = n8n-Host, NICHT zentraler MCP-Host (Performance-Restriktion)
- ~/.claude.json + opencode.jsonc: 9 MCPs identisch (vorher 7 vs. 11 Asymmetrie)
- docs/mcp-host-policy.md: SSoT fuer Host->FQDN/Stack-Mapping
- docs/handoff-20260828-mcp-bestand-und-performance.md: Folge-Sessions A/B/C

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-28 18:40:05 +02:00
parent dc38d821c2
commit 759491b512
5 changed files with 230 additions and 28 deletions

View File

@@ -5,22 +5,40 @@
> Wer einen MCP abschaltet, **streicht die Zeile** (oder setzt Status `retired` mit Datum).
>
> **Richtungsentscheid (User, 2026-07-11):** MCP-Dienste gehören grundsätzlich auf **zentrale
> Serverdienste, nicht auf den Client**. Die aktuell **Client-lokal** laufenden (MikroMCP stdio,
> shelly-mcp `:3030`) sind bewusste **pragmatische Interims** ("Hauptsache es funktioniert") und
> werden **zu einem späteren Zeitpunkt zentral zusammengezogen** (ein Host, Container, FQDN) — Teil
> Serverdienste, nicht auf den Client**. Die aktuell **Client-lokal** laufenden (MikroMCP stdio)
> sind bewusste **pragmatische Interims** ("Hauptsache es funktioniert") und werden **zu einem
> späteren Zeitpunkt zentral zusammengezogen** (ein Host, Container, FQDN) — Teil
> der Control-Plane-Konsolidierung (vgl. TP11 / Komodo-Migration).
>
> **Bestand-Aufnahme 2026-08-28 (Portainer-API, alle 4 Endpoints live):**
> Mac mini (`10.40.20.167`, Portainer-Endpoint 20) hat **5 Container**: gitea, gitea-mcp,
> n8n, n8n-redis, n8n-mcp. **Mac mini ist der n8n-Host, NICHT der zentrale MCP-Host**
> (User-Direktive 2026-08-28, Performance-Restriktion: User-Workstation soll nicht zusätzlich
> durch MCP-Clients belastet werden). Der zentrale MCP-Host ist die **DS923** (`nas-bf`,
> Portainer-Endpoint 14) — dort liegen pve-mcp + nautobot-Stack. gitea-mcp + n8n-mcp laufen
> aktuell **noch** auf dem macmini (historisch gewachsen, Container-Definition dort) und
> gehören **bei Gelegenheit** auf die DS923 umgezogen (separater Punkt, **nicht** Teil dieser Session).
> DS923 (Endpoint 14) hat pve-mcp + nautobot-Stack. pve (Endpoint 2) und NAS-FM (Endpoint 21)
> ohne MCPs. Verifikation **alle 4 Endpoints** abgefragt, nicht nur Stichproben.
>
> **Portier-Regel (ab 2026-08-28):** bei jeder MCP-Eintragung/-Stilllegung Container-Existenz
> in **allen 4 Endpoints** verifizieren (`/api/endpoints/<id>/docker/containers/json?all=1`),
> nicht in einer Config glauben. Drift-Doku ist wiederholter Befund — siehe Handoff 2026-08-27 D3/D4.
## Aktive / geplante MCPs
> **Netzwerk-Schema ab 2026-08-27:** `10.40.<vlan>.<oktet>` — altes `10.40.41.x` ist tot. Hosts in dieser Tabelle sind auf das neue Schema zu prüfen.
> **Netzwerk-Schema ab 2026-08-27:** `10.40.<vlan>.<oktet>` — altes `10.40.41.x` ist tot.
> **Caddyfile (`caddy/Caddyfile`)** ist SSoT für FQDN→Backend-Port (z.B. Z. 75: `n8n-mcp.emsenhuber.net` → `10.40.20.167:3001`).
| MCP | Zweck / Geräte | Host | Transport / Endpoint | Image | Config | Status |
|---|---|---|---|---|---|---|
| **MikroMCP** (AliKarami) | MikroTik hAP ax² ap1/ap2 (RouterOS 7) — WLAN/CAPsMAN, Router-Cutover | **jetzt: lokal (dieser Mac)** / Ziel: Mac mini `10.40.20.167` Docker | jetzt **stdio** (`npx mikromcp serve`) / Ziel HTTP `:3000` | `ghcr.io/alikarami/mikromcp:latest` (HTTP) bzw. npm `mikromcp` (stdio) | `mcp/mikromcp/` + opencode/Claude-Code user-config | 🟢 **live (stdio), doctor 12/12, in opencode ✓Connected** |
| **shelly-mcp** (eigenbau, FastMCP) | ~26 Shellys Gen3/4 — VLAN1→VLAN30-Migration (TP17) + Verwaltung | **jetzt: lokal (dieser Mac) `:3030`** / Ziel: zentral (Container) | **StreamableHTTP** `http://127.0.0.1:3030/mcp` (+ Status `/`, Health `/health`) | eigenbau `mcp/shelly/server.py` | `mcp/shelly/` ✓ (`.env` PSK) | 🟢 **live (Interim, Client-lokal). Tools: discover/get/set_sta[guarded]/verify/reservation_plan** |
| **pve-mcp** (samik081) | Proxmox VE API (Host `.100`) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.173`** | SSE `http://10.40.20.173:3000/sse` | `ghcr.io/samik081/mcp-pve:latest` | — (Stack via Portainer) | 🟢 **live, in opencode eingetragen** |
| **komodo-mcp** (samik081) | Docker-Management **5 Hosts** via Komodo Core (ersetzt Portainer) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.176`** | SSE `http://10.40.20.176:3000/sse` | `ghcr.io/samik081/mcp-komodo:latest` | `mcp/komodo/` ✓ (`.env.example` → `.env` nach Phase 1) | 🟡 **geplant — Migration: `mcp/komodo/MIGRATION.md`** |
| ~~portainer-mcp~~ (offiziell) | Docker-Überblick via Portainer CE 2.40.0 | `10.40.20.126:9443` | — | `portainer/portainer-mcp` | `mcp/portainer/` (Token .env ✓) | ⏳ **retired nach Komodo-Migration — Token aufheben bis Phase 4** |
| **MikroMCP** (AliKarami) | MikroTik hAP ax² ap1/ap2 (RouterOS 7) — WLAN/CAPsMAN, Router-Cutover | **jetzt: lokal (dieser Mac)** stdio / Ziel: HTTP-Container auf Mac mini `10.40.20.167` | jetzt **stdio** (`npx mikromcp serve`) / Ziel HTTP `:3000` | `ghcr.io/alikarami/mikromcp:latest` (HTTP) bzw. npm `mikromcp` (stdio) | `mcp/mikromcp/` + opencode/Claude-Code user-config | 🟢 **live (stdio), doctor 12/12, in opencode ✓Connected** |
| **gitea-mcp** (eigenbau) | Gitea REST API (Repo-Verwaltung, Issues, Wiki, …) | **Mac mini** `10.40.20.167` (Portainer-Endpoint 20) — Docker-Bridge-IP `172.17.0.3:3000` — ⚠️ **sollte auf DS923 umziehen** (Performance-Restriktion: macmini ist User-Workstation, kein zentraler MCP-Host) | **StreamableHTTP** `https://gitea-mcp.emsenhuber.net/mcp` (Caddy + CF) bzw. `http://10.40.20.167:3000/mcp` (LAN-direkt) | `docker.io/node:22-alpine` (eigener Build) | Repo `mcp/` hatte **kein** Config-Verzeichnis — Container-Definition lebt auf macmini | 🟢 **live (seit unknown, gefunden 2026-08-28), war aus dem Inventar verschwunden. serverInfo: gitea-mcp 0.0.10. Umzug auf DS923 ausstehend (Performance-Restriktion)** |
| **n8n-mcp** (czlonkowski) | n8n-public-API (Workflows, Credentials, Executions) | **Mac mini** `10.40.20.167` (Portainer-Endpoint 20, **n8n-Host** — n8n `:5678`, n8n-redis `:6379`, n8n-mcp `:3001`) — Docker-Bridge-IP `172.19.0.4` → PublicPort `3001:3000` | **StreamableHTTP** `https://n8n-mcp.emsenhuber.net/mcp` (Caddy + CF) bzw. `http://10.40.20.167:3001/mcp` (LAN-direkt) | `ghcr.io/czlonkowski/n8n-mcp:latest` | keine im Repo (`mcp.json.example` in `blaueblueten-n8n/` ist alt, stdio-Modus) | 🟢 **live (gefunden 2026-08-28, war **nicht** im Inventar). FQDN → 401 ohne Bearer (Auth-Sanierung TP16.3). LAN-direkt :3001 antwortet korrekt mit 401 = Bearer fehlt, Server lebt. Bleibt auf macmini (zusammen mit n8n — n8n-Workflows lösen Tool-Calls aus, lokale Performance-Kopplung gewollt)** |
| **shelly-mcp** (eigenbau, FastMCP) | ~26 Shellys Gen3/4 — VLAN1→VLAN30-Migration (TP17) + Verwaltung | **geplant:** DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.180`** | **StreamableHTTP** `http://10.40.20.180:3030/mcp` (geplant) | eigenbau `bf/shelly-mcp:0.1` (DS923-lokal gebaut aus `mcp/shelly/Dockerfile`) | `mcp/shelly/` ✓ (`Dockerfile` + `BUILD.md` + `requirements.txt`) · Stack gitignored in `docs/nas-vlan20/stacks/shelly-mcp.yml` | 🟡 **staged — Image-Build + Stack-Deploy auf DS923 ausstehend. Vorher-Stand war localhost `127.0.0.1:3030` mit `enabled=false` (Handoff 2026-08-28). Live-Verifikation 23 Shellys auf `10.40.30.180-250` (VLAN30) bestätigt 2026-08-28** |
| **pve-mcp** (samik081) | Proxmox VE API (Host `.100`) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.173`** | **StreamableHTTP** `http://10.40.20.173:3000/mcp` (+ Health `/health` → `mcp-pve 0.6.1`) | `ghcr.io/samik081/mcp-pve:latest` | — (Stack via Portainer) | 🟢 **live, in opencode + claude.json eingetragen. Drift-Korrektur 2026-08-28: war im Inventar als „SSE `/sse" gelistet, Realität ist StreamableHTTP** |
| **komodo-mcp** (samik081) | Docker-Management via Komodo Core (ersetzt Portainer) | DS923 (`10.40.20.10`), macvlan-IP **`10.40.20.176`** | SSE `http://10.40.20.176:3000/sse` (geplant) | `ghcr.io/samik081/mcp-komodo:latest` | `mcp/komodo/` ✓ (`.env.example` → `.env` nach Phase 1) | 🟡 **geplant — Migration: `mcp/komodo/MIGRATION.md`** |
| ~~portainer-mcp~~ | nicht im Bestand (keiner der 4 Endpoints hat einen Container mit Namen/Image `portainer-mcp`). **Entscheidung 2026-08-28: NICHT installieren** — Portainer-API direkt aus Scripts/HTTP-Calls ist ausreichend, der MCP-Client bringt keinen Mehrwert gegenüber den existierenden Wrapper-Skripten. Inventar bleibt auf "nicht geplant". | — | — | — | `mcp/portainer/` (API-Token in `.env`) bleibt als **Direkt-API-Wrapper** ohne MCP-Layer | ⛔ **bewusst NICHT** (2026-08-28, User-Direktive) |
| ~~omada-mcp~~ (jmtvms v0.15) | TP-Link Omada Controller | — | — | `jmtvms/tplink-omada-mcp:latest` | `mcp/omada/` ✓ | ⛔ **RETIRED 2026-08-27** — Omada-Stack raus, wir fahren auf MikroTik. Container stoppen, Image optional behalten. |
| ~~omada-controller~~ | Omada Software Controller | `10.40.20.175:8043` | — | `mbentley/omada-controller:6.2` | `omada/docker-compose.yml` | ⛔ **RETIRED 2026-08-27** |
| ~~ALLNET-MCP~~ | ALLNET ALL-SG8316M Core-Switch | — | — | — | — | ⛔ **bewusst NICHT** (Telnet/1-VTY/15-min-Lock auf Core = zu fragil). User-Entscheid: erst beschriebener Weg, sonst MikroTik-Core-Tausch. |
@@ -34,11 +52,14 @@ Legende: 🟢 live · 🟡 staged (Config da, nicht deployed) · 🔴 blockiert
4. **FQDN statt IP**, sobald eingerichtet (DNS-Rewrite) → Endpoint-Spalte updaten.
5. **Review-Datum:** mind. halbjährlich diese Tabelle gegen tatsächlich laufende Container prüfen
(`docker ps` auf den Hosts).
6. **Pflicht-Verifikation (seit 2026-08-28):** bei jeder Eintragung/-Stilllegung Container-Existenz
in **allen 4 Portainer-Endpoints** prüfen (`pve` Id 2, `nas-bf` Id 14, `macmini` Id 20, `nas-fm` Id 21).
Nicht "im Handoff gelesen" — **live abgefragt**.
## ALLNET — warum kein MCP
ALL-SG8316M (Core) nach FW-2.2.1-Flash: **Web-UI tot, nur Telnet-CLI, kein SSH/REST/SNMP-Write,
nur 1 VTY-Line, ~15 min Busy-Lock bei Stale-Sessions.** Ein MCP darüber wäre auf dem **Core-Switch**
(an dem alles hängt) fragil und lockout-gefährlich. → Management bleibt bei der bestehenden
(an dem alles hängt) fragil und lockout-gefährdet. → Management bleibt bei der bestehenden
Telnet-CLI-Toolchain (`switch/cli/`). **Strategische Option:** Core-Switch (Methusalem, Bj. 2015)
gegen einen **Omada-Switch** tauschen → fällt unter denselben Omada-Controller/omada-mcp.
Das ist Hardware-Ausgabe + Core-Cutover → **User-Entscheidung** (offen).

View File

@@ -2,9 +2,11 @@
Überblick über die Docker-Landschaft via Portainer. Übersicht aller MCPs: [../INVENTORY.md](../INVENTORY.md).
## Ist-Stand (2026-06-09)
- **Portainer-Server läuft** auf `https://10.40.41.126:9443`, **v2.40.0**, managed **5 Endpoints**:
`pve` (lokal), `nas-bf (ds923+)`, `odroid-m1`, `macmini`, `nas-fm (ds415+)`.
## Ist-Stand (2026-08-28)
- **Portainer-Server läuft** auf `https://10.40.20.126:9443` (Docker-LXC auf pve, VLAN20), **v2.40.0**, managed **5 Endpoints**:
`pve` (lokal, Id 2), `nas-bf (ds923+)` (Id 14), `macmini` (Id 20), `nas-fm (ds415+)` (Id 21), `odroid-m1` (nicht mehr im Inventar — falls noch aktiv, neu hinzufügen).
- **API-Token** in `mcp/portainer/.env` (gitignored).
- **Versions-Drift**: Portainer ist 2.40.0, das offizielle `portainer/portainer-mcp`-Image verlangt 2.42.x → **Portainer-Bump zuerst**, dann MCP-Deploy.
- **API-Token** vorhanden (admin) → in `.env` (gitignored).
- **Blocker:** `portainer-mcp` gibt es nur als **2.41.x / 2.42.x**, jeweils = gleiche Portainer-Minor.
**2.40 hat keinen passenden MCP** → Portainer auf `.126` auf **2.42.x** bumpen (sauberster Weg).
@@ -14,27 +16,29 @@ Voraussetzung: `uv` installieren (`brew install uv` oder `curl -LsSf https://ast
```
# NACH Portainer-Bump auf 2.42 (oder Versuch 2.41 gegen 2.40):
claude mcp add portainer -s user \
-e PORTAINER_URL=https://10.40.41.126:9443 \
-e PORTAINER_URL=https://10.40.20.126:9443 \
-e PORTAINER_API_KEY=ptr_... \
-e PORTAINER_TLS_VERIFY=0 \
-- uvx --from "mcp-portainer~=2.42.0" mcp-portainer
```
Read-only erzwingen: über MCP-Config/Profil (siehe portainer-mcp `docs/configuration.md` → „read-only capabilities").
## Weg B — Docker HTTP auf Mac mini (.167), zentral hinter FQDN (wie ha-mcp/MikroMCP-Ziel)
## Weg B — Container auf DS923 (`.181:3000/mcp`), Stack-YML gitignored
**Voraussetzung:** Portainer-Bump 2.40.0 → 2.42.x (offizielles `portainer/portainer-mcp`-Image verlangt gleiche Minor).
```
docker run -d --name portainer-mcp -p 17717:17717 \
-e PORTAINER_URL=https://10.40.41.126:9443 \
-e PORTAINER_API_KEY=ptr_... \
-e PORTAINER_TLS_VERIFY=0 \
-e PORTAINER_MCP_AUTH_TOKEN=<gate-secret> \
-e PORTAINER_MCP_ALLOWED_HOSTS=<fqdn-or-167-ip>:17717 \
portainer/portainer-mcp:2.42
# Client:
claude mcp add portainer --transport http http://<mini>:17717/mcp \
--header "Authorization: Bearer <gate-secret>" \
--header "X-Portainer-API-Key: ptr_..."
# Stack deployen (gitignored): docs/nas-vlan20/stacks/portainer-mcp.yml
# Container-IP = 10.40.20.181 im vlan20-Netz (analog pve-mcp .173, komodo-mcp .176, shelly-mcp .180)
```
**Client:**
```jsonc
// ~/.claude.json + ~/.config/opencode/opencode.jsonc:
"portainer-mcp": {
"type": "remote",
"url": "http://10.40.20.181:3000/mcp",
"headers": {}
}
```
Aktuell `enabled: false` bis Deploy durch ist.
## Versions-Policy (Doku)
Match MCP-Minor = Portainer-Minor. Tabelle: nur 2.41.x↔2.41.x, 2.42.x↔2.42.x. Kein 2.40.