csdn-blog-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PYTHONPATH | Yes | Path to the source directory so the server module can be found. Set to <项目路径>/src (replace <项目路径> with your actual project path). | |
| CSDN_BLOG_HOME | No | Optional environment variable to customize the drafts/cookie storage directory (default: project root directory). |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| tool_get_style_guideA | Return the CSDN writing style guide (the MCP's own prompt). The guide was distilled from the author's published CSDN posts and documents the tone (address reader '你', casual but neutral, no personal persona), the two article types (intro vs. step-by-step tutorial), title patterns, opening hooks, required elements (tables, code blocks, emoji headers, '注意!' callouts, Star solicitation), SEO rules, and what to avoid. Call this BEFORE generate_blog_scaffold / write_blog so content matches the author's style. Returns: dict with {ok, path, guide} on success, or {ok, message} if missing. |
| tool_generate_blog_scaffoldA | Generate an SEO-optimized markdown scaffold for a CSDN blog post. Returns a markdown skeleton tuned for CSDN ranking: keyword-front-loaded title ideas, H2/H3 hierarchy, intro hook, code-block placeholders, and suggested tags. Use this BEFORE writing to get a good structure, then fill it in and pass the result to write_blog. Tip: call get_style_guide first so the filled-in content matches the author's voice. Args: topic: The blog topic / subject. keywords: SEO keywords (the first one is front-loaded into title ideas). style: Writing style preset — "intro" (开源项目/MCP 介绍文), "tutorial" (保姆级部署教程), "technical", "analysis", "notes", or "general". tags: Optional pre-chosen tags; otherwise suggested from keywords. Returns: dict with {ok, topic, style, title_suggestions, tags_suggested, scaffold} |
| tool_write_blogA | Package blog content into a CSDN-ready markdown file and save it. Adds YAML front-matter (title, summary, tags, category, keywords, style,
visibility, timestamps) and writes the file to the local drafts folder.
The publish_csdn tool reads this same file later. If Args: topic: Blog title (used as H1 and filename slug if filename is empty). content: Markdown body. May include leading front-matter (--- ... ---). keywords: SEO keywords for the front-matter. tags: CSDN tags (3-5 recommended). category: CSDN category, e.g. "后端", "前端", "运维", "AI". summary: Article summary; auto-extracted if empty. style: Writing style (informational; stored in front-matter). visibility: "public", "private", or "fans". filename: Override filename (without .md). Auto-generated if empty. overwrite: If True, overwrite an existing draft with the same name. Returns: dict with {ok, file_path, filename, title, summary, tags, category, visibility, bytes} |
| tool_seo_checkA | Analyze a draft markdown file for CSDN SEO issues before publishing. Checks title length & keyword placement, summary, keyword density, H2/H3 hierarchy, word count, code-block language hints, image alt text, and tag count. Returns a 0-100 score with actionable warnings. Args: file_path: Absolute path to the draft .md file. Returns: dict with {ok, score, checks, fail_count, warn_count, suggestions, summary} |
| tool_list_draftsA | List all draft blog posts in the local drafts folder (newest first). Returns each draft's filename, title, summary, tags, created timestamp, and size. Use this to see what's ready to publish. Returns: dict with {ok, drafts: [...], count} |
| tool_read_draftA | Read a draft markdown file and return its content + parsed metadata. Args: file_path: Absolute path, or just a filename resolved against the drafts folder. Returns: dict with {ok, file_path, title, summary, tags, category, keywords, visibility, status, created, content} |
| tool_delete_draftB | Delete a draft markdown file from the local drafts folder. Args: file_path: Absolute path or filename of the draft to delete. Returns: dict with {ok, message, file_path} |
| tool_check_csdn_loginA | Check whether the saved CSDN session is still logged in. Opens a browser (headless by default), loads www.csdn.net with the saved storage state, and reports login status. Call this before publish_csdn to avoid a failed publish due to an expired session. Args: headless: Run headless (default True for a quick check). Returns: dict with {ok, logged_in, needs_login, saved_session, message} |
| tool_csdn_loginA | Open a visible browser to log into CSDN and save the session. First-time login MUST be visible (headless=False) so you can solve any captcha. After login is detected, the cookies + localStorage are saved so publish_csdn can run headless later. Complete the login in the browser window that opens. Args: headless: Must be False for first login (kept for flexibility). timeout_ms: How long to wait for login (default 3 minutes). Returns: dict with {ok, message, saved, path?} |
| tool_clear_csdn_sessionA | Delete the saved CSDN session (forces a fresh login next time). Returns: dict with {ok, message} |
| tool_publish_csdnA | Send a local draft to CSDN via browser automation (Plan A). By default (as_draft=True) saves the article to CSDN's online 草稿箱 (draft box) WITHOUT publishing — you then review it in the browser and publish manually. Set as_draft=False to publish directly (public immediately, returns the article URL). Fills the CSDN markdown editor: title, body, tags, category, visibility, then clicks 存草稿 or 发布文章. Direct publish enforces a rate limit (default 2/day, min 30 min apart) to avoid anti-automation flags; saving drafts is not rate-limited. Requires a saved session — call csdn_login first. If the session expired, returns needs_login=True so you can re-run csdn_login. WARNING: This drives CSDN's web UI. Selectors may break when CSDN changes its editor; a screenshot is saved on failure to help diagnose. Respect CSDN's terms — keep frequency low and content genuine. Args: file_path: Absolute path to the draft .md file (from write_blog). tags: Override tags from the draft's front-matter (3-5 recommended). category: Override CSDN category (e.g. "后端"). visibility: Override visibility — "public", "private", or "fans" (only meaningful when as_draft=False). as_draft: True (default) = save to CSDN draft box, not public. False = publish directly and return the article URL. headless: Run headless (default True). Set False to watch the action. timeout_ms: Per-action timeout in milliseconds. skip_rate_limit: Bypass the rate limit (use with care — risks a ban). Only applies when as_draft=False. Returns: dict with {ok, as_draft, message, title, draft_manage_url?, article_url?, screenshot?, needs_login?} |
| tool_diagnose_editorA | Diagnose the CSDN markdown editor to detect UI drift / broken selectors. Opens the CSDN editor with your saved session and probes every key element (title display/input, content editor, save-draft button/item, publish button, tag/category inputs, dialog publish button). For each selector it reports which fallback matched (or none), so when publish_csdn starts failing you can run this to see exactly which selectors CSDN changed and update SELECTORS in publisher.py accordingly. Requires a saved session — call csdn_login first. Args: headless: Run headless (default True). Set False to watch. timeout_ms: Per-action timeout in milliseconds. Returns: dict with {ok, url, results: {element: matched_selector | null}, needs_login?, message?} |
| tool_csdn_statsA | Fetch view/like/comment/collect counts for a published CSDN article. Uses CSDN's public article-detail JSON endpoint (no login required). Call this after publish_csdn to track how a post is doing. Args: article_url: Full CSDN article URL (e.g. https://blog.csdn.net//article/details/). Returns: dict with {ok, article_url, article_id, title, views, likes, comments, collects, publish_time} |
| tool_rate_limit_statusA | Check the current publish rate-limit status without publishing. Returns whether a new publish is allowed, today's count, the last publish timestamp, and minutes since the last publish. Returns: dict with {allowed, reason, today_count, last_publish_ts, minutes_since_last} |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 14 tools
Each tool has a distinct purpose: session tools (login/check/clear), draft CRUD (list/read/write/delete), pre-writing helpers (style guide vs scaffold), publishing, diagnostics, stats, and rate limiting are all cleanly separated. The only near-pair (get_style_guide vs generate_blog_scaffold) is clearly differentiated as voice guidance vs structural skeleton. No two tools appear interchangeable.
Most names follow a verb_noun pattern (get_style_guide, write_blog, list_drafts, read_draft, delete_draft, publish_csdn, diagnose_editor). A few deviate with noun-first or noun_verb forms (csdn_login, csdn_stats, seo_check, rate_limit_status), and the uniform 'tool_' prefix is a wrapper artifact. Still readable and mostly predictable.
14 tools is well-scoped for a full draft-to-publish workflow: prep (style/scaffold/SEO), local draft management, session handling, publishing, and post-publish tracking. Each tool earns its place with no obvious redundancy.
The write → SEO check → publish → track lifecycle is well covered, plus session and rate-limit management. Minor gaps exist: no dedicated draft-edit/update tool (relying on write_blog's overwrite flag) and no tool to list or manage already-published articles beyond per-URL stats.