# Reader MCP Workflow Service reader 当前已经收口为面向 OpenClaw 的 MCP workflow service。正式能力边界以 FreshRSS 日报工作流为准:启动 run、写入 `run-state.json`、查询运行状态、读取结构化结果,以及最小可用的 `resume_run`。CLI 仍保留,但定位为 debug / fallback,而不是正式集成入口。 ## 运行 ```bash pip install -e . summary-mcp ``` 服务当前暴露 11 个工具。 正式 workflow service 相关工具: - `run_freshrss_openclaw_pipeline` - `get_run_status` - `list_runs` - `list_run_artifacts` - `get_delivery_payload` - `get_run_report` - `resume_run` 单步处理 / 调试相关工具: - `extract_url_content` - `extract_item_content` - `filter_summary_result` - `generate_article_summaries` ## 正式能力边界 - 当前正式 workflow 只有 `freshrss_daily_digest` - 每次 FreshRSS 主流水线 run 都会在 `outputs/freshrss/rerun//run-state.json` 落地运行真相 - OpenClaw 正式读取结果应优先使用 `get_delivery_payload` 与 `get_run_report`,而不是自己拼输出目录路径 - `digest-brief.json` 当前会随主流水线产出,但还没有独立的 MCP 读取工具;如需定位它,应通过 `list_run_artifacts` 或 `get_run_report` 返回的信息发现 - `run_freshrss_openclaw_pipeline` 与 `resume_run` 当前都是同步 MCP 调用;仓库里还没有后台队列 / worker / 异步任务管理 ## OpenClaw 推荐调用路径 1. 调用 `run_freshrss_openclaw_pipeline` 启动正式日报 run,并保存返回的 `run_id` 2. 后续所有状态判断都基于 `get_run_status(run_id)` 或 `list_runs(...)` 3. 需要看产物列表时用 `list_run_artifacts(run_id)`,不要在 OpenClaw 里硬编码 `outputs/freshrss/rerun/...` 4. 需要消费正式结果时优先用 `get_delivery_payload(run_id)` 与 `get_run_report(run_id)` 5. 仅当 `resume_run` 的最小恢复范围满足时,才对失败 run 调用 `resume_run(run_id)`;否则应重启一个新 run ## `resume_run` 当前最小范围 - 只支持带有效 `run-state.json` 的 run - 只支持 workflow `freshrss_daily_digest` - 恢复时继续沿用原 `run_id`,不会新建 retry run - 当前支持的恢复起点只有:`generate_summaries`、`apply_filters`、`build_delivery_payload`、`write_run_report` - 当前明确不支持从 `fetch_feed`、`extract_articles` 恢复;这类失败应新开 run - 恢复前会校验关键中间产物是否齐备,缺失时直接返回不可恢复,而不会自动回退到更早 stage ## 单篇文章总结后处理(可选使用独立 LLM) ### 生产环境推荐输入 - 单篇总结的正式生产输入,优先使用 FreshRSS 主流水线输出的**单篇 extracted 文件**: - `outputs/freshrss/rerun//extracted/item-XX.extracted.json` - 这些**逐条 extracted 文件**是下游单篇总结的**正式默认产物**。 - 像 `outputs/freshrss/extracted/freshrss.extracted.json` 这样的**批量 extracted 文件**,只作为临时场景、兼容旧流程的输入形态保留,**不是首选生产默认**。 ### daily 知识库默认配置 - `IMA_DAILY_KNOWLEDGE_BASE_ID` —— 单篇日报总结默认上传的 IMA 知识库 ID - `IMA_DAILY_KNOWLEDGE_BASE_NAME` —— 默认知识库名称(预期值:`daily`) - 上传逻辑在运行时应先校验目标知识库;若配置的目标不存在,应先按名称查找,仍不存在则创建 `daily` 相关能力: - `generate_article_summaries` MCP 工具(基于已有 extracted payload 做单篇总结) - `scripts/run_article_summaries.py` CLI 辅助脚本 ## 校验 LLM 摘要结果 ```bash validate-llm-result outputs/reference/summary/result.json --extracted outputs/reference/extracted/read-flow-2026.extracted.json ``` ## 跑最小 extraction → summary 循环 ```bash python scripts/run_summary_loop.py ^ --extracted outputs/reference/extracted/read-flow-2026.extracted.json ^ --prompt outputs/prompts/llm-summary-prompt.txt ^ --output outputs/reference/summary/result.loop.json ``` ## 拉取 FreshRSS 条目并映射为标准化 `item` ```bash set FRESHRSS_API_BASE_URL=http://127.0.0.1:8081/api/greader.php set FRESHRSS_USERNAME=bot set FRESHRSS_API_PASSWORD=your-api-password python scripts/pull_freshrss_items.py --limit 5 --mark-read ``` 默认会排除已经带 `read` 标签的条目。 如果你想拿到完整阅读列表,可以加 `--include-read`。 启用 `--mark-read` 后,脚本会在执行成功后把本次抓到的条目标记为已读。 脚本会写出: - `outputs/freshrss/raw/freshrss.raw.json` - `outputs/freshrss/items/freshrss.items.json` ## 拉取 FreshRSS 条目并逐条做内容提取 ```bash set FRESHRSS_API_BASE_URL=http://127.0.0.1:8081/api/greader.php set FRESHRSS_USERNAME=osiman set FRESHRSS_API_PASSWORD=your-api-password python scripts/run_freshrss_extract.py --limit 1 --mark-read ``` 默认会排除已经带 `read` 标签的条目。 启用 `--mark-read` 后,只有提取成功的条目才会被标记为已读。 脚本会写出: - `outputs/freshrss/raw/freshrss.raw.json` - `outputs/freshrss/items/freshrss.items.json` - `outputs/freshrss/extracted/freshrss.extracted.json` 注意:这个**批量 extracted 文件**主要用于独立提取场景和旧流程兼容。下游单篇总结的正式生产默认输入,仍然是 `outputs/freshrss/rerun//extracted/item-XX.extracted.json` 这类**逐条 extracted 文件**。 ## 跑完整 FreshRSS 流水线,并在最终 delivery payload 写盘成功后再标记已读 ```bash set FRESHRSS_API_BASE_URL=http://127.0.0.1:8081/api/greader.php set FRESHRSS_USERNAME=osiman set FRESHRSS_API_PASSWORD=your-api-password set LLM_API_URL=https://api.deepseek.com set LLM_API_KEY=your-llm-api-key set LLM_MODEL=deepseek-chat python scripts/run_freshrss_pipeline.py --limit 5 --mark-read ``` 如果你希望过滤时引入个人工程兴趣 / AI Agent 兴趣画像,可以传入 context 文件: ```bash python scripts/run_freshrss_pipeline.py ^ --limit 5 ^ --context configs/filter_context.personal.json ^ --mark-read ``` 这条 CLI 与 MCP `run_freshrss_openclaw_pipeline` 共用同一条主流水线逻辑,但正式生产集成应优先走 MCP;CLI 仅用于本地 debug / fallback。默认会写出这些产物: - `outputs/freshrss/rerun//run-state.json` - `outputs/freshrss/rerun//raw/freshrss.raw.json` - `outputs/freshrss/rerun//candidates/openclaw-delivery-payload.json` - `outputs/freshrss/rerun//candidates/digest-brief.json`(给 OpenClaw 生成 public digest 用的轻量输入,仅包含 `keep` 候选) - `outputs/freshrss/rerun//run-report.json` - `outputs/freshrss/rerun//extracted/item-XX.extracted.json`(每篇一份) 同时还会更新每日关键词索引运行数据: - `data/term_index/daily/YYYY-MM-DD.json` - `data/term_index/term_stats.json` 主流水线默认**不会**产出批量级的 `freshrss.extracted.json`。 如果你需要更多逐条中间产物,例如标准化 items、摘要结果、过滤决策、candidate record、candidate input,可以加 `--debug-artifacts`。 当 OpenClaw 接入这个 MCP 服务后,应以 `run_id` 作为稳定句柄:先调用 `run_freshrss_openclaw_pipeline`,再通过 `get_run_status` / `get_delivery_payload` / `get_run_report` 读取状态与结果,而不是直接拼接目录路径。 在排查复杂问题时,也可以把 `debug_artifacts=true` 打开,并结合 `list_run_artifacts` 查看该 run 下实际产物。 ## 对结构化摘要结果执行确定性过滤规则 ```bash python scripts/run_filter_rules.py ^ --summary outputs/reference/summary/result.loop.json ^ --extracted outputs/reference/extracted/read-flow-2026.extracted.json ^ --output outputs/reference/filter/filter-decision.json ``` 如果你希望注入兴趣主题或来源标签,也可以额外传入 context 文件: ```bash python scripts/run_filter_rules.py ^ --summary outputs/reference/summary/result.loop.json ^ --extracted outputs/reference/extracted/read-flow-2026.extracted.json ^ --context outputs/reference/filter/filter-context.json ^ --output outputs/reference/filter/filter-decision.with-context.json ``` 规则引擎设计和规则编写说明见: - `docs/design/filter-rule-engine-design.md` - `docs/design/filter-rule-engine-usage.md` ## 将过滤结果写入 Markdown sink ```bash python scripts/run_markdown_sink.py ^ --summary outputs/reference/summary/result.loop.json ^ --extracted outputs/reference/extracted/read-flow-2026.extracted.json ^ --filter outputs/reference/filter/filter-decision.json ``` 脚本会把 Markdown 笔记写到 `knowledge-base/` 下。 ## 构建内部 `ArticleCandidateRecord` 与精简版 `OpenClawCandidateInput` ```bash python scripts/run_article_candidate.py ^ --summary outputs/reference/summary/result.loop.json ^ --extracted outputs/reference/extracted/read-flow-2026.extracted.json ^ --filter outputs/reference/filter/filter-decision.json ^ --section-hint tools_and_workflows ``` 默认会写出: - `outputs/reference/candidates/article-candidate-record.json` - `outputs/reference/candidates/openclaw-candidate-input.json` ## 构建批量 OpenClaw delivery payload ```bash python scripts/build_openclaw_delivery.py ^ --input-dir outputs/freshrss/candidates/batch ^ --sort-by-rank ^ --date 2026-03-25 ``` 默认会写出: - `outputs/reference/candidates/openclaw-delivery-payload.json` 输出目录布局说明见 `outputs/README.md`。 ## 关键词索引默认配置 相关配置文件位于: - `configs/term_aliases.json` - `configs/term_stopwords.json` - `configs/term_cleanup_policy.json` - `configs/term_watchlist.json` - `configs/term_change_log.json` 你也可以基于已有 delivery payload 重新构建关键词索引: ```bash python scripts/build_keyword_index.py ^ --input outputs/reference/candidates/openclaw-delivery-payload.json ``` 运行期关键词数据存放在: - `data/term_index/` 关键词清理评审 skill 位于: - `skills/keyword-cleanup-review/` 构建给 LLM skill 使用的评审数据包(review bundle): ```bash python skills/keyword-cleanup-review/scripts/build_review_bundle.py ^ --days 7 ^ --top 50 ^ --output outputs/term_index/review/keyword-cleanup-bundle.json ``` 现在这个评审数据包(review bundle)还会额外携带治理上下文: - 来自 `configs/term_cleanup_policy.json` 的清理阈值 - 当前 watch list(`configs/term_watchlist.json`) - 最近已应用的变更(`configs/term_change_log.json`) 这个 skill 只负责生成 review 输入与建议,不会自动修改: - `term_aliases` - `term_stopwords` - `filter_context.personal.json` 如果你想先预览已接受建议,再决定是否写配置文件: ```bash python scripts/apply_term_suggestions.py ^ --suggestions outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json ^ --accept-watch Cron Heartbeat Memory ^ --dry-run ``` 去掉 `--dry-run` 后才会真正写文件。 这个脚本也支持通过 `--accept-alias`、`--accept-stopword`、`--accept-interest` 应用 alias / stopword / interest keyword 变更。 已接受的 watch 词会写入 `configs/term_watchlist.json`,每次应用动作也会被追加到 `configs/term_change_log.json`。 ## 单篇总结 LLM 配置 如果你希望单篇总结后处理使用独立模型,而不影响主流水线,可以设置: - `ARTICLE_SUMMARY_LLM_API_URL` - `ARTICLE_SUMMARY_LLM_MODEL` - `ARTICLE_SUMMARY_LLM_API_KEY` 如果这些变量未设置,单篇总结会回退使用主流程中的 `LLM_*` / `OPENAI_*` 配置。 示例(PowerShell 风格): ```bash set ARTICLE_SUMMARY_LLM_API_URL=https://api.deepseek.com set ARTICLE_SUMMARY_LLM_API_KEY=your-article-summary-key set ARTICLE_SUMMARY_LLM_MODEL=deepseek-chat ``` 然后可以这样调用 CLI。 正式生产环境建议优先使用 `outputs/freshrss/rerun//extracted/` 下的**逐条 extracted 文件**;下面这个**批量 extracted** 示例仅保留为兼容旧流程 / 临时场景输入: ```bash python scripts/run_article_summaries.py ^ --extracted outputs/freshrss/extracted/freshrss.extracted.json ^ --ids 12345 67890 ^ --output-dir outputs/freshrss/single_summaries ``` 也可以通过 `summary_mcp.server` 暴露的 MCP 工具 `generate_article_summaries` 调用: - `extracted_path`(string):单篇 extracted JSON 路径(例如 `outputs/freshrss/rerun//extracted/item-01.extracted.json`),或者包含 `results` 数组的 batch extracted JSON - `selected_ids`(array of strings):要总结的一个或多个 `item_id`。如果传空数组,则对文件中的全部条目做总结 - `output_dir`(optional string):Markdown 输出目录;若不传,则默认写到 extracted 文件旁边的 `single_summaries/` 目录 - `llm_api_key` / `llm_model` / `llm_api_url`(optional strings):单篇总结 LLM 的覆盖配置;不传时会按前文规则回退到 `ARTICLE_SUMMARY_*` 或主 `LLM_*` 该工具返回一个 JSON 数组,内容为生成好的 Markdown 文件路径。 单篇总结使用独立 prompt:`outputs/prompts/article-summary-prompt.txt`。 它与日报 prompt 完全独立,输出的是中文结构化知识笔记,包含这些部分: - 核心结论 - 主要论点 - 关键方法 / 机制 - 重要细节 - 可复用启发 - 关键词 - 主题