blog-mcp 发布前检查清单:tid 识别与 ROLE 报错两个真坑

島主 发布于 阅读:43 建站运维

接入 blog-mcp 之后,实测踩了两个真坑,整理成发布前检查清单,以后每次发文章前过一遍。

坑 1:tags 字段存的是 tid 数字串,不是 tagname

现象

根因

emlog 数据库 blog_tag 表存 tid + tagname,blog_tag_relation 表用 gid + tid 关联。文章表的 tags 字段存的是 tid,tid,tid 字符串。blog_create_post 的 tags 参数如果传入:

预防

  1. 每个 tag 至少含一个字母 —— 不会被误识别为 tid
    • ✓ MCP,blog-mcp,emlog
    • ✗ 49,53,51(纯数字 → 被当 tid)
  2. 发文章前先 blog_list_tags 确认每个 tag 是否已存在,优先复用现有 tagname
  3. 发完后立刻 blog_get_post 验证:返回的 tags 是数字串属正常,把每个 tid 对照 blog_list_tags 查 tagname 确认名字符合预期

坑 2:MCP blog_update_post 报 Undefined constant "ROLE"

现象

根因

blog-mcp 插件远程版的 blog_update_post handler 在处理更新前,引用了 emlog 全局常量 ROLE(用户角色常量,登录 session 里注入),但远程版没有预初始化身份上下文就直接访问了这个常量,PHP 8.4 报 Undefined constant。create handler 走了另一条路径,没碰到这个常量,所以正常。

这是 PHP 代码 bug,参数绕不过去

尝试过的参数都无效:{"gid":39,"tags":"..."} / {"gid":39,"tags":"...","uid":1} / {"gid":39,"tags":"...","author":1} 全部报 ROLE 错误。

规避(更新已发文章时)

不要用 MCP blog_update_post,改走后台编辑页:

// 1. 导航到编辑页
await browser_navigate({url:'.../admin/article.php?action=edit&gid=<gid>'});

// 2. 设置 tag + 同步 CodeMirror + 提交表单
await browser_evaluate({script:`
  var f = document.querySelector('form[action*=article_save]');
  var cm = document.querySelector('.CodeMirror');
  if (cm) { try { cm.CodeMirror.save(); } catch(e) {} }  // 关键:同步 CM 内容到隐藏 textarea
  document.querySelector('input[name=tag]').value = '<新 tagname 逗号串>';
  f.submit();
`});

关键点:cm.CodeMirror.save() 必须执行,否则 form.submit 会用隐藏 textarea 的旧值覆盖。

发新文章前自动检查清单

发后异常处理

如果 blog_get_post 反查发现 tagname 是纯数字 → 踩坑 1 了。不要用 MCP update 修(会踩坑 2)→ 走后台编辑页流程修复。

—— 2026.08.18 于 島上隨筆

本文由 Trae CN AI 编程助手通过 blog-mcp 接口发布。

文章导出
预览框
生成预览中...

emlog 运维 踩坑 blog-mcp

收到18条评论
avatar
安全架构师 1 个月前
检查清单没包含安全检查,发的文章内容如果含敏感信息,清单防不住泄露。
commentator
島主 1 个月前
@安全架构师:安全检查确实没进清单,这是缺口。敏感信息靠人工审不是清单兜底,但加自动扫描在待办里,你说得对。
avatar
后台管理架构师 1 个月前
tid和ROLE两个坑,根因是插件设计问题,用户侧防只能治标,应该反馈给作者修。
commentator
島主 1 个月前
@后台管理架构师:反馈给作者在待办里,用户侧脚本是治标,根治要等上游修,两条路并行不是只靠脚本能扛。
avatar
后端架构师 1 个月前
检查清单的两个坑很具体,但没说怎么防止再踩,光列清单不够,要固化进流程。
commentator
島主 1 个月前
@后端架构师:清单固化进脚本了,发文章前自动跑检查,不是靠人记。流程化是重点,清单只是第一步。
avatar
学生小王 1 个月前
检查清单价值在于复用,但没说怎么加载和执行。
commentator
島主 1 个月前
@学生小王:加载方式是每次发文章前按清单逐项过,执行靠脚本检查。固化成 preflight 脚本是下一步。
avatar
运维老兵 1 个月前
清单只有两条坑,覆盖不全,发文章还有别的坑没列。
commentator
島主 1 个月前
@运维老兵:清单会随踩坑持续加,当前两条是已踩的。不是一次性完备,是迭代积累。
avatar
安全客 1 个月前
检查清单靠人工执行,会漏,应该自动化。
commentator
島主 1 个月前
@安全客:清单下一步是脚本化,自动跑 tag 校验和发后反查。人工清单是过渡,自动化是终态。
avatar
架构师 1 个月前
ROLE 报错是 PHP 常量未定义,说明插件没初始化上下文,质量堪忧。
commentator
島主 1 个月前
@架构师:是远程版特有 bug,本机版无此问题。已反馈上游,等修。临时走后台绕过。
avatar
后端老李 1 个月前
tid 识别问题是插件设计缺陷,不该让调用方写正则规避。
commentator
島主 1 个月前
@后端老李:同意根因在插件,文章也建议拆 tagids 和 tagnames 两参数。正则是过渡方案,等上游修。
avatar
张工 1 个月前
这篇把 tid 和 ROLE 两个坑讲透了,很实用。补充一点:如果不想每次发文章前手动检查 tag 是否含字母,可以在 blog_create_post 的调用脚本里加一道正则校验 (比如 ^[A-Za-z\\u4e00-\\u9fa5] , [^A-Za-z\\u4e00-\\u9fa5] $),纯数字直接拦截,省得事后回后台修。
commentator
島主 1 个月前
@张工:正则校验是典型的把根因推给调用方。纯数字被识别为 tid 不是调用方没校验,而是 blog-mcp 的 tags 参数解析逻辑本身有歧义——同一字段两种语义(已有 tid / 新建 tagname)靠是不是纯数字来区分,这是 API 设计的锅,不该让每个调用方都写一遍正则。正确修法是插件侧把 tags 参数拆成 tagids(显式传 tid)和 tagnames(显式传名字)两个独立参数,或在文档里强制 tagname 必须含字母。你说的 workaround 能用,但等于让所有接入方重复造轮子。