diff --git a/README.md b/README.md index 3b250c6..e304acb 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,282 @@ # MUA — Mikes Unraid Agent -Natives Unraid-Plugin: 21 Docker-, Netzwerk- und System-Tools als MCP-Server (Streamable HTTP) auf Port 3002. +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 ``` -llama.cpp (196) → HTTP → http://192.168.1.2:3002/mcp (MUA Plugin auf Unraid) +┌─────────────────────────────────────────────────────────┐ +│ 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 │ +└──────────────────┘ └──────────────────┘ ``` -Kein SSH, kein Proxy, kein Key-Management (nur URL + API-Key). +**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. -## Unraid-Plugin-Struktur - -``` -MUA-Mikes-Unraid-Agent/ -├── plugin/ -│ ├── mua.plg # Unraid-Plugin-File (XML, ) -│ └── plugin.json # Metadaten (Name, Version, Pfade) -├── mcp/ -│ ├── server.php # MCP-Server (Streamable HTTP, JSON-RPC 2.0) -│ ├── helpers.php # Helper-Funktionen (Docker, Netzwerk, System) -│ ├── tools.php # 21 Tool-Definitionen -│ └── selftest.php # Selftest (12 Tests) -├── scripts/ -│ ├── rc.mua # SysVinit-Service-Script -│ ├── plugin.php # WebGUI-Tab (Settings > MUA) -│ └── unraid-docker-mcp-helper.php # Write-Operationen (DockerClient) -└── README.md -``` +--- ## Installation -### Über Unraid-Plugin-Installer +### 1. Plugin installieren + +Über die Unraid-WebGUI: **Settings → Plugins → Community Plugins** → +`MUA (Mikes Unraid Agent)` suchen und installieren. + +Oder manuell: ```bash -# .plg-File herunterladen und installieren -wget -O /tmp/mua.plg "http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/plugin/mua.plg" -# Im Unraid-WebGUI: Settings > Plugins > Install from URL -# URL: http://192.168.1.2:4000/michael/MUA-Mikes-Unraid-Agent/raw/branch/main/plugin/mua.plg +# .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 ``` -### Manuell +### 2. Service starten ```bash -# Repo klonen -git clone git@192.168.1.2:33/michael/MUA-Mikes-Unraid-Agent.git /tmp/mua - -# Dateien installieren -mkdir -p /usr/local/emhttp/plugins/mua/{mcp,scripts} -cp /tmp/mua/mcp/*.php /usr/local/emhttp/plugins/mua/mcp/ -cp /tmp/mua/scripts/plugin.php /usr/local/emhttp/plugins/mua/ -cp /tmp/mua/scripts/rc.mua /etc/rc.d/rc.mua -chmod 755 /etc/rc.d/rc.mua -cp /tmp/mua/scripts/unraid-docker-mcp-helper.php /usr/local/bin/ -chmod 755 /usr/local/bin/unraid-docker-mcp-helper.php - -# Selftest -php /usr/local/emhttp/plugins/mua/mcp/selftest.php - -# Starten /etc/rc.d/rc.mua start ``` -## Verwaltung +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` | -| WebGUI | Settings > MUA | -## MCP-Endpunkt +### Auto-Restart bei Update -- **URL:** `http://:3002/mcp` -- **Transport:** Streamable HTTP (POST-only) -- **Protokoll:** JSON-RPC 2.0 -- **Session:** `Mcp-Session-Id` Header +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. -## Tools (21) +--- -| Kategorie | Tools | -|---|---| -| **Docker (14)** | list, inspect, logs, analyze_logs, processes, stats, info, start, stop, restart, create, modify, update, rebuild | -| **Netzwerk (6)** | inventory, list, inspect, host_state, audit_tcp, lan_probe | -| **System (1)** | connection_test | +## Konfiguration -## Konformität +| 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 | -- ✅ Echte Unraid-Plugin-Struktur (``, `` + ``) -- ✅ SysVinit-Service (`/etc/rc.d/rc.mua`) statt systemd -- ✅ WebGUI-Tab (`launch="Settings/MUA"`) -- ✅ Standard-Pfade (`/usr/local/emhttp/plugins/mua`, `/boot/config/plugins/mua`) -- ✅ Selftest (12/12) -- ✅ PHP 8.4-kompatibel +### Config-Datei-Format (`mua.conf`) -## Lizenz +```json +{ + "apiKey": "a1b2c3d4...", + "enabledTools": [ + "unraid_docker_list", + "unraid_docker_inspect", + "unraid_network_list", + "unraid_system_connection_test" + ] +} +``` -MIT +--- + +## 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**