用 MCP 自动发 CSDN:从草稿到定时发布的完整工作流
如果你已经用 Cursor 写过几篇技术文,大概率踩过同一套坑:Agent 生成 Markdown 很顺,复制到 CSDN 编辑器、填标签、等定时点发布 仍然靠人手。
本仓库把这条链路拆成两条可验证路径:
单篇对话直发(MCP) + 本地队列定时发(schedule.yaml + tick)。
下面按「怎么跑通 → 怎么控节奏 → 哪里会翻车」讲完整工作流。不写未验证的内部接口细节,只讲本仓库已跑通的工程概念。
你将学到
- 本地 Markdown 如何进入 content-hub / MCP 发布链路
schedule.yaml、tick、publish_slots如何配合定时发- Cookie 过期时怎么刷新、怎么避免泄露
- 节奏看板(dashboard)该盯哪些指标
- 更新旧文、Markdown 转 HTML、SVG 等常见踩坑
一、先结论:两条路径,别混用场景
| 场景 | 推荐路径 | 入口 |
|---|---|---|
| 写完立刻发、对话里交付 | MCP 单篇 | publish_csdn_article |
| 系列文错峰、日更 5 篇 | 本地队列 | schedule.yaml + content-hub tick |
| 先草稿、人工再审 | MCP 草稿 | save_csdn_draft |
| 批量排期、要日历视图 | 队列 + 看板 | content-hub dashboard |
一句话:MCP 解决「这一篇现在发」;schedule + tick 解决「这一批按节奏发」。
二、整体链路:Markdown 是唯一源
无论哪条路径,正文源都是仓库里的 Markdown 文件(常见放在 articles/drafts/)。
articles/drafts/xxx.md ← 人工或 Agent 写稿
↓
┌─────┴─────┐
│ │
MCP 直发 schedule 队列
│ │
↓ ↓
转 HTML tick 到点读取
│ │
↓ ↓
CSDN 后台 写回 schedule.yaml(published / failed)
│ │
└─────┬─────┘
↓
SQLite 发布日志 → dashboard / get_publish_dashboard
工程上坚持 「Markdown 单源」:不要在 CSDN 编辑器里改定稿,否则本地稿与线上稿会分叉。
三、路径 A:MCP 单篇直发
在 Cursor 注册 MCP Server 后,Agent 可直接调用本仓库工具:
| 工具 | 用途 |
|---|---|
check_csdn_config |
启动前检查 Cookie 是否配置 |
set_csdn_cookie |
把浏览器复制的 Cookie 写入本地配置 |
publish_csdn_article |
读取 Markdown 参数,正式发布 |
save_csdn_draft |
先存草稿,适合不确定内容 |
典型对话流:
用户:把 drafts/llm-04-mcp.md 发到 CSDN,标签用大模型,AI,MCP
→ check_csdn_config
→ publish_csdn_article(title, markdown, tags)
→ 返回 ok / url / error
配置放在 ~/.config/csdn-publish-mcp/config.json(或环境变量 CSDN_COOKIE),不要提交进 git。
发布前建议人工或脚本跑一遍结构校验(本仓库有 validate_article.py:行数、踩坑清单、禁 SVG 等),避免把不合格稿推上线。
四、路径 B:schedule.yaml + tick 定时队列
系列连载、日更多篇时,用手改 schedule.yaml 比每次对话更稳。
4.1 队列条目长什么样
每条 pending 稿件至少要有:
- id: llm-04-mcp
title: "MCP 协议实战:为什么 2026 年 Agent 都在接 MCP"
file: drafts/llm-04-mcp.md
tags: "大模型,AI,MCP,Agent,Cursor"
series: "大模型实战"
scheduled_at: "2026-08-07 09:00"
status: pending
tick 只会处理 status: pending 且 scheduled_at 已到期的条目;成功后写回 published、csdn_id、url。
4.2 tick 什么时候真正发
content-hub tick 不是「cron 到了就发」,还要同时满足:
| 条件 | 说明 |
|---|---|
落在 publish_slots 时间窗 |
默认 09:00 / 11:30 / 14:30 / 17:00 / 21:00 |
容差 slot_grace_minutes |
默认 ±20 分钟,避免 LaunchAgent 漂移漏发 |
未超 max_per_day |
默认日上限 5 篇 |
未超 max_per_run |
每次 tick 最多 1 篇 |
auto_publish_enabled 为 true |
可在 config 里一键关停 |
常用命令:
uv run content-hub schedule # 预览队列、当前是否在时间窗
uv run content-hub tick --dry-run # 预览将发哪篇(仍受时间窗限制)
uv run content-hub tick --force --dry-run # 忽略时间窗,只看到期逻辑
uv run content-hub tick # 到点真发
macOS 可用 bash scripts/install-launchd.sh 装 LaunchAgent,每 5 分钟 执行一次 tick。日志在 ~/.config/csdn-publish-mcp/logs/tick.*.log。
4.3 和思源 worker 的关系
本仓库还支持思源驱动的 run_auto_publish_worker(读思源 custom-status=ready/scheduled)。
本地纯 Markdown 系列 用 schedule.yaml 即可,不依赖思源;两条链路最终都走同一套 CSDN 发布客户端。
五、publish_slots:节奏比「能发」更重要
日更 5 篇如果集中在 10 分钟内,推荐流和读者体验都会差。本仓库默认 五拍错峰:
| 时刻 | 典型用途 |
|---|---|
| 09:00 | 通勤阅读高峰 |
| 11:30 | 上午摸鱼档 |
| 14:30 | 午后 |
| 17:00 | 下班前 |
| 21:00 | 晚间深度阅读 |
在 config.json → hub.strategy 调整:
{
"publish_slots": ["09:00", "11:30", "14:30", "17:00", "21:00"],
"slot_grace_minutes": 20,
"max_per_day": 5,
"max_per_run": 1,
"min_interval_seconds": 60
}
两个实操建议:
- 同系列错开 slot:大模型实战与 AI 前端实战不要抢同一时刻
- 排期写进 yaml,策略写进 config:改节奏只动 config,改篇目只动 schedule
六、节奏看板:看得见才控得住
跑 uv run content-hub dashboard(默认 http://127.0.0.1:8766),或用 MCP get_publish_dashboard 拉 JSON。
看板核心不是花哨图表,而是回答四个问题:
| 视图 | 你要确认的事 |
|---|---|
| 今日五拍 slot_board | 哪个窗 live / done / failed |
| 近 8 天日历 | pending 是否堆在某一天 |
| due_now | 此刻到期但还没发的篇目 |
| SQLite 发布日志 | 失败原因、今日已成功几篇 |
API:/api/rhythm 看排期与时间窗,/api/stats 看历史;tick 发了但页面没更新 → 查日志与 schedule status。
七、Cookie 刷新:失败的第一嫌疑人
CSDN 没有稳定的公开写稿 API,本仓库走的是编辑器后台通道,Cookie 会过期。
| 现象 | 处理 |
|---|---|
| 401 / 登录失效 | 浏览器重新登录,复制完整 Cookie |
| 对话里临时更新 | set_csdn_cookie 写入本地 config |
| 定时 tick 半夜失败 | 看 tick.err.log;修复 Cookie 后把 failed 改回 pending |
| 安全 | Cookie 等同账号密码,勿进仓库、勿让模型在对话里明文回显 |
刷新后先用 check_csdn_config 或 save_csdn_draft 测一篇,再开 tick 全自动。
八、发布客户端:概念层必知三点
以下为本仓库 client.py 已验证行为,不是官方 API 文档:
8.1 Markdown 必须转 HTML
CSDN 页面渲染读的是 content(HTML)。若把 Markdown 原样塞进 content,页面上会出现 #、** 等符号。
正确分工:markdowncontent 存原文,content / htmlcontent 存渲染结果。正文若重复一级标题,发布前会去掉,避免双标题。
8.2 更新旧文必须 id + art_id
传 art_id 表示更新已有文章时,payload 里还要带 id(同 art_id)。只带 art_id 会误建新稿。
客户端若发现返回的新 ID 与请求不一致,会拒绝视为成功,避免静默重复发文。
8.3 凭证与签名
除 Cookie 外还需配套签名头(算法见仓库实现);接口可能变更,失败信息要能回灌 Agent 或日志。
踩坑清单
- Markdown 当 HTML 发 → 页面符号乱飞;务必走
markdown_to_html - 更新只传 art_id → 静默新建重复文章;必须 id + art_id 成对
- 正文内嵌 SVG / Mermaid → CSDN 编辑器易挂、移动端更惨;改表格或外链图
- tick 不在 publish_slots → 以为 cron 坏了,其实是时间窗未开;用
--force --dry-run排查 - schedule 与线上稿不同步 → 只在 CSDN 改文、本地 yaml 仍 pending;坚持 Markdown 单源
- Cookie 过期无告警 → tick 连 failed;看板 + 日志要盯 failed 状态
- 一天排 10 篇 pending →
max_per_day=5只会发 5 篇,其余顺延;排期要配合策略 - stdio MCP 里 print 调试 → 破坏 JSON-RPC;日志写文件或 stderr 规范输出
成本与风险提示
| 项 | 说明 |
|---|---|
| 平台依赖 | 非公开接口,需预留「人工兜底发布」 |
| 账号安全 | Cookie 泄露等于账号泄露;本地加密与权限自行评估 |
| 运维 | LaunchAgent + 5 分钟 tick 有进程开销,但远低于手工发布 |
| 合规 | 全自动发前先草稿审阅;敏感题材 human-in-loop |
相关阅读
| 文章 | 主题 |
|---|---|
| MCP 协议实战 | Host / Client / Server 与工具分工 |
| MCP 接本地工具 | FastMCP 从零接入 Cursor |
| 仓库 README | content-hub 命令与 config 字段说明 |
小结
把 CSDN 发布自动化,拆成四块就够用:
- Markdown 单源 — 稿在
articles/drafts/,校验后再进队列 - MCP 直发 — 对话里
publish_csdn_article解决「现在这篇」 - schedule + tick + publish_slots — 解决「这一系列按节奏发」
- 看板 + 日志 — 盯 failed、盯日上限、盯 Cookie
先跑通单篇 MCP,再加 schedule 与 LaunchAgent;不要一上来就全自动五连发——先 dry-run,再真 tick。
更多推荐



所有评论(0)