mcp-server-unifi
by martin3000
README.md
# mcp-server-unifi
Ein MCP-Server (Model Context Protocol), der einer KI Lese- und Schreibzugriff
auf einen UniFi Network Controller (UniFi OS, z.B. UCG Ultra/UDM/UDM-Pro)
gibt. Gedacht fuer Heimnetz-/kleine MFH-Netzwerke mit VLANs, WLANs,
Port-Profilen, Zone-Based-Firewall und WireGuard-VPN.
## Funktionen
| Tool | Beschreibung |
|---|---|
| `discover_schema` | Liest die vom Controller selbst bereitgestellte OpenAPI-Spezifikation aus. Erstes Tool bei unerwarteten Fehlern. |
| `list_sites` | Listet alle Sites, die dieser Controller verwaltet (siehe "Mehrere Sites" unten). |
| `query_config` | Liest Netzwerke, WLANs, Port-Profile, Firewall-Gruppen/-Regeln oder Clients aus (WLAN-Passphrasen standardmaessig maskiert). |
| `find_client` | Sucht bekannte Clients nach MAC, IP, Name oder Netzwerk; liefert Online-Status und verbundenen AP. |
| `get_device` | Details zu einem Geraet (AP/Switch/Gateway): Adoptionsstatus, Firmware, Uptime, Port-Belegung inkl. verbundener Clients. |
| `apply_change` | Aendert ein bestehendes Konfigurationsobjekt (liest zuerst den aktuellen Stand, ueberlagert nur die angegebenen Felder). |
| `get_events` | Controller-Events/Alarme der letzten X Minuten, optional textgefiltert. |
| `run_diagnostic` | Speedtest oder Ping ueber den Controller anstossen (Start + Ergebnis-Polling gekapselt). |
| `manage_backup` | Controller-Backups erstellen, auflisten oder lokal herunterladen. |
Alle Tools geben strukturiertes JSON zurueck; Fehler (Verbindung, Auth,
Controller-Ablehnung) kommen als `{"error": "...", "hint": "..."}` zurueck,
nie als rohe Exception oder HTML.
## Installation
```bash
pip install --user /home/jms/develop/mcp_server_unifi
# oder
./pip_install.sh
```
Abhaengigkeiten: `mcp`, `pydantic`, `httpx`.
## Konfiguration
| CLI-Argument | Env-Variable | Pflicht | Default |
|---|---|---|---|
| `--api-key` | `UNIFI_API_KEY` | ja | - |
| `--controller-ip` | `UNIFI_CONTROLLER_IP` | ja | - |
| `--site` | `UNIFI_SITE` | nein | automatisch aufgeloest, siehe "Mehrere Sites" unten |
| `--verify-ssl` / `--no-verify-ssl` | `UNIFI_VERIFY_SSL` | nein | aus (UniFi-Controller nutzen i.d.R. selbstsignierte Zertifikate) |
CLI-Argumente haben Vorrang vor den Umgebungsvariablen. Der API-Key wird nur
maskiert geloggt (`API-Key: *******XXXX (letzte 4 Zeichen)`), niemals im
Klartext.
### Mehrere Sites
Verwaltet der Controller nur eine Site, ist keine Konfiguration noetig - der
Server loest sie automatisch auf. Verwaltet er **mehrere** Sites (z.B. Zuhause
+ Ferienhaus), gilt:
- Ist `--site`/`UNIFI_SITE` gesetzt, wird immer diese Site verwendet.
- Ist nichts gesetzt, geben alle Tools bei Mehrdeutigkeit einen Fehler mit den
verfuegbaren Sites zurueck (`{"error": "Mehrere Sites vorhanden, keine
ausgewaehlt", "hint": "... 'default' (Zuhause), 'site2' (Ferienhaus) ..."}`)
statt stillschweigend eine davon zu waehlen. Die KI kann dann `list_sites()`
aufrufen und die gewuenschte Site gezielt als `site=...`-Parameter an das
jeweilige Tool uebergeben.
Die mitgelieferte `mcp.json` hat `--site` bereits als Platzhalter
(`"hier-site-name-eintragen-falls-mehrere-sites"`) drin, analog zum
API-Key-Platzhalter:
- **Mehrere Sites:** Platzhalter durch den `name`-Wert aus `list_sites()`
ersetzen (z.B. `"default"` oder `"site2"` - nicht den `desc`-Anzeigenamen).
- **Nur eine Site:** die beiden `--site`-Argumente (Flag + Platzhalterwert)
aus `args` entfernen - der Platzhaltertext ist kein gueltiger Site-Name und
wuerde sonst mit einem `Controller-Fehler` fehlschlagen. Ohne `--site` loest
der Server die einzige vorhandene Site automatisch auf.
Der API-Key wird als [UniFi-API-Key](https://help.ui.com) im Controller unter
Einstellungen -> Control Plane -> Integrations erzeugt (kein Login-Flow, kein
Session-Cookie noetig).
## Starten
```bash
python -m mcp_server_unifi --api-key sk-... --controller-ip 192.168.1.1
```
## Konfiguration in Claude Code / LM Studio
Siehe `mcp.json` in diesem Verzeichnis (API-Key dort ueber die `env`-Sektion
setzen, nicht im Klartext in `args`):
```json
{
"mcpServers": {
"unifi": {
"command": "python",
"args": ["-m", "mcp_server_unifi", "--controller-ip", "192.168.1.1"],
"env": { "UNIFI_API_KEY": "sk-..." }
}
}
}
```
Danach den MCP-Client neu starten.
## Sicherheitshinweise
- Ausschliesslich API-Key-Authentifizierung, keine Session-/Cookie-basierte
Anmeldung.
- `apply_change` aendert nur bestehende Objekte (liest zuerst den aktuellen
Zustand und ueberlagert ihn mit den angegebenen Feldern) - es werden keine
Objekte angelegt oder geloescht.
- Es gibt bewusst keine Tools zum Loeschen von Netzwerken oder Zuruecksetzen
von Geraeten.
## Grenzen / unverifizierte Endpunkte
Gegen einen echten Controller (UDR Ultra, UniFi Network App 10.5.67)
verifiziert: `discover_schema`, `list_sites`, `query_config` (inkl.
WLAN-Passphrasen-Maskierung), `find_client`, `get_device`. Diese funktionieren
zuverlaessig ueber die klassische API (`/proxy/network/api/s/{site}/...`).
**Bestaetigt eingeschraenkt:**
- `get_events`: Auf UniFi Network App 10.5.67 liefert `stat/event` (und
`stat/alarm`, `list/event`) durchgehend 404. Die neue offizielle v1
Integration-API (`/proxy/network/integration/v1/...`, ebenfalls von diesem
Controller bereitgestellt) hat **keine** Events/Alarme-Ressource - im
gesamten OpenAPI-Spec taucht "event"/"alarm" nicht auf. Ein
GraphQL-Endpunkt (`/proxy/network/api/graphql`) existiert, antwortet aber
mit 401 auf API-Key-Auth (verlangt vermutlich Session-Cookie-Auth) und wird
bewusst nicht unterstuetzt (siehe CLAUDE.md: nur API-Key). `get_events`
erkennt den 404-Fall und gibt eine erklaerende Fehlermeldung statt eines
nichtssagenden Controller-Fehlers zurueck. Auf aelteren
Controller-Generationen kann der Endpunkt durchaus funktionieren.
**Weiterhin unverifiziert** (keine Seiteneffekte auf einem echten Controller
ausgeloest, um Bandbreite/Backup-Ressourcen nicht unnoetig zu beanspruchen):
- `run_diagnostic(test="ping")`: Endpunkt/Ergebnisformat unverifiziert;
`test="speedtest"` (`cmd/devmgr` + Polling auf `/stat/device`) ist nach
Code-Review der wahrscheinlichere korrekte Fall, aber nicht live getestet.
- `manage_backup`: Backup-Endpunkte (`cmd/backup`, `list-backups`,
`/dl/backup/...`) sind die am wenigsten dokumentierten der klassischen
UniFi-API und nicht live getestet.
- Zone-Based-Firewall (`v2/api/site/{site}/firewall-*`) wird bewusst nicht
fest verdrahtet - `discover_schema` oder `run_overpass_query`-artiges
Vorgehen (Rohdaten lesen, nicht Feldnamen raten) nutzen.
## Struktur
```
mcp_server_unifi/ ← Projekt-Root
├── pyproject.toml
├── README.md
├── CLAUDE.md
├── mcp.json
├── tests/
│ ├── test_server.py ← Unit-Tests, gemockter httpx-Transport
│ └── integration/ ← manuelle Tests gegen echten Controller
└── mcp_server_unifi/ ← Python-Package
├── __init__.py ← Einstiegspunkt & Argument-Parsing
├── __main__.py ← Ermoeglicht python -m mcp_server_unifi
├── server.py ← FastMCP-Instanz, alle Tools
└── unifi_client.py ← HTTP-Client, Config, Fehlerbehandlung
```
## Tests
```bash
pip install --user -e ".[test]"
pytest tests/
```
## Development
Publish to PyPI:
```bash
./push_pypi.sh
```
Push to GitHub:
```bash
./push_github.sh
```
## License
MIT — Martin Schlatter
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues