Skip to main content
Glama
CarlDog
by CarlDog

plex-mcp

code confidence · claude-opus-4-8[1m] · 2026-07-07 · 详情

一个面向 Plex Media Server 的 MCP 服务器,打包为 Docker 容器。它让 MCP 客户端(Claude Desktop 等)能够浏览和搜索你的 Plex 媒体库。

工具

工具

描述

plex_list_libraries

列出服务器上的所有媒体库(分区)

plex_search

搜索所有媒体库

plex_hub_search

通过 Plex 的 hub-search 端点进行搜索,包括合集(不同于 plex_search)

plex_recently_added

最近添加的项目,可选按分区筛选

plex_on_deck

“待播”项目(已部分观看 / 接下来的内容);可选的 section_id 用于限定到一个媒体库分区

plex_get_item

按 rating key 获取单个项目的元数据。传入 minimal=true 可剔除庞大的演员/剧组/图片数组(对于演员众多的电影可减少约 80% 的大小),同时保留字幕轨信息;传入 fields=[...] 进行显式投影

plex_browse

列出媒体库分区中的项目(分页,可选类型筛选,可选的 collection 标题筛选,可选的稀疏 fields 投影)

plex_list_collections

列出媒体库分区中的合集(对 plex_browse 的合集类型的轻量封装)

plex_get_children

项目的子项(剧集→季,季→集,艺术家→专辑)

plex_now_playing

服务器上当前正在播放的会话

plex_history

播放历史记录(分页,最近优先)

plex_mark_watched

将项目标记为已观看(可撤销)

plex_mark_unwatched

将项目标记为未观看(可撤销)

plex_rate_item

设置项目的 0-10 用户星级评分;省略 rating 可将其清除回未评分状态

plex_list_playlists

列出所有播放列表(普通 + 智能)

plex_get_playlist_items

列出播放列表的内容

plex_create_playlist

创建以单个项目为初始项的普通播放列表

plex_add_to_playlist

将项目追加到普通播放列表

plex_remove_from_playlist

按 playlistItemID 移除项目

plex_delete_playlist

删除播放列表(仅元数据——媒体不受影响)

plex_hubs

Plex 精选的全服务器 hub(继续观看、最近发布等)

plex_section_hubs

限定到单个媒体库分区的精选 hub

plex_related

Plex 为项目精选的“相关”hub(按来源分组)

plex_similar

项目的算法相似项目(扁平列表)

plex_refresh_metadata

从当前代理重新拉取项目的元数据(可选 force)

plex_get_matches

列出项目的候选匹配(TMDB / TVDB / 等);可选的标题/年份/代理/语言覆盖

plex_apply_match

将选定的匹配(guid/name)应用到项目;覆盖代理绑定

plex_edit_metadata

覆盖标量元数据字段(标题、摘要、年份等),支持字段级锁定

plex_unmatch

将项目与其代理绑定分离(回到未匹配状态);已锁定的字段依然保留

plex_refresh_section

触发整个媒体库分区的元数据刷新(增量或深度)

plex_split_item

将 Plex 项目拆分回其组成媒体变体,作为 N 个独立项目

plex_merge_items

将其它项目合并到目标项目中(源项目被吸收;目标项目保留)

plex_get_image

获取项目的海报/背景图/横幅/clearLogo 字节,作为 MCP 图像内容块(以便支持视觉的客户端能够真正看到图片);可选的 max_width/max_height 通过 Plex 的转码器路由

plex_save_image

与 plex_get_image 相同的输入接口,但会将字节写入 MCP_IMAGE_SAVE_DIR(默认为 /data/images/)下的磁盘并返回路径+大小。通过将主机目录绑定挂载到该路径,即可桥接到下游流水线(ImageMagick、filesystem-mcp 消费者等),无需进行视觉渲染

plex_download_logs

获取 Plex Media Server 自身的诊断日志包(ZIP),并将其写入 MCP_LOG_SAVE_DIR(默认为 /data/logs/)下的磁盘

plex_list_posters

列出项目的所有海报候选(代理提供、本地扫描、之前上传的),包括当前正在使用的那一个

plex_set_poster

通过候选自身的 poster_rating_key(来自 plex_list_posters)选择一个现有的海报候选作为当前生效项

plex_upload_poster

添加一张来自外部 URL(Plex 会抓取它)或 MCP_IMAGE_SAVE_DIR 下本地文件的新海报。默认会自动选中它;select=false 时只添加而不改变当前显示的内容

Related MCP server: Plex Assistant MCP

配置

两个环境变量,均为必填:

Var

Example

Notes

PLEX_URL

http://192.168.1.50:32400

你的 Plex 服务器的基础 URL

PLEX_TOKEN

(见下文)

Plex 认证令牌

要找到你的 Plex 令牌,请参阅 Plex 的 查找身份验证令牌 指南。

可选环境变量

全部都有可用的默认值;仅需在需要覆盖时设置。

Var

Default

Notes

MCP_FETCH_TIMEOUT_MS

30000

每个出站 Plex 请求的超时时间(日志下载除外)

MCP_IMAGE_MAX_BYTES

4194304 (4 MiB)

plex_get_image/plex_save_image 的大小上限

MCP_LOG_MAX_BYTES

52428800 (50 MiB)

plex_download_logs 的大小上限

MCP_LOG_FETCH_TIMEOUT_MS

120000 (2 min)

plex_download_logs 的超时时间——与 MCP_FETCH_TIMEOUT_MS 分开,因为日志 ZIP 具有不同的大小/延迟特征

MCP_SESSION_IDLE_TIMEOUT_MS

3600000 (1 hr)

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 客户端直接调用

docker run -i --rm ... plex-mcp(无 MCP_PORT)

Streamable HTTP

长期运行的部署(Portainer、Compose、k8s)

设置 MCP_PORT=3000(docker-compose.yml 中已完成)

在 HTTP 模式下,服务器暴露:

  • POST/GET/DELETE /mcp — MCP Streamable HTTP 端点(按规范)

  • GET /health — 存活探针(用于 docker healthcheck)

HTTP 模式没有调用方认证——TLS(见下文)对流量加密,但不会识别调用方。 请仅绑定到私有网络。依赖主机防火墙或局域网隔离。在未先添加 bearer-token 认证的情况下,不要暴露到公共互联网。

启用 HTTPS

HTTPS 为可选启用。启动时的解析顺序:

  1. 自带证书 — 将 MCP_TLS_CERT_FILE 和 MCP_TLS_KEY_FILE 都设置为 PEM 文件路径。在终止 Let's Encrypt 或内部 CA 时使用此项。服务器在启动时读取这些文件; 重启容器以加载续期后的文件。

  2. 自管理证书(推荐用于纯局域网环境)— 设置 MCP_TLS=auto。服务器在首次启动时生成一个 ECDSA P-256 自签名 证书,将其写入 MCP_TLS_DIR(默认 /data/certs),并在后续启动时复用。当证书在到期前 30 天内时,会自动重新生成。

  3. 否则服务器保持纯 HTTP(当前默认)。

Var

Default

Notes

MCP_TLS

未设置

auto / true / on / 1 以启用自管理模式

MCP_TLS_DIR

/data/certs

server.crt / server.key 所在位置。挂载一个卷以持久化。

MCP_TLS_SAN

DNS:localhost,IP:127.0.0.1

主题备用名称。以逗号分隔的 DNS: / IP: 条目。

MCP_TLS_CN

第一个 DNS SAN,否则为 plex-mcp

证书通用名称。

MCP_TLS_DAYS

365

有效期。证书在剩余 <30 天时轮换。

MCP_TLS_CERT_FILE

未设置

自带证书(PEM)。与密钥一起设置时覆盖 MCP_TLS=auto。

MCP_TLS_KEY_FILE

未设置

自带密钥(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

MCP_OAUTH_ISSUER

IdP 签发方 URL。设置此项即选择启用认证——未设置(默认)表示无认证,与当前行为相同。

MCP_OAUTH_AUDIENCE

一旦设置了 MCP_OAUTH_ISSUER 即为必填。期望的 aud 声明——应等于此服务器的规范公共 URL。如果缺失,服务器拒绝启动。

MCP_OAUTH_REQUIRED_SCOPES

以逗号分隔。默认 plex:read。

启用后,每个 /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 up

MCP 端点将位于 http://<host>:${HOST_PORT}/mcp。

要从源码重新构建而不是拉取:

docker build -t ghcr.io/carldog/plex-mcp:latest .
docker compose up

通过 Portainer 部署(来自 Git 的 Stack)

  1. 在 Portainer 中,Stacks → Add Stack → Repository。

  2. 仓库 URL:https://github.com/CarlDog/plex-mcp

  3. Compose 路径:docker-compose.yml

  4. 环境变量:设置 PLEX_URL、PLEX_TOKEN、 MCP_ALLOWED_HOSTS、HOST_IMAGE_DIR 和 HOST_LOG_DIR——全部 必填(见下文);HOST_PORT 可选。

  5. 部署。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):

级别

显示内容

error

仅错误

warn

+ 4xx Plex 响应

info(默认)

+ 工具调用与完成

debug

+ 每次 Plex API 调用,含方法、路径、状态、毫秒

trace

(保留)

容器日志由 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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables 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
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for reelgrep - browse and search your local video library from any MCP client.
    10 npm
    MIT