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 修复)
四、部署上线(零数据损失)
部署策略的核心是只替换代码文件,不碰数据库和配置:
- 本地
dotnet publish -c Release - 备份远端目录
webdoor.bak.20260802(可随时回滚) - rsync 上传,排除
appsettings.json(保留远端Urls:5003配置) - 重启服务,
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-Next 的 EnhancedVerify 只接受 EnhancedHashPassword 生成的增强哈希,连标准 BCrypt.Verify 生成的哈希都不接受。
解决:必须用应用自身的 EnhancedHashPassword 生成哈希。
经验:更换密码存储时,务必用目标应用的原始加密方法生成,跨库生成哈希极易踩兼容性坑。
坑2:PostgreSQL 列名大小写
现象:psql 查询 SELECT "Id" FROM posts 报错"column does not exist"。
原因:EF Core 映射的列名是小写(id、username),未加引号的标识符被 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 服务器配置后,新会话才生效。
七、经验总结
- 接口优先 + 责任分层:MCP 工具按"协议层(McpController)+ 处理器层(IToolHandler)+ 服务层"三层划分,鉴权集中统一执行,业务逻辑复用既有 Service,代码清晰可测。
- MCP 规范细节决定成败:
jsonrpc字段名、protocolVersion协商、响应结构规范化,任何一处不符都会导致客户端连接失败——MCP 标准比想象中严格。 - 部署要"最小侵入":只换代码文件、保留配置和数据、备份可回滚,是生产环境零风险部署的正确姿势。
- 排错要有证据链:从"现象"到"根因"的排查过程(写测试程序验证、对比 localhost/nginx 路径、查看日志)比直接改代码有效得多。
- 踩坑要沉淀:每个坑都值得记录"现象→排查→解决→经验",形成可复用的知识库。
八、后续经验与展望
- 动态 token 方案:当前用 10 年静态 token 换取便利,后续可设计"登录→自动刷新→注入请求"的动态鉴权中间件,兼顾安全与体验。
- 更多 MCP 工具扩展:可增加评论管理、分类标签、图片上传、用户管理等工具,完善 AI 对博客的全方位操作能力。
- 多模型接入:MCP 标准化后,同一套工具可被 Claude、GPT、Gemini 等任意 MCP 客户端调用,实现"一次开发,处处可用"。
- 安全性增强:生产环境建议为 MCP 端点增加 IP 白名单、请求限流,防止未经授权的 AI 调用。
- 观测与监控:为 MCP 调用增加结构化日志和调用统计,方便追踪 AI 操作行为。
版本: 1.0
日期: 2026-08-02
作者: admin
技术栈: ASP.NET Core 10 + PostgreSQL + MCP (JSON-RPC 2.0)