Skip to main content
Glama

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

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 im Controller unter Einstellungen -> Control Plane -> Integrations erzeugt (kein Login-Flow, kein Session-Cookie noetig).

Starten

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):

{
  "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

pip install --user -e ".[test]"
pytest tests/

Development

Publish to PyPI:

./push_pypi.sh

Push to GitHub:

./push_github.sh

License

MIT — Martin Schlatter