前言:wechatsync通过MCP同步文章到WordPress时分类标签为空,根源在于tags字段定义了却从未透传。本文梳理五层数据链路断点,并完成WordPress REST API分类与标签映射的字段透传修复。
前两天在折腾一个事儿。
我用 wechatsync 把文章同步到 WordPress 的时候,发现一个特别别扭的问题,文章发过去之后,分类目录和标签全是空的。
就是那种,文章标题有了,正文有了,封面图也有了,但你点进 WordPress 后台一看,分类没选,标签没填,光秃秃的一篇文章挂在那儿。

我寻思了一下,这不对啊。
wechatsync 这个插件我用了挺久了,它是个浏览器扩展,能把公众号文章一键同步到 WordPress、知乎、掘金这些平台,省得你手动复制粘贴。平时用着挺顺手,但这次我换了个工作流,开始用 MCP 来调它发文章,就撞上了这个问题。
用 MCP 发文章的时候,我可以传 tags 和 category 参数进去,但发完之后 WordPress 后台啥也没变。
这就很诡异了???
参数传了,没报错,文章也发出去了,但分类和标签就是没生效。像你往邮筒里塞了一封信,邮筒吃了,邮递员也走了,但收件人那边啥也没收到。信去哪了?
我决定自己查一查。
不查不知道,一查发现这事儿还挺有意思。
先说结论,wechatsync 的代码里,tags 这个字段,定义了,但从头到尾,没人用它。
怎么说呢,就像你在家里装了一根网线,从客厅拉到卧室,线也买了,孔也打了,但两头都没接上路由器。线躺在墙里,看着挺像那么回事,实际上一个字节都没跑过。
我一层一层跟你说。
第一层,类型定义。在 types.ts 里,Article 类型上确实定义了 tags?: string[] 和 category?: string,字段在,类型在,看起来一切正常。
第二层,MCP 工具。sync_article 这个工具的参数 schema 里,也有 tags 和 category,你调用的时候可以传进去,也不会报错。
到这里为止,一切都很美好。
第三层,MCP 调用逻辑。index.ts 里,sync_article 实际执行的时候,只传了 title、content、markdown、cover 这四个字段。tags 和 category?收到了,但没往下传。就像快递员把包裹签收了,然后往仓库一堆,忘了派送。
第四层,sync-service。sync-service.ts 里做了一层数据标准化,normalizedArticle 也没有 tags 和 category 字段。到这一层,tags 的信息已经彻底丢了。
第五层,WordPress 适配器。wordpress.ts 里的 restPublish,往 WordPress 发 POST 请求的时候,body 里只有 title、content、status。categories 字段?没有。tags 字段?也没有。
你想想看,一条完整的数据链路,从入口到出口,五层,每一层都把 tags 给丢了。
但最骚的是,第一层定义了它,第二层接收了它。就好像这把枪,第一幕挂在墙上了,但第二幕第三幕第四幕第五幕,没人扣扳机。

坦率的讲,我一开始还有点懵。
不是因为问题复杂,恰恰相反,是因为问题太简单了。这不是什么深奥的架构问题,不是什么性能瓶颈,不是什么并发冲突,就是单纯的,字段没透传。
就像你家水笼头不出水,查了半天,发现不是水管堵了,不是水压不够,就是阀门没开。
但话说回来,这种问题其实最容易被忽视。因为它不报错。程序不会因为一个可选字段没传而崩溃,文章也照常发出去了,只是分类和标签是空的。如果你不专门去 WordPress 后台看一眼,你根本不知道这事儿。
说真的,这种「沉默的缺失」比报错更可怕。报错至少告诉你哪里坏了,这种缺失是,一切看起来正常,但实际上该做的事没做。。。
好,问题找到了,接下来就是改。
但在改之前,有个事儿得先搞清楚。
WordPress 的分类体系,不是一个东西,是两个。
很多朋友可能不知道,WordPress 后台「文章」菜单下面,「分类目录」和「标签」是分开管理的,两个独立的东西,REST API 也是两套独立的接口。
分类目录是层级的,有父子关系,一篇文章通常归到一个分类里。标签是平铺的,没有层级,一篇文章可以挂好几个标签。
打个比方,分类目录像是你家的书架,历史放一层,科幻放一层,历史下面还能再分古代史近代史。标签像是书签,你可以同时贴「推荐」「睡前读物」「已读完」好几个标签在一本书上。
这俩在 REST API 里也是分开的。分类目录用 /wp-json/wp/v2/categories,标签用 /wp-json/wp/v2/tags,各自有各自的查询和创建接口。发文章的时候,POST body 里 categories 和 tags 也是两个独立的字段,都需要先拿到对应的 ID 再传。
所以这里有个选择题。
tags 和 category 这两个字段,怎么映射到 WordPress?
最直觉的方案是把 tags 直接当分类用,毕竟我最开始的需求就是「根据标签设置分类目录」。但这样 tags 数组里的每个值都会变成一个分类,而 WordPress 的分类通常一篇文章只选一个,挂一堆分类上去不太合理。
更合理的方式是,category 这个单字符串映射到 WordPress 的分类目录,tags 这个数组映射到 WordPress 的标签。各回各家,各找各妈。
我选了后者。

接下来就是动手了。
核心逻辑其实就一件事,写一个 helper 函数,按名字去 WordPress 查分类或标签,查到了就用它的 ID,没查到就创建一个,拿到 ID。然后发文章的时候把这个 ID 塞进 POST body 里。
听起来简单,但有几个坑。
第一个坑,WordPress 的 search 接口是模糊匹配。你搜「AI」,它可能给你返回「AI绘画」「AI工具」「AI时代」一堆结果。所以拿到结果之后不能直接用,得遍历一遍,按 name 精确比对。先大小写敏感比一次,没匹配上再不敏感比一次,确保拿到的是你要的那个。
第二个坑,并发创建。如果你运气好,两个人同时发文章,传了同一个不存在的分类名,两个请求几乎同时到达 WordPress,第一个创建了,第二个创建的时候 WordPress 告诉你「已存在」,返回 400。所以创建失败之后得再查一次,把已经创建好的那个 ID 拿回来用。
第三个坑,容错。分类或标签的解析创建如果失败了,不应该阻断文章发布。文章本身是能发的,只是分类没挂上而已。所以失败的时候记个日志,返回 null,继续往下走,别因为一个分类没创建成功就把整篇文章给拦住。
这三个坑处理完,核心的 resolveOrCreateTerm 函数大概五十行,加上 restPublish 里解析和传参的逻辑,适配器这块就搞定了。
剩下的就是全链路透传。
sync-service.ts 加两个字段,background/index.ts 加两个字段,MCP 的两个入口文件各加几行 schema 和透传。每个文件改的都不多,五到十行,但架不住文件多,五个文件串起来,整条链路才通。
这事儿让我想起一个比喻。
你修一条水管,从水库到家里,中间五段管子,只要有一段没接上,你家就不出水。你查的时候不能只看出水口,得一段一段顺着摸过去。问题往往不在最显眼的地方,而在某个你以为是通的接头那里。
改完之后跑了一遍验证。
extension 的 typecheck,过了。MCP server 的 build,过了。WordPress 适配器的 11 个测试,全过。

那一刻的感觉太爽了。
不是那种「我解决了一个世纪难题」的爽,是那种「一根卡了很久的水管终于通了」的爽。你拧开水龙头,水来了。你发一篇文章,分类和标签都在了。
就这么个事儿。
说真的,整个改动加起来大概八十行代码,集中在五个文件,没有架构性的调整,没有新依赖,没有破坏性变更。就是顺着已有的数据链路,把一个定义了但从未使用的字段,一层一层接通了。
回到开头那个画面。
现在我用 MCP 发文章,传上 tags 和 category,文章发到 WordPress 之后,分类目录选好了,标签也挂上了。不再是那个光秃秃的模特了。
我有时候觉得,代码和故事是一回事。
剧作法里有个原则叫契诃夫之枪,你在第一幕挂了一把枪在墙上,第三幕它就得开火。反过来说,如果你挂了一把枪,但从来没开过,那这把枪就是多余的,是 dead code。
wechatsync 里的 tags 字段,就是那把挂了但没开的枪。
它在类型定义里挂了不知道多久,在 MCP 的 schema 里也挂了不知道多久,但从来没有人扣过扳机。没有一行代码去读取它,没有一个适配器去处理它,它就那么挂在墙上,安静地存在着。
我做的事,不是造一把新枪,是让一把已经挂在那儿的枪,终于响了一声。
这大概就是编程里最朴素的一种快乐吧。不是创造,是接通。不是发明,是兑现。让一个早就该工作的东西,终于开始工作。
磨平一些信息差,有时候不是往外面磨,是往自己代码里磨。
/ 注意,本项目仅在 SyncMein 的500人小群分享。
/ 谢谢你看完了我的文章,我们下次再见吧。
/ 作者:明察
/ 投稿或爆料,请联系邮箱:mingcha@gqmg.com
标签:wechatsync WordPress MCP REST API 字段透传
关键词:wechatsync分类标签透传 wechatsync同步WordPress分类为空 MCP发文章标签未生效 WordPress REST API分类与标签映射 wechatsync字段透传修复
– END –













暂无评论内容