内容
# feed-curator-mcp
[](https://github.com/yunbow/feed-curator-mcp/actions/workflows/ci.yml)
[](./LICENSE)
> 收集RSS订阅源,评分,提取版权自由的事实,并撰写文章 — 所有这些都来自您主机的AI聊天,通过模型上下文协议。
一个 **MCP服务器** ,它摄取RSS订阅源,然后让 **主机AI(MCP客户端)** 对每篇文章进行评分,提取版权自由的事实,并撰写原创文章。 这里 **没有外部LLM API调用** — 主机AI进行推理,服务器将所有内容存储在SQLite中(`data/curator.db`)。
订阅源和设置存储在数据库中(`feeds` / `settings`表),因此您可以完全从聊天中管理它们 — 不需要`feeds.yaml`。
## 为什么选择feed-curator-mcp?
- **五个专注的步骤** — 获取 → 评分 → 提取事实 → 列表 → 生成,每个步骤都由您的主机AI聊天驱动
- **主机AI是生成器** — 评分 / 事实提取 / 文章写作由连接的AI完成(`prepare_*` 将材料交给AI,`save_*` 存储结果);没有 `claude -p` 和 API密钥
- **版权意识** — 事实和文章独立重写;不翻译或复制源文本
- **确定性去重** — URL规范化 + 标题相似性(Jaccard)过滤重复项,然后进行AI推理
- **AI评分** — 九个价值/热点标准,每个标准评分0–10,归一化为0–100的评分
- **本地和可检查** — 普通SQLite存储,包括订阅源和设置;除了订阅源获取外,机器上没有任何内容离开
## 需求
- Node.js 20+(验证版本为v22)
- 一个MCP客户端作为主机AI(例如Claude Desktop,Claude Code或任何MCP-capable客户端)
## 安装
```bash
npm install
npm run build # 编译到dist/(入口:dist/index.js)
```
## 连接到主机AI
使用您的MCP客户端注册服务器。服务器通过 **stdio** 进行JSON-RPC通信。
### Claude Code
```bash
claude mcp add feed-curator -- node /absolute/path/to/feed-curator-mcp/dist/index.js
```
### Claude Desktop (`claude_desktop_config.json`)
```json
{
"mcpServers": {
"feed-curator": {
"command": "node",
"args": ["/absolute/path/to/feed-curator-mcp/dist/index.js"],
"env": {
"CURATOR_DB_PATH": "/absolute/path/to/data/curator.db"
}
}
}
}
```
环境变量(均为可选):
- `CURATOR_DB_PATH` — SQLite路径(默认为工作目录下的`data/curator.db`)
- `CURATOR_OUTPUT_DIR` — 生成文章的基础目录(默认为`output`)
### 检查服务器
使用 [MCP Inspector](https://github.com/modelcontextprotocol/inspector) 手动执行工具(使用v0.14.1+):
```bash
npm run build
npm run inspect # npx @modelcontextprotocol/inspector node dist/index.js
```
## 用法(5个步骤,从聊天开始)
连接后,请主机AI调用这些工具。一个典型的运行:
1. **注册订阅源,然后获取** — `add_feed`,然后`fetch_feeds`
- "添加Hacker News订阅源`https://hnrss.org/frontpage`,然后获取。"
2. **评分** — `prepare_scoring` → (主机AI评分)→ `save_scores`
- "准备评分并对新文章进行评分。" 主机AI评估9个标准(0–10);服务器归一化为0–100。
3. **提取事实** — `prepare_facts` → (主机AI提取)→ `save_facts`
- 从非重复文章中,主机AI以 ≥ 阈值的评分写入版权自由的事实。
4. **列出推荐** — `list_facts`
- "显示推荐的事实。" (仅限未生成;`all: true` 包括已生成)
5. **生成文章** — `prepare_article` → (主机AI撰写)→ `save_article`
- "从事实1生成文章。" 事实被标记为已生成,Markdown文件写入 `output/`。
## 工具
| # | 工具 | 功能 | 影响 |
|---|---|---|---|
| — | `add_feed` / `list_feeds` / `remove_feed` | 管理RSS订阅源 | `feeds` 表 |
| — | `get_settings` / `update_settings` | 读取/更新阈值和批次大小 | `settings` 表 |
| 1 | `fetch_feeds` | 从注册的订阅源获取URL/标题/摘要 | `articles` 表 |
| 2 | `prepare_scoring` | 去重(URL + 标题相似性),返回批次 + 评分指令 | `articles` (标记重复项) |
| 2 | `save_scores` | 保存主机AI评分(归一化为0–100) | `articles` |
| 3 | `prepare_facts` | 返回评分 ≥ 阈值的文章 + 提取指令 | (只读) |
| 3 | `save_facts` | 保存主机AI的版权自由事实 | `facts` 表 |
| 4 | `list_facts` | 按评分排序的推荐事实 | (只读) |
| 5 | `prepare_article` | 返回事实 + 文章写作指令 | (只读) |
| 5 | `save_article` | 保存草拟的文章,标记生成,写入Markdown | `facts` / `output/` |
`prepare_*` / `save_*` 的分割使得生成在主机AI上进行:`prepare_*` 返回源材料 + 指令,告诉AI调用哪个 `save_*` 工具。
### 工具响应
每个工具返回一个 **两层响应**:人类可读的Markdown摘要(`content`)和机器可读的JSON(`structuredContent`),验证为每个工具的 `outputSchema`。 工具带有注释(`readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint`),大多数成功的返回结果包含一个结构化的 `next_step`,指向主机AI到下一个工具。 业务错误(未找到,缺少先决条件,路径遍历)作为结构化的 `isError` 返回结果,带有 `error_code` 和 `suggestion`,以便AI可以自我纠正。
## 配置(在数据库中)
设置存储在 `settings` 表中,并在首次运行时使用默认值初始化。 通过 `update_settings` 从聊天中更改它们:
| 键 | 默认值 | 含义 |
|---|---|---|
| `score_threshold` | 50 | 事实提取/推荐的最低评分 |
| `title_similarity_threshold` | 0.7 | 标题相似性重复检测阈值 |
| `score_batch_size` | 5 | `prepare_scoring` 的批次大小 |
| `fact_batch_size` | 5 | `prepare_facts` 的批次大小 |
| `target_country` | 日本 | 用于 `gap` 标准和假定的读者(例如 `日本`,`United States`) |
| `target_language` | 日本語 | 提取的事实和生成的文章的输出语言(例如 `日本語`,`English`) |
默认值针对日本受众。 要为其他国家/语言策划 - 例如从聊天: "将target_country设置为United States,将target_language设置为English." - 调用 `update_settings`。 从那时起, `prepare_scoring` 根据该国家评估 `gap` 标准, `prepare_facts` / `prepare_article` 指示主机AI用该语言编写。
## 数据库模式
- **feeds**:注册的RSS订阅源(`name`,`url`唯一)。
- **settings**:键值配置(使用默认值初始化)。
- **articles**:获取的文章。 包含重复标志(`is_duplicate` / `dup_reason`)和评分(`total_score`,每个标准的`score_detail`,`score_reason`)。
- **facts**:版权自由的事实信息。 包含`article_generated`(生成标志)和`generated_content`(草拟的文章正文)。
## 评分标准(0–10,每个标准,归一化为0–100)
新颖性 / 实用性 / 缺口(vs. `target_country`) / 情感 / 权威性 / 趋势 / 惊喜 / 数字影响 / 同理心
`Gap` 标准衡量与您的 `target_country` 设置(默认为 `日本`)的差异。
## 版权
步骤3和5永远不会翻译或复制源文本。 事实被重建为简洁的原始陈述,文章根据这些事实从头开始编写,在您的 `target_language` 中(在返回给主机AI的指令中明确执行)。
## 开发
```bash
npm run build # 编译到dist/
npm run type-check # tsc --noEmit
npm run lint # ESLint
npm test # node:test单元测试
```
所有四个都在每次推送和拉取请求上在CI中运行。
## 贡献
参见 [CONTRIBUTING.md](./CONTRIBUTING.md)。 安全策略: [SECURITY.md](./SECURITY.md)。
## 许可证
[MIT](./LICENSE)
---
语言: English | [日本語](docs/i18n/ja/README.md) | [简体中文](docs/i18n/zh-CN/README.md) | [한국어](docs/i18n/ko/README.md) | [Español](docs/i18n/es/README.md)