- 图形学
- 游戏开发
- 3D渲染
【免费下载链接】Babylon.js
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.
本文围绕 Babylon.js 仓库中的packages/tools/flow-graph-mcp-server展开,系统讲解这个为 AI 智能体设计的 MCP(Model Context Protocol)服务器:它如何让 LLM 通过标准工具调用创建、编辑、校验并导出 Flow Graph(可视化脚本图),以及导出的 JSON 如何被 Babylon.js 运行时与 Scene MCP 服务器消费。读完本文,你将掌握该服务器提供的全部 MCP 工具、资源与 Prompt,理解信号连接与数据连接、事件块out/done输出语义、丰富类型序列化格式等关键概念,并能复现"创建点击处理、可见性切换、点击移动其他网格"等典型交互图的完整构建流程。
一、Flow Graph MCP Server 是什么
Flow Graph 是 Babylon.js 中的可视化脚本系统:开发者以"事件块 + 执行块 + 数据块"组成有向图来描述场景交互逻辑。flow-graph-mcp-server把这套系统的"建图能力"包装成一组 MCP 工具,使 AI 智能体(或任何 MCP 客户端)能够:
- 创建(create)、查看(inspect)、校验(validate)、删除(delete)Flow Graph;
- 添加块(block),并连接数据端口(data port)或信号端口(signal port);
- 更新块的属性(property)与上下文变量(context variable);
- 导出 coordinator 级 JSON 或纯图级(graph-only)JSON;
- 导入此前导出的 Flow Graph JSON 继续编辑。
据 src/index.ts 的头部注释,该服务器从 Flow Graph 完整块目录中提供约 165 种块类型,传输层采用 MCP 标准的 stdio 传输(本地工具服务器的标准做法)。服务器名称与二进制名均为babylonjs-flow-graph(见 src/index.ts 中new McpServer({ name: "babylonjs-flow-graph", version: "1.0.0" }))。
与 Scene MCP 的分工
README 明确给出了集成分工:Flow Graph MCP 负责"建图并导出 JSON",Scene MCP 负责"把图挂到场景里"。导出的 coordinator JSON 可以交给 Scene MCP 服务器,通过attach_flow_graph工具(内联 JSON 或coordinatorJsonFile文件路径两种方式)附加到场景。这条链路正是 AI 驱动 Babylon.js 场景编排的关键一环。
二、设计原理:零运行时依赖的序列化数据模型
理解该服务器前,先看它的设计目标。在 flowGraphManager.ts 的文件头注释中明确写了两条:
- 无 Babylon.js 运行时依赖:MCP 服务器必须保持为轻量、独立的进程,它只操作一个镜像
FlowGraphCoordinator.serialize()输出的 JSON 数据模型,不加载 Babylon.js 引擎。 - 有状态且可增量编辑:manager 在内存中保存当前图,AI 智能体可以反复 add/connect/set,最后一次性导出;多个图可以按名字共存(
Map<string, InMemoryGraph>)。
这意味着整个建图过程发生在"纯 JSON 世界",不触碰引擎,天然适合需要逐步决策的 LLM 会话。
序列化格式与引擎侧的对应
Manager 中定义了与引擎序列化格式一一对应的接口(见 flowGraphManager.ts):
ISerializedConnection:连接点,含uniqueId、name、_connectionType(0=输入,1=输出)、connectedPointIds、richType(类型名与默认值)、optional、defaultValue等字段;ISerializedBlock:单个块的序列化形式,含className(如FlowGraphAddBlock)、config、uniqueId、四组连接点(dataInputs / dataOutputs / signalInputs / signalOutputs)、metadata;ISerializedContext:执行上下文,含_userVariables与_connectionValues;ISerializedFlowGraph:单张图,含allBlocks与executionContexts;ISerializedCoordinator:coordinator 顶层结构,含_flowGraphs数组与dispatchEventsSynchronously布尔开关。
引擎侧对应关系可以在 flowGraphCoordinator.ts 的serialize()方法中验证:它输出的正是serializationObject._flowGraphs = [...]与serializationObject.dispatchEventsSynchronously,与 Manager 的exportJSON()结构完全一致(flowGraphManager.ts 中exportJSON构造{ _flowGraphs: [serializedGraph], dispatchEventsSynchronously: false })。这也印证了 README 与工具描述中所说的:导出 JSON 可由FlowGraphCoordinator.parse()在运行时加载。
丰富类型的默认值
flowGraphManager.ts中维护了一张丰富类型默认值表,建块时写入每个数据端口的richType.defaultValue:
| 类型 | 默认值 |
|---|---|
any | undefined |
string | "" |
number | 0 |
boolean | false |
FlowGraphInteger | { value: 0, className: "FlowGraphInteger" } |
Vector2 | { value: [0, 0], className: "Vector2" } |
Vector3 | { value: [0, 0, 0], className: "Vector3" } |
Vector4 | { value: [0, 0, 0, 0], className: "Vector4" } |
Quaternion | { value: [0, 0, 0, 1], className: "Quaternion" } |
Matrix | 4x4 单位矩阵(16 个元素的数组,className: "Matrix") |
Color3 | { value: [0, 0, 0], className: "Color3" } |
Color4 | { value: [0, 0, 0, 0], className: "Color4" } |
Matrix2D/Matrix3D | 2x2 / 3x3 单位矩阵 |
三、构建与运行
仓库中该包位于 packages/tools/flow-graph-mcp-server,包名为@tools/flow-graph-mcp-server(见 package.json)。README 给出的构建与运行命令:
npm run build -w @tools/flow-graph-mcp-server npm run start -w @tools/flow-graph-mcp-serverpackage.json还提供了dev(tsc --watch增量编译)与clean(清空 dist)脚本;构建底层走rollup -c,配置文件复用 rollup.config.mjs 中从../rollup.config.mcp.mjs引入的通用 MCP 构建配置。服务器启动后,通过标准输入输出(stdio)与 MCP 客户端通信,日志输出到 stderr(src/index.ts 的Main()打印 "Babylon.js Flow Graph MCP Server running on stdio")。依赖方面,它基于@modelcontextprotocol/sdk、内部工具库@tools/mcp-server-core与zod(用于工具输入校验)。
二进制入口为:
babylonjs-flow-graph四、三个内置 MCP 资源(只读参考数据)
服务器注册了三个资源,供 AI 智能体随时查阅建图所需的元信息(src/index.ts):
flow-graph://block-catalog:完整块目录的 Markdown 摘要,由GetBlockCatalogSummary()生成,对应 blockRegistry.ts 中的静态目录。flow-graph://rich-types:数据连接使用的类型参考。除了上一节的类型默认值表,还明确给出序列化值格式:number:42、3.14;boolean:true、false;string:"hello";Vector3:{ "value": [1, 2, 3], "className": "Vector3" };Color3:{ "value": [1, 0, 0], "className": "Color3" };Quaternion:{ "value": [0, 0, 0, 1], "className": "Quaternion" };Matrix:{ "value": [16 个元素], "className": "Matrix" };- Mesh 引用:
{ "name": "myMesh", "className": "Mesh", "id": "mesh-id" }。
flow-graph://concepts:Flow Graph 概念文档,涵盖事件块/执行块/数据块的三角色模型、信号流与数据流的区别、常见交互模式、对象绑定方式与out/done陷阱(详见下文)。
五、核心概念:信号连接、数据连接与事件块陷阱
信号流 vs 数据流
Flow Graph 有两类连接,语义完全不同(flow-graph://concepts资源):
- 信号连接(Signal):控制"何时执行"。链路形如
Event → Execution Block → Execution Block → …,用connect_signal把源块的信号输出接到目标块的信号输入(默认名in)。它决定执行顺序,类似电路中的"控制线"。 - 数据连接(Data):控制"用什么值"。链路是"数据块的输出 → 执行块的输入",用
connect_data连接,携带类型化的值(message、condition、a、b等输入)。
事件块的out与done:最常见的坑
事件块通常有两个语义完全不同的信号输出(这也是服务器instructions与concepts资源反复强调的要点):
out:图启动时只触发一次(初始化),适合做 setup 逻辑;done:每次事件真正发生都触发(每次点击、每帧 tick),适合做交互响应。
因此:MeshPickEvent、PointerOverEvent、PointerOutEvent、SceneTickEvent的响应逻辑必须连done而非out;唯独SceneReadyEvent用out是正确的(场景就绪只发生一次)。例如经典的"点击切换可见性"模式:
MeshPickEvent.done → Branch.in (⚠ 用 'done',不要用 'out') GetProperty(visible).value → Branch.condition Branch.onTrue → SetProperty(visible=false).in Branch.onFalse → SetProperty(visible=true).in config.targetMesh 必须设置: { type: 'Mesh', name: 'myMeshName' }服务器对out→done误用做了三层防护:connect_signal会对事件块自动把out重映射为done(flowGraphManager.ts 的connectSignal中"Gap 32"逻辑,返回结果附带提示);validate_graph会检测"out已连接而done未连接"并给出警告(SceneReadyEvent除外);add_block在添加需要网格目标的事件块而缺少targetMesh时直接返回警告。
对象/网格绑定:显式连接 vs 配置默认值
GetProperty.object、SetProperty.object、MeshPickEvent.asset有两种绑定方式:
- 显式数据连接(推荐):用
connect_data把网格来源(pickedMesh/GetAsset.value/GetVariable.value)接到 object/asset 输入,在编辑器中可见可编辑; - 配置默认值:设置
config.object/config.target(Get/SetProperty)或config.targetMesh(MeshPickEvent)为网格引用{ name: 'myMesh', className: 'Mesh' },仅在不需要连线时使用。
底层实现中,flowGraphManager.ts的CONFIG_TO_INPUT_DEFAULT_ALIASES表记录了引擎构造器把配置键映射到数据输入的别名关系:targetMesh → asset、target → object。propagateConfigToInputDefaults()会把配置值写到对应数据输入的defaultValue上,使引擎与编辑器读到的默认值一致(这正是 examples/DefaultScene_ClickSphereColor.flowgraph.json 中FlowGraphMeshPickEventBlock的asset输入带有defaultValue: { className: "Mesh", name: "sphere" }的原因)。
一个进阶场景:点击一个网格、移动另一个网格(如点击球、把盒子向上移动 0.1)。此时"被点击的网格"与"被修改的网格"不是同一个,不能把pickedMesh接进 GetProperty/SetProperty 的 object 输入,而应给它们各自独立的网格来源:用GetAsset(配置{ type: 'Mesh', index: TARGET_INDEX })或GetVariable(配置{ variable: 'targetMesh' },配合set_variable预置网格引用),再把其.value分别连到 GetProperty/SetProperty 的 object 输入。
上下文变量
变量在图的多次执行之间持续存在,并可在块之间共享:SetVariable存值、GetVariable取值,导出前用set_variable工具初始化值(flow-graph://concepts资源)。序列化后变量保存在执行上下文的_userVariables中,如 examples/ToggleVisibility.flowgraph.json 里的"_userVariables": { "isVisible": true }。
六、完整工具参考
服务器注册了二十余个工具(src/index.ts),按职责分组如下。所有工具的参数均使用 zod schema 描述并校验。
图生命周期
| 工具 | 说明 |
|---|---|
create_graph | 在内存中新建空图,总是建图第一步;成功后返回 MCP Session URL |
delete_graph | 按名字删除图并关闭对应会话 |
clear_all | 清空内存中所有图,恢复干净状态 |
list_graphs | 列出内存中所有图名 |
get_session_url/start_session | 获取/开启某图的实时编辑会话 URL,可粘贴到 Flow Graph Editor 的 MCP 会话面板 |
close_session/stop_session_server | 关闭某图会话 / 停止整个 HTTP/SSE 会话服务器 |
create_graph只要求一个name参数(如'ClickHandler'、'AnimationController')。会话机制由@tools/mcp-server-core的McpEditorSessionController提供(默认端口 3001),使 Flow Graph Editor 能实时同步 MCP 端对图的每次修改(每次增删块、连线后都会调用_notifyIfSession)。
块操作
| 工具 | 说明 |
|---|---|
add_block | 添加块,返回块的数字id供连线使用;blockType来自目录(如'SceneReadyEvent'、'Branch'、'ConsoleLog'、'Add'、'SetProperty'),可选name与config |
remove_block | 删除块,并级联删除所有关联连接 |
set_block_config | 更新已有块的配置,键由块类型决定,可用get_block_type_info查询 |
add_blocks_batch | 一次添加多个块(比反复调用add_block高效),返回全部 id;支持type作为blockType的别名 |
常用config示例(add_block工具描述原文):
Constant:{ value: 42 }或{ value: { "value": [1,2,3], "className": "Vector3" } }GetVariable/SetVariable:{ variable: "myVar" }SetProperty/GetProperty:{ propertyName: "position" }、{ propertyName: "isVisible" }Sequence:{ outputSignalCount: 3 }Switch:{ cases: [0, 1, 2] }SendCustomEvent/ReceiveCustomEvent:{ eventId: "myEvent" }FunctionReference:{ code: 'function(params) { ... }' }MeshPickEvent:{ targetMesh: { type: 'Mesh', name: 'meshName' } }(必需,否则点击事件静默失效)
动态端口是建块时的隐藏行为:Sequence/MultiGate类块按outputSignalCount生成out_0、out_1…;Switch按cases数组生成case_0、case_1…;WaitAll按inputSignalCount生成in_0、in_1…(flowGraphManager.ts 的addBlock)。
连接操作
| 工具 | 说明 |
|---|---|
connect_signal | 源块信号输出 → 目标块信号输入(默认输出名out、输入名in);对事件块自动重映射out→done;输出/输入名均支持多个别名(signalOutputName/outputName/signalOut/outName) |
disconnect_signal | 断开某信号输出的全部目标 |
connect_data | 源块数据输出 → 目标块数据输入(如pickedPoint→message) |
disconnect_data | 断开某数据输入的全部来源 |
connect_signals_batch | 批量连接多个信号对 |
connect_data_batch | 批量连接多个数据对 |
数据连接在端口名上做了容错:当Constant块实际输出名是output而 LLM 常写value时,connectData会按别名表(value ↔ output)自动匹配(flowGraphManager.ts)。信号连接的数据结构方向也值得注意:信号连接时输出端记录输入端的uniqueId,数据连接时输入端记录输出端的uniqueId(对应引擎的反序列化约定)。
变量、查询与校验
| 工具 | 说明 |
|---|---|
set_variable | 设置图上下文变量;复杂类型用序列化格式(Vector3等) |
describe_graph | 返回整张图的 Markdown 描述:按分类分组的块、每条数据/信号连接、上下文变量 |
describe_block | 返回单个块的详细描述:类名、分类、配置、四组端口及连接状态 |
list_block_types | 列出全部块类型(可按Event、Execution、ControlFlow、Animation、Data、Math、Vector、Matrix、Combine、Extract、Conversion、Utility分类过滤) |
get_block_type_info | 查询某块类型的信号输入/输出、数据输入/输出(含类型、可选性)、config 键说明 |
validate_graph | 运行校验并返回问题列表,存在 ERROR 级问题时工具返回isError |
导入导出
| 工具 | 说明 |
|---|---|
export_graph_json | 导出 coordinator 级 JSON(可由FlowGraphCoordinator.parse()加载);graphOnly: true时只导出图级 JSON(适合嵌入 glTF 等格式);outputFile可写盘避免超大 JSON 挤占对话上下文 |
import_graph_json | 导入已有 JSON 到内存继续编辑;接受 coordinator 级或图级两种格式;支持内联json或jsonFile路径(二选一) |
import_graph_json内部走ValidateFlowGraphAttachmentPayload(见 sceneAttachmentValidation.ts)校验 payload,取graphs[0]重建内存图;对未知块类型会用_makeUnknownTypeInfo生成 Utility 分类的兜底类型信息,保证导入不断链(flowGraphManager.ts 的importJSON)。
七、标准工作流与配置容错机制
README 给出的典型工作流:
create_graph -> add_block -> connect_data/connect_signal -> set_block_properties -> validate_graph -> export_graph_json服务器指令文本(instructions)把这一流程补充为更完整的形式:create_graph → 添加事件块(入口点)→ 添加动作/逻辑块 → 连接信号(执行流)与数据(类型化值)→ validate_graph → export_graph_json。同时强调:每张图至少需要一个事件块作为入口、MeshPickEvent必须配置targetMesh、事件驱动逻辑用done而非out、输出 JSON 可交给 Scene MCP 的attach_flow_graph消费。
在配置容错上,flowGraphManager.ts提供了两类"对 LLM 友好"的机制:
- 配置键别名规范化(
_normalizeConfigAliases):把 LLM 常写的键名映射到引擎规范名,如variableName→variable、variableNames→variables、varName→variable、eventName→eventId,并支持大小写不敏感匹配; - 未知配置键警告:
add_block会对不在该块类型 config schema 中的键返回Unknown config key警告并提示已知键列表,帮助 LLM 自纠。
八、六个内置 Prompt:开箱即用的建图模板
服务器注册了六个 Prompt(提示词模板),每个都给出了可直接执行的建图步骤:
| Prompt | 用途 |
|---|---|
create-click-handler | 点击网格时记录拾取点:MeshPickEvent.done → ConsoleLog.in,数据连接pickedPoint → message |
create-toggle-visibility | 点击切换可见性:done → Branch.in,GetProperty(isVisible).value → Branch.condition,onTrue/onFalse分别驱动两个SetProperty(isVisible) |
create-click-move-other-mesh | 点击球移动盒子:网格来源用独立GetAsset/GetVariable,Add累加Constant(Vector3 0,0.1,0)后写入SetProperty(position) |
create-animation-on-ready | 场景就绪播放动画:SceneReadyEvent.out → PlayAnimation.in,GetAsset提供动画组,两个Constant分别接speed与loop |
create-tick-counter | 每 60 帧记一次数:SceneTickEvent+GetVariable/SetVariable+Add+Modulo+Equality+Branch |
create-state-machine | 变量驱动开关状态机:GetVariable(isActive)分支,两条路径分别SetVariable(false/true)并打日志 |
以create-toggle-visibility为例,其完整步骤为:create_graph 'ToggleVisibility'→ 添加带targetMesh配置的MeshPickEvent→ 添加GetProperty({ propertyName: 'isVisible' })并connect_data pickedMesh → GetProperty.object→ 添加Branch,connect_signal done → Branch.in、connect_data GetProperty.value → Branch.condition→ 添加两个SetProperty(isVisible的 false/true 版本)→connect_signal Branch.onTrue/onFalse → SetProperty.in→ 把pickedMesh接到两个SetProperty.object→validate_graph→export_graph_json。
九、校验规则:validate_graph 会检查什么
validate_graph(flowGraphManager.ts 的validateGraph)按以下规则输出 WARNING/ERROR:
- 图为空 →
WARNING: Graph is empty; - 缺少事件块 → 警告"至少需要一个事件块作为入口";
- 必需数据输入(非 optional 且无 config 默认值)未连接 → 警告;
- 执行块(有信号输出)没有入站信号连接 → 警告"可能永远不会执行";
- 信号输出 / 数据输入引用了不存在的连接目标 →ERROR(悬空引用);
MeshPickEvent/PointerOverEvent/PointerOutEvent既无targetMesh配置也未连接asset输入 → 警告"事件将静默失效";- 事件块
out已连接而done未连接(SceneReadyEvent除外)→ 提示"是否想连done"。
全部通过时输出OK: No issues found。单元测试 flowGraphManager.test.ts 覆盖了图生命周期、默认执行上下文、块添加、未知块类型拒绝、缺图错误、信号/数据连接与out→done重映射、coordinator JSON 结构校验(_flowGraphs、allBlocks、executionContexts、dispatchEventsSynchronously)等行为,可作为行为契约参考。
十、导出格式与仓库示例
导出结果以_flowGraphs数组包裹,顶层带dispatchEventsSynchronously(默认false)。仓库 examples 目录提供了 9 个完整示例(*.flowgraph.json),包括:
DefaultScene_ClickSphereColor.flowgraph.json:点击球切换漫反射颜色——MeshPickEvent+GetProperty(material)+FlipFlop+ 两个Constant(Color3)+ 两个SetProperty(diffuseColor);ToggleVisibility.flowgraph.json:点击盒子切换可见性,上下文预置isVisible: true;DefaultScene_ClickBoxJump、DefaultScene_ClickCylinderToggle、SphereClickRotateGround、AnimateOnReady、ClickLogger、SequentialSetup、TickCounter等。
这些文件与flowGraphManager.ts的导出结构逐字段对应,是最直观的"可运行格式参考"。
十一、与 Scene MCP 集成
README 的 Integration 一节给出了落地路径:将导出的 coordinator JSON 通过 Scene MCP 服务器的attach_flow_graph附加到场景,既支持内联 JSON,也支持coordinatorJsonFile文件路径。import_graph_json使用的ValidateFlowGraphAttachmentPayload与 Scene MCP 的附件校验共用同一套@tools/mcp-server-core工具库(sceneAttachmentValidation.ts),保证"Flow Graph 导出 → Scene 附加"链路中 JSON 格式的一致性。
十二、动手建议
- 按仓库构建:在仓库根目录执行
npm run build -w @tools/flow-graph-mcp-server与npm run start -w @tools/flow-graph-mcp-server,即可启动 stdio 服务器接入你的 MCP 客户端。 - 先读资源再动手:让智能体先读取
flow-graph://concepts与flow-graph://rich-types,能显著减少out/done混用、丰富类型格式错误等问题。 - 以小步验证:遵循
create_graph → add_block → connect_* → set_block_config → validate_graph → export_graph_json的顺序,每次add_block/连线后可用describe_graph复查,最后用validate_graph兜底。 - 善用模板与批处理:交互场景可从六个内置 Prompt 起步;需要建大量块/连线时用
add_blocks_batch、connect_signals_batch、connect_data_batch减少往返。 - 与示例对照:用
import_graph_json载入 examples 中的 JSON,再describe_graph,是理解"合法图长什么样"的高效路径。
- 图形学
- 游戏开发
- 3D渲染
【免费下载链接】Babylon.js
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.
相关推荐
perfetto-sdk-protos-gpu:Perfetto Rust SDK 的 GPU 事件 Protobuf 绑定 crate
perfetto sdk protos gpu:Perfetto Rust SDK 的 GPU 事件 Protobuf 绑定 crate 本文基于 Perfet
图形学游戏开发3D渲染如何看懂 cwc-workshops 的 runner.ts 验证运行器:React 组件验证四步流水线完整指南
如何看懂 cwc workshops 的 runner.ts 验证运行器:React 组件验证四步流水线完整指南 cwc workshops 是一个开源的 AI
图形学游戏开发3D渲染ChatGPT Shortcut 浏览器扩展使用指南:侧边栏、显示模式与 Alt+Shift+S 快捷键
ChatGPT Shortcut 浏览器扩展使用指南:侧边栏、显示模式与 Alt+Shift+S 快捷键 导读 :本文基于 ChatGPT Shortcut(A
AI 应用提示工程人工智能前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考