Skip to main content
Glama
README.md
# csdn-mcp

让 AI Agent 通过 MCP 协议管理 CSDN 博客:发布、查询、修改、删除、上传图片。

[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Leaderxin/csdn-mcp/blob/main/LICENSE)
[![Node.js](https://img.shields.io/badge/node-%3E%3D18.17-brightgreen.svg)](https://nodejs.org/)
[![CI](https://github.com/Leaderxin/csdn-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Leaderxin/csdn-mcp/actions/workflows/ci.yml)
[![MCP](https://img.shields.io/badge/MCP-Compatible-blue.svg)](https://modelcontextprotocol.io/)

## 30 秒快速开始

```bash
git clone https://github.com/Leaderxin/csdn-mcp.git
cd csdn-mcp
npm install
npm run build
```

然后把下面这段加进 MCP 客户端配置(`args` 必须是 `dist/index.js` 的**绝对路径**):

```json
{
  "mcpServers": {
    "csdn": {
      "command": "node",
      "args": ["/absolute/path/to/csdn-mcp/dist/index.js"],
      "env": {
        "CSDN_COOKIE": "把整段 Cookie 粘到这里",
        "CSDN_LOG_LEVEL": "warn"
      }
    }
  }
}
```

`CSDN_COOKIE` 是唯一必填项,没有它任何写操作都会返回 `AUTH_MISSING`。获取方式见 [docs/CONFIGURATION.md](docs/CONFIGURATION.md#cookie-怎么取)。

## 工具一览

11 个工具,全部走 stdio。参数、返回结构、错误码的完整定义见 [docs/TOOLS.md](docs/TOOLS.md)。

| 工具              | 说明                                                                 |
| ----------------- | -------------------------------------------------------------------- |
| `auth_login`      | 运行期设置 Cookie,随后所有请求立即生效,无需重启进程                |
| `auth_status`     | 检查当前 Cookie 是否已配置、格式是否合法、账号名是什么               |
| `publish_article` | 新建文章;`mode` 默认 `draft`,发布必须显式传 `mode: "publish"`      |
| `update_article`  | 更新已有文章;改标题/标签/摘要/封面 + 草稿副本                       |
| `get_article`     | 按 ID 读取单篇文章,可选是否带正文                                   |
| `list_articles`   | 列出文章;`scope=published` 只看已发布,`scope=all` 含草稿与分类计数 |
| `delete_article`  | 删除文章,默认进回收站,`permanent: true` 彻底删除                   |
| `upload_image`    | 上传本地图片,返回公网 URL,分 `cover` / `body` 两条通道             |
| `list_categories` | 列出文章分类;接口不可用时回退到内置列表                             |
| `list_tags`       | 列出常用标签;接口不可用时回退到内置列表                             |
| `verify_article`  | 回查 API 状态 + 公开页 HTTP 码,确认文章真实状态                     |

## 一次真实的 Agent 调用流程

```
用户:把这篇《MCP 协议入门》给我发成草稿,先别公开。

Agent → publish_article({
          "title": "MCP 协议入门",
          "markdown": "# MCP 协议入门\n\n...",
          "tags": ["MCP", "TypeScript"],
          "categories": "后端"
        })
← { "articleId": "149234567",
    "url": "https://blog.csdn.net/Leaderxin/article/details/149234567",
    "state": "draft",
    "verification": { "articleId": "149234567", "state": "draft", "statusCode": 2,
                      "publicStatusCode": 404, "consistent": true,
                      "message": "草稿已确认:接口 status=2,公开页 404" } }

Agent → verify_article({ "article_id": "149234567", "expected": "draft" })
← { "articleId": "149234567", "state": "draft", "statusCode": 2,
    "publicStatusCode": 404, "consistent": true, "message": "..." }

用户:内容我看过了,发布吧。

Agent → update_article({ "article_id": "149234567", "mode": "publish" })
← { "articleId": "149234567",
    "url": "https://blog.csdn.net/Leaderxin/article/details/149234567",
    "state": "published" }

Agent → verify_article({ "article_id": "149234567", "expected": "publish" })
← { "articleId": "149234567", "state": "published", "statusCode": 1,
    "publicStatusCode": 200, "consistent": true, "message": "..." }
```

注意 `publish_article` 在步骤 1 里**没有**传 `mode` —— 默认就是草稿。只有用户在步骤 3 明确要求之后,Agent 才发出版本。原因见 [docs/TOOLS.md](docs/TOOLS.md#publish_article)。

## 配置项

完整说明(含"什么时候需要改")见 [docs/CONFIGURATION.md](docs/CONFIGURATION.md)。

| 变量                    | 默认值                             | 作用                                                          |
| ----------------------- | ---------------------------------- | ------------------------------------------------------------- |
| `CSDN_COOKIE`           | `""`                               | 认证凭据。所有写操作的必填项                                  |
| `CSDN_USERNAME`         | `""`                               | Cookie 里没有 `UserName` 时使用                               |
| `CSDN_LOG_LEVEL`        | `warn`                             | `silent` / `error` / `warn` / `info` / `debug`,日志走 stderr |
| `CSDN_TIMEOUT_MS`       | `20000`                            | 单次请求超时                                                  |
| `CSDN_MAX_RETRIES`      | `2`                                | 可重试失败的额外尝试次数                                      |
| `CSDN_MIN_INTERVAL_MS`  | `250`                              | 普通请求之间的最小间隔                                        |
| `CSDN_SAVE_INTERVAL_MS` | `11000`                            | 写操作之间的最小间隔(CSDN 约 10s 内会拒绝)                  |
| `CSDN_API_BASE`         | `https://bizapi.csdn.net`          | bizapi 网关地址                                               |
| `CSDN_BLOG_BASE`        | `https://blog.csdn.net`            | 公开页地址,用于写后校验                                      |
| `CSDN_COMMUNITY_BASE`   | `https://blog.csdn.net`            | 社区列表接口地址                                              |
| `CSDN_USER_AGENT`       | Chrome 131 UA                      | 请求头 `User-Agent`                                           |
| `CSDN_APP_KEY`          | `203803574`                        | bizapi 网关 app key(公开常量)                               |
| `CSDN_APP_SECRET`       | `9znpamsyl2c7cdrr9sas0le9vbc3r6ba` | bizapi 网关签名密钥                                           |

## 它是怎么工作的

**HMAC 签名。** 所有走 `bizapi.csdn.net` 的请求都要带 `X-Ca-Signature`。签名串由 method、accept、content-type、`x-ca-key`、`x-ca-nonce` 和含查询串的 uri 按固定换行拼成,再做 `base64(HMAC-SHA256(appSecret, stringToSign))`;同时必须带 `X-Ca-Signature-Headers: x-ca-key,x-ca-nonce` 告诉网关哪几个 header 参与了签名。少一行就是 `401 HMAC signature does not match`。完整格式见 [docs/API-NOTES.md](docs/API-NOTES.md#hmac-签名规范串)。

**两步图片上传。** 先 POST `/resource-api/v1/image/direct/upload/signature` 拿上传凭据,再 multipart 直传到返回的存储 host,响应里的 `data.imageUrl` 才是公网地址。正文图和封面图是两条不同的通道(`appName` 不同),不可互换。见 [docs/TOOLS.md](docs/TOOLS.md#upload_image)。

**为什么每次写入都要回查公开页。** `saveArticle` 返回 200 不等于成功。接口里的 `status` 表达的是"这篇文章是否对外可见",不是"这次调用算不算草稿"——两者共用同一组数字编码(`0` / `1` 已发布,`2` 草稿,`6` 审核拒绝,`16` 审核中),写入用的值和 `getArticle` 报回来的值含义并不对称(发布时发的是 `0`,`getArticle` 报的是 `1`)。所以 `publish_article` / `update_article` 默认跑一次校验:既看 API 返回的 `status`,也真的去请求一次公开页,只有两边都说"是草稿"(公开页 404)或都说"已发布"(公开页 200)才判定 `consistent: true`。任何一边不一致都会如实报告,不会因为一个 200 就宣称"发布成功"。

## 文档

| 文档                                               | 内容                                       |
| -------------------------------------------------- | ------------------------------------------ |
| [docs/README.md](docs/README.md)                   | 文档索引                                   |
| [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md) | 从零到第一次成功调用                       |
| [docs/TOOLS.md](docs/TOOLS.md)                     | 11 个工具的参数、返回、错误码              |
| [docs/CONFIGURATION.md](docs/CONFIGURATION.md)     | 环境变量 + 各客户端配置                    |
| [docs/API-NOTES.md](docs/API-NOTES.md)             | 逆向记录:签名串、saveArticle 字段、状态码 |
| [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) | 按症状排查                                 |
| [docs/FAQ.md](docs/FAQ.md)                         | 常见问题与能力边界                         |
| [docs/CHANGELOG.md](docs/CHANGELOG.md)             | 版本变更                                   |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)       | 分层、模块边界、冻结的工具面               |
| [docs/KNOWN-ISSUES.md](docs/KNOWN-ISSUES.md)       | 已修项复核、历史问题回归表、待线上验证     |

## 许可

MIT,见 [LICENSE](LICENSE)。

TDQS

A4.4/5.0

Scored across 11 tools

Disambiguation5/5

The tools target distinct operations: authoring (publish/update), retrieval (get/list), verification, auth, metadata lookup, and image upload. Descriptions explicitly draw boundaries between similar tools such as get_article vs verify_article vs list_articles, so misselection is unlikely.

Naming Consistency4/5

Most names follow a consistent snake_case action_object pattern (publish_article, delete_article, list_articles, upload_image). The auth_login/auth_status pair and list_categories/list_tags remain readable and stylistically consistent, though auth_status deviates slightly from strict verb_noun naming.

Tool Count5/5

11 tools for a CSDN publishing integration covering article CRUD, auth, categories, tags, and image upload is well-scoped. There is no obvious bloat, and the count sits comfortably in the ideal 3-15 range.

Completeness4/5

Core article lifecycle is well covered, including draft/publish modes, delete with recycle/permanent options, update, list, verify, auth, metadata, and image upload. Minor gaps exist around explicitly restoring articles from recycle and setting/updating an article cover beyond uploading the image.

Maintenance

ActivityMaintained
ResponsivenessNo issues