17 KiB
Reader MCP Workflow Service
reader 当前已经收口为面向 OpenClaw 的 MCP workflow service。正式能力边界以 FreshRSS 日报工作流为准:启动 run、写入 run-state.json、查询运行状态、读取结构化结果,以及最小可用的 resume_run。CLI 仍保留,但定位为 debug / fallback,而不是正式集成入口。
运行
pip install -e .
summary-mcp
服务当前暴露 17 个工具。
正式 workflow service 相关工具:
start_freshrss_pipeline_jobget_freshrss_pipeline_job_statusget_freshrss_pipeline_job_resultget_run_statuslist_runslist_run_artifactsget_delivery_payloadget_run_reportresume_run
单步处理 / 调试相关工具:
run_freshrss_openclaw_pipeline(同步 debug / fallback)extract_url_contentextract_item_contentfilter_summary_resultgenerate_article_summaries(同步模式)start_article_summary_jobget_article_summary_job_statusget_article_summary_job_result
正式能力边界
- 当前正式 workflow 只有
freshrss_daily_digest - 每次 FreshRSS 主流水线 run 都会在
outputs/freshrss/rerun/<run_dir>/run-state.json落地运行真相 - FreshRSS 主日报的正式生产启动路径已切到最小异步 job:
start_freshrss_pipeline_job->get_freshrss_pipeline_job_status->get_freshrss_pipeline_job_result - OpenClaw 正式读取结果应优先使用
get_delivery_payload与get_run_report,而不是自己拼输出目录路径 digest-brief.json当前会随主流水线产出,但还没有独立的 MCP 读取工具;如需定位它,应通过list_run_artifacts或get_run_report返回的信息发现run_freshrss_openclaw_pipeline仍保留,但定位已降级为同步 debug / fallback 路径,不再是 OpenClaw 的默认生产启动入口- 单篇总结已补上最小异步 job 形态:
start_article_summary_job/get_article_summary_job_status/get_article_summary_job_result generate_article_summaries仍保留,但定位是同步 debug 路径,而不是 OpenClaw 的正式生产集成入口
OpenClaw 推荐调用路径
- 调用
start_freshrss_pipeline_job启动正式日报 job,并保存返回的job_id - 轮询
get_freshrss_pipeline_job_status(job_id),直到status变成success或failed - 成功后调用
get_freshrss_pipeline_job_result(job_id)读取run_id与关键产物路径 - 后续所有 run 级状态判断都基于
get_run_status(run_id)或list_runs(...) - 需要看产物列表时用
list_run_artifacts(run_id),不要在 OpenClaw 里硬编码outputs/freshrss/rerun/... - 需要消费正式结果时优先用
get_delivery_payload(run_id)与get_run_report(run_id) - 仅当
resume_run的最小恢复范围满足时,才对失败 run 调用resume_run(run_id);否则应重启一个新 run
主日报 async job 的自身状态目录固定在 outputs/freshrss/pipeline_jobs/<job_id>/,最少包含 run-state.json、input.json、result.json(成功时)和 job-report.json。
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/<run_id>/extracted/item-XX.extracted.json
- 这些逐条 extracted 文件是下游单篇总结的正式默认产物。
- 像
outputs/freshrss/extracted/freshrss.extracted.json这样的批量 extracted 文件,只作为临时场景、兼容旧流程的输入形态保留,不是首选生产默认。
daily 知识库默认配置
IMA_DAILY_KNOWLEDGE_BASE_ID—— 单篇日报总结默认上传的 IMA 知识库 IDIMA_DAILY_KNOWLEDGE_BASE_NAME—— 默认知识库名称(预期值:daily)- 上传逻辑在运行时应先校验目标知识库;若配置的目标不存在,应先按名称查找,仍不存在则创建
daily
相关能力:
start_article_summary_job/get_article_summary_job_status/get_article_summary_job_result(正式推荐的最小异步 job 路径)generate_article_summariesMCP 工具(同步 debug 路径)scripts/run_article_summaries.pyCLI 辅助脚本scripts/run_article_summary_job.py后台 runner 入口
校验 LLM 摘要结果
validate-llm-result outputs/reference/summary/result.json --extracted outputs/reference/extracted/read-flow-2026.extracted.json
跑最小 extraction → summary 循环
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
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.jsonoutputs/freshrss/items/freshrss.items.json
拉取 FreshRSS 条目并逐条做内容提取
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.jsonoutputs/freshrss/items/freshrss.items.jsonoutputs/freshrss/extracted/freshrss.extracted.json
注意:这个批量 extracted 文件主要用于独立提取场景和旧流程兼容。下游单篇总结的正式生产默认输入,仍然是 outputs/freshrss/rerun/<run_id>/extracted/item-XX.extracted.json 这类逐条 extracted 文件。
跑完整 FreshRSS 流水线,并在最终 delivery payload 写盘成功后再标记已读
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 文件:
python scripts/run_freshrss_pipeline.py ^
--limit 5 ^
--context configs/filter_context.personal.json ^
--mark-read
这条 CLI 与 MCP run_freshrss_openclaw_pipeline / start_freshrss_pipeline_job 共用同一条主流水线逻辑,但正式生产集成应优先走 async MCP job;CLI 与同步 MCP 入口仅用于本地 debug / fallback。默认会写出这些产物:
outputs/freshrss/rerun/<run_dir>/run-state.jsonoutputs/freshrss/rerun/<run_dir>/raw/freshrss.raw.jsonoutputs/freshrss/rerun/<run_dir>/candidates/openclaw-delivery-payload.jsonoutputs/freshrss/rerun/<run_dir>/candidates/digest-brief.json(给 OpenClaw 生成 public digest 用的轻量输入,仅包含keep候选)outputs/freshrss/rerun/<run_dir>/run-report.jsonoutputs/freshrss/rerun/<run_dir>/extracted/item-XX.extracted.json(每篇一份)
同时还会更新每日关键词索引运行数据:
data/term_index/daily/YYYY-MM-DD.jsondata/term_index/term_stats.json
主流水线默认不会产出批量级的 freshrss.extracted.json。
如果你需要更多逐条中间产物,例如标准化 items、摘要结果、过滤决策、candidate record、candidate input,可以加 --debug-artifacts。
当 OpenClaw 接入这个 MCP 服务后,应先通过 start_freshrss_pipeline_job 启动任务,轮询 get_freshrss_pipeline_job_status,再从 get_freshrss_pipeline_job_result 读取稳定的 run_id。拿到 run_id 之后,再通过 get_run_status / get_delivery_payload / get_run_report 读取状态与结果,而不是直接拼接目录路径。run_freshrss_openclaw_pipeline 仅保留为同步 debug / fallback 路径。
在排查复杂问题时,也可以把 debug_artifacts=true 打开,并结合 list_run_artifacts 查看该 run 下实际产物。
对结构化摘要结果执行确定性过滤规则
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 文件:
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.mddocs/design/filter-rule-engine-usage.md
将过滤结果写入 Markdown sink
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
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.jsonoutputs/reference/candidates/openclaw-candidate-input.json
构建批量 OpenClaw delivery payload
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.jsonconfigs/term_stopwords.jsonconfigs/term_cleanup_policy.jsonconfigs/term_watchlist.jsonconfigs/term_change_log.json
你也可以基于已有 delivery payload 重新构建关键词索引:
python scripts/build_keyword_index.py ^
--input outputs/reference/candidates/openclaw-delivery-payload.json
运行期关键词数据存放在:
data/term_index/
关键词清理评审 skill 位于:
skills/keyword-cleanup-review/
构建给关键词治理流程使用的评审数据包(review bundle,临时工作文件):
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)
接下来可以把 bundle 渲染成正式建议产物(默认走确定性规则,不把 LLM 作为默认路径):
python scripts/generate_term_cleanup_suggestions.py ^
--bundle outputs/term_index/review/keyword-cleanup-bundle.json
默认只生成:
outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json(唯一正式建议产物,建议短期保留)
如需人工审阅展示稿,再显式加:
python scripts/generate_term_cleanup_suggestions.py ^
--bundle outputs/term_index/review/keyword-cleanup-bundle.json ^
--emit-markdown
这时才会额外生成:
outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md(临时展示稿,可按需生成,不必作为长期资产保留)
其中本轮最小版本优先覆盖 interest_keyword_suggestions 和 watch_terms 主链路;alias_suggestions / stopword_suggestions 先保持保守。
产物保留策略建议:
data/term_index/daily/YYYY-MM-DD.json、data/term_index/term_stats.json作为事实层长期保留configs/filter_context.personal.json、configs/term_watchlist.json、configs/term_aliases.json、configs/term_stopwords.json、configs/term_change_log.json作为状态层长期保留term-cleanup-suggestions-YYYY-MM-DD.json作为正式建议产物短期保留(最近少量几份或仅保留已应用过的)keyword-cleanup-bundle.json仅作为临时工作文件,默认只保留当前最新一份term-cleanup-suggestions-YYYY-MM-DD.md仅作为临时展示稿,优先按需生成,不建议默认长期归档
如果你想先预览已接受建议,再决定是否写配置文件:
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_URLARTICLE_SUMMARY_LLM_MODELARTICLE_SUMMARY_LLM_API_KEY
如果这些变量未设置,单篇总结会回退使用主流程中的 LLM_* / OPENAI_* 配置。
如果显式指定 DeepSeek 作为单篇总结模型且请求超时或失败,当前实现会自动再用主流程默认模型配置重试一次。
示例(PowerShell 风格):
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/<run_id>/extracted/ 下的逐条 extracted 文件;下面这个批量 extracted 示例仅保留为兼容旧流程 / 临时场景输入:
python scripts/run_article_summaries.py ^
--extracted outputs/freshrss/extracted/freshrss.extracted.json ^
--ids 12345 67890 ^
--output-dir outputs/freshrss/single_summaries ^
--timeout 120
也可以通过 summary_mcp.server 暴露的 MCP 工具 generate_article_summaries 调用:
extracted_path(string):单篇 extracted JSON 路径(例如outputs/freshrss/rerun/<run_id>/extracted/item-01.extracted.json),或者包含results数组的 batch extracted JSONselected_ids(array of strings):必填,至少传一个item_id;如果传入的 ID 在 extracted payload 中一个都匹配不到,会直接报错output_dir(optional string):Markdown 输出目录;若不传,则默认写到 extracted 文件旁边的single_summaries/目录llm_api_key/llm_model/llm_api_url(optional strings):单篇总结 LLM 的覆盖配置;不传时会按前文规则回退到ARTICLE_SUMMARY_*或主LLM_*
该工具返回一个 JSON 数组,内容为生成好的 Markdown 文件路径。
OpenClaw / 正式集成建议优先走异步 job:
- 调
start_article_summary_job启动任务,立即拿到job_id - 轮询
get_article_summary_job_status(job_id),直到status进入success或failed - 成功后调用
get_article_summary_job_result(job_id)读取written_paths与结构化结果 - 失败时优先查看
error_summary与 job 目录中的job-report.json
异步 job 状态目录固定落在 outputs/freshrss/article_summary_jobs/<job_id>/,最小会包含:
run-state.jsoninput.jsonresult.json(成功时)job-report.json
单篇总结使用独立 prompt:outputs/prompts/article-summary-prompt.txt。
它与日报 prompt 完全独立,输出的是中文结构化知识笔记,包含这些部分:
- 核心结论
- 主要论点
- 关键方法 / 机制
- 重要细节
- 可复用启发
- 关键词
- 主题