plex-mcp
plex-mcp
·
claude-opus-4-8[1m] · 2026-07-07 · 详情
一个面向 Plex Media Server 的 MCP 服务器,打包为 Docker 容器。它让 MCP 客户端(Claude Desktop 等)能够浏览和搜索你的 Plex 媒体库。
工具
工具 | 描述 |
| 列出服务器上的所有媒体库(分区) |
| 搜索所有媒体库 |
| 通过 Plex 的 hub-search 端点进行搜索,包括合集(不同于 |
| 最近添加的项目,可选按分区筛选 |
| “待播”项目(已部分观看 / 接下来的内容);可选的 |
| 按 rating key 获取单个项目的元数据。传入 |
| 列出媒体库分区中的项目(分页,可选类型筛选,可选的 |
| 列出媒体库分区中的合集(对 |
| 项目的子项(剧集→季,季→集,艺术家→专辑) |
| 服务器上当前正在播放的会话 |
| 播放历史记录(分页,最近优先) |
| 将项目标记为已观看(可撤销) |
| 将项目标记为未观看(可撤销) |
| 设置项目的 0-10 用户星级评分;省略 |
| 列出所有播放列表(普通 + 智能) |
| 列出播放列表的内容 |
| 创建以单个项目为初始项的普通播放列表 |
| 将项目追加到普通播放列表 |
| 按 |
| 删除播放列表(仅元数据——媒体不受影响) |
| Plex 精选的全服务器 hub(继续观看、最近发布等) |
| 限定到单个媒体库分区的精选 hub |
| Plex 为项目精选的“相关”hub(按来源分组) |
| 项目的算法相似项目(扁平列表) |
| 从当前代理重新拉取项目的元数据(可选 |
| 列出项目的候选匹配(TMDB / TVDB / 等);可选的标题/年份/代理/语言覆盖 |
| 将选定的匹配( |
| 覆盖标量元数据字段(标题、摘要、年份等),支持字段级锁定 |
| 将项目与其代理绑定分离(回到未匹配状态);已锁定的字段依然保留 |
| 触发整个媒体库分区的元数据刷新(增量或深度) |
| 将 Plex 项目拆分回其组成媒体变体,作为 N 个独立项目 |
| 将其它项目合并到目标项目中(源项目被吸收;目标项目保留) |
| 获取项目的海报/背景图/横幅/clearLogo 字节,作为 MCP 图像内容块(以便支持视觉的客户端能够真正看到图片);可选的 max_width/max_height 通过 Plex 的转码器路由 |
| 与 |
| 获取 Plex Media Server 自身的诊断日志包(ZIP),并将其写入 |
| 列出项目的所有海报候选(代理提供、本地扫描、之前上传的),包括当前正在使用的那一个 |
| 通过候选自身的 |
| 添加一张来自外部 URL(Plex 会抓取它)或 |
Related MCP server: Plex Assistant MCP
配置
两个环境变量,均为必填:
Var | Example | Notes |
|
| 你的 Plex 服务器的基础 URL |
| (见下文) | Plex 认证令牌 |
要找到你的 Plex 令牌,请参阅 Plex 的 查找身份验证令牌 指南。
可选环境变量
全部都有可用的默认值;仅需在需要覆盖时设置。
Var | Default | Notes |
|
| 每个出站 Plex 请求的超时时间(日志下载除外) |
|
|
|
|
|
|
|
|
|
|
| HTTP 模式的 MCP 会话在闲置达到此时间后被驱逐 |
LOG_LEVEL、MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS 和
HOST_IMAGE_DIR/HOST_LOG_DIR 将在下文各自的章节(日志、HTTP 传输加固、
Portainer 部署)中说明,因为每项都不止需要一行注释。
Plex 与容器在同一主机上? 使用
PLEX_URL=http://host.docker.internal:32400。compose 文件通过extra_hosts将host.docker.internal映射到 Docker 主机网关, 因此容器可以访问运行在主机上的 Plex 服务器。如果没有该映射, 容器内部将无法解析主机自身的主机名(例如my-nas)。
传输模式
Mode | 何时使用 | 如何启动 |
stdio(默认) | 由 Claude Desktop / MCP 客户端直接调用 |
|
Streamable HTTP | 长期运行的部署(Portainer、Compose、k8s) | 设置 |
在 HTTP 模式下,服务器暴露:
POST/GET/DELETE /mcp— MCP Streamable HTTP 端点(按规范)GET /health— 存活探针(用于 docker healthcheck)
HTTP 模式没有调用方认证——TLS(见下文)对流量加密,但不会识别调用方。 请仅绑定到私有网络。依赖主机防火墙或局域网隔离。在未先添加 bearer-token 认证的情况下,不要暴露到公共互联网。
启用 HTTPS
HTTPS 为可选启用。启动时的解析顺序:
自带证书 — 将
MCP_TLS_CERT_FILE和MCP_TLS_KEY_FILE都设置为 PEM 文件路径。在终止 Let's Encrypt 或内部 CA 时使用此项。服务器在启动时读取这些文件; 重启容器以加载续期后的文件。自管理证书(推荐用于纯局域网环境)— 设置
MCP_TLS=auto。服务器在首次启动时生成一个 ECDSA P-256 自签名 证书,将其写入MCP_TLS_DIR(默认/data/certs),并在后续启动时复用。当证书在到期前 30 天内时,会自动重新生成。否则服务器保持纯 HTTP(当前默认)。
Var | Default | Notes |
| 未设置 |
|
|
|
|
|
| 主题备用名称。以逗号分隔的 |
| 第一个 DNS SAN,否则为 | 证书通用名称。 |
|
| 有效期。证书在剩余 <30 天时轮换。 |
| 未设置 | 自带证书(PEM)。与密钥一起设置时覆盖 |
| 未设置 | 自带密钥(PEM)。 |
启动时,服务器会记录证书的 SHA-256 指纹和
notAfter。在客户端固定该指纹,或在操作系统密钥库中信任该
证书,以供浏览器和 CLI 工具使用。
当 TLS 开启时,compose healthcheck 需要
--no-check-certificate 标志——将 test: 行更新为
["CMD", "wget", "--no-check-certificate", "-q", "-O-", "https://localhost:3000/health"]。
将 mcp-remote 指向 HTTPS 端点
对于自签名证书,要么通过 Node 的 CA 捆绑包固定证书文件, 要么在客户端跳过验证(仅限局域网):
# 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/mcp反向代理替代方案
当你尚未运行入口控制器时,进程内 TLS 很方便。如果你在
家庭服务前面有 Caddy、Traefik 或 nginx,更惯用的模式是在
代理处终止 TLS(使用自动 Let's Encrypt),并让 plex-mcp
在其后面保持纯 HTTP。这两种方法可以互换——选择
与你现有环境匹配的一种即可。
OAuth 2.1 bearer-token 认证(可选启用,尚不能实际使用)
代码端已具备 OAuth 2.1 受保护资源认证的支持 (ChatGPT Apps SDK 对齐阶段 2——完整计划见 docs/CHATGPT-APPS-SDK.md), 但尚不是你可以实际开启并使用的东西:它需要一个真实的 OAuth 2.1 身份提供方来签发令牌,而此部署尚未配置这样的提供方 (那是阶段 3,尚未开始)。此处记录仅为完整性,并非操作指南。
Var | Notes |
| IdP 签发方 URL。设置此项即选择启用认证——未设置(默认)表示无认证,与当前行为相同。 |
| 一旦设置了 |
| 以逗号分隔。默认 |
启用后,每个 /mcp 请求都需要 Authorization: Bearer <jwt>——
由已配置的 IdP 签发,并带有正确的受众和范围。/health
始终不受影响(它是独立的路由,而且 Docker 自身的
healthcheck 无法附加 bearer token)。/.well-known/oauth-protected-resource
按 RFC 9728 自动提供服务。
使用 Docker 运行(stdio,按需)
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使用 Docker Compose 运行(HTTP,长期运行)
compose 文件拉取 ghcr.io/carldog/plex-mcp:latest(多架构:
linux/amd64 + linux/arm64),由 CI 在每次推送到 main 时发布。
# 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 upMCP 端点将位于 http://<host>:${HOST_PORT}/mcp。
要从源码重新构建而不是拉取:
docker build -t ghcr.io/carldog/plex-mcp:latest .
docker compose up通过 Portainer 部署(来自 Git 的 Stack)
在 Portainer 中,Stacks → Add Stack → Repository。
仓库 URL:
https://github.com/CarlDog/plex-mcpCompose 路径:
docker-compose.yml环境变量:设置
PLEX_URL、PLEX_TOKEN、MCP_ALLOWED_HOSTS、HOST_IMAGE_DIR和HOST_LOG_DIR——全部 必填(见下文);HOST_PORT可选。部署。healthcheck 在约 10 秒内变为绿色。
HTTP 模式下必须设置 MCP_ALLOWED_HOSTS
服务器在 /mcp 上接受的 Host 头值的逗号分隔列表——
例如 nas.local:3001(必须与客户端实际拨打的
host:port 匹配,包括映射后的 HOST_PORT)。没有它,
服务器在 HTTP 模式下拒绝启动;如果未设置,docker compose config
也会以同样的方式失败——两者都在容器启动之前就失败,这是
有意为之,而不是以悄然无保护的状态启动。
这样做的原因是,容器内绑定 0.0.0.0 并不像裸主机上的
回环绑定那样是真正的访问边界:局域网上任意位置浏览器中
加载的页面都可以执行 DNS 重绑定——将自己的主机名指向此
容器的 IP——并作为混乱代理驱动各种工具(包括
plex_delete_playlist 之类的写入操作),从而完全绕过
“仅限局域网、无 bearer token”这一安全姿态。
Host 允许列表在不要求完整认证的情况下弥补了这一缺口。
MCP_ALLOWED_ORIGINS(可选,默认空)对 Origin 头做同样
的事情——除非基于浏览器的客户端确实需要直接调用此服务器,
否则请保持未设置;非浏览器客户端(mcp-remote 桥接、直接的
fetch)从不发送 Origin 头,因此空的默认值只会拒绝
DNS 重绑定攻击实际发送的请求形态。
HOST_IMAGE_DIR 和 HOST_LOG_DIR 为必填——没有相对路径默认值
compose 文件中两个卷的主机路径均为 ${VAR:?...}:没有
回退默认值,因此如果其中任何一个未设置,docker compose up /
Portainer 重新部署都会以明确的错误快速失败,而不是在损坏的
状态下启动。
以前这是一个软默认值 ${VAR:-./data/images},它只对从稳定
克隆进行的本地 docker compose up 是安全的。在 Portainer
git stack 中,它是一个陷阱:每次重新部署都会将仓库克隆到
一个全新的按提交划分的目录(/data/compose/<stack-id>/<commit>/),
而 ./data/images 这样的相对路径在那里并不存在。Docker
拒绝了绑定挂载,容器因此卡在 created 状态——从未启动。
这也影响到了自动重新部署(镜像更新、git 轮询),所以一个
原本健康的 stack 在没有任何手动操作的情况下宕机了;唯一的
症状就是容器停在 created 状态。这导致已部署的 stack 在
2026-07-31 宕机了约 10 小时——参见 docker-deployments.md
规则 #10 和舰队经验教训
2026-07-31-relative-compose-volume-defaults-break-portainer-git-stacks。
compose 文件现在将这一要求变为结构性的,而不仅仅是文档约定。
在 stack 的环境变量中将两者都设置为绝对主机路径:
HOST_IMAGE_DIR——plex_save_image的输出目录。 建议:使用 filesystem-mcp 的/media/_mcp-scratch挂载所对应的主机目录——例如 Synology NAS 上的/volume1/Media/_mcp-scratch——这样plex_search → plex_save_image → filesystem-mcp流水线就可以在同一个共享目录中运行。HOST_LOG_DIR——plex_download_logs的输出目录,与HOST_IMAGE_DIR分开存放,因为诊断 ZIP 不是媒体产物——例如 Synology NAS 上的/volume1/docker/plex-mcp/logs(与本机群按容器隔离 appdata 的惯例保持一致)。
请确保这两个目录在首次部署 之前 就已存在于主机上:Docker 不会自动创建缺失的绑定挂载源,只会拒绝启动容器。
与 Claude Desktop 配合使用
stdio(本地调用)
{
"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(远程 MCP 服务器)
{
"mcpServers": {
"plex": {
"url": "http://nas.local:3001/mcp"
}
}
}(需要 Claude Desktop 或支持远程 MCP HTTP 的客户端。)
本地开发
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 # HTTP日志
服务器将结构化日志输出到 stderr(在 stdio 模式下,stdout 承载 MCP 线协议,不能被污染)。格式:
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通过 LOG_LEVEL 环境变量配置日志详细程度(默认 info):
级别 | 显示内容 |
| 仅错误 |
| + 4xx Plex 响应 |
| + 工具调用与完成 |
| + 每次 Plex API 调用,含方法、路径、状态、毫秒 |
| (保留) |
容器日志由 Docker 的 json-file 驱动捕获并自动轮转(10MB × 3 个文件 = ~30MB 上限;轮转时删除最旧的)。使用 docker logs plex-mcp 或 docker logs -f 查看。
安全
容器以非 root 用户(
plexmcp)身份运行。Plex 令牌通过环境变量传入——切勿将其固化到镜像中。
.githooks/pre-commit会在每次提交时运行 gitleaks。每次克隆后激活一次: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