AI摘要:本文介绍了一个基于Node.js的MCP Server项目,该项目实现了自动化发布博客文章和动态到Typecho博客系统。文章详细描述了项目背景、技术架构、关键问题与解决方案、核心代码实现、认证优化、测试结果以及安全注意事项。通过遵循JSON-RPC标准、处理表单参数、动态获取token、探索正确的API路径和优化认证策略,项目成功实现了博客自动化发布功能。

Powered by AISummary.

MCP Server 开发与调试实战:Typecho 博客自动化发布

一、项目背景

MCP (Model Context Protocol) 是一种用于连接 AI 模型与外部工具的协议。本项目实现了一个基于 Node.js 的 MCP Server,可以自动化发布博客文章和动态到 Typecho 博客系统。

问题起源

最初遇到的问题是 MCP Server 连接超时:

MCP server "xmprpc" connection timed out after 30000ms

经过排查,发现是 JSON-RPC 协议实现问题和登录流程错误导致的。

二、技术架构

MCP Server 架构

┌─────────────┐     JSON-RPC      ┌─────────────┐     HTTP      ┌─────────────┐
│   AI Model  │ ────────────────> │   MCP Server│ ───────────> │  Typecho    │
│   (Trae)    │ <─────────────── │   (Node.js) │ <────────── │   Blog      │
└─────────────┘      stdio        └─────────────┘              └─────────────┘

核心技术栈

  • Node.js - MCP Server 运行环境
  • Axios - HTTP 请求库
  • JSON-RPC - 协议通信标准
  • Typecho - 目标博客系统

三、关键问题与解决方案

问题 1:JSON-RPC 协议实现错误

现象:服务器无法正确响应 MCP 协议请求

分析:协议格式不正确,缺少必要的方法实现

解决方案:实现标准的 JSON-RPC 方法:

  • initialize - 协议初始化
  • tools/list - 返回工具列表
  • tools/call - 调用具体工具

问题 2:登录流程错误

现象:登录失败,提示密码错误

分析:登录表单的 referer 字段值设置错误,应该为空字符串而不是完整 URL

解决方案:修改登录请求参数:

formData.append('referer', ''); // 改为空字符串

问题 3:动态 Token 处理

现象:表单提交 URL 包含动态生成的 token

分析:Typecho 的表单 action URL 包含时间戳参数 ?_=xxx,需要动态获取

解决方案:每次请求前先获取页面,提取最新的表单 action:

const formActionMatch = writeHtml.match(/<form[^>]*action="([^"]+)"/i);
const postUrl = formActionMatch[1]; // 动态获取包含 token 的 URL

问题 4:博客发布按钮缺失

现象:文章保存为草稿而不是发布

分析:缺少发布按钮参数,默认行为是保存草稿

解决方案:添加发布按钮字段:

formData.append('do', 'publish'); // 触发发布操作

问题 5:API 路径错误

现象:后台管理路径返回 404

分析:管理后台路径不是 /index.php/action/admin,而是 /login/

解决方案:更新 API 路径映射:

  • 写文章:/login/write-post.php
  • 发布处理:/action/contents-post-edit

四、核心代码实现

登录方法

async function login() {
  // 1. 获取登录页面
  const loginPageResponse = await axios.get('/login/login.php', { headers });
  
  // 2. 提取动态 token
  const html = loginPageResponse.data.toString();
  const formActionMatch = html.match(/<form[^>]*action="([^"]+)"/i);
  const tokenMatch = loginUrl.match(/[?&]_=([a-f0-9]+)/);
  const token = tokenMatch[1];

  // 3. 提交登录请求
  const formData = new URLSearchParams();
  formData.append('name', username);
  formData.append('password', password);
  formData.append('remember', '1');
  formData.append('referer', ''); // 关键修复

  const loginResponse = await axios.post('/index.php/action/login?_=' + token, formData, {
    headers: { ...headers, 'Cookie': sessionCookies },
    maxRedirects: 0
  });
}

发布博客方法

'create_post': async () => {
  // 1. 获取写文章页面(动态 token)
  const writePageResponse = await axios.get('/login/write-post.php', { headers });
  const formActionMatch = writeHtml.match(/<form[^>]*action="([^"]+)"/i);
  const postUrl = formActionMatch[1];

  // 2. 构建表单数据
  const formData = new URLSearchParams();
  formData.append('title', title);
  formData.append('text', content);
  formData.append('category[]', category);
  formData.append('allowComment', '1');
  formData.append('allowPing', '1');
  formData.append('allowFeed', '1');
  formData.append('do', 'publish'); // 关键:触发发布

  // 3. 提交发布请求
  const response = await axios.post(postUrl, formData, {
    headers,
    maxRedirects: 0
  });

  // 4. 判断发布结果
  return response.status === 302 || 
    response.headers['refresh'] || 
    noticeCookie.includes('已发布');
}

五、认证优化

按需认证机制

最初所有方法都强制登录,导致公共接口也失败。优化后:

async function callMethod(method, params) {
  const authRequired = ['create_post', 'create_dynamic', 'get_posts', 'get_page'];
  let cookies = '';
  
  if (authRequired.includes(method)) {
    cookies = await getCookies(); // 仅需要认证的方法才登录
  }
}

六、测试结果

功能状态说明
协议初始化JSON-RPC 正常响应
健康检查网站在线检测
用户登录获取认证 cookies
获取动态返回动态列表
发布动态成功发布动态
发布博客成功发布文章

七、安全注意事项

1. 凭据管理

使用环境变量存储敏感信息,避免硬编码:

XMRPC_HOST=https://your-blog.com
XMRPC_USERNAME=your-username
XMRPC_PASSWORD=your-password

2. 请求头模拟

模拟浏览器请求头,防止被识别为机器人:

const headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
  'Referer': host + '/login/write-post.php',
  'Origin': host
};

3. Token 动态更新

每次操作前获取最新 token,避免过期:

const writePageResponse = await axios.get('/login/write-post.php', { headers });

八、总结

本次开发过程中遇到了多个典型问题:

  1. 协议实现问题 - 需要严格遵循 JSON-RPC 标准
  2. 表单参数问题 - 字段值必须与页面一致
  3. 动态 token 问题 - 需要实时获取最新值
  4. 路径映射问题 - 需要实际探索正确的 API 路径
  5. 认证策略问题 - 公共接口不应强制登录

通过系统的调试和分析,最终成功实现了完整的博客自动化发布功能。


技术栈:Node.js | Axios | Typecho | MCP Protocol

关键字:MCP Server | Typecho API | 博客自动化 | JSON-RPC | 接口调试

Last modification:July 14, 2026
If you think my article is useful to you, please feel free to appreciate