Files
homelab/docs/08-omada-mcp.md

7.9 KiB
Raw Blame History

08 · TPLink Omada MCP Server

Erstellt: 2026-03-18 Aktualisiert: 2026-03-18 — Credentials rotiert (CLIENT_ID/SECRET), Service auf NodePort 31777 umgestellt Namespace: omada-mcp Image: jmtvms/tplink-omada-mcp:latest Status: Running · Pod omada-mcp-dfdbfbcf8-x6t5k · NodePort 31777 → Container 3000


Übersicht

Der tplink-omada-mcp Server stellt eine MCP-Schnittstelle (Model Context Protocol) für den TPLink Omada Controller bereit. Claude und andere KI-Assistenten können darüber das Netzwerk verwalten (Clients, SSIDs, VLANs, Geräte usw.).

Der Server läuft im HTTP-Modus auf Port 3000 (MCP_SERVER_USE_HTTP=true).


Dateien

homelab/k8s/omada-mcp/
├── kustomization.yaml   # Kustomize-Einstiegspunkt
├── namespace.yaml       # Namespace omada-mcp
├── secret.yaml          # Credentials (Platzhalter  vor Anwenden befüllen!)
├── deployment.yaml      # Deployment (1 Replica)
└── service.yaml         # NodePort Service Port 3000 → NodePort 31777

Credentials (Secret)

Das Secret omada-mcp-credentials enthält folgende Schlüssel:

Key Beschreibung
OMADA_BASE_URL URL des Omada Controllers, z. B. https://192.168.11.29
OMADA_CLIENT_ID OAuth Client-ID aus dem Omada Controller
OMADA_CLIENT_SECRET OAuth Client-Secret
OMADA_OMADAC_ID Omada-Controller-ID (zu finden in den Controller-Einstellungen)
OMADA_STRICT_SSL false deaktiviert SSL-Verifikation (Self-signed Certs)
MCP_SERVER_USE_HTTP true aktiviert HTTP-Modus
MCP_HTTP_BIND_ADDR 0.0.0.0 lauscht auf allen Interfaces

Secret anlegen (empfohlen kein base64 nötig)

kubectl create secret generic omada-mcp-credentials \
  --namespace omada-mcp \
  --from-literal=OMADA_BASE_URL='https://192.168.11.29' \
  --from-literal=OMADA_CLIENT_ID='dein-client-id' \
  --from-literal=OMADA_CLIENT_SECRET='dein-client-secret' \
  --from-literal=OMADA_OMADAC_ID='dein-omadac-id' \
  --from-literal=OMADA_STRICT_SSL='false' \
  --from-literal=MCP_SERVER_USE_HTTP='true' \
  --from-literal=MCP_HTTP_BIND_ADDR='0.0.0.0'

Danach secret.yaml nicht anwenden (das Secret existiert bereits).

Alternativ: secret.yaml befüllen

# Werte base64-kodieren
echo -n 'https://omada.example.com' | base64
echo -n 'dein-client-id'            | base64
echo -n 'dein-client-secret'        | base64
echo -n 'dein-omadac-id'            | base64

Die Ausgaben in secret.yaml bei den REPLACE_WITH_*-Platzhaltern eintragen.


Deployment

Voraussetzungen

  • Namespace existiert (wird durch namespace.yaml erstellt)
  • Secret ist befüllt (siehe oben)

Anwenden mit Kustomize

# Dry-run  Manifeste prüfen
kubectl apply -k homelab/k8s/omada-mcp/ --dry-run=client

# Anwenden
kubectl apply -k homelab/k8s/omada-mcp/

Einzelne Manifeste anwenden

kubectl apply -f homelab/k8s/omada-mcp/namespace.yaml
kubectl apply -f homelab/k8s/omada-mcp/secret.yaml      # nur wenn nicht per kubectl create
kubectl apply -f homelab/k8s/omada-mcp/deployment.yaml
kubectl apply -f homelab/k8s/omada-mcp/service.yaml

Umgebungsvariablen im Container

Variable Wert Quelle
OMADA_BASE_URL https://192.168.11.29 Secret omada-mcp-credentials
OMADA_CLIENT_ID aus Secret omada-mcp-credentials
OMADA_CLIENT_SECRET aus Secret omada-mcp-credentials
OMADA_OMADAC_ID aus Secret omada-mcp-credentials
OMADA_STRICT_SSL false omada-mcp-credentials
MCP_SERVER_USE_HTTP true omada-mcp-credentials
MCP_HTTP_BIND_ADDR 0.0.0.0 omada-mcp-credentials

Verifikation

# Pod-Status prüfen
kubectl get pods -n omada-mcp

# Logs anzeigen
kubectl logs -n omada-mcp deployment/omada-mcp

# Service prüfen
kubectl get svc -n omada-mcp

# Direkter Test via Port-Forward
kubectl port-forward -n omada-mcp svc/omada-mcp 3000:3000
curl http://localhost:3000/

Erwartete Ausgabe (Pod läuft)

NAME                         READY   STATUS    RESTARTS   AGE
omada-mcp-xxxxxxxxx-xxxxx   1/1     Running   0          1m

MCP-Endpunkt in Claude Code einbinden

Sobald der Pod läuft, kann der MCP-Server per Port-Forward oder Ingress angebunden werden.

Option A: NodePort (dauerhaft, direkt erreichbar)

Der Service ist auf NodePort 31777 auf allen Nodes erreichbar:

Node URL
rnk-cp01 http://192.168.11.170:31777
rnk-wrk01 http://192.168.11.171:31777
rnk-wrk02 http://192.168.11.172:31777

Claude Code .mcp.json:

{
  "mcpServers": {
    "omada": {
      "type": "http",
      "url": "http://192.168.11.171:31777/mcp"
    }
  }
}

Option B: Port-Forward (lokal/temporär)

kubectl port-forward -n omada-mcp svc/omada-mcp 3000:3000 &

Option B: Ingress (dauerhaft, mit Traefik)

Ingress-Manifest erstellen (optional):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: omada-mcp
  namespace: omada-mcp
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    cert-manager.io/cluster-issuer: letsencrypt-production
spec:
  ingressClassName: traefik
  tls:
    - hosts:
        - omada-mcp.homelab.local
      secretName: omada-mcp-tls
  rules:
    - host: omada-mcp.homelab.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: omada-mcp
                port:
                  number: 3000

Ressourcen

  • CPU: 50m Request / 200m Limit
  • Memory: 64Mi Request / 256Mi Limit

Troubleshooting

# Pod-Events anzeigen
kubectl describe pod -n omada-mcp -l app.kubernetes.io/name=omada-mcp

# Secret-Inhalte prüfen (base64-dekodiert)
kubectl get secret omada-mcp-credentials -n omada-mcp -o jsonpath='{.data.OMADA_BASE_URL}' | base64 -d

# Pod neu starten
kubectl rollout restart deployment/omada-mcp -n omada-mcp

Häufige Fehler

Fehler Ursache Lösung
ImagePullBackOff Image nicht erreichbar Internet-Zugang der Nodes prüfen
CrashLoopBackOff Falsche Credentials Logs prüfen, Secret aktualisieren
Pending Ressourcen fehlen kubectl describe pod → Events
SSL-Fehler Self-signed Cert OMADA_STRICT_SSL=false bestätigen

Deployment-Geschichte

Datum Aktion Ergebnis
2026-03-18 Namespace, Secret, Deployment, Service erstellt Pod in CrashLoopBackOff wegen falscher Probe-Pfade
2026-03-18 Liveness/Readiness Probe auf /healthz geändert Pod 1/1 Running, /healthz{"status":"ok"}
2026-03-18 MCP Initialize-Request getestet Server antwortet korrekt, Version 0.1.0
2026-03-18 Service von ClusterIP auf NodePort 31777 umgestellt Extern erreichbar auf allen Nodes
2026-03-18 Credentials rotiert (CLIENT_ID + CLIENT_SECRET) Pod-Rollout erfolgreich, 1/1 Running

Bekannte Besonderheit: Probe-Pfad

Der MCP-Server gibt auf GET / HTTP 404 zurück (MCP-Protokoll beantwortet nur POST mit korrekten Headers). Der Health-Endpoint ist /healthz{"status":"ok"}.

MCP-Endpunkt aufrufen

curl -s -X POST http://192.168.11.171:31777/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

Nächste Schritte

  • Credentials im Secret befüllen und anwenden
  • Pod-Status und Logs nach Deployment prüfen
  • MCP-Server in Claude Code .mcp.json eintragen
  • Optional: Ingress für dauerhaften Zugriff erstellen
  • Optional: Horizontal Pod Autoscaler bei Bedarf hinzufügen