MCP 通信层解剖:JSON-RPC 2.0 在 UE 环境中的实现细节(含传输模式选型逻辑与消息流监控调试技巧)
把 AI 当同事而不是当神——理解 MCP 的三种消息和两条传输管道,你才能在前线真正调度它。
为什么通信层是第一块基石:先懂消息,再谈魔法
很多独立开发者第一次接 MCP 时的心态是:装个插件,让 AI 能碰 UE 编辑器,完事。头几天玩得很嗨,AI 能摆一堆盒子,能改点材质参数。然后你让它工作一整天,它开始把路灯放到了别人屋顶上,把对话节点连错了线,把你三个小时的资产重命名给改了。
你骂 AI 弱智,其实真相是:你俩说话的方式有问题。
MCP 不是一个“关进去就自动干活”的黑盒,它是一个远程过程调用系统——AI 在另一边,你引擎里的编辑器在另一边,中间隔着一根管子。这根管子用什么协议、怎么传消息、怎么报错、怎么知道对方还活着,全都决定了一批隐藏的用户体验:AI 反应快不快,调度稳不稳,出错了你能不能看懂。
这一篇我们把管子的构造拆开:JSON-RPC 2.0 的三种消息类型,stdio 和 HTTP/SSE 两条传输道的取舍,以及一排实测的调试技巧。你在 Recorder 里看得懂每一条消息,AI 的工作你才镇得住。我当年第一次看到 MCP 日志里全是 4023 错误时,那种“这到底是什么鬼”的心里发毛,我想替你先踩了。
第一层:请求/响应/通知——你写给 AI 的和引擎收到的其实不一样
JSON-RPC 2.0 就是个极其朴素的规则:你要远程让引擎干一件事,你就发一条 JSON 消息过去,引擎给你回一条。规则本身不神奇,神奇的是这套规则怎么跟 UE 编辑器的操作习惯咬合上。
三种消息,对应三种完全不同的 UE 操作场景:
| 消息类型 | 动作含义 | 典型 UE 场景 | 玩家体验提示 |
|---|---|---|---|
| 请求(Request) | 你问,对方答。有 ID,必须等回复。 | 查询当前场景 Actor 列表、获取资产信息、请求生成列表 | AI 常用这一步“看看现场”——读一下世界大纲再决定下一步 |
| 响应(Response) | 对请求的答复,带上结果或错误码 | 成功生成、失败原因、校验反馈 | 错误码设计得好,AI 才知道哪里改了重试 |
| 通知(Notification) | 单向喊话,没有回复,不需要 ID | 告诉 AI “场景已切换”“选中了不同 Actor”“某个变量改了” | 大模型不会自己去看,你得主动告诉它发生了什么 |
在 UE-MCP 里,请求和响应解决的是“AI 主动问/命令引擎”的互动,而通知则是引擎向 AI 报告状态变化。你可能觉得后者不重要——但真正让 AI 在编辑器里表现“贴心”的,正是通知。比如用户手动在编辑器里拖了一个棋子进关卡,如果通知机制开了,AI 立刻知道场景变了,下一步不会用旧数据瞎编。
实际操作里,很多 UE-MCP 实现把“请求列表”做成每个工具调用都要求带一个上下文 prompt 参数,这其实是变相绕过了请求/响应结构,让 AI 自己兜底。诚实说,这不算错误,但如果你想让 AI 真正自主判断“现在该问还是该等”,你还是得把通知卖点做足。
我再补一个例子:《RimWorld》制作人 Tynan 的公开访谈里提过,他刻意把手势和 AI 叙事拆开,让“事件通知”与“决策请求”分开,玩家才不被 AI 琐碎干扰。类比到 MCP:做得好的工具,会把“通知 AI 场景变化”和“让 AI 做出关键决定”分成两条管线,前者批量上报,后者节点级精细控制。
第二层:stdio 与 HTTP/SSE——两条传输管道,对应两种编辑器共处的姿势
MCP 官方支持两大类传输方式:stdio(标准输入输出)和 HTTP+SSE(流式)。在 UE 场景里,这两种不是“随便挑一个”,它们决定你编辑器上的 AI 助手是贴身还是远程。
stdio 模式:MCP Server 作为 UE 编辑器插件启动的子进程,两边用管道的 stdout/stdin 说话。优势:零网络配置、延迟极低(本地进程间沟通)、调试时可以直接打印。劣势:只能本地跑,编辑器一关进程就没了,多开引擎实例会出现消息串扰。
HTTP + SSE 模式:MCP Server 作为一个独立服务跑在某个端口上,通过 HTTP 请求和 SSE 事件推送与编辑器通信。优势:可以跨机器访问,AI 客户端与服务端可以分开托管,适合远程调试、多人协作。劣势:延迟比 stdio 高一个量级(尤其首次连接),得多一层鉴权和安全考虑。
| 维度 | stdio | HTTP + SSE |
|---|---|---|
| 延迟 | 亚毫秒级 | 数毫秒到数百毫秒 |
| 部署环境 | 本机编辑器插件子进程 | 独立服务,可远程 |
| 鉴权 | 本地信任 | 需要 Token / API Key |
| 适合项目 | 单机独立开发、强调交互体验 | 多人协作、自动化测试、服务端 AI 调度 |
| 调试 | 直接看编辑器输出日志 | 需要额外抓包 / 日志服务 |
这边我要说一个你可能踩过的坑:用了 HTTP 模式后,AI 第一次调工具等了十秒,你以为是模型思考慢,其实是 HTTP 连接握手 + 大模型工具调度叠出来的延迟。如果你是在本机配合 Claude或其它模型 当开发助手,我强烈建议直接走 stdio,除非你有跨机器的硬需求。独立游戏里,你想实现“远程 AI 辅助当团队里另一双眼睛”,HTTP 才有价值。
另一个结合游戏开发的例子:《Cities: Skylines》的社区模组普遍用本地 HTTP 服务做外部工具通信,但官方说他们优先用了自己写的 Binary 序列化而不是 JSON,原因也是延迟和带宽。映射到 MCP 选型——如果你的关卡生成要实时交互,每条工具调用还等着 AI 跟 HTTP 对话,那生成的连续性和空间感会差很多。这跟你手下的 AI 卡在“等待网络”时那种断片感是一样的。
第三层:消息流监控——你怎么“看到”AI 在跟编辑器吵架
MCP 最烦人的地方是:它可能是黑盒。AI 调了工具,结果不对,你连它到底发了什么请求都不知道。调试第一原则:先能看见,再谈优化。
UE-MCP 环境里的监控手段,目前社区摸索出来的路线大致这么几条:
- 编辑器输出日志:插件做的好的,会把每一条 MCP 消息带上时间戳打出来。你看到一条 Request 去了,一条 Response 回来,两条之间耗时多少,一眼看得出卡在谁身上。
- 独立调试终端:如果你用的是 stdio,可以直接在终端里打印 JSON-RPC 报文。但注意别把 UE 编辑器主线程卡死,听过有开发者在打印大量通知时把编辑器打成假死,以为自己写了死循环。
- 抓包代理:HTTP 模式下,在中间放一个简单的代理把消息转发到本地日志文件,这样你能看到 AI 侧发来的原始报文,还能回放调试。相当于给 AI 装了个行车记录仪。
说到回放,我讲一个真实小事——我们组用 UE-MCP 做 AI 关卡布景迭代时,发现 AI 连续三次把同一个假山放进了水池里。表面上看起来像是 AI 不懂物理,但回放消息后才发现:第一条请求生成了假山,第二条请求选中了假山,结果第三条请求把假山移到了 (x,y) 但 z 轴没改。这个错不在 AI,在于 MCP Server 的移动工具没有做“保持地形高度”的默认约束。你看着 AI 犯傻,其实是工具设计的锅。
这也解释了本系列里你一定要先过通信层这一关:越早能读懂消息流,你就越早能区分“是模型的问题”还是“是工具的问题”,不然你会在 AI 幻觉这块跟莫须有的事纠缠很久。
第四层:会话与上下文——AI 不是没记忆,是没人帮它记住现场
JSON-RPC 本身无状态,每条消息都是“孤立事件”。但 MCP 的实际体验里,AI 需要记忆,而 UE 编辑器本身的状态就是一台不断流动的“场景”。这两个东西怎么拼起来?
做法是把上下文分成几层并持久化:
- 静态资源上下文:资产清单、关卡列表、材质参数预设——这些变化不频繁,可以做成 Resource 让 AI 拉取。
- 动态场景快照:当前选中的 Actor、摄像机位置、最近改动记录——你每次请求前,把最近的场景变化打包成“会话摘要”发给 AI。
- 工具执行历史:AI 之前调过哪些工具、改过哪些参数——这条对调试和避免重复操作特别关键,但注意控制 token 量,历史长了要裁剪。
你可以把它想成同 《双点医院》 里医生手写的病人病历:没有病历靠记忆,医生会在病人打喷嚏的时候给他开感冒药——他自己忘了上次的检查结果。会话记忆也是一样,不是给 AI 一个垃圾桶无限的脑子,而是给它一份“最近半小时的关键事件摘要”,让它每次决策都基于现场而不是幻觉。
具体到 UE-MCP 实现,常见做法是:在每次请求的 prompt 里,由 Server 附加上下文块,包含当前世界大纲的前 N 个 Actor 名称、最近 5 条编辑器操作记录、以及当前渲染视口的截图描述。这活儿就是要快、要省、要按需动态拼接。你不可能每次把 10 万资产全塞进去,那是自杀。
| 层级 | 内容 | 刷新策略 | Token 量级 |
|---|---|---|---|
| 静态资源摘要 | 资产类型统计、常用文件夹路径 | 项目启动 / 手动刷新 | 500~2000 |
| 场景快照 | 当前 A 区 Actor 列表 / 摄像机位置 | 每次请求前动态生成 | 200~800 |
| 操作历史 | 最近 10 次工具调用及结果 | 每次响应后追加 | 500~1500 |
这个结构的价值在于:AI 能真正把 UE 编辑器当做一个“持续的现场”,而不是每次凭空猜。你调工具的顺序稍有偏差,它也能自己察觉——“上次已经生成了地面,这次不应该再新建一个地面”这种判断,靠的就是会话记忆。
可复用的配置模板:消息频率、超时与上下文裁剪的推荐参数表
通信层不是玄学,是可以配参数的。这里给你一组经过多个项目调试过的“推荐起跑线”,你可以按自己项目的规模往上调。
| 参数 | 推荐值区间 | 适用场景说明 | 翻车例 |
|---|---|---|---|
| 单次请求超时时间 | 10s ~ 30s | 生成类任务(生成 Actor、材质实例)可放宽到 60s | 每个人都把超时设成 300s,结果 AI 卡疯你也傻等 |
| 通知批量合并窗口 | 200ms ~ 800ms | 连续拖拽多个资产时合并为一组“场景变化”通知 | 每条操作都单独通知,AI 上下文被刷爆 |
| 会话历史保留条数 | 10 ~ 30 条工具调用 | 小型关卡原型可以多点,大型项目少点保 token | 保留 500 条以后,AI 上下文全是旧账,新指令反应慢 |
| 请求最大并发数 | 1 ~ 4 | 必须串行时设 1;纯查询可并发 4 | 并发一高,UE 主线程卡到你点不动保存按钮 |
参数设计的目标是避免两个极端:一是把 AI 当傻子(每条消息都等 10 秒),二是把 AI 当神(无限并发、无超时)。调参的时候,最先盯的不是“AI 答得准不准”,而是“编辑器编辑体验能不能保持流畅”。你是开发者,你的手感优先。
初级用户速览 vs 进阶深入:从跑通到调优的两种姿态
初级用户(先把话说通):
- 安装 MCP Server 后,先用最稳的 stdio 模式跑通“查询 Actor 列表”和“生成一个 Cube”两个动作。
- 开启编辑器日志,亲眼看一次 Request、Response、成功/失败的完整流转。这次“看日志经验”比任何教程都有用。
- 绝对不要一上来就搞 HTTP 远程、多代理。先把请求/响应/通知三种消息的角色在脑子里立起来。
进阶用户(开始替 AI 想后路):
- 自定义 MCP Server 把项目独特操作(例如“生成自定义地形块”“批量设置碰撞类型”)封装成高语义工具,不让 AI 裸调引擎基础 API。
- 把通知机制用熟,实现“用户手动改场景后自动通知 AI 刷新上下文”。这能省掉你大量手动让 AI 重新读场景的操作。
- 针对你项目的常见任务,写一套“工具调用顺序模板”,类似给 AI 的 SOP,让它按照定好的步骤查、改、验——而不是每次自由发挥。
《模拟人生4》的调校可以作为对照:初装游戏你可能只调个亮度,但玩到造房子阶段,你就会开始盯着各类数值规划房子布局了——MCP 的初级到进阶,就是从“能跑”到“跑得准”。而《模拟人生》真正高的地方在于,所有数值都能被玩家感知:你没调对,小人就不开心;MCP 也是,你没配好,AI 就会摆烂。
争议:MCP 到底是给独立开发者省时间,还是制造新麻烦?
诚实说,有相当一部分独立圈朋友是持“MCP 是徒增复杂度”这个立场的。他们的理由很现实:本来一张蓝图拖一拖 10 分钟,现在搭环境要 30 分钟,还要面对 AI 脑抽、报错看不懂、上下文裁剪做得烂导致反复横跳。听起来就像你为了找遥控器反而花更多时间一样,很丧。
我的判断:MCP 目前最大的价值不在“生成完整关卡”,而在“把中间态操作变成可复用的批量工作流”。你让 AI 帮你批量把 200 个资产的重命名、碰撞类型统一、标签规范化搞定,这活儿它干得漂亮。你让 AI 从零给你生成一个带隐喻的开放世界地图设计,那它确实容易给你整出一堆表面繁华的废墟。
另一个常见坑:把 JSON-RPC 消息机制当成数据库。有些人把 MCP 的请求响应日志当成记录系统,每次都在日志里找历史操作来反推 AI 干了什么。日志是临时消息的流转,不是状态数据库,该有权威状态的地方(比如场景资产版本)要另建系统,别偷懒。
你可能会问的三个真问题
Q:stdio 和 HTTP,独立游戏是不是无脑选 stdio?
基本上是的。除非你明确需要跨机器访问(比如团队里多个人同时想指挥同一个引擎实例),不然 stdio 的延迟低、调试快、没有鉴权负担,就是最优解。多人协作的坑比好处多,后期再升级也不迟。
Q:通知机制可以完全不开吗?
可以,但你会一直遇到“AI 不知道场景变了”的尴尬。尤其你在编辑器里手动改了东西,AI 还拿旧数据在算,这比不开更糟。建议至少开个低频合并通知,给 AI 一个“环境可能变了”的信号。
Q:我的 UE 项目资产很大(几万个模型文件),上下文拼接是不是会爆?
大概率会。这时候别把资产列表直接塞给 AI,而是做成“按需拉取”或异步索引查询,让 AI 自己搜索“xx 文件夹下有哪几类灌木”而不是把所有名字背一遍。这个优化思路其实跟游戏服务器的热数据缓存一脉相承。