diff --git a/compose.yaml b/compose.yaml index 97a1236..a9a844f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -747,7 +747,7 @@ services: # Seed native MCP connections on a fresh Open WebUI database. Secrets # stay inside the tool containers, so these internal URLs need no keys. TOOL_SERVER_CONNECTIONS: >- - [{"url":"http://mike-ai-mcp-platform-context:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"athena-platform","name":"Athena Plattformwissen","description":"Zuerst aktivieren und verwenden, wenn an Athena/MikeAI, Modellen, Profilen, Router, OpenWebUI, MCPs, TTS/STT, Vision, Netzwerk oder Recovery gearbeitet wird. Liefert versionierte Dokumentation und einen begrenzten aktuellen Systemstand. Dokumentationspflege nur über Vorschau und ausdrückliche Freigabe; keine Container-, Shell-, Netzwerk-, Git- oder Secretrechte."}},{"url":"http://mike-ai-mcp-web:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"web-local","name":"Web (öffentlich, read-only)","description":"Für aktuelle öffentliche Internetdaten, Quellenprüfung, Hugging Face und Produktsuche. Für GitHub-Quellcode den offiziellen GitHub-MCP verwenden; nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose."}},{"url":"http://mike-ai-mcp-github:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"github-local","name":"GitHub (offiziell, read-only)","description":"Für GitHub-Repositories, Quellcode, README-Dateien, Verzeichnisbäume und Code-Suche. Strikt read-only mit genau vier Werkzeugen; nicht für allgemeine Webrecherche oder Änderungen an Repositories."}},{"url":"http://mike-ai-mcp-homeassistant:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"homeassistant-local","name":"Home Assistant (lokal)","description":"Für Home-Assistant-Entitäten, Zustände, Historie, Automationen, Dashboards, HA-Diagnose und freigegebene YAML-Dateien. YAML-Lesen ist begrenzt; Änderungen benötigen serverseitige Vorschau, explizite Freigabe, Sicherung und Validierung. Nicht für Unraid, Sonarr/Radarr oder allgemeine Websuche."}},{"url":"http://mike-ai-mcp-arr:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"arr-local","name":"Sonarr und Radarr (lokal)","description":"Nur für verwaltete Serien/Filme, fehlende Episoden, Queue und Suche über konfigurierte Indexer. Keine allgemeine Websuche; Schreibaktionen benötigen Vorschau und Freigabe."}},{"url":"http://mike-ai-mcp-navidrome:3000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"navidrome-local","name":"Navidrome (Musikbibliothek)","description":"Nur für die persönliche Navidrome-Musikbibliothek: Titel, Alben, Künstler, Playlists, Favoriten und Hörverlauf. Nicht für Sonarr/Radarr, allgemeine Websuche oder Audioausgabe auf dem KI-Host. Wegen des großen Werkzeugkatalogs nur bei Musikaufgaben aktivieren."}},{"url":"http://mike-ai-mcp-unraid-official:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"unraid-readonly-local","name":"Unraid (Systemdiagnose)","description":"Nur für Unraid-Host, Array, Datenträger, Docker-Container, Shares, Netzwerk, UPS und Systemlogs. Nicht für Home Assistant oder Medieninhalte; Standardzugriff read-only."}}] + [{"url":"http://mike-ai-mcp-platform-context:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"athena-platform","name":"Athena Plattformwissen","description":"Zuerst aktivieren und verwenden, wenn an Athena/MikeAI, Modellen, Profilen, Router, OpenWebUI, MCPs, TTS/STT, Vision, Netzwerk oder Recovery gearbeitet wird. Liefert versionierte Dokumentation und einen begrenzten aktuellen Systemstand. Dokumentationspflege nur über Vorschau und ausdrückliche Freigabe; keine Container-, Shell-, Netzwerk-, Git- oder Secretrechte."}},{"url":"http://mike-ai-mcp-web:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"web-local","name":"Web (öffentlich, read-only)","description":"Für aktuelle öffentliche Internetdaten, Quellenprüfung, Hugging Face und Produktsuche. Für GitHub-Quellcode den offiziellen GitHub-MCP verwenden; nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose."}},{"url":"http://mike-ai-mcp-github:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"github-local","name":"GitHub (offiziell, read-only)","description":"Für GitHub-Repositories, Quellcode, README-Dateien, Verzeichnisbäume und Code-Suche. Strikt read-only mit genau vier Werkzeugen; nicht für allgemeine Webrecherche oder Änderungen an Repositories."}},{"url":"http://mike-ai-mcp-homeassistant:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"homeassistant-local","name":"Home Assistant (lokal)","description":"Für Home-Assistant-Entitäten, Zustände, Historie, Automationen, Dashboards, HA-Diagnose und freigegebene YAML-Dateien. YAML-Lesen ist begrenzt; Änderungen benötigen serverseitige Vorschau, explizite Freigabe, Sicherung und Validierung. Nicht für Unraid, Sonarr/Radarr oder allgemeine Websuche."}},{"url":"http://mike-ai-mcp-arr:8000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"arr-local","name":"Sonarr und Radarr (lokal)","description":"Nur für verwaltete Serien/Filme, fehlende Episoden, Queue und Suche über konfigurierte Indexer. Keine allgemeine Websuche; Schreibaktionen benötigen Vorschau und Freigabe."}},{"url":"http://mike-ai-mcp-navidrome:3000/mcp","path":"","type":"mcp","auth_type":"none","headers":null,"key":"","config":{"enable":true,"access_grants":[]},"info":{"id":"navidrome-local","name":"Navidrome (Musikbibliothek)","description":"Nur für die persönliche Navidrome-Musikbibliothek: Titel, Alben, Künstler, Playlists, Favoriten und Hörverlauf. Nicht für Sonarr/Radarr, allgemeine Websuche oder Audioausgabe auf dem KI-Host. Wegen des großen Werkzeugkatalogs nur bei Musikaufgaben aktivieren."}}] DO_NOT_TRACK: "true" SCARF_NO_ANALYTICS: "true" dns: ["${AI_DNS:-1.1.1.1}"] diff --git a/config/mua-mcp.env.example b/config/mua-mcp.env.example new file mode 100644 index 0000000..5a6853e --- /dev/null +++ b/config/mua-mcp.env.example @@ -0,0 +1,4 @@ +# Root-only auf Athena unter /etc/mike-ai/mua-mcp.env ablegen (Modus 0600). +# Der echte Bearer-Token gehört niemals ins Git-Repository. +MUA_MCP_URL=http://192.168.1.2:3002/mcp +MUA_MCP_BEARER_TOKEN=REPLACE_WITH_MUA_BEARER_TOKEN diff --git a/docs/BARE_METAL_RECOVERY.md b/docs/BARE_METAL_RECOVERY.md index e6d3f31..2828920 100644 --- a/docs/BARE_METAL_RECOVERY.md +++ b/docs/BARE_METAL_RECOVERY.md @@ -51,7 +51,6 @@ Das Skript nimmt ausschließlich auf: - `/etc/mike-ai` einschließlich aller Fach-MCP-Secrets, - `/root/mike-ai-install.env`, -- das lokale `runraid`-Binary, falls vorhanden, - das produktive Dokumentations-Overlay unter `/opt/mike-ai/stack/docs`, - Vorschläge, Sicherungen und Auditstatus des Platform Context MCP unter `/data/mike-ai-platform-context`, diff --git a/docs/COMPONENTS.md b/docs/COMPONENTS.md index 5893fc5..a800fb6 100644 --- a/docs/COMPONENTS.md +++ b/docs/COMPONENTS.md @@ -15,7 +15,7 @@ | Platform Context MCP | Athena-/MikeAI-Wissen, begrenzter Laufzeitsnapshot und kontrollierte Dokumentationspflege | eigener Container ohne Docker-Socket, Shell, Egress oder Secrets | Kern | | Athena Operator MCP | Entwicklung und vollständiger Betrieb der KI-Plattform mit gebundenen Freigaben | unprivilegierte MCP-Fassade plus rootseitiger strukturierter Executor; keine freie Shell | Kern | | Operator-Kontext | `docs/QWEN_OPERATOR_CONTEXT.md` plus `config/operator-system-prompt.txt` | versionierte Selbstbeschreibung und Sicherheitsregeln für Qwen | Kern | -| Unraid-MCP | lokales `runraid`-Binary | eigener optionaler Container | optional | +| Unraid/MUA | MUA-Plugin auf dem HomeServer, direkter MCP-Endpunkt | read-only Automatik plus bewusst aktivierte Verwaltung in Open WebUI | Kern | | Whisper | ggml-org/whisper.cpp | Service im Router-Deploy | optional | | XTTS-v2 | Coqui, offizielles CUDA-12.1-Image per Digest | RTX-3060-Container, Stimme `Annmarie Nele`, CPML | Kern | | TTS-Gateway | `platform/docker/tts-gateway/` | interne Queue, stabile deutsche Satzblöcke, automatische Erkennung rein englischer Texte und Piper-Fallback | Kern | diff --git a/docs/CURRENT_REFERENCE.md b/docs/CURRENT_REFERENCE.md index 3b6a2d2..b5d76a4 100644 --- a/docs/CURRENT_REFERENCE.md +++ b/docs/CURRENT_REFERENCE.md @@ -175,6 +175,11 @@ mit erweiterten Verwaltungsrechten bleibt von der Automatik ausgeschlossen; eine automatisch bereitgestellte Verbindung erteilt niemals Schreibrechte oder eine Änderungsfreigabe. +Unraid ist ausschließlich über das MUA-Plugin angebunden. Die automatische +Verbindung `mua-readonly-local` und die bewusst aktivierte Verbindung `mua` +nutzen denselben MUA-Endpunkt. Der frühere GraphQL-basierte Unraid-MCP wurde +entfernt und gehört weder zum Start noch zum Recovery. + Der GitHub-Container läuft produktiv. Token-Datei, interner Streamable-HTTP-Handshake, fehlende Host-Portfreigabe und exakt vier read-only Werkzeuge wurden am 23. August 2026 verifiziert. diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index dfd3fd2..ebe7458 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -162,10 +162,14 @@ vorhanden ist: /etc/mike-ai/homeassistant-admin-mcp.env /etc/mike-ai/arr-mcp.env /etc/mike-ai/navidrome-mcp.env -/etc/mike-ai/runraid/.env -/usr/local/bin/runraid Version 0.4.2 +/etc/mike-ai/mua-mcp.env ``` +Die MUA-Datei wird nach `config/mua-mcp.env.example` angelegt und mit Modus +`0600` geschützt. Sie verbindet Open WebUI direkt mit dem MUA-Plugin auf dem +Unraid-HomeServer. Unraids GraphQL-API wird nicht benötigt und soll deaktiviert +bleiben. + Nach dem Nachreichen einer Datei genügt: ```bash diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md index 9c9230f..71e4bdf 100644 --- a/docs/MIGRATION.md +++ b/docs/MIGRATION.md @@ -53,8 +53,7 @@ Das Skript prüft zuerst die Archiv-Hashes und übernimmt ausschließlich: - die persistente OpenWebUI-Datenbank samt Einstellungen und Uploads, - das zur Datenbank passende, gesicherte OpenWebUI-Container-Image, - den dazugehörigen WebUI- und Router-Schlüssel, -- die freigegebenen HA-, ARR- und Unraid-Secrets, -- `runraid`, dessen privaten Schlüssel, Zertifikat und Known-Hosts-Datei. +- die freigegebenen HA-, ARR- und MUA-/Unraid-Secrets. Es übernimmt bewusst **keine** alten Compose-Dateien, Routerprofile, Experimentdienste oder `.before-*`-Altstände. Vor dem Ersetzen des frischen diff --git a/docs/PLATFORM_OVERVIEW.md b/docs/PLATFORM_OVERVIEW.md index 6f4e486..b62d9d2 100644 --- a/docs/PLATFORM_OVERVIEW.md +++ b/docs/PLATFORM_OVERVIEW.md @@ -71,6 +71,9 @@ erzeugt nicht ungefragt eine zweite Deemix-Instanz. Automatische Unraid-Abfragen verwenden einen eigenen MUA-Read-only-Zugang, der in Open WebUI ausschließlich Diagnosewerkzeuge sichtbar macht. Der vollständige MUA-Verwaltungszugang bleibt davon getrennt und muss bewusst gewählt werden. +Beide Verbindungen sprechen denselben MCP-Endpunkt des MUA-Plugins auf dem +HomeServer an. Athena betreibt keinen zusätzlichen Unraid-GraphQL-MCP; die +GraphQL-API von Unraid darf deaktiviert bleiben. Open WebUI und Router veröffentlichen keinen normalen Host-Port. Der WireGuard-Gateway-Container stellt nur die vorgesehenen VPN-Endpunkte bereit. diff --git a/docs/QWEN_OPERATOR_CONTEXT.md b/docs/QWEN_OPERATOR_CONTEXT.md index 2532e2c..a86e55e 100644 --- a/docs/QWEN_OPERATOR_CONTEXT.md +++ b/docs/QWEN_OPERATOR_CONTEXT.md @@ -239,7 +239,7 @@ Netzzugriff. Kein MCP-Port wird am Host veröffentlicht. | Home Assistant | Zustände, Historie, Diagnose, begrenzte YAML-Abläufe | Lesen; Schreiben nur Preview/Approval | | ARR | Sonarr/Radarr, Indexersuche, kontrollierte Grabs | Lesen; Schreiben nur Preview/Approval | | Navidrome | Bibliothek, Empfehlungen, Playlists/Favoriten | eigener Benutzer; gezielt aktivieren | -| Unraid | Host-, Docker-, Array-, Netzwerk- und Logdiagnose | read-only Standard | +| MUA read-only | Host-, Docker-, Array-, Netzwerk- und Logdiagnose | automatischer Standard | | MUA/Admin | eng definierte Unraid-Verwaltung | bewusst aktivieren | Für automatische Unraid-Diagnose existiert in Open WebUI zusätzlich @@ -247,6 +247,8 @@ Für automatische Unraid-Diagnose existiert in Open WebUI zusätzlich blendet aber Start/Stop, Installation, Änderungen und die freie Root-Shell serverseitig in Open WebUI aus. Die vollständige Verbindung `mua` wird niemals automatisch bereitgestellt. +Es gibt keinen zweiten GraphQL-basierten Unraid-MCP. Schlägt MUA fehl, darf +nicht auf GraphQL ausgewichen oder dessen API eigenmächtig aktiviert werden. Der vorhandene Deemix-Dienst läuft auf Unraid und ist als externe Abhängigkeit im Diensteverzeichnis eingetragen. Für ein Deemix-MCP wird standardmäßig nur diff --git a/docs/RECOVERY_REQUIREMENTS.md b/docs/RECOVERY_REQUIREMENTS.md index b6de7cf..a2f0f0c 100644 --- a/docs/RECOVERY_REQUIREMENTS.md +++ b/docs/RECOVERY_REQUIREMENTS.md @@ -56,8 +56,8 @@ Im Repository gesichert sind inzwischen: Noch extern zu beschaffen und exakt festzuhalten sind: - Home-Assistant-MCP -- `runraid` 0.4.2 für den read-only Unraid-MCP -- gegebenenfalls eigener Unraid-Administrations-MCP +- MUA-Plugin auf dem Unraid-HomeServer sowie die root-only gesicherte + `/etc/mike-ai/mua-mcp.env` - LLama-GUI, falls sie erhalten bleibt Jede noch externe Komponente bekommt zusätzlich: diff --git a/platform/checks/verify-platform.sh b/platform/checks/verify-platform.sh index 7339ead..86905a5 100755 --- a/platform/checks/verify-platform.sh +++ b/platform/checks/verify-platform.sh @@ -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 diff --git a/platform/host/mike-ai-emergency-access b/platform/host/mike-ai-emergency-access index 01dc57e..38e9965 100644 --- a/platform/host/mike-ai-emergency-access +++ b/platform/host/mike-ai-emergency-access @@ -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 diff --git a/platform/mcp/README.md b/platform/mcp/README.md index 29f9ce9..0e17c5c 100644 --- a/platform/mcp/README.md +++ b/platform/mcp/README.md @@ -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. diff --git a/platform/mcp/compose.yaml b/platform/mcp/compose.yaml index 190419a..69e6913 100644 --- a/platform/mcp/compose.yaml +++ b/platform/mcp/compose.yaml @@ -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] diff --git a/platform/mcp/install-tools.sh b/platform/mcp/install-tools.sh index e88fbaf..673386a 100755 --- a/platform/mcp/install-tools.sh +++ b/platform/mcp/install-tools.sh @@ -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. # diff --git a/platform/migration/restore-reference-backup.sh b/platform/migration/restore-reference-backup.sh index 580c400..f554c7b 100755 --- a/platform/migration/restore-reference-backup.sh +++ b/platform/migration/restore-reference-backup.sh @@ -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" diff --git a/platform/openwebui/install-filters.sh b/platform/openwebui/install-filters.sh index 0e1cd98..dbf0efc 100755 --- a/platform/openwebui/install-filters.sh +++ b/platform/openwebui/install-filters.sh @@ -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", diff --git a/platform/recovery/create-recovery-bundle.sh b/platform/recovery/create-recovery-bundle.sh index 2cce2a3..8e4b8d5 100755 --- a/platform/recovery/create-recovery-bundle.sh +++ b/platform/recovery/create-recovery-bundle.sh @@ -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 diff --git a/platform/recovery/restore-recovery-bundle.sh b/platform/recovery/restore-recovery-bundle.sh index 4acb4d8..ad5e4f7 100755 --- a/platform/recovery/restore-recovery-bundle.sh +++ b/platform/recovery/restore-recovery-bundle.sh @@ -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