README: aktuelle Architektur + Client-Anbindung (Hermes, curl, WebGUI)
This commit is contained in:
@@ -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://<unraid-ip>:3002/mcp` (Streamable HTTP, POST-only, JSON-RPC 2.0)
|
||||
- **Health-Check:** `http://<unraid-ip>: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, <!DOCTYPE PLUGIN>)
|
||||
│ └── 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: <dein-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 <dein-api-key>" \
|
||||
-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 <dein-api-key>" \
|
||||
-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 <dein-api-key>" \
|
||||
-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://<unraid-ip>: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 (`<!DOCTYPE PLUGIN>`, `<FILE Run="/bin/bash">` + `<INLINE>`)
|
||||
- ✅ 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**
|
||||
|
||||
Reference in New Issue
Block a user