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://<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 (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:

# .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

/etc/rc.d/rc.mua start

Der Service startet automatisch bei jedem Boot (SysVinit).

3. Health-Check

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 <dein-api-key>

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:

# ~/.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: <dein-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)

# 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

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)

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 (Runtime + Build-Tool)
  • xz (für .txz-Packing)
  • xmllint (für .plg-Validierung)

Build

# 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

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

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
S
Description
No description provided
Readme
898 MiB
Languages
TypeScript 54.3%
PHP 42.6%
Shell 3.1%