内容
# Seedbox MCP
为 Plex + Radarr + Sonarr 堆栈提供两个联合托管服务:
- **MCP 服务器** (`seedbox-mcp`) — 为 Plex、Radarr 和 Sonarr 提供紧凑的工具,使您的代理可以选择检查媒体状态并执行基本操作。
- **聊天界面** (`seedbox-chat`) — 一个由 Claude Haiku 驱动的 Plex 身份验证单页聊天 UI,预连接到 MCP 服务器。设计用于家庭成员,他们可以访问 Plex 但不能访问 Claude。
可以在 Python 可以访问您的 Plex 和 *arr 服务的任何地方运行 — seedbox 槽(Whatbox、Ultraseedbox 等)、家庭实验室、NAS、VPS。下面的 Whatbox 特定示例涵盖了一个经过充分测试的部署路径;请根据您的环境(systemd、Docker、反向代理)进行调整。
## MCP 服务器
该服务故意设计得较为狭窄:
- Plex 仅为只读。
- Radarr 和 Sonarr 的写入权限仅限于添加、重新搜索、队列操作和精确 ID 删除。
- 写入工具默认情况下通过 `confirm=false` 进行试运行。
- 删除工具默认情况下通过 `delete_files=false` 保留文件。
- 没有 torrent、索引器、文件系统、shell、调度程序、数据库或前端功能。
## 本地设置
需要 `just` 和 `uv`。
```bash
cp .env.example .env
# 填写所需的值 - 请参见下面的配置
just setup
just run # MCP 服务器在 :17432
just run-chat # 聊天界面在 :17433(单独的终端)
```
MCP 端点是 `/mcp`;一个基本的未经身份验证的健康检查可在 `/health` 上使用。
每个 `/mcp` 请求都需要一个静态的 bearer token 或有效的 OAuth 访问 token:
```http
Authorization: Bearer <MCP_BEARER_TOKEN>
```
## 配置
所有设置都从 `.env` 或环境变量中读取。
### 必须
| 变量 | 备注 |
|---|---|
| `MCP_BEARER_TOKEN` | 用于 bearer 身份验证和 OAuth 同意门的共享密钥 |
| `MCP_PUBLIC_BASE_URL` | 公共 HTTPS 基本 URL(例如 `https://mcp.example.box.ca`)- OAuth 发现元数据所需 |
| `RADARR_URL` | Radarr 基本 URL |
| `RADARR_API_KEY` | Radarr → 设置 → 通用 → 安全 |
| `RADARR_DEFAULT_ROOT_FOLDER` | Radarr 看到的电影根文件夹的绝对路径 |
| `RADARR_DEFAULT_QUALITY_PROFILE_ID` | 整数 - 参见[查找质量配置文件 ID](#查找质量配置文件-id) |
| `SONARR_URL` | Sonarr 基本 URL |
| `SONARR_API_KEY` | Sonarr → 设置 → 通用 → 安全 |
| `SONARR_DEFAULT_ROOT_FOLDER` | Sonarr 看到的 TV 根文件夹的绝对路径 |
| `SONARR_DEFAULT_QUALITY_PROFILE_ID` | 整数 - 参见[查找质量配置文件 ID](#查找质量配置文件-id) |
| `PLEX_URL` | Plex 基本 URL - 必须可以从服务器运行的位置访问。如果在 seedbox 槽上使用公共 HTTPS URL;在与 Plex 相同的宿主上使用 `http://127.0.0.1:32400` 即可 |
| `PLEX_TOKEN` | Plex 身份验证令牌 - 参见[查找 Plex 令牌](#查找-plex-令牌) |
### 可选
| 变量 | 默认值 | 备注 |
|---|---|---|
| `MCP_HOST` | `127.0.0.1` | 绑定地址 |
| `MCP_PORT` | `17432` | 绑定端口 |
| `RADARR_DEFAULT_MIN_AVAILABILITY` | `released` | `announced`, `in_cinemas`, 或 `released` |
| `SONARR_DEFAULT_LANGUAGE_PROFILE_ID` | _(无)_ | Sonarr v3 语言配置文件 ID;Sonarr v4+ 省略 |
| `SONARR_DEFAULT_SERIES_TYPE` | `standard` | `standard`, `daily`, 或 `anime` |
| `PLEX_VERIFY_TLS` | `true` | 验证 Plex HTTPS 证书。如果自签名证书可信,设为 `false` |
| `PLEX_MOVIE_SECTION` | `Movies` | Plex 电影库的显示名称 |
| `PLEX_TV_SECTION` | `TV Shows` | Plex TV 库的显示名称 |
| `TAUTULLI_ENABLED` | `false` | 启用 Tautulli 观看历史记录丰富 |
| `TAUTULLI_URL` | _(无)_ | Tautulli 基本 URL |
| `TAUTULLI_API_KEY` | _(无)_ | Tautulli API 密钥 |
| `OAUTH_ACCESS_TOKEN_TTL` | `3600` | OAuth 访问令牌寿命(秒) |
启动日志打印一个简化的配置摘要。永远不会记录 API 密钥、Plex 令牌、bearer 令牌和请求头。
## 聊天界面
一个由 Claude Haiku 支持的单页聊天 UI。任何具有 Plex 服务器好友访问权限的人都可以使用他们的 Plex 帐户登录,并与具有 MCP 工具完全访问权限的助手聊天。
写入操作(添加、删除、队列)需要聊天中的确认步骤 - Haiku 始终使用 `confirm=false` 调用工具来显示预览,只有在用户确认后才会使用 `confirm=true` 继续。
### 配置
聊天服务器读取与 MCP 服务器相同的 `.env` 文件,并添加:
#### 必须
| 变量 | 备注 |
|---|---|
| `CHAT_PUBLIC_BASE_URL` | 聊天应用的公共 HTTPS 基本 URL(例如 `https://chat.example.com`)- 用作 Plex OAuth 回调源 |
| `CHAT_SESSION_SECRET` | 用于签名会话 cookie 的长随机字符串 |
| `CHAT_PLEX_CLIENT_ID` | 此应用的稳定 UUID 标识 Plex - 使用 `python3 -c "import uuid; print(uuid.uuid4())"` 生成一次 |
| `ANTHROPIC_API_KEY` | Claude Haiku 的 Anthropic API 密钥 |
#### 可选
| 变量 | 默认值 | 备注 |
|---|---|---|
| `CHAT_HOST` | `127.0.0.1` | 绑定地址 |
| `CHAT_PORT` | `17433` | 绑定端口 |
| `SYSTEM_PROMPT_PATH` | _(无)_ | 重写默认系统提示的纯文本文件路径 |
### 身份验证工作原理
1. 用户访问聊天 URL 并被重定向到 `plex.tv` 登录。
2. 登录后,Plex 重定向回 `/auth/callback`。
3. 服务器验证用户是 Plex 服务器的好友(共享访问用户)。
4. 设置签名会话 cookie - 没有过期时间,有效期直到浏览器清除 cookie 为止。
只有已经具有 Plex 好友访问权限的用户才能登录。没有单独的用户管理。
## 部署(Whatbox 示例)
下面的模式是作者在 Whatbox 上运行的。对于 systemd 家庭实验室,请交换 `screen` + `@reboot` 为 systemd 单元;在 Docker 上,请打包相同的 `python -m seedbox_mcp.server` 调用。无论运行时如何,服务器都期望在 `MCP_PUBLIC_BASE_URL` 处由 HTTPS 提供服务 - 在 Whatbox 上,这是“托管 HTTPS 链接”;在其他地方,请使用 Caddy、nginx、Tailscale Serve 或类似工具。
### 克隆和安装
```bash
git clone <repo-url> ~/seedbox-mcp
cd ~/seedbox-mcp
cp .env.example .env
# 填写所有必填值
uv sync
```
#### 重新部署
一旦克隆完成,请使用 `just deploy`(或 `bash scripts/deploy.sh`)从工作站推送新代码。它通过 SSH 连接,快速转发检出,运行 `uv sync`,并重启两个服务器。它期望在 `~/.ssh/config` 中有一个 `seedbox` 主机,并设置了密钥身份验证(`ssh-copy-id seedbox`);通过 `SEEDBOX_SSH`、`SEEDBOX_DIR`、`SEEDBOX_BRANCH` 覆盖目标/路径/分支。
### 在后台使用 screen 运行
`scripts/start.sh` 杀死任何现有的会话并在分离的 `screen` 会话(`media-mcp` 和 `media-chat`)中启动两个服务器,将输出记录到 `mcp.log` 和 `chat.log`:
```bash
bash scripts/start.sh
```
重新连接:`screen -r media-mcp`(或 `media-chat`)。断开连接:`Ctrl-A D`。
### 重启后自动重启
```bash
crontab -e
```
添加:
```cron
@reboot sleep 30 && bash ~/seedbox-mcp/scripts/start.sh
```
`sleep 30` 为主机提供了一些时间来启动网络,然后服务器尝试连接。
### 重启服务器
```bash
bash scripts/start.sh
```
(脚本在重新启动之前会杀死现有的 screen 会话。)
### 公共 HTTPS 前端
使用 HTTPS 将 `http://127.0.0.1:17432`(MCP)和 `http://127.0.0.1:17433`(聊天)前端 - Whatbox 管理链接、反向代理(Caddy / nginx)、Tailscale Serve 或等效工具 - 并将 `MCP_PUBLIC_BASE_URL` 和 `CHAT_PUBLIC_BASE_URL` 设置为生成的 URL。OAuth 发现元数据从这些值派生,因此它们必须与客户端实际使用的内容相匹配。
### 验证
```bash
curl https://<your-host>/health
curl https://<your-host>/.well-known/oauth-authorization-server
```
## 连接到代理
Claude.ai 和 ChatGPT MCP 连接器都需要 OAuth 2.0。服务器自动实现授权码 + PKCE - 只需运行服务器并设置 `MCP_PUBLIC_BASE_URL`。
### 设置步骤
1. 在您选择的代理中添加新的 MCP 集成:
- **MCP 服务器 URL:** `https://<your-host>/mcp`
- **客户端 ID:** 任意字符串,例如 `claude-ai`(服务器接受此处任意值)
- **客户端密钥:** 留空或输入任意虚拟值 - 不会验证(PKCE 替换客户端密钥)
2. 代理将打开 `https://<your-host>/oauth/authorize` 在您的浏览器中。
3. 将您的 `MCP_BEARER_TOKEN` 粘贴到同意表单中并提交。
4. 代理存储生成的访问令牌(默认 1 小时 TTL)并通过 30 天的刷新令牌自动刷新。
### 建议的模型面对指令
```text
优先使用只读工具。对于添加、删除、重新搜索和队列操作,首先使用 media_search 或概览工具识别确切的项目。对于模糊的标题,返回候选者或要求消歧义。不要发明 ID。队列操作需要来自 radarr_overview 或 sonarr_overview 输出的 queue_id。不要声称可以访问 torrent 客户端、索引器、shell 或文件系统;此应用程序故意不公开这些功能。
```
## 命令界面
咨询 `justfile`:
```bash
just setup # 使用 uv 安装运行时和开发依赖
just run # 运行 MCP 服务器(:17432)
just run-chat # 运行聊天界面(:17433)
just test # 运行 MCP 单元测试(不需要实时服务)
just test-chat # 运行聊天单元测试(不需要实时服务)
just test-live # 运行 MCP 实时集成测试(需要 LIVE_TESTS=1)
just test-chat-live # 运行聊天实时测试(需要 LIVE_TESTS=1 + 运行的 MCP 服务器)
just test-smoke # 调用 /health 到配置的主机/端口
just format # 使用 ruff 格式化
just check # ruff lint + mypy 类型检查
```
## 工具表面
只读工具:
- `media_status` — Radarr、Sonarr 和 Plex 的可达性、版本、健康状况和磁盘空间
- `radarr_overview` — 电影列表、下载队列和已请求/缺失内容
- `sonarr_overview` — 系列列表、下载队列和已请求/缺失的剧集
- `plex_overview` — 活动会话、最近添加的内容和未观看的陈旧候选者
- `media_search` — 跨 Radarr、Sonarr 和 Plex 使用外部 TMDb/TVDb 查找的模糊搜索
- `staleness_report` — 将 Plex 观看历史记录与 Radarr/Sonarr 交叉引用,以显示旧的未观看、未管理的和卡住的队列项目
写入工具:
- `radarr_add_movie` — 通过 TMDb ID 添加电影(默认情况下试运行)
- `radarr_research_movie` — 对 Radarr 电影触发搜索、刷新或下载扫描命令
- `radarr_delete_movie` — 通过内部 ID 从 Radarr 删除电影(默认情况下保留文件)
- `radarr_queue_action` — 通过队列 ID 删除或阻止卡住的队列项目
- `sonarr_add_series` — 通过 TVDb ID 添加系列(默认情况下试运行)
- `sonarr_research_series` — 对 Sonarr 系列触发搜索、刷新或缺失剧集搜索
- `sonarr_delete_series` — 通过内部 ID 从 Sonarr 删除系列(默认情况下保留文件)
- `sonarr_queue_action` — 通过队列 ID 删除或阻止卡住的队列项目
写入工具需要明确的标识符。添加操作需要 TMDb 或 TVDb ID。删除、重新搜索和队列操作需要确切的 Radarr 或 Sonarr 内部 ID。队列操作永远不会触摸 torrent 客户端(`removeFromClient=false`)。
## 示例提示
```text
Plex 上当前正在播放什么?
```
```text
Radarr 或 Sonarr 是否卡在任何事情上?
```
```text
显示添加到 Plex 超过 90 天且无人观看的电影。
```
```text
Heat 是否已经在服务器上?如果没有,请准备添加 1995 年的 Michael Mann 电影,但不要实际添加。
```
```text
从 Radarr 中删除 2013 年的电影 The Heat,但不要删除文件。
```
```text
Radarr 或 Sonarr 队列中是否有卡住或导入阻止的项目?如果有,请清除它们。
```
## 故障排除
- **缺少配置:** 运行 `cp .env.example .env`,然后填写所有必填值。
- **`/mcp` 返回 401:** 验证 `Authorization: Bearer <MCP_BEARER_TOKEN>`。
- **OAuth 同意表单拒绝您的令牌:** 粘贴您的 `.env` 中的 `MCP_BEARER_TOKEN` 的确切值,不要有额外的空格。
- **Claude.ai "身份验证失败" 同意后:** 检查 `MCP_PUBLIC_BASE_URL` 是否已设置并与您的公共主机名匹配;使用 `curl https://<host>/.well-known/oauth-authorization-server` 验证 `token_endpoint` 是否为完整的 HTTPS URL。
- **Radarr 或 Sonarr 身份验证错误:** 验证每个应用中的 API 密钥。
- **Plex 错误:** `PLEX_URL` 必须可以从服务器运行的位置访问。在 seedbox 槽上,通常意味着公共 HTTPS URL,而不是 `127.0.0.1:32400`。验证 `PLEX_TOKEN` 和章节名称(`PLEX_MOVIE_SECTION`、`PLEX_TV_SECTION`)。
- **部分状态警告:** 一个上游可能已关闭,而 MCP 服务器本身是健康的。
自动测试(`just test`)使用模拟的上游,不需要实时服务。使用 `just test-live` 测试对外部服务的访问。
连接信息
猜你喜欢
暂无推荐服务器