Replace GraphQL Unraid MCP with MUA

This commit is contained in:
Mikei386
2026-08-23 22:08:31 +02:00
parent b723f820bf
commit a3297dbdd9
19 changed files with 84 additions and 76 deletions
+7 -2
View File
@@ -64,8 +64,7 @@ else
fi
for optional in mike-ai-mcp-web mike-ai-mcp-homeassistant mike-ai-mcp-arr \
mike-ai-mcp-github mike-ai-mcp-platform-context mike-ai-mcp-athena-operator \
mike-ai-mcp-unraid-official; do
mike-ai-mcp-github mike-ai-mcp-platform-context mike-ai-mcp-athena-operator; do
if container_healthy "$optional"; then
pass "$optional aktiv"
else
@@ -73,6 +72,12 @@ for optional in mike-ai-mcp-web mike-ai-mcp-homeassistant mike-ai-mcp-arr \
fi
done
if docker ps -a --format '{{.Names}}' | grep -qx 'mike-ai-mcp-unraid-official'; then
fail "veralteter GraphQL-basierter Unraid-MCP ist noch vorhanden"
else
pass "kein GraphQL-basierter Unraid-MCP vorhanden"
fi
if [[ -s /var/lib/mike-ai-platform-context/runtime.json ]]; then
snapshot_age=$(( $(date +%s) - $(stat -c %Y /var/lib/mike-ai-platform-context/runtime.json) ))
if (( snapshot_age <= 180 )); then
+1 -3
View File
@@ -60,10 +60,8 @@ case "${1:-}" in
start_proxy mike-ai-emergency-mcp-web mike-ai-tools 18090 mike-ai-mcp-web
start_proxy mike-ai-emergency-mcp-homeassistant mike-ai-tools 18091 mike-ai-mcp-homeassistant
start_proxy mike-ai-emergency-mcp-arr mike-ai-tools 18092 mike-ai-mcp-arr
start_proxy mike-ai-emergency-mcp-unraid mike-ai-tools 18093 mike-ai-mcp-unraid-official
echo 'Notfall-Proxys laufen ausschließlich auf 127.0.0.1.'
echo 'Jetzt vom Client einen SSH-Tunnel auf die Ports 18080 und 18090-18093 öffnen.'
echo 'Jetzt vom Client einen SSH-Tunnel auf die Ports 18080 und 18090-18092 öffnen.'
;;
stop)
remove_proxies
+13 -3
View File
@@ -17,9 +17,14 @@ Prompts heraus, verhindert den früher beobachteten Kontextverbrauch von über
| `mcp-arr` | `http://mike-ai-mcp-arr:8000/mcp` | Sonarr/Radarr/Prowlarr mit serverseitiger Policy | Profil `arr` |
| `mcp-navidrome` | `http://mike-ai-mcp-navidrome:3000/mcp` | Navidrome-Bibliothek, Suche, Playlists, Favoriten und Hörverlauf | Profil `navidrome` |
| `mcp-github` | `http://mike-ai-mcp-github:8000/mcp` | offizieller GitHub-MCP, auf vier reine Repository-Lesewerkzeuge begrenzt | Profil `github` |
| `mcp-unraid-official` | `http://mike-ai-mcp-unraid-official:8000/mcp` | offizieller, read-only begrenzter Unraid-Zugang | Profil `unraid` |
| `mcp-unraid-ssh` | `http://mike-ai-mcp-unraid-ssh:8000/mcp` | erweiterte Diagnose über einen erzwungenen SSH-Befehl | optional (`extended`) |
Unraid wird produktiv ausschließlich über das auf dem HomeServer laufende
MUA-Plugin (`http://192.168.1.2:3002/mcp`) angebunden. Open WebUI führt davon
zwei Ansichten: `mua-readonly-local` für automatische Diagnose und `mua` für
bewusst aktivierte Verwaltungsaktionen. Ein GraphQL-basierter Unraid-MCP ist
nicht Bestandteil des Stacks.
Die drei Websuch-Container verwenden `AI_DNS` aus
`/etc/mike-ai/stack.env`. Der Web-MCP hängt zusätzlich am getrennten
`mike-ai-tools-egress`-Netz, weil er gefundene öffentliche Seiten nach der
@@ -88,7 +93,7 @@ passenden Server wählen:
| Entitäten, Zustände, Historie, Automationen und Dashboards | Home Assistant | Web, Unraid |
| Serien, Filme, fehlende Episoden und Indexer-Releases | Sonarr und Radarr | Web |
| Persönliche Musikbibliothek, Titel, Alben, Künstler und Playlists | Navidrome | Web, ARR |
| Lesende NAS-, Docker-, Array-, Netzwerk- und Logdiagnose | Unraid (Systemdiagnose) | MUA |
| Lesende NAS-, Docker-, Array-, Netzwerk- und Logdiagnose | MUA · Unraid-Diagnose (read-only) | MUA-Verwaltung |
| Athena-KI-Plattform entwickeln, testen, deployen, Modelle/Git/Recovery pflegen | Athena Operator | Platform Context für reine Architekturauskunft |
| Ausdrücklich benötigte MUA-Verwaltungsaktion | MUA | Unraid-Diagnose nicht parallel |
@@ -132,9 +137,14 @@ Die lokale Installation benötigt die vorhandenen Secret-Dateien:
/etc/mike-ai/arr-mcp.env
/etc/mike-ai/navidrome-mcp.env
/etc/mike-ai/github-mcp.env
/etc/mike-ai/runraid/.env
/etc/mike-ai/mua-mcp.env
```
`mua-mcp.env` enthält ausschließlich MUA-Endpunkt und Bearer-Token. Der
Installer legt daraus die vollständige MUA-Verbindung und eine strikt auf
Lesewerkzeuge begrenzte automatische Ansicht an. Die Datei ist root-only
(Modus `0600`) und wird nur verschlüsselt im Recovery-Bundle gesichert.
Die erweiterte Unraid-Diagnose benötigt zusätzlich die Konfigurationsdatei,
den eingeschränkten Schlüssel und die bekannte Hostsignatur. Sie wird nur mit
`--profile extended` gestartet.
-23
View File
@@ -213,29 +213,6 @@ services:
retries: 5
start_period: 15s
mcp-unraid-official:
<<: *tool-common
image: debian:13-slim
container_name: mike-ai-mcp-unraid-official
profiles: [unraid]
env_file:
- ${RUNRAID_ENV_FILE:-/etc/mike-ai/runraid/.env}
environment:
UNRAID_RMCP_HOST: 0.0.0.0
UNRAID_RMCP_PORT: "8000"
UNRAID_RMCP_DISABLE_HTTP_AUTH: "true"
UNRAID_NOAUTH: "true"
UNRAID_RMCP_ALLOWED_HOSTS: "mike-ai-mcp-unraid-official:8000,mike-ai-mcp-unraid-official,localhost:8000,127.0.0.1:8000"
# Public DNS cannot resolve the Fritzbox-only name. Preserve the hostname
# used by the TLS endpoint while binding it to the verified home-LAN IP.
extra_hosts:
- "homeserver.fritz.box:192.168.1.2"
volumes:
- ${RUNRAID_BINARY:-/usr/local/bin/runraid}:/usr/local/bin/unraid:ro
entrypoint: ["/usr/local/bin/unraid"]
command: ["serve"]
networks: [tools, egress]
mcp-unraid-ssh:
<<: *tool-common
profiles: [extended]
-6
View File
@@ -61,12 +61,6 @@ if [[ -s /etc/mike-ai/github-mcp.env ]] && \
else
echo "GitHub bleibt aus: dedizierter Read-only-Token fehlt."
fi
if [[ -s /etc/mike-ai/runraid/.env && -x /usr/local/bin/runraid ]]; then
profiles+=(--profile unraid)
else
echo "Unraid bleibt aus: runraid 0.4.2 oder Secret-Datei fehlt."
fi
# TinySearch keeps the embedding bundle outside the container. Download it
# once on a fresh host; subsequent rebuilds reuse the named volume.
#
+2 -11
View File
@@ -107,11 +107,8 @@ tar -xzf "$mcp_archive" -C "$stage/approved" \
etc/mike-ai/router-api-key \
etc/mike-ai/homeassistant-admin-mcp.env \
etc/mike-ai/arr-mcp.env \
etc/mike-ai/runraid/.env \
etc/mike-ai/runraid/homeserver-cert.pem \
etc/mike-ai/keys/unraid_root \
etc/mike-ai/ssh/known_hosts_unraid_ai \
usr/local/bin/runraid
etc/mike-ai/ssh/known_hosts_unraid_ai
old_router_key=$(<"$stage/approved/etc/mike-ai/router-api-key")
[[ -n $old_router_key ]] || die "Router-Key in der Sicherung ist leer."
@@ -151,21 +148,15 @@ if [[ -f $INSTALL_CONFIG ]]; then
set_env_value "$INSTALL_CONFIG" OPENWEBUI_IMAGE "$REFERENCE_OPENWEBUI_TAG"
fi
install -d -m 0700 "$SECRETS_DIR/runraid" "$SECRETS_DIR/keys" "$SECRETS_DIR/ssh"
install -d -m 0700 "$SECRETS_DIR/keys" "$SECRETS_DIR/ssh"
install -m 0600 "$stage/approved/etc/mike-ai/homeassistant-admin-mcp.env" \
"$SECRETS_DIR/homeassistant-admin-mcp.env"
install -m 0600 "$stage/approved/etc/mike-ai/arr-mcp.env" \
"$SECRETS_DIR/arr-mcp.env"
install -m 0600 "$stage/approved/etc/mike-ai/runraid/.env" \
"$SECRETS_DIR/runraid/.env"
install -m 0600 "$stage/approved/etc/mike-ai/runraid/homeserver-cert.pem" \
"$SECRETS_DIR/runraid/homeserver-cert.pem"
install -m 0600 "$stage/approved/etc/mike-ai/keys/unraid_root" \
"$SECRETS_DIR/keys/unraid_root"
install -m 0600 "$stage/approved/etc/mike-ai/ssh/known_hosts_unraid_ai" \
"$SECRETS_DIR/ssh/known_hosts_unraid_ai"
install -m 0755 "$stage/approved/usr/local/bin/runraid" /usr/local/bin/runraid
log "Tool-Container mit der neuen Stackdefinition aktivieren"
"$STACK_DIR/platform/mcp/install-tools.sh"
+35 -14
View File
@@ -6,6 +6,7 @@ CONTAINER=${OPENWEBUI_CONTAINER:-mike-ai-open-webui}
VOLUME=${OPENWEBUI_VOLUME:-mike-ai_open-webui-data}
FILTER_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/filters" && pwd)
ACTION_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/actions" && pwd)
MUA_MCP_ENV_FILE=${MUA_MCP_ENV_FILE:-/etc/mike-ai/mua-mcp.env}
die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || die "Bitte als root ausführen."
@@ -42,7 +43,7 @@ if [[ -s /etc/mike-ai/github-mcp.env ]] && \
grep -Eq '^GITHUB_PERSONAL_ACCESS_TOKEN=.+$' /etc/mike-ai/github-mcp.env; then
github_enabled=true
fi
python3 - "$db" "$FILTER_DIR" "$ACTION_DIR" "${OPENWEBUI_FILTER_OWNER_ID:-}" "$navidrome_enabled" "$github_enabled" <<'PY'
python3 - "$db" "$FILTER_DIR" "$ACTION_DIR" "${OPENWEBUI_FILTER_OWNER_ID:-}" "$navidrome_enabled" "$github_enabled" "$MUA_MCP_ENV_FILE" <<'PY'
import json
import copy
import pathlib
@@ -50,7 +51,10 @@ import sqlite3
import sys
import time
db, filter_dir, action_dir, requested_owner, navidrome_enabled_raw, github_enabled_raw = sys.argv[1:]
(
db, filter_dir, action_dir, requested_owner, navidrome_enabled_raw,
github_enabled_raw, mua_mcp_env_file,
) = sys.argv[1:]
navidrome_enabled = navidrome_enabled_raw.lower() == "true"
github_enabled = github_enabled_raw.lower() == "true"
con = sqlite3.connect(db)
@@ -173,8 +177,9 @@ with con:
isinstance(connection, dict)
and (
str((connection.get("info") or {}).get("id", "")).lower()
== "athena-terminal-local"
in {"athena-terminal-local", "unraid-readonly-local"}
or "mike-ai-mcp-athena-terminal" in str(connection.get("url", "")).lower()
or "mike-ai-mcp-unraid-official" in str(connection.get("url", "")).lower()
)
)
]
@@ -199,14 +204,8 @@ with con:
"konfigurierte Indexer. Keine allgemeine Websuche; Schreibaktionen benötigen "
"Vorschau und Freigabe.",
),
"unraid-readonly-local": (
"Unraid (Systemdiagnose)",
"Bevorzugtes Werkzeug für lesende Unraid-Diagnose: Host, Array, Datenträger, "
"Docker, Shares, Netzwerk, UPS und Logs. Für dieselbe Anfrage nicht zusätzlich "
"MUA aufrufen; MUA nur für dessen spezielle oder freigegebene Verwaltungsaktionen.",
),
"mua-readonly-local": (
"Unraid-Diagnose (MUA read-only)",
"MUA · Unraid-Diagnose (read-only)",
"Automatisch verwendbarer, serverseitig in Open WebUI auf reine Lese- und "
"Diagnosewerkzeuge begrenzter MUA-Zugang. Für Containerbestand, Logs, System, "
"Storage, Shares und Netzwerkstatus. Keine Start/Stop-, Installations-, "
@@ -215,8 +214,8 @@ with con:
"mua": (
"MUA (Unraid-Verwaltung)",
"Nur für ausdrücklich benötigte MUA-spezifische oder freigegebene Unraid-"
"Verwaltungsaktionen. Für reine Statusabfragen und Diagnosen stattdessen "
"Unraid (Systemdiagnose) verwenden; niemals beide parallel ausprobieren.",
"Verwaltungsaktionen. Für reine Statusabfragen und Diagnosen die read-only-"
"MUA-Verbindung verwenden; niemals beide parallel ausprobieren.",
),
"navidrome-local": (
"Navidrome (Musikbibliothek)",
@@ -267,8 +266,6 @@ with con:
match = "github-local"
elif "mike-ai-mcp-athena-operator" in url:
match = "athena-operator-local"
elif "mike-ai-mcp-unraid-official" in url:
match = "unraid-readonly-local"
else:
continue
name, description = descriptions[match]
@@ -289,6 +286,30 @@ with con:
),
None,
)
if mua_source is None and pathlib.Path(mua_mcp_env_file).is_file():
mua_env = {}
for raw_line in pathlib.Path(mua_mcp_env_file).read_text().splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
mua_env[key.strip()] = value.strip().strip('"').strip("'")
mua_url = mua_env.get("MUA_MCP_URL", "")
mua_token = mua_env.get("MUA_MCP_BEARER_TOKEN", "")
if mua_url and mua_token:
name, description = descriptions["mua"]
mua_source = {
"url": mua_url,
"path": "",
"type": "mcp",
"auth_type": "bearer",
"headers": None,
"key": mua_token,
"config": {"enable": True, "access_grants": []},
"info": {"id": "mua", "name": name, "description": description},
}
connections.append(mua_source)
changed = True
if mua_source is not None:
readonly_functions = ",".join((
"unraid_docker_list", "unraid_docker_inspect", "unraid_docker_logs",
@@ -32,7 +32,6 @@ mkdir -p "$stage/rootfs" "$stage/payload"
for source in \
/etc/mike-ai \
/root/mike-ai-install.env \
/usr/local/bin/runraid \
/opt/mike-ai/stack/docs \
/data/mike-ai-platform-context; do
[[ -e $source ]] || continue
@@ -44,9 +44,6 @@ tar -C "$stage/rootfs" -xzf "$stage/host-config.tar.gz"
install -d -m 0700 /etc/mike-ai
rsync -a "$stage/rootfs/etc/mike-ai/" /etc/mike-ai/
install -m 0600 "$stage/rootfs/root/mike-ai-install.env" /root/mike-ai-install.env
if [[ -x $stage/rootfs/usr/local/bin/runraid ]]; then
install -m 0755 "$stage/rootfs/usr/local/bin/runraid" /usr/local/bin/runraid
fi
log "Reproduzierbaren Host-Installer ausführen"
set +e