About plex-mcp
plex-mcp is an MCP server published by CarlDog in the Search category: mCP server that bridges Plex Media Server with AI assistants. Get real-time viewing context, subtitle-based summaries, and spoiler-safe insights while watching movies. Built with Laravel 12 and Laravel MCP.
Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/CarlDog/plex-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (44)
plex_add_to_playlistAppend an item to a regular playlist
Parameters not published.
plex_apply_matchApply a chosen match (`guid`/`name`) to an item; overwrites the agent binding
Parameters not published.
plex_browseList items in a library section (paged, optional type filter, optional `collection` title filter, optional sparse `fields` projection)
Parameters not published.
plex_create_playlistCreate a regular playlist seeded with one item
Parameters not published.
plex_delete_playlistDelete a playlist (metadata only — media untouched)
Parameters not published.
plex_download_logsFetch Plex's diagnostic ZIP under `MCP_LOG_SAVE_DIR`; on Plex 5xx/transport failure, copy the primary server log from the read-only filesystem fallback mount
Parameters not published.
plex_edit_metadataOverride scalar metadata fields (title, summary, year, etc.) with field-level locking
Parameters not published.
plex_find_by_external_idFind all exact IMDb/TMDB/TVDB child-GUID matches in one section via a bounded paged scan; returns lean identity/context rows and reports whether the result is complete or truncated
Parameters not published.
plex_get_childrenChildren of an item (show→seasons, season→episodes, artist→albums)
Parameters not published.
plex_get_imageFetch poster/art/banner/clearLogo bytes for an item as an MCP image content block (so vision-capable clients can actually see the picture); optional max_width/max_height routes through Plex's transcoder
Parameters not published.
Show all 44 tools
plex_get_itemMetadata for one item by rating key. Pass `minimal=true` to drop bulky cast/crew/image arrays (~80% size reduction on movies with deep casts) while keeping subtitle-track info; pass `fields=[...]` for explicit projection
Parameters not published.
plex_get_matchesList candidate matches for an item (TMDB / TVDB / etc.); optional title/year/agent/language overrides
Parameters not published.
plex_get_playlist_itemsList a playlist's contents
Parameters not published.
plex_historyPlayback history entries (paged, most recent first)
Parameters not published.
plex_hub_searchSearch via Plex's hub-search endpoint, including collections (unlike `plex_search`)
Parameters not published.
plex_hubsPlex's curated server-wide hubs (Continue Watching, Recently Released, etc.)
Parameters not published.
plex_list_collectionsList collections in a library section (thin wrapper over `plex_browse`'s collection type)
Parameters not published.
plex_list_librariesList all libraries (sections) on the server
Parameters not published.
plex_list_playlistsList all playlists (regular + smart)
Parameters not published.
plex_list_postersList every poster candidate for an item (agent-supplied, locally-scanned, previously uploaded), including which one is currently active
Parameters not published.
plex_mark_unwatchedMark an item as unwatched (reversible)
Parameters not published.
plex_mark_watchedMark an item as watched (reversible)
Parameters not published.
plex_merge_itemsMerge other items INTO a target item (sources absorbed; target survives)
Parameters not published.
plex_now_playingCurrently-playing sessions on the server
Parameters not published.
plex_on_deckItems "on deck" (partially watched / next up); optional `section_id` scopes to one library section
Parameters not published.
plex_rate_itemSet an item's 0-10 user star rating; omit `rating` to clear it back to unrated
Parameters not published.
plex_recently_addedRecently added items, optionally per-section
Parameters not published.
plex_refresh_metadataRe-pull metadata for an item from its current agent (optional `force`)
Parameters not published.
plex_refresh_sectionTrigger a metadata refresh for an entire library section (incremental or deep)
Parameters not published.
plex_relatedPlex's curated "related" hubs for an item (provenance-grouped)
Parameters not published.
plex_remove_from_continue_watchingRemove an item from the Continue Watching hub without touching its watch progress; reappears automatically once resumed
Parameters not published.
plex_remove_from_playlistRemove an item by `playlistItemID`
Parameters not published.
plex_save_imageSame input surface as `plex_get_image`, but WRITES the bytes to disk under `MCP_IMAGE_SAVE_DIR` (default `/data/images/`) and returns the path + size. Bind-mount a host directory onto that path to bridge to a downstream pipeline (ImageMagick, filesystem-mcp consumer, etc.) without a vision render.
Parameters not published.
plex_searchSearch across all libraries
Parameters not published.
plex_section_hubsCurated hubs scoped to one library section
Parameters not published.
plex_set_posterSelect an existing poster candidate as the active one, by the candidate's own `poster_rating_key` from `plex_list_posters`
Parameters not published.
plex_similarAlgorithmic similar items for an item (flat list)
Parameters not published.
plex_split_itemSplit a Plex item back into its constituent media variants as N separate items
Parameters not published.
plex_tautulli_activityNormalized current Tautulli sessions with email, IP, machine-id, and file-path fields omitted
Parameters not published.
plex_tautulli_historyPaged, filtered Tautulli watch history with sensitive network/filesystem fields omitted
Parameters not published.
plex_tautulli_statusOptional Tautulli configuration and on-demand connectivity status; never affects `/health`
Parameters not published.
plex_tautulli_watch_timeLibrary play-count and watch-time totals for selected day windows
Parameters not published.
plex_unmatchDetach an item from its agent binding (back to unmatched state); locked fields survive
Parameters not published.
plex_upload_posterAdd a new poster from an external URL (Plex fetches it) or a local file under `MCP_IMAGE_SAVE_DIR`. Auto-selects it by default; `select=false` adds it without changing what's displayed
Parameters not published.
Ask AI
Ask AI about plex-mcp
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
plex-mcp
An MCP server for Plex Media Server, packaged as a Docker container. Lets an MCP client (Claude Desktop, etc.) browse and search your Plex libraries.
Tools
| Tool | Description |
|---|---|
plex_list_libraries |
List all libraries (sections) on the server |
plex_search |
Search across all libraries |
plex_recently_added |
Recently added items, optionally per-section |
plex_on_deck |
Items "on deck" (partially watched / next up) |
plex_get_item |
Full metadata for one item by rating key |
plex_browse |
List items in a library section (paged, optional type filter) |
plex_get_children |
Children of an item (show→seasons, season→episodes, artist→albums) |
plex_now_playing |
Currently-playing sessions on the server |
plex_history |
Playback history entries (paged, most recent first) |
plex_mark_watched |
Mark an item as watched (reversible) |
plex_mark_unwatched |
Mark an item as unwatched (reversible) |
plex_list_playlists |
List all playlists (regular + smart) |
plex_get_playlist_items |
List a playlist's contents |
plex_create_playlist |
Create a regular playlist seeded with one item |
plex_add_to_playlist |
Append an item to a regular playlist |
plex_remove_from_playlist |
Remove an item by playlistItemID |
plex_delete_playlist |
Delete a playlist (metadata only — media untouched) |
plex_hubs |
Plex's curated server-wide hubs (Continue Watching, Recently Released, etc.) |
plex_section_hubs |
Curated hubs scoped to one library section |
plex_related |
Plex's curated "related" hubs for an item (provenance-grouped) |
plex_similar |
Algorithmic similar items for an item (flat list) |
Configuration
Two environment variables, both required:
| Var | Example | Notes |
|---|---|---|
PLEX_URL |
http://192.168.1.50:32400 |
Base URL of your Plex server |
PLEX_TOKEN |
(see below) | Plex auth token |
To find your Plex token, see Plex's Finding an authentication token guide.
Plex on the same host as the container? Use
PLEX_URL=http://host.docker.internal:32400. The compose file mapshost.docker.internalto the Docker host gateway viaextra_hosts, so the container can reach a Plex server running on the host. The host's own hostname (e.g.my-nas) won't resolve from inside the container without that mapping.
Transport modes
| Mode | When to use | How to start |
|---|---|---|
| stdio (default) | Direct invocation by Claude Desktop / MCP clients | docker run -i --rm ... plex-mcp (no MCP_PORT) |
| Streamable HTTP | Long-lived deployment (Portainer, Compose, k8s) | Set MCP_PORT=3000 (already done in docker-compose.yml) |
In HTTP mode the server exposes:
POST/GET/DELETE /mcp— MCP Streamable HTTP endpoint (per spec)GET /health— liveness probe (used by docker healthcheck)
HTTP mode currently has no auth. Bind only to a private network. Rely on host firewall or LAN isolation. Don't expose to the public internet without adding bearer-token auth first.
Run with Docker (stdio, on demand)
docker build -t plex-mcp .
docker run -i --rm \
-e PLEX_URL=http://192.168.1.50:32400 \
-e PLEX_TOKEN=your-token \
plex-mcp
Run with Docker Compose (HTTP, long-lived)
The compose file pulls ghcr.io/carldog/plex-mcp:latest (multi-arch:
linux/amd64 + linux/arm64), published by CI on every push to main.
# Required env vars (or use a .env file):
export PLEX_URL=http://192.168.1.50:32400
export PLEX_TOKEN=your-token
export HOST_PORT=3001 # optional, defaults to 3001
docker compose up
The MCP endpoint will be at http://<host>:${HOST_PORT}/mcp.
To rebuild from source instead of pulling:
docker build -t ghcr.io/carldog/plex-mcp:latest .
docker compose up
Deploy via Portainer (Stack from Git)
- In Portainer, Stacks → Add Stack → Repository.
- Repository URL:
https://github.com/CarlDog/plex-mcp - Compose path:
docker-compose.yml - Environment variables: set
PLEX_URL,PLEX_TOKEN, optionallyHOST_PORT. - Deploy. Healthcheck reaches green within ~10 seconds.
Use with Claude Desktop
stdio (local invocation)
{
"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"
}
}
}
(Requires Claude Desktop or a client that supports remote MCP HTTP.)
Local development
npm install
cp .env.example .env # then edit
PLEX_URL=... PLEX_TOKEN=... npm run dev # stdio
MCP_PORT=3000 PLEX_URL=... PLEX_TOKEN=... npm run dev # HTTP
Logging
The server emits structured logs to stderr (stdout is the MCP wire protocol in stdio mode and must not be polluted). 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=337
Configure verbosity via the LOG_LEVEL env var (default info):
| Level | Shows |
|---|---|
error |
Errors only |
warn |
+ 4xx Plex responses |
info (default) |
+ Tool invocations and completions |
debug |
+ Every Plex API call with method, path, status, ms |
trace |
(reserved) |
Container logs are captured by Docker's json-file driver and
rotated automatically (10MB × 3 files = ~30MB cap; oldest deleted
on rotation). View with docker logs plex-mcp or docker logs -f.
Security
- The container runs as a non-root user (
plexmcp). - The Plex token is passed via env var — never bake it into the image.
- A
.githooks/pre-commitruns gitleaks on every commit. Activate it once per clone:git config core.hooksPath .githooks
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.