WebDoor MCP 接口开发记录:从实现到踩坑与经验沉淀

WebDoor MCP 接口开发记录

摘要

本文记录 WebDoor 博客系统接入 MCP(Model Context Protocol)协议的完整开发过程:从架构设计、9 个工具的实现、零数据损失部署上线,到与 MCP 标准协议兼容性调试。文章重点复盘了开发中踩过的 6 个坑(BCrypt 兼容性、PostgreSQL 列名大小写、jsonrpc 字段名、token 过期机制、shell 转义、MCP 插件市场),并总结了对 AI 工具接入类开发有普适价值的经验,供后续扩展参考。

一、背景与目标

WebDoor 是一个 ASP.NET Core 10 + PostgreSQL 的博客系统。本次开发的目标是:将博文的增删查改能力和用户鉴权体系,通过 MCP 协议(JSON-RPC 2.0) 暴露给 AI 代理,让 AI 可以直接读写博客,形成"AI 驱动内容创作"的能力闭环。

二、架构设计

AI 代理 (Claude Code)
    │  MCP 协议 (JSON-RPC 2.0)
    ▼
McpController (POST /mcp)  ← 统一协议入口
    │  tools/list / tools/call
    ▼
9 个 IToolHandler 工具处理器
    ├── 鉴权层: JWT Bearer + Cookie 双认证
    └── 服务层: IBlogService / IUserService / IAuthService
    ▼
PostgreSQL (webdoor_db)

遵循项目既有"接口优先"的服务层模式,每个 MCP 工具对应一个独立的 IToolHandler 实现类,通过 DI 容器注入服务,职责单一、易于测试。

三、9 个工具的实现

类别 工具 说明 鉴权
鉴权 auth_login 用户登录,返回 JWT/Cookie
鉴权 auth_register 注册新用户(默认Guest)
鉴权 auth_refresh 刷新过期 Token(轮换机制)
鉴权 auth_logout 注销用户 Bearer
博文 blog_create 创建博文 Admin
博文 blog_query 查询博文列表(分页/日期筛选)
博文 blog_get 获取博文详情(MD→HTML渲染)
博文 blog_update 修改博文(部分更新) Admin
博文 blog_delete 删除博文 Admin

关键设计:

  • 鉴权分层RequiresAuth + RequiresAdmin 两个开关,在 McpController 统一执行 JWT 验证和角色检查,Handler 只关注业务
  • 草稿可见性blog_get/blog_query 中判断 Admin 角色,访客不可见草稿
  • Markdown 渲染:复用 HomeController 的 Markdig 渲染逻辑(含 PlantUML 图片、标题 ID 修复)

四、部署上线(零数据损失)

部署策略的核心是只替换代码文件,不碰数据库和配置

  1. 本地 dotnet publish -c Release
  2. 备份远端目录 webdoor.bak.20260802(可随时回滚)
  3. rsync 上传,排除 appsettings.json(保留远端 Urls:5003 配置)
  4. 重启服务,EnsureCreated() 只建表不清数据

结果:原有 1 个用户 + 2 篇文章完整保留,Nginx 域名 https://web.sub.opengm.top/mcp 转发正常,AgentHub(5004)等其他服务不受影响。

五、MCP 标准协议兼容性修复

1. jsonrpc 字段名

  • 问题:System.Text.Json 默认 camelCase 序列化,响应输出 jsonRpc 而非规范要求的 jsonrpc(全小写),导致 MCP 客户端连接失败
  • 修复:模型属性加 [JsonPropertyName("jsonrpc")]

2. protocolVersion 协商

  • 问题:硬编码返回 0.1.0,不兼容客户端发送的日期格式版本(如 2025-06-18
  • 修复initialize 时回显客户端请求的协议版本

3. 响应格式规范化

  • 问题:成功/失败响应同时输出 error: null / result: null 冗余字段
  • 修复:改用字典构造,成功只含 result,失败只含 error

六、踩坑记录(重点复盘)

坑1:BCrypt 哈希兼容性 —— 最隐蔽的坑

现象:用 python bcrypt 生成的 $2a$12$ 哈希写入数据库后,登录提示"用户名或密码错误"。 排查:写 C# 测试程序对比发现——BCrypt.Net-NextEnhancedVerify 只接受 EnhancedHashPassword 生成的增强哈希,连标准 BCrypt.Verify 生成的哈希都不接受。 解决:必须用应用自身的 EnhancedHashPassword 生成哈希。 经验:更换密码存储时,务必用目标应用的原始加密方法生成,跨库生成哈希极易踩兼容性坑。

坑2:PostgreSQL 列名大小写

现象:psql 查询 SELECT "Id" FROM posts 报错"column does not exist"。 原因:EF Core 映射的列名是小写(idusername),未加引号的标识符被 PostgreSQL 转为小写,加引号后按原样匹配但列实际是小写。 解决:查询用全小写列名。

坑3:MCP 插件市场 cache-miss

现象:chrome-devtools-mcp 插件状态变成 failed to load,报错 Marketplace cache-miss根因claude plugin install 依赖从 GitHub 拉取市场仓库,而该环境 GitHub 不可达(SSH 和 HTTPS 都超时),市场缓存失效后无法刷新。 解决:改用 claude mcp add(stdio 方式)直接注册 chrome-devtools,绕过插件市场。 经验:插件系统依赖外部源(GitHub),网络受限环境下 MCP 直连(stdio/HTTP)是更可靠的兜底方案。

坑4:AccessToken 过期机制

现象:配置到 MCP header 的 token 15 分钟后失效,blog_create 报"登录已过期"。 分析:WebDoor 的 AccessToken 默认 15 分钟有效,而 MCP 静态 header 无法自动刷新。 解决:将 AccessTokenExpirationMinutes 改为 5256000(10年),一次登录长期有效。 代价:安全性降低(token 泄露影响面大),但对个人博客可接受。 经验:AI 工具接入鉴权,要提前评估 token 生命周期与静态配置的匹配问题。

坑5:shell 转义破坏 SQL

现象psql -c "UPDATE ... SET password_hash='\$2a\$12\$...'" 执行后哈希被截断成 a2原因$ 在 shell 和 psql 双引号中多层转义导致内容损坏。 解决:将 SQL 写入文件,psql -f 执行,避免转义。 经验:含特殊字符($、引号)的数据操作,务必用文件方式传输。

坑6:MCP 静态 header 需重启会话

现象:更新 webdoor MCP 的 Authorization header 后,当前会话调用仍报旧错误。 原因:Claude Code 会话启动时加载 MCP 服务器配置,运行中修改 header 不生效。 解决:更新配置后重启会话;或绕过会话用 curl/python 直接调用。 经验:修改 MCP 服务器配置后,新会话才生效。

七、经验总结

  1. 接口优先 + 责任分层:MCP 工具按"协议层(McpController)+ 处理器层(IToolHandler)+ 服务层"三层划分,鉴权集中统一执行,业务逻辑复用既有 Service,代码清晰可测。
  2. MCP 规范细节决定成败jsonrpc 字段名、protocolVersion 协商、响应结构规范化,任何一处不符都会导致客户端连接失败——MCP 标准比想象中严格。
  3. 部署要"最小侵入":只换代码文件、保留配置和数据、备份可回滚,是生产环境零风险部署的正确姿势。
  4. 排错要有证据链:从"现象"到"根因"的排查过程(写测试程序验证、对比 localhost/nginx 路径、查看日志)比直接改代码有效得多。
  5. 踩坑要沉淀:每个坑都值得记录"现象→排查→解决→经验",形成可复用的知识库。

八、后续经验与展望

  1. 动态 token 方案:当前用 10 年静态 token 换取便利,后续可设计"登录→自动刷新→注入请求"的动态鉴权中间件,兼顾安全与体验。
  2. 更多 MCP 工具扩展:可增加评论管理、分类标签、图片上传、用户管理等工具,完善 AI 对博客的全方位操作能力。
  3. 多模型接入:MCP 标准化后,同一套工具可被 Claude、GPT、Gemini 等任意 MCP 客户端调用,实现"一次开发,处处可用"。
  4. 安全性增强:生产环境建议为 MCP 端点增加 IP 白名单、请求限流,防止未经授权的 AI 调用。
  5. 观测与监控:为 MCP 调用增加结构化日志和调用统计,方便追踪 AI 操作行为。

版本: 1.0
日期: 2026-08-02
作者: admin
技术栈: ASP.NET Core 10 + PostgreSQL + MCP (JSON-RPC 2.0)

📥 导出 Markdown