Add isolated Navidrome MCP service
This commit is contained in:
+1
-1
@@ -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-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, GitHub/Hugging Face und Produktsuche. Nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose."}},{"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-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-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, GitHub/Hugging Face und Produktsuche. Nicht für Home Assistant, Medienverwaltung oder NAS-Diagnose."}},{"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."}}]
|
||||
DO_NOT_TRACK: "true"
|
||||
SCARF_NO_ANALYTICS: "true"
|
||||
dns: ["${AI_DNS:-1.1.1.1}"]
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Root-only deployment secret. Copy to /etc/mike-ai/navidrome-mcp.env,
|
||||
# replace the two placeholders and chmod 600. Never commit the real file.
|
||||
NAVIDROME_URL=http://192.168.1.2:4533
|
||||
NAVIDROME_USERNAME=REPLACE_WITH_DEDICATED_USER
|
||||
NAVIDROME_PASSWORD=REPLACE_WITH_DEDICATED_PASSWORD
|
||||
@@ -145,6 +145,7 @@ Allzweck-MCP mit sämtlichen Zugangsdaten.
|
||||
Open WebUI ── internes Netz ───────────┬── web-mcp
|
||||
├── home-assistant-mcp
|
||||
├── arr-mcp
|
||||
├── navidrome-mcp
|
||||
└── unraid-mcp-read
|
||||
|
||||
Hermes Agent ─ WireGuard ─┐
|
||||
@@ -158,6 +159,7 @@ weitere MCP-Clients ──────┴── mcp-gateway (später) ── das
|
||||
| `home-assistant-mcp-write` | kontrollierte HA-Änderungen | Preview/Approval |
|
||||
| `arr-mcp-read` | Sonarr/Radarr-Status und Releasesuche | nur lesen |
|
||||
| `arr-mcp-write` | Suche fehlender Episoden über Sonarr-Indexer | Preview/Approval; Monitoring unverändert |
|
||||
| `navidrome-mcp` | Musikbibliothek, Suche, Playlists, Favoriten, Hörverlauf | eigener Navidrome-Benutzer; gezielt aktivieren |
|
||||
| `unraid-mcp-read` | System-, Container- und begrenzte Logdiagnose | nur lesen |
|
||||
| `unraid-mcp-admin` | eng definierte Verwaltungsaktionen | bewusst aktivieren |
|
||||
| `sandbox-mcp` | temporäre Code- und Dateiarbeit | isolierter Arbeitsraum |
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
| Web-MCP-Fassade | `platform/web-search/web_search_mcp.py` | eigener Container | Kern |
|
||||
| Home-Assistant-MCP | HA-Endpunkt plus lokaler Relay | eigener optionaler Container | optional |
|
||||
| ARR-MCP | `arr-mcp` 1.0.1 plus dokumentierter Sonarr-Patch | eigener optionaler Container | optional |
|
||||
| Navidrome-MCP | Blakeem/Navidrome-MCP 2.2.0, Image per OCI-Digest | eigener optionaler Container ohne mpv | optional |
|
||||
| Unraid-MCP | lokales `runraid`-Binary | eigener optionaler Container | optional |
|
||||
| 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 |
|
||||
|
||||
@@ -161,6 +161,7 @@ vorhanden ist:
|
||||
```text
|
||||
/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
|
||||
```
|
||||
|
||||
@@ -13,6 +13,7 @@ Prompts heraus, verhindert den früher beobachteten Kontextverbrauch von über
|
||||
| `mcp-web` | `http://mike-ai-mcp-web:8000/mcp` | kompakte Websuche und Quellenvergleich | an |
|
||||
| `mcp-homeassistant` | `http://mike-ai-mcp-homeassistant:8000/mcp` | Relay zum nativen HA-MCP; Token bleibt serverseitig | Profil `homeassistant` |
|
||||
| `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-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`) |
|
||||
|
||||
@@ -55,6 +56,7 @@ passenden Server wählen:
|
||||
| Aktuelle öffentliche Informationen, Quellen, GitHub/Hugging Face, Produkte | Web | HA, ARR, Unraid |
|
||||
| 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 |
|
||||
| Ausdrücklich benötigte MUA-Verwaltungsaktion | MUA | Unraid-Diagnose nicht parallel |
|
||||
|
||||
@@ -95,6 +97,7 @@ Die lokale Installation benötigt die vorhandenen Secret-Dateien:
|
||||
```text
|
||||
/etc/mike-ai/homeassistant-admin-mcp.env
|
||||
/etc/mike-ai/arr-mcp.env
|
||||
/etc/mike-ai/navidrome-mcp.env
|
||||
/etc/mike-ai/runraid/.env
|
||||
```
|
||||
|
||||
@@ -106,6 +109,31 @@ TinySearch speichert sein lokales Embedding-Modell in einem Docker-Volume.
|
||||
Nach einer Erstinstallation wird das Modell einmalig im Container mit
|
||||
`tinysearch setup` geladen. Das Volume bleibt bei Containerupdates erhalten.
|
||||
|
||||
## Navidrome
|
||||
|
||||
Der Navidrome-MCP basiert auf `Blakeem/Navidrome-MCP` 2.2.0; das amd64-Image
|
||||
ist per OCI-Digest festgeschrieben. Der Container veröffentlicht keinen
|
||||
Host-Port, besitzt keinen Dateizugriff auf die Musikbibliothek und enthält
|
||||
bewusst kein `mpv`. Er kann daher nicht auf Athena selbst Musik wiedergeben.
|
||||
|
||||
Navidrome sollte einen eigenen normalen Benutzer `mcp` erhalten. Dessen
|
||||
Zugangsdaten liegen ausschließlich in der root-only Datei
|
||||
`/etc/mike-ai/navidrome-mcp.env`; die Vorlage steht unter
|
||||
`config/navidrome-mcp.env.example`. Anschließend genügt:
|
||||
|
||||
```bash
|
||||
sudo install -m 0600 config/navidrome-mcp.env.example /etc/mike-ai/navidrome-mcp.env
|
||||
sudoedit /etc/mike-ai/navidrome-mcp.env
|
||||
sudo platform/mcp/install-tools.sh
|
||||
sudo platform/openwebui/install-filters.sh
|
||||
```
|
||||
|
||||
Der Upstream-Server stellt ohne Playback noch immer über 40 Werkzeuge bereit.
|
||||
Darum wird Navidrome **nicht** als Standardwerkzeug an jedes Modellprofil
|
||||
gehängt. Es wird in OpenWebUI nur für konkrete Musikaufgaben ausgewählt und
|
||||
danach wieder ausgeschaltet. Schreibende Funktionen wie Playlist-Änderungen,
|
||||
Favoriten und Bewertungen wirken unmittelbar im Konto des MCP-Benutzers.
|
||||
|
||||
## Client-Auswahl
|
||||
|
||||
Werkzeuge werden nicht pauschal an jedes Modell gehängt. Für Home-Assistant-
|
||||
|
||||
@@ -111,6 +111,29 @@ services:
|
||||
- ${ARR_RADARR_PATCH:-./patches/mcp_radarr.py}:/usr/local/lib/python3.13/site-packages/arr_mcp/mcp/mcp_radarr.py:ro
|
||||
networks: [tools, egress]
|
||||
|
||||
mcp-navidrome:
|
||||
<<: *tool-common
|
||||
# Version and amd64 manifest are pinned. The image contains no mpv, so it
|
||||
# cannot play audio on the headless AI host and does not expose playback
|
||||
# controls. It talks to Navidrome only through its authenticated API.
|
||||
image: ghcr.io/blakeem/navidrome-mcp:2.2.0@sha256:047f911a5a8f7cc8f185bb4d6e7ca6c435542edefff4694a00c2f718ab0ee7f5
|
||||
container_name: mike-ai-mcp-navidrome
|
||||
profiles: [navidrome]
|
||||
env_file:
|
||||
- ${NAVIDROME_MCP_ENV_FILE:-/etc/mike-ai/navidrome-mcp.env}
|
||||
environment:
|
||||
MCP_TRANSPORT: http
|
||||
MCP_HTTP_EXPOSE: "true"
|
||||
MCP_HTTP_PORT: "3000"
|
||||
# The endpoint is not published on the host. Host filtering still makes
|
||||
# accidental access from any other Docker name fail closed.
|
||||
MCP_HTTP_ALLOWED_HOSTS: "mike-ai-mcp-navidrome:3000,mike-ai-mcp-navidrome"
|
||||
WEBUI_ENABLED: "false"
|
||||
tmpfs:
|
||||
- /tmp:rw,noexec,nosuid,nodev,size=64m
|
||||
- /config:rw,noexec,nosuid,nodev,size=4m,mode=0700
|
||||
networks: [tools, egress]
|
||||
|
||||
mcp-unraid-official:
|
||||
<<: *tool-common
|
||||
image: debian:13-slim
|
||||
|
||||
@@ -28,6 +28,11 @@ if [[ -s /etc/mike-ai/arr-mcp.env ]]; then
|
||||
else
|
||||
echo "ARR bleibt aus: Secret-Datei fehlt."
|
||||
fi
|
||||
if [[ -s /etc/mike-ai/navidrome-mcp.env ]]; then
|
||||
profiles+=(--profile navidrome)
|
||||
else
|
||||
echo "Navidrome bleibt aus: Secret-Datei fehlt."
|
||||
fi
|
||||
if [[ -s /etc/mike-ai/runraid/.env && -x /usr/local/bin/runraid ]]; then
|
||||
profiles+=(--profile unraid)
|
||||
else
|
||||
|
||||
@@ -35,14 +35,17 @@ backup=$volume_path/webui.db.before-filter-install-$stamp
|
||||
cp -a "$db" "$backup"
|
||||
rm -f "$volume_path/webui.db-wal" "$volume_path/webui.db-shm"
|
||||
|
||||
python3 - "$db" "$FILTER_DIR" "$ACTION_DIR" "${OPENWEBUI_FILTER_OWNER_ID:-}" <<'PY'
|
||||
navidrome_enabled=false
|
||||
[[ -s /etc/mike-ai/navidrome-mcp.env ]] && navidrome_enabled=true
|
||||
python3 - "$db" "$FILTER_DIR" "$ACTION_DIR" "${OPENWEBUI_FILTER_OWNER_ID:-}" "$navidrome_enabled" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sqlite3
|
||||
import sys
|
||||
import time
|
||||
|
||||
db, filter_dir, action_dir, requested_owner = sys.argv[1:]
|
||||
db, filter_dir, action_dir, requested_owner, navidrome_enabled_raw = sys.argv[1:]
|
||||
navidrome_enabled = navidrome_enabled_raw.lower() == "true"
|
||||
con = sqlite3.connect(db)
|
||||
columns = {row[1] for row in con.execute("pragma table_info(function)")}
|
||||
required = {
|
||||
@@ -182,6 +185,13 @@ with con:
|
||||
"Verwaltungsaktionen. Für reine Statusabfragen und Diagnosen stattdessen "
|
||||
"Unraid (Systemdiagnose) verwenden; niemals beide parallel ausprobieren.",
|
||||
),
|
||||
"navidrome-local": (
|
||||
"Navidrome (Musikbibliothek)",
|
||||
"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.",
|
||||
),
|
||||
}
|
||||
changed = False
|
||||
for connection in connections:
|
||||
@@ -203,6 +213,8 @@ with con:
|
||||
match = "homeassistant-local"
|
||||
elif "mike-ai-mcp-arr" in url:
|
||||
match = "arr-local"
|
||||
elif "mike-ai-mcp-navidrome" in url:
|
||||
match = "navidrome-local"
|
||||
elif "mike-ai-mcp-unraid-official" in url:
|
||||
match = "unraid-readonly-local"
|
||||
else:
|
||||
@@ -212,6 +224,34 @@ with con:
|
||||
info["name"] = name
|
||||
info["description"] = description
|
||||
changed = True
|
||||
if navidrome_enabled and not any(
|
||||
isinstance(connection, dict)
|
||||
and (
|
||||
str(connection.get("url", "")).lower()
|
||||
== "http://mike-ai-mcp-navidrome:3000/mcp"
|
||||
or str((connection.get("info") or {}).get("id", "")).lower()
|
||||
== "navidrome-local"
|
||||
)
|
||||
for connection in connections
|
||||
):
|
||||
name, description = descriptions["navidrome-local"]
|
||||
connections.append(
|
||||
{
|
||||
"url": "http://mike-ai-mcp-navidrome:3000/mcp",
|
||||
"path": "",
|
||||
"type": "mcp",
|
||||
"auth_type": "none",
|
||||
"headers": None,
|
||||
"key": "",
|
||||
"config": {"enable": True, "access_grants": []},
|
||||
"info": {
|
||||
"id": "navidrome-local",
|
||||
"name": name,
|
||||
"description": description,
|
||||
},
|
||||
}
|
||||
)
|
||||
changed = True
|
||||
if changed:
|
||||
con.execute(
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user