Skip to main content
Glama
README.md
# 📝 csdn-blog-mcp — CSDN 博文自动写作与发布 MCP

**语言 / Languages:** **简体中文** | [English](./README.en.md)

一个 MCP(Model Context Protocol)服务器,让 AI Agent(Cursor、Claude 等)成为 CSDN 博客的**写作 + 发布助手**——生成 SEO 优化的博文骨架、打包保存草稿、SEO 自检、再通过浏览器自动化一键推送到 CSDN 草稿箱。它还能从你已发布的博文里提炼写作风格,让 AI 按你的语气写。

基于 [FastMCP](https://github.com/jlowin/fastmcp) 构建,发布走 Playwright 浏览器自动化路线,跨平台支持 Windows / macOS / Linux。

> ⭐ **如果这个项目帮到你,欢迎去仓库点个 Star 支持一下~**
> 👉 https://gitee.com/gdouage/csdn-mcp
> 你的一颗星,是个人开发者继续更新的最大动力 ❤️

| | |
|---|---|
| 仓库 | [gitee.com/gdouage/csdn-mcp](https://gitee.com/gdouage/csdn-mcp) |
| 协议 | [MIT](./LICENSE) |
| 作者 | abbuibuibui |
| 联系 | [3244940576@qq.com](mailto:3244940576@qq.com) |

> ⚠️ **重要风险提示**
> CSDN 没有公开的博文发布 API,本工具通过浏览器自动化模拟人工操作发布。
> - CSDN 用户协议禁止「使用未经授权的自动化程序发布内容」,请知悉风险。
> - 内置频率限制(默认每天 2 篇、间隔 ≥ 30 分钟)以降低封号风险。
> - 登录/发布可能触发验证码,需人工介入。
> - CSDN 编辑器改版会导致选择器失效,失败时会自动截图存证。

---

## 📌 项目介绍

| 能力 | 说明 |
|------|------|
| 写博文 | 生成 SEO 优化的 markdown 骨架(6 种风格预设),打包正文 + front-matter 保存为草稿 |
| 风格对齐 | 从你已发布的博文提炼写作风格,AI 按你的语气写(不套个人化称呼) |
| SEO 自检 | 标题长度/关键词前置、摘要、关键词密度、H2/H3 层级、代码块语言、图片 alt、标签数,0-100 评分 |
| 草稿管理 | 列出 / 读取 / 删除本地草稿,统一存放在 drafts/ |
| 发布 CSDN | Playwright 自动化打开编辑器、填标题、粘正文、选标签/分类/可见性、点发布、读回文章 URL |
| 登录管理 | 首次可见浏览器登录保存 session,之后 headless 发布;可检查/清除登录态 |
| 文章统计 | 通过 CSDN 公开接口读取阅读/点赞/评论/收藏数(无需登录) |
| 频率限制 | 内置每天发文上限 + 最小间隔,可查询当前状态 |

**核心流程:**

```text
get_style_guide → generate_blog_scaffold → 填充正文 → write_blog → seo_check → csdn_login(首次) → publish_csdn → csdn_stats
```

---

## 🏗️ 项目架构

```text
┌──────────────────────────────────────────────┐
│              AI Agent (Cursor / Claude)        │
│                  通过 MCP 协议调用               │
└──────────────────────┬───────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────┐
│            csdn-blog-mcp Server               │
│              (FastMCP, 14 个工具)              │
├──────────┬──────────┬──────────┬──────────────┤
│  写博文   │  草稿库   │  发布登录  │   统计/限流    │
│ (4 tools)│ (3 tools)│ (5 tools)│  (2 tools)  │
├──────────┴──────────┴──────────┴──────────────┤
│                  底层能力                       │
│  Markdown 解析 │ YAML front-matter │ Playwright │
└──────────────────────────────────────────────┘
                       │
                       ▼
┌──────────────────────────────────────────────┐
│         CSDN 网页编辑器 / 公开统计 API           │
└──────────────────────────────────────────────┘
```

**目录结构:**

```text
csdn-blog-mcp/
├── src/csdn_blog_mcp/
│   ├── server.py          # MCP 服务入口 + 工具注册
│   ├── writer.py          # 写博文:generate_blog_scaffold / write_blog
│   ├── seo.py             # SEO 自检:seo_check
│   ├── library.py         # 草稿库:list / read / delete
│   ├── auth.py            # 登录态:check_login / login / clear_session
│   ├── publisher.py       # 发布:publish_csdn(Playwright 方案 A)
│   ├── stats.py           # 统计:csdn_stats(公开 API)
│   ├── style.py           # 风格指南加载:get_style_guide
│   ├── util.py            # run_in_thread:让浏览器工具绕开 MCP 的 asyncio 循环
│   └── config.py          # 路径 / cookie 存储 / 频率限制
├── STYLE_GUIDE.md         # 从作者博文提炼的写作风格提示词(MCP 自用)
├── drafts/                # 本地草稿存放处(git 忽略)
├── pyproject.toml
├── .gitignore
├── README.md             # 中文(默认,Gitee 首页展示)
└── README.en.md           # English
```

---

## 🛠️ 技术栈与依赖

| 层级 | 技术 |
|------|------|
| 协议 | MCP (Model Context Protocol) |
| 框架 | FastMCP |
| 语言 | Python 3.12+ |
| 浏览器自动化 | Playwright (Chromium) |
| HTTP 请求 | httpx(统计接口) |
| 构建系统 | setuptools |

---

## 🚀 快速开始

### 1. 环境要求

- Python **3.12+**
- 支持 MCP 的 AI 客户端(Cursor、Claude Desktop 等)
- 发布功能需安装 Playwright 浏览器内核(见下)

### 2. 获取代码

```bash
git clone https://gitee.com/gdouage/csdn-mcp.git
cd csdn-mcp
```

### 3. 安装

```bash
# 创建虚拟环境
python -m venv .venv

# Windows
.venv\Scripts\pip install -e .
.venv\Scripts\playwright install chromium

# macOS / Linux
.venv/bin/pip install -e .
.venv/bin/playwright install chromium
```

> `playwright install chromium` 会把浏览器内核下到本机缓存目录(Windows 是 `%LOCALAPPDATA%\ms-playwright`,macOS/Linux 是 `~/.cache/ms-playwright`),**不在项目里**,跨平台自动适配。

### 4. 配置 MCP 客户端

#### Cursor

添加到 `~/.cursor/mcp.json`(把 `<项目路径>` 换成你本机的实际路径):

```json
{
  "mcpServers": {
    "csdn-blog-mcp": {
      "command": "<项目路径>/.venv/Scripts/python.exe",
      "args": ["-m", "csdn_blog_mcp.server"],
      "env": {
        "PYTHONPATH": "<项目路径>/src"
      }
    }
  }
}
```

> macOS / Linux 把 `Scripts/python.exe` 换成 `bin/python`。
> 可选环境变量 `CSDN_BLOG_HOME`:自定义草稿/cookie 存放目录(默认项目根目录)。

### 5. 首次登录 CSDN 🎬

让 AI 调用 `csdn_login`,会弹出一个浏览器,手动登录 CSDN(首次必须可见,可能遇验证码)。登录成功后 session 自动保存,之后发布就能 headless 跑。重启 Cursor,MCP 服务自动启动。

---

## 📡 14 个工具一览

### 写博文(4 个)

| 工具 | 功能 |
|------|------|
| `get_style_guide` | 返回从作者已发布博文提炼的写作风格提示词(语气、两种文章类型、标题/开头/结构/必备元素/SEO),写文前先调它对齐风格 |
| `generate_blog_scaffold` | 生成 SEO 优化的 markdown 骨架(6 种风格:开源项目介绍/保姆级教程/技术教程/原理分析/踩坑笔记/通用) |
| `write_blog` | 打包正文 + YAML front-matter,保存为本地草稿 |
| `seo_check` | 分析草稿 SEO,返回 0-100 评分 + 改进建议 |

### 草稿库(3 个)

| 工具 | 功能 |
|------|------|
| `list_drafts` | 列出本地草稿(按时间倒序) |
| `read_draft` | 读取草稿内容 + 元数据 |
| `delete_draft` | 删除草稿 |

### 发布与登录(5 个)

| 工具 | 功能 |
|------|------|
| `check_csdn_login` | 用已保存 session 检查是否仍登录 |
| `csdn_login` | 打开可见浏览器手动登录,保存 session |
| `clear_csdn_session` | 清除已保存 session |
| `publish_csdn` | 浏览器自动化把草稿发到 CSDN:**默认存草稿箱**(不公开),`as_draft=False` 时直接发布 |
| `diagnose_editor` | 探测 CSDN 编辑器各关键元素,报告每个选择器是否命中——`publish_csdn` 失败时跑它定位是哪个选择器被改版了 |

### 统计与限流(2 个)

| 工具 | 功能 |
|------|------|
| `csdn_stats` | 读取已发布文章的阅读/点赞/评论/收藏数(公开 API) |
| `rate_limit_status` | 查询当前发文频率限制状态 |

---

## 📝 典型工作流

### 场景 1:从零写一篇并发布

```text
get_style_guide()                  # 先读风格提示词,对齐作者语气/结构
generate_blog_scaffold("Playwright 自动化", ["playwright","python","爬虫"], "tutorial")
  → 拿到骨架,AI 按风格指南填充正文
write_blog(topic="Playwright 自动化完全指南", content=<填充后的正文>, tags=[...])
  → 保存草稿,拿到 file_path
seo_check(file_path)
  → 看评分,按建议修改
csdn_login()                      # 首次登录(会弹浏览器,手动登录)
publish_csdn(file_path)           # 默认存入 CSDN 草稿箱(不公开)
# 审阅满意后,在 CSDN 后台手动点发布;或 publish_csdn(file_path, as_draft=False) 直接发
csdn_stats(article_url)           # 直接发布后看数据
```

### 场景 2:只写不发(零风险)

```text
get_style_guide → generate_blog_scaffold → 填充 → write_blog → seo_check
# 草稿留在 drafts/,手动复制到 CSDN 编辑器发布(5 秒的事)
```

### 场景 3:发布前检查登录与限流

```text
rate_limit_status()       # 今天还能发吗?
check_csdn_login()         # session 还有效吗?
publish_csdn(file_path)   # 都 OK 再发
```

---

## 💡 设计说明

- **写作零风险**:`get_style_guide` / `generate_blog_scaffold` / `write_blog` / `seo_check` 纯本地文本处理,不碰网络
- **风格对齐**:从作者已发布博文提炼写作风格,但**不套个人化称呼**(如"小b"),保持中性语气
- **发布走方案 A**:Playwright 模拟人工操作 CSDN 网页编辑器,不碰内部 API,封号风险最低
- **默认存草稿箱**:`publish_csdn` 默认 `as_draft=True`,只存到 CSDN 在线草稿箱不公开,你审阅后再手动发布
- **session 持久化**:登录态存为 Playwright 标准 storageState JSON,git 忽略,过期提示重登
- **频率限制**:仅对**直接发布**生效(默认每天 2 篇、间隔 ≥ 30 分钟);存草稿箱不限频
- **失败存证**:发布失败自动截图到 `.cookies/screenshots/`,方便排查选择器失效
- **选择器集中**:`publisher.py` 顶部 `SELECTORS` 字典统一管理,关键元素配多组回退选择器,CSDN 改版只需改这里
- **抗 UI 漂移**:固定视口 + 网络层广告拦截 + 弹层自动关闭 + 多选择器回退 + 鲁棒点击重试,缓解分辨率变化/广告/小改版导致的失效
- **自诊断**:`diagnose_editor` 探测编辑器各元素命中情况,`publish_csdn` 失败时跑它定位是哪个选择器被改版了
- **绕开 asyncio 循环**:MCP 服务在 asyncio 事件循环里跑工具函数,而 Playwright 的 sync API 拒绝在运行中的循环里启动;`util.run_in_thread` 装饰器检测到循环时把浏览器工具丢到独立线程执行,无循环时(独立脚本)直接跑,零开销
- **正文用剪贴板粘贴**:往 CSDN 编辑器逐字符 `keyboard.type` 会触发自动缩进/自动列表,把 markdown 弄乱(列表 `-` 变 `- -`、代码块缩进失控);改为写剪贴板后 `Ctrl+V` 一次性粘贴,保留原始 markdown 结构
- **拟人节奏**:每步操作间随机延迟 0.8-2.2 秒,降低风控触发概率

---

## ⚠️ 风险与合规

| 风险 | 说明 | 应对 |
|------|------|------|
| 封号 | CSDN 对批量发文有风控 | 默认每天 2 篇、间隔 30 分钟、内容差异化 |
| 验证码 | 登录/发布可能弹滑块验证码 | 自动化过不了,需人工介入(csdn_login 弹浏览器) |
| ToS | 协议禁止未授权自动化发布 | 方案 A 风险最低;默认只存草稿箱 |
| UI 漂移 | CSDN 编辑器改版 | 多选择器回退 + 失败截图存证 + `diagnose_editor` 自诊断 |

**最务实路径**:先只用「写博文」部分(零风险),发布那一下保留人工点击。稳定运行后再开自动发布。

---

## 💬 反馈与贡献

如果这个项目对你有帮助,拜托:

1. ⭐ 去仓库点个 **Star**:[csdn-mcp](https://gitee.com/gdouage/csdn-mcp)
2. 🐛 遇到问题提 [Issue](https://gitee.com/gdouage/csdn-mcp/issues)
3. ✉️ 想交流可发邮件:[3244940576@qq.com](mailto:3244940576@qq.com)(作者:abbuibuibui)

也欢迎提交 Pull Request(请先说明改动目的与测试方式)~

---

## 📄 许可证

本项目基于 [MIT License](./LICENSE) 开源。

```text
Copyright (c) 2026 abbuibuibui
```

Maintenance

ActivityStale
ResponsivenessNo issues