plex-mcp
plex-mcp
·
claude-opus-4-8[1m] · 2026-07-07 · Details
Ein MCP-Server für den Plex Media Server, verpackt als Docker- Container. Er ermöglicht einem MCP-Client (Claude Desktop usw.), in deinen Plex-Bibliotheken zu stöbern und zu suchen.
Werkzeuge
Tool | Beschreibung | |
| Alle Bibliotheken (Sektionen) auf dem Server auflisten. | |
| Über alle Bibliotheken suchen. | |
| Über den Hub-Such-Endpunkt von Plex suchen, einschließlich Sammlungen (im Gegensatz zu | |
| Zuletzt hinzugefügte Elemente, optional pro Sektion. | |
| Elemente „on deck“ (teilweise gesehen / als Nächstes); optional | |
| Metadaten für ein Element anhand des Rating-Keys abrufen. | |
| Elemente in einer Bibliothekssektion auflisten (paginier, optionaler Typ-Filter, optionaler | |
| Sammlungen in einer Bibliothekssektion auflisten (dünner Wrapper über den Sammlungstyp von | |
| Unterelemente eines Elements (Serie→Staffel, Folge→Folgen, Künstler→Alben). | |
| Aktuell laufende Wiedergabesitzungen auf dem Server. | |
| Wiedergabe-Verlaufseinträge (paginiert, neueste zuerst). | |
| Ein Element als gesehen markieren (umkehrbar). | |
| Ein Element als ungesehen markieren (umkehrbar). | |
| Die 0-10-Steinen Sternebewertung eines Elements setzen; | |
| Alle Wiedergabelisten auflisten (regulär + smart). | |
| Den Inhalt einer Wiedergabeliste auflisten. | |
| Eine normaler Wiedergabeliste mit einem Element als Startinhalt erstellen. | |
| Ein Element an eine reguläre Wiedergabeliste anhängen. | |
| Ein Element per | |
| Eine Wiedergabeliste löschen (nur Metadaten – Medien bleiben unberührt). | |
| Kurzierte serverweite Hubs von Plex (Weiterschauen, Kürzlich veröffentlicht usw.). | |
| Kurzierte Hubs, begrenzt auf eine Bibliothekssektion. | |
| Plex’ kurzeierte „related“-Hubs für ein Element (nach Herkunft gruppiert). | |
| Algorithmisch ähnliche Elemente zu einem Element (flache Liste). | |
| Metadaten für ein Element vom aktuellen Agenten erneut abrufen (optional | |
| Mögliche Zusammenführungen für ein Element auflisten (TMDB / TVDB usw.); optionale Titel-/Jahres-/Agent-/Sprach-Überschreibungen. | |
| Eine gewählte Übereinstimmung ( | |
| Skalare Metadatenfelder (Titel, Zusammenfassung, Jahr, etc.) mit Feldsperre überschreiben. | |
| Ein Element von seiner Agentenbindung lösen (zurück zum unmatchsit); gesperrte Felder bleiben erhalten. | |
| Metadaten-Refresh für eine gesamte Bibliothekssektion auslösen (inkrementell oder tief). | |
| Ein Plex-Element zurück in die einzelnen Medienvarianten als N getrennte Elemente aufteilen. | |
| Andere Elemente IN ein Ziel-Element überführen (Quellen werden absorbiert; Ziel bleibt erhalten). | |
| Poster-/Art-/Banner-/clearLogo-Bytes für ein Element als MCP-Bildinhaltsblock abrufen (damit auffähige Clients das Bild tatsächlich sehen können); optionale | |
| Gleiche Eingabeschnittstelle wie | |
| Das eigene Diagnose-Log-Bundle des Plex Media Server (eine ZIP) abrufen und unter | |
| Alle Poster-Kandidaten für ein Element auflisten (vom Agenten geliefert, lokal gescannt, zuvor hochgeladen), einschließlich der aktuell aktiven. | |
| Einen vorhandenen Poster-Kandidaten über seinen eigenen | |
| Neues Poster von einer externen URL (wird von Plex abgerufen)Wie einer lokalen Datei unter | To ensure maximum accuracy, I will now provide the complete, corrected German translation. |
Tool | Beschreibung |
| Alle Bibliotheken (Sektionen) auf dem Server auflisten. |
| Über alle Bibliotheken suchen. |
| Über den Hub-Such-Endpunkt von Plex suchen, einschließlich Sammlungen (im Gegensatz zu |
| Zuletzt hinzugefügte Elemente, optional pro Sektion. |
| Elemente „on deck“ (teilweise gesehen / als Nächstes); optional |
| Metadaten für ein Element anhand des Rating-Keys abrufen. Übergib |
| Elemente in einer Bibliothekssektion auflisten (paginiert, optionaler Typ-Filter, optionaler |
| Sammlungen in einer Bibliothekssektion auflisten (dünner Wrapper um den Sammlungstyp von |
| Unterelemente eines Elements (Serie→Staffeln, Staffel→Episoden, Künstler→Alben). |
| Aktuell laufende Sessions auf dem Server. |
| Wiedergabe-Verlaufseinträge (paginiert, neueste zuerst). |
| Ein Element als gesehen markieren (reversibel). |
| Ein Element als ungesehen markieren (reversibel). |
| Eine 0–10-Sterne-Bewertung für ein Element setzen; |
| Alle Wiedergabelisten auflisten (regulär + intelligent). |
| Inhalt einer Wiedergabeliste auflisten. |
| Eine reguläre Wiedergabeliste mit einem Startelement erstellen. |
| Ein Element an einer regulären Wiedergabeliste anhängen. |
| Ein Element per |
| Eine Wiedergabeliste löschen (nur Metadaten – Medien bleiben unberührt). |
| Plex‘ kuratierte serverweite Hubs (Weiterschauen, kürzlich veröffentlicht, usw.). |
| Kuratierte Hubs, begrenzt auf eine Bibliothekssektion. |
| Plex‘ kuratierte „related“-Hubs für ein Element (herkunftsgruppiert). |
| Algorithmisch ähnliche Elemente zu einem Element (flache Liste). |
| Metadaten für ein Element vom aktuellen Agenten erneut abrufen (optional |
| Kandidaten für ein Element auflisten (TMDB / TVDB etc.); optionale Überschreibungen für Titel/Jahr/Spot Agent/Sprache. |
| Eine gewählte Übereinstimmung ( |
| Skalare Metadatenfelder (Titel, Zusammenfassung, Jahr, etc.) mit Sperre auf Feldebene überschreiben. |
| Ein Element von seiner Agentenbindung lösen (zurück in den Status „Nicht zugeordnet“); gesperrte Felder bleiben erhalten. |
| Metadaten-Refresh für eine gesamte Bibliothekssektion auslösen (inkrementell or tief. |
| Ein Plex-Element wieder in seine einzelnen Medienvarianten als n separate Elemente Aufteilen. |
| Andere Elemente IN ein Ziel-Element überführen (Quellen werden absorbiert; Ziel bleibt erhalten). |
| Poster-/Art-/Banner-/clear-Logo-Bytes für ein Element als MCP-Bildinhaltsblock abrufen (damit Visions-fähige Clients das Bild tatsächlich sehen können); optionale max_width/max_height leiten über den Transcoder von Plex. |
| Gleiche Eingabefläche wie |
| Das Diagnose-Protokoll-Paket des Plex Media Server selbst (eine ZIP) abrufen und unter |
| Alle Poster-Kandidaten für ein Element auflisten (vom Agenten geliefert, lokal gescannt, zuvor hochgeladen), einschließlich des aktuell aktiven. |
| Einen vorhandenen Poster-Kandidaten über dessen eigenen |
| Ein neues Poster aus einer externen URL (Plex ruft sie ab) oder einer lokalen Datei unter |
Related MCP server: Plex Assistant MCP
Konfiguration
Zwei Umgebungsvariablen, beide erforderlich:
Variable | Beispiel | Hinweise |
|
| Basis-URL Ihres Plex-Servers |
| (siehe unten) | Plex-Authentifizierungs-Token |
Um Ihr Plex-Token zu finden, siehe die Plex-Anleitung zum Finden eines Authentifizierungstokens.
Optionale Umgebungsvariablen
Alle haben funktionierende Standardwerte; setzen Sie sie nur, um diese zu überschreiben.
Variable | Standard | Hinweis |
|
| Timeout für jede ausgehende Plex-Anfrage außer Log-Downloads |
|
| Größenlimit für |
|
| Größenlimit für |
|
| Timeout für |
|
| Verwird eine MCP-Sitzung im HTTP-Modus nach dieser Inaktivitätsdauer |
LOG_LEVEL, MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS sowie HOST_IMAGE_DIR/HOST_LOG_DIR werden weiter unten in eigenen Abschnitten behandelt (Logging, HTTP-Transport-Härtung, Portainer-Deployment), da jede Variable mehr als eine einzeilige Anmerkung benötigt.
Plex auf demselben Host wie der Container? Verwenden Sie
PLEX_URL=http://host.docker.internal:32400. Die Compose-Datei bildethost.docker.internalüberextra_hostsauf das Docker-Host-Gateway ab, sodass der Container einen auf dem Host laufenden Plex-Server erreichen kann. Der eigene Hostname des Hosts (z. B.my-nas) lässt sich ohne dieses Mapping aus dem Container heraus nicht auflösen.
Transportmodi
Modus | Verwendung | So starten Sie |
stdio (Standard) | Direkter Aufruf durch Claude Desktop / MCP-Clients |
|
Streamable HTTP | Dauerhaftigkeit längerer Betrieb (Portainer, Compose, k8s) |
|
Im HTTP-Modus stellt der Server Folgendes bereit:
POST/GET/DELETE /mcp– MCP-Streamable-HTTP-Endpunkt (gemäß Spezifikation)GET /health– Liveness-Probe (wird vom Docker-Healthcheck verwendet)
Der HTTP-Modus hat keine Authentifizierung des Aufrufers – TLS (weiter unten) verschlüsselt den Datenverkehr, identifiziert den Aufrufer aber nt. Binden Sie nur an ein privates Netzwerk. Verlassen Sie sich auf die Host-Firewall oder LAN-Isolierung. Setzen Sie es nicht dem öffentlichen Internet aus, ohne zuerst eine Bearer-Token-Authentifizierung hinzuzufügen.
HTTPS aktivieren
HTTPS ist optional (opt-in). Auflösungsreihenfolge beim Start:
Bring-your-own-Zertifikat – Setzen Sie sowohl
MCP_TLS_CERT_FILEals alsoMCP_TLS_KEY_FILEauf PEM-Dateipfade. Verwenden Sie dies, wenn Sie Let's Encrypt oder eine interne CA terminieren. Der Server liest die Dateien beim Start; starten Sie den Container neu, um erneuerte Dateien zu übernehmen.Selbstverwaltetes Zertifikat (empfohlen für reine LAN-Setups) – Setzen Sie
MCP_TLS=auto. Der Server erstellt beim ersten Start ein selbst signiertes ECDSA-P-256-Zertifikat, schreibt es inMCP_TLS_DIR(Standard/data/certs) und verwendet es auch bei späteren starts weiter. Wenn das Zertifikat noch weniger als 30 Tage gültig bleibt, wird es automatisch neu erstellt.Andernfalls bleibt der Server bei einfachem HTTP (heutiges Standardverhalten).
Variable | Standard | Anmerkungen |
| nicht gesetzt |
|
|
| Wo |
|
| Subject Alternative Names. Kommagetrennte |
| erste DNS-SAN, sonst | Allgemeiner Name (Common Name) des Zertifikats. |
|
| Gültigkeitsdauer. Das Zertifikat rotiert, wenn weniger als 30 Tage verbleiben. |
| nicht gesetzt | Eigenes Zertifikat (PEM). Überschreibt |
| nicht gesetzt | Eigener Schlüssel (PEM). |
Beim Start protokolliert der Server den SHA-256-Fingerabdruck des Zertifikats und notAfter. Führen Sie den Fingerabdruck clientseitig fest (Pinning) oder hinterlegen Sie das Zertifikat im Zertifikatsspeicher Ihres Betriebssystems, damit Browser und CLI-Tools ihm vertrauen.
Wenn TLS eingeschaltet ist, benötigt der Compose-Healthcheck das --no-check-certificate-Flag – aktualisieren Sie die test:-Zeile auf ["CMD", "wget", "--no-check-certificate", "-q", "-O-", "https://localhost:3000/health"].
mcp-remote auf einen HTTPS-Endpunkt ausrichten
Für ein selbst signiertes Zertifikat: entweder die Zertifikatdatei über das CA-Bundle von Node pinnen oder die Verifizierung am Client überspringen (nur LAN):
# Trust the server's self-signed cert (preferred):
NODE_EXTRA_CA_CERTS=./server.crt \
npx -y mcp-remote https://nas.local:3443/mcp
# Or skip verification for quick testing (LAN-only):
NODE_TLS_REJECT_UNAUTHORIZED=0 \
npx -y mcp-remote https://nas.local:3443/mcpReverse-Proxy-Alternative
TLS im selben Prozess ist praktisch, wenn Sie keinen Ingress-Controller betreiben. Wenn Sie Caddy, Traefik oder nginx vor Ihre Heimdienste geschaltet haben, ist das idiomatische Muster, TLS am Proxy zu terminieren (mit automatischem Let's Encrypt) und dieses plex-mcp dahinter mit reinem HTTP zu betreiben. Beide Ansätze sind austauschbar – wählen Sie den, der zu Ihrer bestehenden Umgebung passt.
OAuth-2.1-Bearer-Token-Authentifizierung (opt-in, noch nicht praktisch nutzbar)
Code-seitige Unterstützung für die Authentifizierung geschützter Ressourcen im OAuth-2.1-Bereich existiert (ChatGPT-Apps-SDK, Alignment Phase 2 – siehe docs/CHATGPT-APPS-SDK.md für den vollständigen Plan), ist aber noch nicht so etwas, das Sie tatsächlich einschalten und nutzen können: Dafür ist ein echter OAuth-2.1-Identity-Provider erforderlich, die Token ausstellt, und für diese Bereitstellung ist keiner vorgesehen (das ist Phase 3, noch nicht gestartet). Es wird der Vollständigkeit halber dokumentiert, nicht als Anleitung.
Variable | Anmerkung |
| Aussteller-URL des IdP. Wenn gesetzt, aktiviert dies die Authentifizierung – nicht gesetzt (Standard) bedeutet keine Authentifizierung, identisch zum bisherigen Verhalten. |
| Erforderlich, sobald |
| Durch Kommata getrennt. Standard: |
Wenn aktiviert, benötigt jede /mcp-Anfrage Authorization: Bearer <jwt> – ausgestellt vom konfigurierten IdP, mit der richtigen Audience und Scope. /health ist nie. gefüllt/d be affected: eine eigene Route, und der Docker-Healthcheck kann keine Token anhängen. /.well-known/oauth-protected-resource wird automatisch gemäß RFC 9728 ausgeliefert.
Mit Docker ausführen (stdio, auf Abruf)
docker build -t plex-mcp .
docker run -i --rm \
-e PLEX_URL=http://192.168.1.50:32400 \
-e PLEX_TOKEN=your-token \
plex-mcpMit Docker Compose ausführen (HTTP, dauerhaft)
Die Compose-Datei zieht ghcr.io/carldog/plex-mcp:latest (Multi-Arch: linux/amd64 + linux/arm64), die bei jedem Push auf main von der CI veröffentlicht wird.
# Required env vars (or use a .env file):
export PLEX_URL=http://192.168.1.50:32400
export PLEX_TOKEN=your-token
export MCP_ALLOWED_HOSTS=nas.local:3001 # required — see below
export HOST_PORT=3001 # optional, defaults to 3001
docker compose upDer MCP-Endpunkt befindet sich unter http://<host>:${HOST_PORT}/mcp.
Um statt der Pulls den Container aus dem Quellcode neu zu bauen:
docker build -t ghcr.io/carldog/plex-mcp:latest .
docker compose upBereitstellung über Portainer (Stack aus Git)
In Portainer: Stacks → Add Stack → Repository.
Repository-URL:
https://github.com/CarlDog/plex-mcpCompose-Pfad:
docker-compose.ymlUmgebungsvariablen: Setzen Sie
PLEX_URL,PLEX_TOKEN,MCP_ALLOWED_HOSTS,HOST_IMAGE_DIRundHOST_LOG_DIR– alle erforderlich (siehe unten); optionalHOST_PORT.Bereitstellen. Der Healthcheck wird innerhalb von ~10 Sekunden grün.
MCP_ALLOWED_HOSTS ist im HTTP-Modus erforderlich
Durch Kommaregeln getrennte Liste von Werten des Host-Headers, die der Server auf /mcp akzeptiert – z. B. nas.local:3001 (muss mit der Host:Port übereinstimmen, die ein Client tatsächlich aufgerufen hat, einschließlich des abgebildeten HOST_PORT). Der Server verweigert im HTTP-Modus ohne Liste den Start zu starten, und docker compose config schlägt auf dieselbe Weise fehl, wenn sie nicht gesetzt ist – in dem Fall beides nonsensense, bevor der Container steht, bewusst, statt in einen instsill schweigend geschützten Zustand übergeht.
Der Grund besteht darin, dass die Bindung an 0.0.0.0 im Inneren eines Containers keine echte Zugriffsgrenze ist, wie die Loopback-Bindung auf einem wil ein Host. Ein im Browser irgendwo im LAN geladenes Seite kann DNS-Unverbindung durchführen – den eigenen Hostnamen auf das dieser IP setzen – und Tools wie Schreiboperationen wie plex_delete_playlist als verwirrter Stellvertreter steuern, wobei die Sicherheitshaltung "nur LAN, das gesetzte Bearer-Token" vollständig umgangen wird. Die Host-Allowlist schließt diese Lücke, ohne eine vollständige Authentifizierung zu verlangen. MCP_ALLOWED_ORIGINS (optional, Standardwert leer) bewirkt dasselbe für den Origin-Header – lassen Sie ihn unbesetzt, es sei denn, ein Browser-basierter Client muss tatsächlich direkt von hier aus den Server aufrufen.: Browser-basierte Clients die Brücke mcp-remote, ein direkter fetch senden nie einen Origin-Header, daher lehnt der leere Standard nur die Anfrageform ab, die ein DNS-Rebinding-Angriff tatsächlich sendet.
HOST_IMAGE_DIR und HOST_LOG_DIR sind erforderlich – kein relativer Standardwert
Beide Host-Pfade für Volumes sind in der Compose-Datei ${VAR:?...} angegeben: Es gibt keinen Fallback-Standard, daher schlägt der docker compose up oder ein Portainer-Redeployment bei nicht gesetzter Variable schnell mit einer eindeutigen Meldung fehl, statt starten in einen broken Zustand zu starten.
Früher gab es einen weichen Standardwert ${VAR:-./data/images}, der nur bei einem lokalen docker compose up aus einem stabilen Klon. Bei Portainer Git Stack wird hat es dort als Falle: Jedes redeploy klert das Repo in ein neues Verzeichnis in (z. B. /data/docker/<stack-id>/<commit>/, also) ein relativer Pfad wie ./data/images nicht existiert. Docker verweigerte den Bind-Mount-Zutritt und das Container blieb im Zustand created – er wurde nie gestartet. Das betraf auch automatische Redeploye (Image-Update, Git-Poll) getroffen, sodass ein zuvor gesunder Stack ohne manuellen Eingriff ausfiel und das einzige Symptom dazu nur noch created war. Dadurch nachweisbar einen ausgeführten Stack am 2026-07-31 für ~10 Stunden aus fallen – siehe docker-deployments.md Regel #10 und Fleet-Lektion 2026-07-31-relative-compose-volume-defaults-break-portainer-git-stacks. Die Compose-Datei macht diese Anforderung jetzt strukturell und ist nicht als convention.
So setzen Sie beide in den Umgebungsvariablen des Stacks absolute Host-Pfade:
HOST_IMAGE_DIR— das Ausgabeverzeichnis vonplex_save_image. Empfohlen: das Host-Verzeichnis, das den Mount/media/_mcp-scratchvon filesystem-mcp bereitstellt — z. B./volume1/Media/_mcp-scratchauf einer Synology NAS — sodass die Pipelineplex_search → plex_save_image → filesystem-mcpin einem gemeinsamen Verzeichnis bleibt.HOST_LOG_DIR— das Ausgabeverzeichnis vonplex_download_logs, getrennt vonHOST_IMAGE_DIRgehalten, da eine Diagnose-ZIP kein Medienartefakt ist — z. B./volume1/docker/plex-mcp/logsauf einer Synology NAS (gemäß der Konvention dieser Flotte für Appdata pro Container).
Stellen Sie sicher, dass beide Verzeichnisse auf dem Host vor dem ersten Deployment vorhanden sind. Docker erzeugt eine fehlende Bind-Mount-Quelle nicht automatisch, sondern verweigert den Start des Containers.
Verwendung mit Claude Desktop
stdio (lokaler Aufruf)
{
"mcpServers": {
"plex": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "PLEX_URL", "-e", "PLEX_TOKEN",
"plex-mcp"
],
"env": {
"PLEX_URL": "http://192.168.1.50:32400",
"PLEX_TOKEN": "your-token"
}
}
}
}HTTP (Remote-MCP-Server)
{
"mcpServers": {
"plex": {
"url": "http://nas.local:3001/mcp"
}
}
}(Erfordert Claude Desktop oder einen Client, der Remote-MCP über HTTP unterstützt.)
Lokale Entwicklung
npm install
cp .env.example .env # then edit
PLEX_URL=... PLEX_TOKEN=... npm run dev # stdio
MCP_PORT=3000 MCP_ALLOWED_HOSTS=localhost:3000 PLEX_URL=... PLEX_TOKEN=... npm run dev # HTTPProtokollierung
Der Server schreibt strukturierte Logs nach stderr (stdout ist das MCP-Wire-Protokoll im stdio-Modus und darf nicht verunreinigt werden). Format:
2026-04-29T15:30:00.000Z INFO [tool:plex_browse] invoke section_id=7 type=show limit=2
2026-04-29T15:30:00.337Z INFO [tool:plex_browse] ok ms=337Konfigurieren Sie die Ausführlichkeit über die Umgebungsvariable
LOG_LEVEL (Standard: info):
Level | Zeigt |
| Nur Fehler |
| + 4xx-Plex-Antworten |
| + Tool-Aufrufe und -abschlüsse |
| + Jeden Plex-API-Aufruf mit Methode, Pfad, Status, ms |
| (reserviert) |
Container-Logs werden vom json-file-Treiber Docker erfasst und
automatisch rotiert (10MB × 3 Dateien = ~30MB Limit; die ältesten
werden bei der Rotation gelöscht). Anzeigen mit docker logs plex-mcp
oder docker logs -f.
Sicherheit
Der Container läuft als Nicht-Root-Benutzer (
plexmcp).Das Plex-Token wird über eine Umgebungsvariable übergeben — niemals in das Image einbauen.
Ein
.githooks/pre-commit-Hook führt bei jedem Commit gitleaks aus. Aktivieren Sie ihn einmal pro Clone:git config core.hooksPath .githooks
This server cannot be deployed
Maintenance
Related MCP Connectors
Unlock a world of television with the TV Maze MCP server. Effortlessly search for shows by name or
Search MCP servers, MCP clients and AI agents, and retrieve listing details. Free, read-only access.
Search events, conference weeks, cities, venues and artist schedules via remote MCP.
Search events, conference weeks, cities, venues and artist schedules via remote MCP.
Related MCP Servers
- FlicenseAqualityFmaintenanceA Python-based MCP server that integrates with Plex Media Server API to search for movies and manage playlists in your Plex media library.96-
- AlicenseNot gradedqualityDmaintenanceEnables users to manage and control their Plex media library through natural language commands in MCP-compatible AI clients. It supports searching content, managing playlists, tracking library statistics, and monitoring live viewing sessions.MIT
- AlicenseNot gradedqualityDmaintenanceMCP server for reelgrep - browse and search your local video library from any MCP client.10 npmMIT
- AlicenseAqualityCmaintenanceMCP server for Plex Media Server, focused on media discovery, search, library management, and playback control.25MIT