JS 可以写 3D 渲染,但它通常不是“JS 自己在 CPU 上一个像素一个像素画 3D”,而是 JS 调浏览器提供的 GPU 图形 API。

Three.js 这种库,它是 JS 写的,但它不是靠 JS 手搓全部渲染结果。它本质上是封装了 WebGL/WebGPU。MDN 对 WebGL 的定义就是:WebGL 是一个 JavaScript API,用来在浏览器中渲染高性能交互式 2D 和 3D 图形,并且能利用设备硬件图形加速。MDN Web Docs

最底层如果不用库,你可以直接用 WebGL 写:

但这很底层,接近 OpenGL ES 风格。

Three.js 则是更上层的封装:

JavaScript
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();
const renderer = new THREE.WebGLRenderer();

renderer.render(scene, camera);

Three.js 官方 WebGLRenderer 文档里说,它会用给定的 camera 渲染 scene / 3D object,渲染到 canvas 或 render target。Three.js 也就是说你写的是 JS 场景代码,Three.js 负责把它转换成 WebGL 调用。

MDN 全称现在是 MDN Web Docs,历史上叫 Mozilla Developer Network。MDN 官方 About 页面写得很直接:MDN 是一个开源协作项目,归 Mozilla Corporation 所有,由 Mozilla 和社区、合作伙伴共同开发维护。MDN Web Docs

你会感觉它像“微软文档”,主要是因为后来 Web 标准文档逐渐集中到 MDN。2017 年左右,Mozilla、Microsoft、Google、W3C、Samsung 等一起推动跨浏览器 Web 文档协作,目标是让开发者不要分别查 Firefox / Chrome / Edge / Safari 各自一套文档。Mozilla 当时也宣布 Microsoft、Google、W3C、Samsung 会参与 MDN Web Docs 的协作。Mozilla Blog W3C 也确认过它和 Mozilla、Microsoft、Google、Samsung 一起支持 MDN 文档。W3C

所以正确关系是:

WebGL
  是 Web 标准/浏览器图形 API

MDN
  是 Mozilla 主导的 Web 技术文档站

Microsoft
  不是 MDN 所有者,但参与过 Web 文档协作,也会把一些 Web API 文档指向 MDN

Google / W3C / Samsung / Open Web Docs
  也参与过或支持过相关文档生态

WebGL 使用文档 → MDN 是最常用参考之一

注册 = 把某个功能挂到一个表里。
分发 = 请求来了以后,根据名字/类型/ID,从表里找到对应功能并调用。

“注册分发”可以拆成两个动作看:

在 MCP / UE 插件这种架构里,它通常长这样:

C++
// 注册阶段:把 "spawn_actor" 这个名字,对应到某个处理函数
RegisterHandler("spawn_actor", SpawnActorHandler);

// 分发阶段:收到请求
ProcessAutomationRequest(Request)
{
    Handler = AutomationHandlers[Request.CommandName];
    Handler(Request);
}


TMap<FString, TFunction<void(const FRequest&)>> AutomationHandlers;

所以查找 handler 的复杂度平均接近 O(1),也就是“给我命令名,我几乎可以直接找到对应函数”,不用从头遍历一大串命令。

截图后半句也说了重点:“但实际大量逻辑仍集中在 ProcessAutomationRequest() 的一长串 handler callback 里。”

McpAutomationBridge 已经有“命令名 → 处理函数”的注册表机制,理论上新增命令可以注册进去,然后请求来了自动分发到对应 handler。但是它现在的实际代码组织可能还是偏集中式,很多功能逻辑没有被拆成独立 command/handler/service,而是堆在一个大函数或大类里。

MCP 到底是“一个能执行东西的程序”,还是“一个规定能调用什么的规则”?

MCP 本身不是执行器。MCP 是一套“让 AI 知道有哪些外部工具、怎么调用、用什么参数调用、返回什么结果”的协议。真正能做什么,取决于 MCP Server 内部写了哪些 tool。

MCP Client
↓ JSON-RPC

Claude / ChatGPT / Cursor / Codex
        ↓
MCP Client
        ↓ JSON-RPC / stdio / HTTP
UE Bridge 插件
        ↓
Unreal Editor API

这种情况下,UE Bridge 直接负责:

tools/list
tools/call
参数 schema
JSON-RPC 请求响应
调用 UE C++ / Editor API

这就可以直接叫 MCP Server

第二种更常见:外部 MCP Server + UE Bridge 插件。

Claude / ChatGPT / Cursor / Codex
        ↓
MCP Client
        ↓ JSON-RPC
外部 MCP Server,例如 Node.js / Python
        ↓ WebSocket / HTTP / TCP / 本地 IPC
UE Bridge 插件
        ↓
Unreal Editor API

这种情况下,严格说:

外部 Node/Python 程序 = MCP Server
UE Bridge 插件 = MCP Server 的后端执行端 / UE Adapter / Editor Bridge

它不是直接面对 MCP Host 的 server,而是 server 后面的 Unreal 执行层。

MCP Server / 外部入口层

它负责接收外部 AI 客户端的请求,比如:

call_tool("spawn_actor", { class: "StaticMeshActor", location: [...] })
call_tool("get_selected_actors", {})
call_tool("create_material", { name: "M_WetRock" })

这一层的问题是:外部世界只知道“工具名”和“参数 JSON”。它并不知道 UE 里面应该调用哪个 C++ 函数、蓝图函数、Editor Utility、Python API,或者哪个子系统。

所以需要第二层。

第二层就是 Command Registry + Command 类

Command Registry 可以理解为一个命令表:

"spawn_actor"          -> FSpawnActorCommand
"get_selected_actors"  -> FGetSelectedActorsCommand
"create_material"     -> FCreateMaterialCommand
"set_actor_transform" -> FSetActorTransformCommand

它的作用是:
外部传进来一个字符串命令名,Registry 负责找到对应的 Command 对象,然后调用它。

典型伪代码大概是:

C++
class ICommand
{
public:
    virtual FString GetName() const = 0;
    virtual FCommandResult Execute(const FJsonObject& Args) = 0;
};

然后每个命令单独写一个类:

C++
class FSpawnActorCommand : public ICommand
{
public:
    FString GetName() const override
    {
        return TEXT("spawn_actor");
    }

    FCommandResult Execute(const FJsonObject& Args) override
    {
        // 解析 JSON 参数
        // 校验 class / location / rotation
        // 调用 Service 层执行真正的 UE 操作
        return ActorService->SpawnActor(Args);
    }
};

Registry 负责注册:

C++
CommandRegistry.Register(MakeShared<FSpawnActorCommand>());
CommandRegistry.Register(MakeShared<FGetSelectedActorsCommand>());
CommandRegistry.Register(MakeShared<FCreateMaterialCommand>());

收到请求时:

C++
auto Command = CommandRegistry.Find(CommandName);
return Command->Execute(Args);

这个结构的核心意义是:把“外部命令名”从“具体实现逻辑”里解耦出来。

否则你会写出一大坨:

C++
if (CommandName == "spawn_actor") { ... }
else if (CommandName == "get_selected_actors") { ... }
else if (CommandName == "create_material") { ... }
else if (CommandName == "set_actor_transform") { ... }

这种写法一开始快,后面会变成灾难。命令越多,分支越长,参数校验、权限、日志、错误处理、UE 操作全部混在一起,架构就不干净。

第三层是 Service 层

Service 层才是真正操作 UE Editor / Runtime 的地方。比如:

ActorService
AssetService
MaterialService
LevelService
BlueprintService
SelectionService
ViewportService
WorldService

业务动作交给 Service。

Sequence 不是“视频文件本身”,而是 PR 里的时间线容器。
它可以只包含一段视频,也可以包含很多视频、音频、字幕、图片、Adjustment Layer、嵌套序列等。你现在拖入的第一个音频/视频创建了一条时间线,所以 PR 自动生成了一个默认序列,名字通常就是 Sequence 01

名为 Sequence 01 的时间线的 Transcript 导出文本。

Adobe 官方也把这个叫 sequence transcript:当你把 clips 加入 timeline 后,Premiere 会创建一个新的 sequence transcript;这个 transcript 可以跟时间线同步,用于 Text-Based Editing。

Nasdaq 交易所:撮合买卖股票的市场基础设施。
Nasdaq-100 指数:Nasdaq 公司编制的一个产品化指数。
追踪 Nasdaq-100 的 ETF / 指数基金 / 衍生品:必须尽量复制这个指数的投资产品。

AUM

指数本身不会下单。Nasdaq 不会因为 48% 被触发就亲自去卖苹果、英伟达、微软。真正交易的是追踪指数的基金。

short for exchange-traded fund.

"investments in ETFs have not fallen"

ETF / 指数基金为了继续贴近 Nasdaq-100,就要按照新权重调仓。
如果不调仓,基金净值走势就会偏离指数,产生 tracking error。
指数基金的商业承诺就是“我尽量复制这个指数”,所以它不能随便说“我觉得这次规则不合理,我不跟”。

这就是“强制交易”的含义。不是法律上有人拿枪逼基金交易,而是产品契约、跟踪误差、基金章程、投资者预期共同形成的强制性

Nasdaq-100 的季度 rebalance 在 3、6、9、12 月进行;如果特殊集中度约束被打破,也可以触发 special rebalance。比如官方规则规定:没有一家公司权重可超过 24%;权重超过 4.5% 的公司合计权重不能超过 48%。如果触发,就会提前公告特别再平衡。Nasdaq Global Index Watch

QQQ 就是典型例子。Nasdaq 自己回顾 QQQ 历史时说,Nasdaq 在 1999 年创建了 QQQ ETF,用来追踪 Nasdaq-100 Index;2007 年又把 QQQ 卖给 PowerShares,也就是现在 Invesco 的一部分。nasdaq.com Invesco 现在也把 QQQ 表述为一个有 25 年以上历史、追踪 Nasdaq-100 的被动 ETF;其官网写明 QQQ 自 1999 年 3 月 10 日成立,总费用率为 0.18%。Invesco

可以把它类比成:

第一层:温度计显示今天 30°C。
第二层:有人发行一个合约,承诺你的收益尽量等于“这个温度计数值变化”。
第三层:为了兑现承诺,发行方必须不断调整自己的仓位。

Nasdaq-100 指数本身不买卖股票。
QQQ、QQQM、iShares Nasdaq-100 ETF、各类 UCITS ETF、养老金产品、结构票据、期货和掉期产品,才是真正要买卖股票的主体。

为什么它们必须交易?因为它们卖给投资者的不是“我帮你挑科技股”,而是:

我尽量复制 Nasdaq-100 的表现。

BlackRock 加拿大的 iShares Nasdaq 100 Index ETF 就直接写明:该 ETF 的投资目标是通过复制 Nasdaq-100 Index 的表现,扣除费用后寻求长期资本增长。BlackRock 这类表述不是随口宣传,而是产品目标。基金如果长期偏离指数,就会出现 tracking error,也就是跟踪误差。

UE 还有 .modules / BuildId 机制避免加载过期二进制,Epic 文档里也说明这是为了防止 stale binaries。参考:Epic 的 ​编辑Versioning of Binaries

QQQ 官网显示总费用率 0.18%。Invesco 投资者每年把基金资产的一小部分交给基金管理人。资产规模越大,费用收入越多。假设一个 ETF 管 3000 亿美元,费用率 0.18%,年化毛费用就是约 5.4 亿美元。当然实际还要扣除运营、营销、授权、托管等成本。

开发期不应该强行保留 bUsePrecompiled = true。这个开关的语义是让模块使用预编译数据;如果你正在频繁改源码,它会让 UBT 更倾向于把这个模块当作已经预编译好的消费品,而不是当前源码开发模块。

稳定后再 package/build plugin,生成可分发版本,才切回 Installed/Precompiled 的消费形态。

指数基金和主动基金的根本区别。

主动基金卖的是:

“我比市场聪明,我来选股。”

指数基金卖的是:

“我不声称比市场聪明,我给你低成本、透明、可复制的市场暴露。”

没有这个承诺,ETF 的商业价值会崩掉。因为投资者买 Nasdaq-100 ETF,不是为了让基金经理自由判断苹果该不该减仓、英伟达该不该加仓、SpaceX IPO 后贵不贵。投资者买它,是为了获得一个明确的风险包:

100 家 Nasdaq 上市的大型非金融公司,按照 Nasdaq-100 方法论加权。

Source development
↓ build
Local compiled binary
↓ package / BuildPlugin
Packaged binary plugin
↓ install / enable
Installed precompiled plugin
↓ consume in project
Loaded UE module

Nasdaq-100 之所以能成为“可以提供子生态的大型环境”,不是因为它只是一个指数,而是因为它变成了一个标准化风险接口

它最初确实只是一个指数。Nasdaq-100 在 1985 年 1 月 31 日推出,用来追踪 Nasdaq 市场上 100 家最大的非金融公司;Nasdaq 后来把它描述为大型成长股、创新公司暴露的代表性指数。Nasdaq+1

但后来它长出了很多下游产品:ETF、期货、期权、共同基金、结构化票据、保险产品、模型组合、机构对冲工具。Nasdaq 2026 年文章称,围绕 Nasdaq-100 的生态规模已经达到约 1.4 万亿美元,覆盖 ETFs、derivatives、mutual funds、structured notes 和 insurance products。Nasdaq

这就是所谓“子生态”。

Nasdaq-100 把一堆复杂股票压缩成一个清晰标签:美国大型非金融成长股 / 科技创新股暴露

投资者本来要自己判断苹果、微软、英伟达、亚马逊、Meta、谷歌、博通、特斯拉这些股票怎么配。但 Nasdaq-100 给了市场一个现成的组合规则:只要你买这个指数暴露,你就大致买到了“美国大型科技成长风险包”。

这件事很重要。金融市场讨厌每次都重新解释。它需要标准接口。Nasdaq-100 就像一个 API:

NDX = Nasdaq 上市的大型非金融成长公司风险敞口

有了这个 API,资产管理公司、券商、期货交易所、期权做市商、养老金、散户平台都可以围绕它继续开发产品。

QQQ 把这个指数变成了可交易入口。

1999 年,QQQ 这个 ETF 出现,目标就是追踪 Nasdaq-100。Nasdaq 自己回顾 QQQ 历史时说,QQQ 是 1999 年创建、用来追踪 Nasdaq-100 的 ETF;Invesco 现在也把 QQQ 定位为追踪 Nasdaq-100、成立于 1999 年 3 月 10 日的 ETF。Nasdaq+1

这一步的意义非常大。指数本身不能被买。ETF 让普通投资者和机构可以一键买入这个指数风险。

在 QQQ 之前,Nasdaq-100 更多是一个 benchmark。
在 QQQ 之后,Nasdaq-100 变成了一个可以直接交易、配置、对冲、套利的资产入口。

第三步,期货和期权让它从“投资产品”变成“交易基础设施”。

CME 的 E-mini Nasdaq-100 futures 允许投资者用一个期货合约获得接近 Nasdaq-100 的市场暴露,并且可以近乎 24 小时交易;CME 还强调 NQ futures 可以比直接交易 100 只股票更快、更灵活、更资本效率。CME Group+1

Nasdaq 也提供 Nasdaq-100 Index Options,例如 NDX / XND,用来管理风险、获取指数暴露、定制特定时间窗口的市场敞口。Nasdaq

这就形成第二层生态:

现货 ETF:QQQ、QQQM、各国 UCITS Nasdaq-100 ETF。
期货:NQ、Micro NQ。
期权:NDX options、XND options、QQQ options。
结构化产品:挂钩 Nasdaq-100 的票据、保险产品、收益凭证。
机构组合:以 Nasdaq-100 为 growth sleeve / tech sleeve / hedge sleeve。

到这一步,Nasdaq-100 已经不只是“指数”。它变成了一个金融市场的基础模块。

第四步,流动性本身会吸引更多流动性。

这叫网络效应。

为什么交易员喜欢 QQQ?因为它流动性深。
为什么它流动性深?因为很多交易员都用它。
为什么期权市场活跃?因为现货 ETF 活跃。
为什么机构愿意用它对冲?因为期货、ETF、期权都能互相转换。
为什么做市商愿意报价?因为成交量大,套利链条完整。

于是 Nasdaq-100 变成一个自我强化系统:

更多投资者使用
→ 更多 ETF 资产
→ 更多期权和期货成交
→ 更低交易成本
→ 更多机构策略接入
→ 更多衍生品和结构化产品
→ 更强品牌认知
→ 更多投资者继续使用

这就是“子生态”的本质:
不是一个产品成功,而是一套围绕同一风险接口互相喂养的产品族成功。

第五步,Nasdaq-100 有足够强的叙事。

S&P 500 的叙事是“美国大盘”。
Dow 的叙事是“传统蓝筹”。
Russell 2000 的叙事是“小盘股”。
Nasdaq-100 的叙事是“科技、成长、创新、AI、互联网、半导体、平台公司”。

这个叙事非常容易商品化。

基金公司可以卖:
“买美国创新。”
“买 AI 和大型科技。”
“买未来生产率。”
“买不含金融股的大型成长公司。”

Nasdaq-100 的官方描述也强调它包含 Nasdaq 市场上最大的国内和国际非金融公司,覆盖计算机硬件和软件、电信、零售/批发、生物技术等行业,并且不含金融公司。Nasdaq Global Index Watch

这比“我给你一个复杂多因子组合”更容易传播。
金融产品不只需要数学规则,也需要市场能理解的叙事包装。

指数生态不是自然长出来的,它需要指数公司、资产管理公司、交易所、做市商、数据商一起商业化。

Nasdaq 通过指数授权获得收入。
资产管理公司通过 ETF 管理费赚钱。
交易所通过期权、期货、上市、数据、交易服务赚钱。
券商通过订单流、融资融券、期权交易、结构化产品赚钱。
做市商通过报价、套利、对冲赚钱。
投资者则获得一个可交易的风险暴露工具。

所以 Nasdaq-100 的子生态本质上是一个多方分润系统。

不是只有 Nasdaq 赚。
Invesco、BlackRock、State Street、CME、Cboe / Nasdaq Options、券商、做市商、结构化产品发行商都可以围绕它赚钱。

.uplugin

插件名字、版本、描述、EnabledByDefault

CanContainContent:是否有插件自己的 Content

插件描述层

模块源码层:Source/ModuleName
│ ├─ Public/*.h:对外可 include 的 API
│ ├─ Private/*.cpp:内部实现
│ ├─ ModuleName.Build.cs:UBT 如何编译这个模块
│ └─ UCLASS/USTRUCT/UFUNCTION:交给 UHT 生成反射 glue code

构建规则层:Build.cs / Target.cs / UBT / UHT

编译产物层:Binaries / Intermediate
│ ├─ UnrealEditor-PluginName.dll

运行功能层:Subsystem / Command Registry / Handler / Service

“开发期不要 Installed / 不要 bUsePrecompiled”不是一个永久架构约束,最好不要写进 AGENTS.md 当长期规则。

它更像是当前阶段的工作模式

  • 现在你持续扩展插件:源码开发模式
  • 以后插件稳定、要跨项目分发:预编译/Installed 模式

这种会随阶段变化的东西,写进 AGENTS.md 容易过期,之后反而误导 agent。

更合适的放法:

  • AGENTS.md:写长期不变的工程约束
    比如“新增 MCP 能力走 registry,不要污染大 dispatcher”。

  • docs/McpAutomationBridgeDevelopment.md 或 README 的开发章节:写阶段性工作流
    比如“开发期使用源码插件 + Live Coding;发布期再 BuildPlugin 预编译”。

  • 如果要更强一点:在 AGENTS.md 里只写一句中性的长期规则:
    “不要在开发期和发布期之间混用源码插件与预编译插件配置;切换模式时同步更新 .uplugin 和 .Build.cs。”
    这不是固定某个模式,而是防止混用。

AI 实际上就变成了一个隐形上级:

domain 本来就是“领域、范围、管辖区、知识区域”的意思。比如:


legal domain        法律领域
medical domain      医学领域
business domain     业务领域
problem domain      问题领域
application domain  应用领域

所以在软件里说 Asset domain / Actor domain / Blueprint domain,底层含义是:


这一组问题属于 Asset 这个知识范围
这一组操作由 Asset 这块负责
这一组代码应该按 Asset 的规则组织

它不是 UE 专属词,也不是 MCP 专属词。

来自软件架构里的 Domain-Driven Design / DDD 文化。

在 DDD 里,domain 指的是软件真正服务的“业务世界”或“问题世界”。例如银行系统里,账户、转账、贷款、风控是 domain;电商系统里,订单、库存、支付、物流是 domain。

这个词的重点不是“文件夹分类”,而是:


代码结构应该贴近真实问题世界的边界

所以它反对把所有逻辑塞进一个巨大类里。因为巨大类通常意味着:


技术结构压过了问题结构

比如:


BigSystemManager
  - 订单
  - 库存
  - 用户
  - 支付
  - 日志
  - 权限
  - 通知

这种结构从机器角度可以运行,但从人类理解角度会变得混乱。DDD 文化倾向于说:


Order domain
Inventory domain
Payment domain
User domain

每个 domain 自己拥有自己的概念、规则、命令、错误、测试和扩展点。

所以 domain-owned handler 这个说法里,真正的重心是 owned

它不是单纯说:


把 handler 放到不同文件夹

而是说:


Asset 相关命令由 Asset 区域自己注册、自己维护、自己解释。
Actor 相关命令由 Actor 区域自己注册、自己维护、自己解释。
Core 不要知道每个功能的细节。
Core 只负责接收、调度、线程、安全、返回格式。

这就是为什么 domain-owned registry architecture 听起来有一种“企业架构味”。它不是日常口语,而是架构设计语言。

一个复杂系统不应该靠中心大脑理解所有东西,
而应该让每个能力区域自己拥有自己的规则和入口。

专业交流中用 domain 往往更“架构化”,但它也更抽象;feature 更接近“可交付的功能点 / 功能模块 / 产品能力”。你这个直觉是对的:很多情况下,feature 的范围通常比 domain 小

domain
> feature area / capability area
> feature
> handler / command / function

所以 Unity 的层级大致是:


Rendering domain
  > URP renderer customization area
      > Scriptable Renderer Feature
          > Scriptable Render Pass

Codex / Roo / Claude / Cursor 这类 AI 客户端
→ 读取某个 MCP 配置
→ 启动或连接一个 MCP server
→ MCP server 再通过 WebSocket / stdio / HTTP / 本地进程等方式访问外部系统
→ 这里外部系统就是 UE Editor 里的 bridge 插件。

所以你截图里 Codex 说的情况是合理的:UE 插件侧并没有启动 Node,它只是维护 WebSocket bridge;Node server 是由外部 MCP client 根据配置启动的。 图中提到 npx -y unreal-engine-mcp-server,这就是 Node 侧 MCP server 的启动方式。MCP 官方文档也把 MCP server 定义成给 AI 应用暴露工具、资源、能力的外部服务,而不是某个客户端私有功能。Model Context Protocol+1

关键点在这里:

你之前 Roo Code 能用 MCP,通常是因为项目里还有 .roo/mcp.json,或者全局 Roo 配置里还有 MCP server 配置。Roo 文档里也明确有 project/global MCP 配置的概念,例如 .roo/mcp.json 或全局 MCP 设置。Roo Code Docs+1

现在你换成 Codex 后还“能用”,可能有三种情况。

第一种:Codex 自己也配置了同一个 MCP server。Codex 使用的是自己的配置体系,官方配置参考是 config.toml,MCP server 通常会以 [mcp_servers.xxx] 形式登记,而不是天然读取 Roo 的 .roo/mcp.jsonOpenAI Developers 有些 MCP 项目会同时给 Cursor、Codex、Roo 等客户端提供配置示例,比如 Codex 侧常见是 .codex/config.toml~/.codex/config.tomlAwesome MCP Servers

第二种:虽然你删了 Roo Code 扩展,但项目里的 .roo/mcp.json 还在,Codex 或你当前项目中的某段脚本/插件逻辑把它当作参考读到了。严格说这不是 MCP 标准要求,而是具体工具/项目实现可以这么做。截图里 Codex 已经扫描到了 .roo/mcp.json,说明它至少把这个文件纳入了分析上下文。

第三种:MCP server 还在另一个地方以 Node 进程或 npx 方式被启动。删 VS Code 扩展不一定杀掉所有后台 Node 进程,也不一定删除 npm/npx 缓存、全局包、项目配置、UE 插件配置。MCP server 本质上只是一个可执行程序;只要有人启动它,它就还能工作。

bounded exponential backoff

退避的意思是:


第一次失败:1 秒后重试
第二次失败:2 秒后重试
第三次失败:4 秒后重试
第四次失败:8 秒后重试
……
最多不超过 30 秒

心跳超时说明什么?说明“某个已经建立的连接可能死了”。它不说明“UE 监听端口本身坏了”。

旧逻辑如果心跳超时后直接把所有 server socket 也打掉,会发生误伤:


Node 连接断了
UE 认为 bridge 整体坏了
于是关闭监听端口
重新启动监听

这会带来更大的不稳定。因为监听 socket 是“门口”,客户端连接是“已经进门的那个人”。某个人没回应,不等于你要把整栋楼大门拆掉。

多个端口主要是为了这些情况:


1. 兼容旧配置:以前 Roo 用 8765,后来 Codex 用 8766。
2. 多个外部工具可能默认连不同端口。
3. 调试时避免端口冲突。
4. 以后支持多个 UE Editor / 多个项目实例。
5. 旧 Node server 和新 Node server 迁移期间同时兼容。

不是要求你开多个端口,而是让“配置里如果有多个端口”时,代码别因为一个端口成功就误判全部成功。

是 UE Editor 进程里的 McpAutomationBridge 插件创建了一个 WebSocket server / socket listener。它会绑定到某个本地地址和端口,比如:


127.0.0.1:8765

绑定成功后,UE Editor 就处于:


我在这个端口等外部程序连进来

这个动作就叫 listening / 监听。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐