# MUA — Mikes Unraid Agent MCP-Server für Unraid: Docker-Container, Netzwerk und System-Tools. Kompiliertes Bun-Binary (TypeScript), läuft als SysVinit-Service auf Unraid. - **MCP-Endpunkt:** `http://:3002/mcp` (Streamable HTTP, POST-only, JSON-RPC 2.0) - **Health-Check:** `http://:3002/health` (offen, ohne Auth) - **Config-Server:** `http://127.0.0.1:3013/config` (localhost + separater Admin-Token) - **Auth:** API-Key (Bearer-Token) für `/mcp` - **Tools:** 33 (Docker, Community Applications, Netzwerk und Unraid-System) --- ## Architektur ``` ┌─────────────────────────────────────────────────────────┐ │ Unraid (192.168.1.2) │ │ │ │ /usr/local/bin/mua (kompiliertes Bun-Binary) │ │ ├── MCP-Server 0.0.0.0:3002 (Bearer-Auth) │ │ └── Config-Server 127.0.0.1:3013 (nur localhost) │ │ │ │ /etc/rc.d/rc.mua (SysVinit-Service) │ │ /boot/config/plugins/mua/mua.conf (API-Key + Tools) │ │ /usr/local/emhttp/plugins/mua/mua.page (WebGUI-Tab) │ └─────────────────────────────────────────────────────────┘ ▲ ▲ │ HTTP + Bearer-Token │ HTTP (localhost) │ │ ┌────────┴─────────┐ ┌────────┴─────────┐ │ MCP-Client │ │ Unraid WebGUI │ │ (Hermes, etc.) │ │ User Utilities → MUA │ └──────────────────┘ └──────────────────┘ ``` **Wichtig:** Der MCP-Endpunkt (Port 3002) ist **extern** erreichbar und braucht einen Bearer-Token. Der Config-Server (Port 3013) läuft **nur auf localhost** und verlangt zusätzlich einen bei jedem Start neu erzeugten Admin-Token. Die WebGUI schützt schreibende Formulare außerdem mit einem CSRF-Token. ## Sicherheitsmodell - Neuinstallationen starten im Profil **Nur Lesen**. Container-Steuerung, aktive Netzwerktests, Container-Umbauten und die Root-Shell sind aus. - Für Diagnosen steht `unraid_system_shell_readonly` bereit. Es startet nur fest freigegebene Leseprogramme als direkte Argumentliste, niemals über `/bin/sh`; Verkettungen, Pipes, Umleitungen und schreibende Optionen werden dadurch verhindert. Die freie Root-Shell bleibt separat und kritisch. - `none` bedeutet tatsächlich **keine Tools aktiv**; `all` ist ein expliziter Vollzugriff und wird in der GUI deutlich gewarnt. - Container-Umgebungswerte werden nie ausgegeben, nur ihre Variablennamen. - Häufige Secret-Formate in Logs werden zusätzlich redigiert. Logs können trotzdem Nutzdaten enthalten und sollten gezielt abgefragt werden. - Der API-Key erscheint nur unmittelbar nach seiner Erzeugung vollständig. - Tool-Aufrufe werden ohne Argumente oder Ausgaben in `/var/log/plugins/mua-audit.log` protokolliert. - Community-Applications-Installationen laufen immer über Suche, Vorschau und ein exakt an diese Änderung gebundenes, zehn Minuten gültiges Freigabeticket. Das Ergebnis bleibt über ein reguläres Unraid- Benutzertemplate vollständig in der Docker-GUI verwaltbar. - CORS ist standardmäßig aus. Requests sind auf 1 MiB, 120 pro Minute je Client und vier gleichzeitig laufende Werkzeuge begrenzt. Diese Grenzen lassen sich per Umgebungsvariable anpassen. --- ## Installation ### 1. Plugin installieren Über die Unraid-WebGUI: **Settings → Plugins → Community Plugins** → `MUA (Mikes Unraid Agent)` suchen und installieren. Oder manuell: ```bash # .txz von Gitea laden curl -O http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/dist/mua-2026.08.22.r015-x86_64-1.txz # Installieren upgradepkg --install-new mua-2026.08.22.r015-x86_64-1.txz ``` ### 2. Service starten ```bash /etc/rc.d/rc.mua start ``` Der Service startet automatisch bei jedem Boot (SysVinit). ### 3. Health-Check ```bash curl http://192.168.1.2:3002/health # → {"status":"ok","version":"2026.08.22.r015","auth":"required"} ``` --- ## API-Key generieren (WebGUI) 1. **Settings → User Utilities → MUA** in der Unraid-WebGUI öffnen 2. Unter **„API-Key (Authentifizierung)"** auf **„Neuen API-Key generieren"** klicken 3. Den einmalig angezeigten Key kopieren (64-stellige Hex-Zeichenfolge) Der Key wird in `/boot/config/plugins/mua/mua.conf` gespeichert (chmod 600). > **Hinweis:** Der Key wird nur einmal angezeigt. Wenn du ihn verlierst, > generiere einen neuen — der alte funktioniert dann nicht mehr. --- ## MCP-Client konfigurieren MUA ist ein **Standard-MCP-Server** (Streamable HTTP, POST-only, JSON-RPC 2.0). Jeder MCP-Client kann es nutzen — URL + Bearer-Token reichen: ``` URL: http://192.168.1.2:3002/mcp Auth: Authorization: Bearer ``` > **Unterschied zu den anderen MCP-Servern:** Die übrigen Tools > (Web-Suche, Home Assistant, Unraid, Sonarr/Radarr) laufen auf > **192.168.1.196** und werden per **SSH-stdio** angebunden. MUA läuft > direkt auf Unraid und spricht **HTTP** — kein SSH-Wrapper nötig. ### Beispiel: Hermes Agent Hermes kann MCP-Server per stdio (Wrapper) oder direkt per HTTP anbinden. Da MUA HTTP spricht, reicht ein HTTP-Client-Wrapper, der die stdio-Requests an `http://192.168.1.2:3002/mcp` mit dem Bearer-Token weiterleitet: ```yaml # ~/.hermes/config.yaml mcp_servers: mua: command: /usr/bin/ssh args: - -T - -o - BatchMode=yes - -o - IdentitiesOnly=yes - -i - /Users/mike_i386/.ssh/lmstudio_unraid - root@192.168.1.196 - /usr/bin/python3 - /opt/mike-ai/mua/mua_mcp_http.py env: MUA_URL: http://192.168.1.2:3002/mcp MUA_API_KEY: connect_timeout: 30.0 enabled: true ``` > **Hinweis:** Der Wrapper `mua_mcp_http.py` (auf 196) übersetzt > stdio → HTTP mit Bearer-Token. Alternativ: jeder MCP-Client, der > Streamable HTTP nativ unterstützt, kann MUA direkt anbinden. ### Beispiel: Direkter HTTP-Test (curl) ```bash # Health-Check (ohne Auth) curl http://192.168.1.2:3002/health # MCP-Initialisierung (mit Auth) curl -X POST http://192.168.1.2:3002/mcp \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' # Tool-Liste curl -X POST http://192.168.1.2:3002/mcp \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' # Tool aufrufen curl -X POST http://192.168.1.2:3002/mcp \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"unraid_docker_list","arguments":{}}}' ``` ### Ohne API-Key → 401 ```bash curl -X POST http://192.168.1.2:3002/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' # → 401 Unauthorized ``` --- ## Tools aktivieren/deaktivieren (WebGUI) In **Settings → User Utilities → MUA** stehen vier Sicherheitsprofile bereit: - **Nur Lesen (empfohlen):** Status, Diagnose, Logs und Inventar - **Betrieb + Diagnose:** zusätzlich aktive Prüfungen und Start/Stop/Restart - **Alles sperren:** MCP bleibt erreichbar, bietet aber keine Werkzeuge an - **Vollzugriff:** einschließlich Container-Umbau und uneingeschränkter Root-Shell Zusätzlich kann jedes Werkzeug einzeln nach Risikostufe freigegeben werden: | Gruppe | Tools | |--------|-------| | **Docker (15)** | `unraid_docker_list`, `unraid_docker_inspect`, `unraid_docker_logs`, `unraid_docker_analyze_logs`, `unraid_docker_processes`, `unraid_docker_stats`, `unraid_docker_info`, `unraid_docker_update_status`, `unraid_docker_start`, `unraid_docker_stop`, `unraid_docker_restart`, `unraid_docker_create`, `unraid_docker_modify`, `unraid_docker_update`, `unraid_docker_rebuild` | | **Community Applications (3)** | `unraid_ca_search`, `unraid_ca_install_preview`, `unraid_ca_install` | | **Netzwerk (6)** | `unraid_network_inventory`, `unraid_network_list`, `unraid_network_inspect`, `unraid_network_host_state`, `unraid_network_audit_tcp`, `unraid_network_lan_probe` | | **System (9)** | `unraid_system_health`, `unraid_storage_status`, `unraid_disk_health`, `unraid_notifications_list`, `unraid_shares_list`, `unraid_share_inspect`, `unraid_system_connection_test`, `unraid_system_shell_readonly`, `unraid_system_shell` | Deaktivierte Tools werden vom MCP-Server gefiltert — sie erscheinen nicht in `tools/list` und können nicht aufgerufen werden (→ `ERROR: Tool disabled`). --- ## Service-Verwaltung | Aktion | Befehl | |--------|--------| | Starten | `/etc/rc.d/rc.mua start` | | Stoppen | `/etc/rc.d/rc.mua stop` | | Neu starten | `/etc/rc.d/rc.mua restart` | | Status | `/etc/rc.d/rc.mua status` | | Logs | `tail -f /var/log/plugins/mua.log` | ### Auto-Restart bei Update Das Binary prüft alle 30 s, ob sich das Binary auf Platte geändert hat (mtime + size). Wenn ja → `rc.mua restart` + sauber beenden. Der neue Prozess startet automatisch. Zusätzlich führt der POST-INSTALL-Hook im `.plg` nach jedem Update `rc.mua restart` aus. --- ## Konfiguration | Datei | Zweck | |-------|-------| | `/boot/config/plugins/mua/mua.conf` | API-Key + Tool-Filter (chmod 600) | | `/usr/local/emhttp/plugins/mua/mua.page` | WebGUI-Tab (PHP) | | `/etc/rc.d/rc.mua` | SysVinit-Service-Script | | `/usr/local/bin/mua` | Kompiliertes Bun-Binary | ### Config-Datei-Format (`mua.conf`) ```ini MUA_API_KEY=a1b2c3d4... MUA_ENABLED_TOOLS=unraid_docker_list,unraid_docker_inspect,unraid_network_list ``` Sonderwerte: `all` aktiviert ausdrücklich alles, `none` deaktiviert alles. --- ## Entwicklung ### Voraussetzungen - [Bun](https://bun.sh) (Runtime + Build-Tool) - `xz` (für `.txz`-Packing) - `xmllint` (für `.plg`-Validierung) ### Build ```bash # TypeScript-Check bunx tsc --noEmit # Linux-Binary (für Unraid) bun build src/index.ts --compile --target=bun-linux-x64 --outfile dist/mua # macOS-Binary (für lokalen Test) bun build src/index.ts --compile --target=bun-darwin-arm64 --outfile dist/mua-mac # .txz packen (Version wird aus package.json gelesen) bash scripts/package.sh ``` ### Lokaler Test ```bash # Test-Setup (ohne Unraid) MUA_CONFIG_DIR=/tmp/mua-test MUA_PORT=3999 MUA_CONFIG_PORT=3998 ./dist/mua-mac # Health-Check curl http://127.0.0.1:3999/health # Config-Server curl http://127.0.0.1:3998/config ``` ### Versionierung Format: `YYYY.MM.DD.rNNN` (Release-Counter hinter Datum). Version in **allen** Dateien aktualisieren: - `package.json` - `src/helpers.ts` (`MUA_VERSION`) - `plugin/plugin.json` - `plugin/mua.plg` (Version + txzURL + CHANGES) - `mcp/server.php` - `mcp/helpers.php` Nach Build: **SHA256** im `.plg` aktualisieren: ```bash shasum -a 256 dist/mua-*.txz ``` ### Release-Prozess 1. Version erhöhen (alle Dateien) 2. `bunx tsc --noEmit` 3. `bun build src/index.ts --compile --target=bun-linux-x64 --outfile dist/mua` 4. `bash scripts/package.sh` 5. SHA256 im `.plg` aktualisieren 6. `xmllint --noout plugin/mua.plg` 7. `git add -A && git commit -m "rNNN: ..." && git push` 8. Auf Unraid: **Plugins → MUA → Update**