7.9 KiB
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.yamlerstellt) - 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.jsoneintragen - Optional: Ingress für dauerhaften Zugriff erstellen
- Optional: Horizontal Pod Autoscaler bei Bedarf hinzufügen