内容
# opds-mcp
[](https://github.com/pastukhov/opds-mcp/actions/workflows/ci.yml)
[](https://github.com/pastukhov/opds-mcp/actions/workflows/coverage-badge.yml)
一款MCP服务器,允许LLM浏览、搜索和下载来自OPDS目录(开放出版物分发系统)的书籍 - 这是一种由数字图书馆如古腾堡计划、标准电子书、Feedbooks等使用的基于Atom/JSON的订阅源格式。
支持OPDS 1.x(Atom + XML)和OPDS 2.0(JSON)目录、基于OpenSearch的全文搜索,以及下载获取链接到磁盘。
## 工具
- **`opds_browse`** — 获取目录/订阅源文档并返回其导航链接(搜索、下一步/上一步、子部分、筛选条件)以及条目(标题、作者、摘要、类别、获取链接、封面图片)。
- **`opds_search`** — 在目录中搜索。给它目录的订阅源URL(自动发现其`rel="search"`链接)或OpenSearch描述URL,以及一个自由文本查询。
- **`opds_get_entry`** — 获取单个条目/出版物文档(例如,条目的`rel="alternate"`链接)以获取完整详细信息。
- **`opds_download`** — 将获取链接后面的文件下载到本地目录并返回保存的文件路径。
所有工具都接受可选的`username`/`password`,用于需要HTTP基本身份验证的目录。如果服务器配置了默认目录,`OPDS_BASE_URL`(见下文),则`opds_browse`/`opds_search`/`opds_get_entry`的`url`参数是可选的 - 显式传递`url`以浏览该调用的不同目录。
## 安装
```bash
npm install
npm run build
```
## 在MCP客户端中配置
### 通过npx(无需本地检出)
该软件包尚未发布到npm注册表,但`npx`可以直接从此GitHub仓库安装和运行 - 它克隆仓库,运行`npm install`(触发`prepare`脚本以构建`dist/`),然后执行`opds-mcp`二进制文件:
```json
{
"mcpServers": {
"opds": {
"command": "npx",
"args": ["-y", "github:pastukhov/opds-mcp"],
"env": {
"OPDS_BASE_URL": "https://example.com/opds/root.xml",
"OPDS_USERNAME": "optional-default-username",
"OPDS_PASSWORD": "optional-default-password",
"OPDS_DOWNLOAD_DIR": "/absolute/path/to/save/books"
}
}
}
}
```
要固定特定分支或提交,请附加它:`"github:pastukhov/opds-mcp#branch-or-sha"`。
### 通过本地检出
适用于Claude Desktop / Claude Code(`claude_desktop_config.json`或`.mcp.json`)的示例:
```json
{
"mcpServers": {
"opds": {
"command": "npx",
"args": ["-y", "/absolute/path/to/opds-mcp"],
"env": {
"OPDS_BASE_URL": "https://example.com/opds/root.xml",
"OPDS_USERNAME": "optional-default-username",
"OPDS_PASSWORD": "optional-default-password",
"OPDS_DOWNLOAD_DIR": "/absolute/path/to/save/books"
}
}
}
}
```
`npx -y /absolute/path`在第一次运行安装依赖项并构建,与上面的GitHub表单相同。或者,自己运行`npm install && npm run build`,并将`command`/`args`直接指向`node`和`dist/index.js`。
- **`OPDS_BASE_URL`** — 当工具调用未传递其自己的`url`时,`opds_browse`/`opds_search`/`opds_get_entry`使用的目录。这是一种推荐的方式,通过指向特定的图书馆(例如`https://your-library.example/opds`),而不需要模型知道或猜测地址;省略它以要求每次调用都显式传递`url`。
- **`OPDS_USERNAME`/`OPDS_PASSWORD`** — 在工具调用未传递其自己的凭证时用作备用,当服务器专用于单个身份验证目录时很方便。
- **`OPDS_DOWNLOAD_DIR`** — `opds_download`保存文件的位置;默认为操作系统临时文件夹下的目录。
## 示例流程
1. 使用目录的根URL调用`opds_browse`,查看导航链接和/或第一页的条目。
2. 使用相同的根URL和查询调用`opds_search`,查找特定书籍。
3. 从结果中选择一个条目的`acquisitions[].href`,并将其传递给`opds_download`以本地保存文件(或如果需要比搜索结果中包含的更多详细信息,请先使用`opds_get_entry`)。
## 开发
```bash
npm run dev # 直接使用tsx运行服务器
npm run typecheck # tsc --noEmit
npm test # vitest,使用fixtures/下的固定OPDS文档
npm run test:coverage # vitest,带有coverage/下的覆盖率报告
npm run build # 编译到dist/
```
每个拉取请求都运行`.github/workflows/ci.yml`中的`typecheck`、`build`和`test:coverage`。在每次推送到`main`时,`.github/workflows/coverage-badge.yml`重新计算覆盖率并提交`.github/badges/coverage.json`,该文件通过shields.io的端点徽章读取。
## 备注
- 仅接受`http:`/`https:` URL;其他方案在发出请求之前会被拒绝。
- 默认情况下,下载的文件大小上限为200MB,并写入配置的下载目录中的净化文件名内。
- 由于订阅源文档可能任意大,`opds_browse`/`opds_search`返回单个页面包含的内容;使用响应中的`navigation.next`链接遍历目录的其余部分。