# 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` (nur localhost, für WebGUI) - **Auth:** API-Key (Bearer-Token) für `/mcp` - **Tools:** 21 (Docker: 14, Netzwerk: 6, System: 1) --- ## 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.) │ │ Settings → 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 wird ausschließlich von der WebGUI-Page (`mua.page`) über PHP/curl angesprochen — er ist von außen nicht erreichbar. --- ## 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.18.r004-x86_64-1.txz # Installieren ./mua-2026.08.18.r004-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.18.r004","auth":"required"} ``` --- ## API-Key generieren (WebGUI) 1. **Settings → MUA** in der Unraid-WebGUI öffnen 2. Unter **„API-Key (Authentifizierung)"** auf **„Neuen API-Key generieren"** klicken 3. Den angezeigten Key kopieren (64-stellige Hex-String) 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 ### Hermes Agent In `~/.hermes/config.yaml` unter `mcp_servers`: ```yaml 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:** Hermes nutzt SSH-stdio (Python-Wrapper auf 196), nicht direkt > HTTP. Der Wrapper `mua_mcp_http.py` übersetzt stdio → HTTP mit Bearer-Token. ### 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 → MUA** → **„Tools (aktivieren / deaktivieren)"**: | Gruppe | Tools | |--------|-------| | **Docker (14)** | `unraid_docker_list`, `unraid_docker_inspect`, `unraid_docker_logs`, `unraid_docker_analyze_logs`, `unraid_docker_processes`, `unraid_docker_stats`, `unraid_docker_info`, `unraid_docker_start`, `unraid_docker_stop`, `unraid_docker_restart`, `unraid_docker_create`, `unraid_docker_modify`, `unraid_docker_update`, `unraid_docker_rebuild` | | **Netzwerk (6)** | `unraid_network_inventory`, `unraid_network_list`, `unraid_network_inspect`, `unraid_network_host_state`, `unraid_network_audit_tcp`, `unraid_network_lan_probe` | | **System (1)** | `unraid_system_connection_test` | 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`) ```json { "apiKey": "a1b2c3d4...", "enabledTools": [ "unraid_docker_list", "unraid_docker_inspect", "unraid_network_list", "unraid_system_connection_test" ] } ``` --- ## 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**