news 2026/10/1 2:03:48

使用 flow-graph-mcp-server 以 AI 驱动方式构建 Babylon.js Flow Graph

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 flow-graph-mcp-server 以 AI 驱动方式构建 Babylon.js Flow Graph
  • 图形学
  • 游戏开发
  • 3D渲染

【免费下载链接】Babylon.js

Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

项目地址:https://gitcode.com/gh_mirrors/ba/Babylon.js
点击查看免费下载

本文围绕 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 的文件头注释中明确写了两条:

  1. 无 Babylon.js 运行时依赖:MCP 服务器必须保持为轻量、独立的进程,它只操作一个镜像FlowGraphCoordinator.serialize()输出的 JSON 数据模型,不加载 Babylon.js 引擎。
  2. 有状态且可增量编辑: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:

类型默认值
anyundefined
string""
number0
booleanfalse
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" }
Matrix4x4 单位矩阵(16 个元素的数组,className: "Matrix")
Color3{ value: [0, 0, 0], className: "Color3" }
Color4{ value: [0, 0, 0, 0], className: "Color4" }
Matrix2D/Matrix3D2x2 / 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-server

package.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):

  1. flow-graph://block-catalog:完整块目录的 Markdown 摘要,由GetBlockCatalogSummary()生成,对应 blockRegistry.ts 中的静态目录。
  2. 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" }。
  3. 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有两种绑定方式:

  1. 显式数据连接(推荐):用connect_data把网格来源(pickedMesh/GetAsset.value/GetVariable.value)接到 object/asset 输入,在编辑器中可见可编辑;
  2. 配置默认值:设置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 友好"的机制:

  1. 配置键别名规范化(_normalizeConfigAliases):把 LLM 常写的键名映射到引擎规范名,如variableName→variable、variableNames→variables、varName→variable、eventName→eventId,并支持大小写不敏感匹配;
  2. 未知配置键警告: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 格式的一致性。

十二、动手建议

  1. 按仓库构建:在仓库根目录执行npm run build -w @tools/flow-graph-mcp-server与npm run start -w @tools/flow-graph-mcp-server,即可启动 stdio 服务器接入你的 MCP 客户端。
  2. 先读资源再动手:让智能体先读取flow-graph://concepts与flow-graph://rich-types,能显著减少out/done混用、丰富类型格式错误等问题。
  3. 以小步验证:遵循create_graph → add_block → connect_* → set_block_config → validate_graph → export_graph_json的顺序,每次add_block/连线后可用describe_graph复查,最后用validate_graph兜底。
  4. 善用模板与批处理:交互场景可从六个内置 Prompt 起步;需要建大量块/连线时用add_blocks_batch、connect_signals_batch、connect_data_batch减少往返。
  5. 与示例对照:用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.

项目地址:https://gitcode.com/gh_mirrors/ba/Babylon.js
点击查看免费下载
上一篇:从卡顿到丝滑:Redux Thunk如何拯救实时地图的状态管理
下一篇:3个技巧:用Sandboxie打造安全隔离的虚拟工作空间

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 2:03:20

路径分析实战:结构方程模型、效应拆解与Python实现

简介&#xff1a;面向社会科学、计量经济学等领域研究者及Python初学者&#xff0c;这份路径分析&#xff08;Path Analysis&#xff09;代码用于构建结构方程模型并量化变量间因果关系&#xff0c;写法简洁、结果直观。项目基于回归分析计算路径系数&#xff0c;借助NetworkX绘…

作者头像 李华
网站建设 2026/10/1 2:02:44

越省越费?杰文斯悖论揭示效率提升背后的能耗反弹

先别急着把这篇文章关了。我一开始看到“Jev”这个词也懵&#xff1a;这到底是个库&#xff1f;是个算法&#xff1f;还是某位网友的外号&#xff1f;后来翻了上下文才发现&#xff0c;大家口中的 Jev&#xff0c;大概率是 Jevons Paradox&#xff08;杰文斯悖论&#xff09;的…

作者头像 李华
网站建设 2026/10/1 2:01:14

C#超市管理系统源码实战:从数据库还原到事务与连接池

简介&#xff1a;基于C#与SQL Server 2008开发的超市管理系统源码与数据库包&#xff0c;适合需要学习桌面数据库应用开发的学生、初级程序员&#xff0c;也适合有超市信息化实践需求的项目使用者。系统覆盖商品管理、采购管理、销售管理、会员管理、库存预警与报表生成等业务模…

作者头像 李华
网站建设 2026/10/1 1:59:30

IT6122 MIPI到LVDS桥接芯片调试实战:从点屏到量产

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华