3D-MCP 是一个通用实现的 模型上下文协议,适用于 3D 软件。它创建了一个统一的 TypeScript 接口,使 LLM 能够通过单一连贯的 API 与 Blender、Maya、Unreal Engine 和其他 3D 应用程序进行交互。
// 不管底层 3D 软件是什么,LLMs 都使用相同的接口
await tools.animation.createKeyframe({
objectId: "cube_1",
property: "rotation.x",
time: 30,
value: Math.PI/2
});
3D-MCP 基于四个相互关联的架构原则,共同创建了一个统一的 3D 内容创作系统:
这种架构创建了依赖倒置,其中特定平台的实现细节被隔离到原子操作中,而大部分代码库则保持平台无关性。
┌─────────────────────────────────────────────────────────────────────────┐
│ LLM / 用户 API │
└───────────────────────────────────┬─────────────────────────────────────┘
│ MCP 工具 API
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 复合操作 │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ 建模工具 │ │ 动画工具 │ │ 骨骼绑定工具 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────────────┘ │
└───────────────────────────────────┬─────────────────────────────────────┘
│ 实现为
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 原子操作 │
│ │
│ ┌─────────── 实体 CRUD ────────────┐ ┌────────── 非 CRUD ─────────┐ │
│ │ create{Entity}s update{Entity}s ...│ │ select, undo, redo, etc. │ │
│ └────────────────────────────────────┘ └─────────────────────────────┘ │
└───────────────────────────────────┬─────────────────────────────────────┘
│ 插件服务器请求
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 特定平台适配器 │
│ │
│ ┌──── Blender ────┐ ┌────── Maya ─────┐ ┌─── Unreal Engine ────┐ │
│ │ createKeyframes │ │ createKeyframes │ │ createKeyframes │ │
│ └─────────────────┘ └─────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
实体优先设计被选择是因为:
CRUD 操作作为基础因为:
createCrudOperations原子和复合工具分离因为:
系统的基石是一个丰富的类型系统,该系统生成 CRUD 操作:
// 使用 Zod 定义具有丰富元数据的实体
export const Mesh = NodeBase.extend({
vertices: z.array(Tensor.VEC3).describe("顶点位置数组 [x, y, z]"),
normals: z.array(Tensor.VEC3).optional().describe("法线向量数组"),
// ... 其他属性
});
// 从实体模式自动生成 CRUD 操作
const entityCruds = createCrudOperations(ModelEntities);
// => 创建 createMeshs, getMeshs, updateMeshs, deleteMeshs, listMeshs
// 所有操作保留完整的类型信息
await tool.createRigControls.execute({
name: "arm_ctrl",
shape: "cube", // 如果不是有效的枚举值,则 TypeScript 错误
targetJointIds: ["joint1"], // 必须是字符串数组
color: [0.2, 0.4, 1], // 必须符合颜色模式格式
// IDE 自动完成显示所有必需/可选字段
});
实体模式提供:
┌──────────────────────────────────────────────────────────────┐
│ 核心实体定义 │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 基础实体 │ │ 节点基础 │ │ 其他核心实体 │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
▲
│ 继承
│
┌──────────────────────────────────────────────────────────────┐
│ 领域特定实体 │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 模型 │ │ 动画 │ │ 骨骼绑定 │ │
│ │ 实体 │ │ 实体 │ │ 实体 │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
│ 输入到
▼
┌──────────────────────────────────────────────────────────────┐
│ 自动生成 CRUD │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ createCrudOperations(Entities) │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
│ 生成
▼
┌──────────────────────────────────────────────────────────────┐
│ 原子操作 │
│ │
│ ┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ create{Entity}s │ │ get{Entity}s │ │ update{Entity}s │ .. │
│ └─────────────────┘ └──────────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│
│ 基础为
▼
┌──────────────────────────────────────────────────────────────┐
│ 复合操作 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 不需要特定平台代码。仅使用原子操作。│ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
系统创建了原子操作和复合操作之间的清晰分离:
// 来自 compounded.ts - 由原子操作组成的高级操作
createIKFKSwitch: defineCompoundTool({
// ... 参数和返回定义 ...
execute: async (params) => {
// 使用原子操作创建 IK 链
const ikChainResult = await tool.createIKChains.execute({/*...*/});
// 使用完整类型检查创建控制
const ikControlResult = await tool.createRigControls.execute({
name: `${switchName}_IK_CTRL`,
shape: ikControlShape, // 对模式进行类型检查
targetJointIds: [jointIds[jointIds.length - 1]],
color: ikColor,
// ... 其他参数
});
// 将控制定位在末端效应器处
await tool.batchTransform.execute({/*...*/});
// 创建约束以连接系统
await tool.createConstraint.execute({/*...*/});
// 返回标准化响应,带有创建的 ID
return {
success: true,
switchControlId: switchControlResult.id,
ikControlId: ikControlResult.id,
fkControlIds,
poleVectorId: poleVectorId || undefined,
};
}
})
这种架构提供了几个技术优势:
原子操作(约占系统的 20%):
复合操作(约占系统的 80%):
┌─────────────────────────────────────────────────────────────────────────┐
│ 高级工具定义 │
└──────────────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 复合工具模式 │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ defineCompoundTool({ │ │
│ │ description: string, │ │
│ │ parameters: zod.Schema, │ │
│ │ returns: zod.Schema, │ │
│ │ execute: async (params) => { │ │
│ │ // 完全由原子操作组成 │ │
│ │ await tool.atomicOperation1.execute({...}); │ │
│ │ await tool.atomicOperation2.execute({...}); │ │
│ │ return { success: true, ...results }; │ │
│ │ } │ │
│ │ }) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────┬─────────────────────────────────────┘
│ 插件服务器请求
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 平台适应性 │
│ │
│ ┌──────────────────────────┐ ┌─────────────────────────────────────┐ │
│ │ Blender 实现 │ │ Maya 实现 │ │
│ │ 的原子操作 │ │ 的原子操作 │ │
│ └──────────────────────────┘ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
复合工具架构的关键文件:
系统自动从 TypeScript 定义生成特定平台的实现:
┌─────────────────┐ ┌────────────────────┐ ┌─────────────────────────┐
│ 实体模式 │ │ 模式 │ │ 特定平台代码 │
│ & 工具 (TS) │ ──> │ 提取 (TS) │ ──> │ (Python/C++/等) │
└─────────────────┘ └────────────────────┘ └─────────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌────────────────────┐ ┌─────────────────────────┐
│ 类型 │ │ 参数 │ │ 实现 │
│ 定义 │ │ 验证 │ │ 模板 │
└─────────────────┘ └────────────────────┘ └─────────────────────────┘
生成系统的关键方面:
代码生成系统实现于:
系统按照镜像 3D 内容创作工作流的领域进行组织:
每个领域遵循相同的组织模式:
entity.ts: 领域特定的实体定义atomic.ts: 领域实体的原子操作compounded.ts: 由原子工具构建的高级操作packages/src/tool/
│
├── core/ # 核心共享组件
│ ├── entity.ts # 所有领域使用的基实体
│ ├── utils.ts # 包括 CRUD 生成在内的共享实用工具
│ └── ...
│
├── model/ # 建模领域
│ ├── entity.ts # 网格、顶点、面等
│ ├── atomic.ts # 原子建模操作
│ ├── compounded.ts # 高级建模工具
│ └── ...
│
├── animation/ # 动画领域
│ ├── entity.ts # 关键帧、AnimCurve、剪辑等
│ ├── atomic.ts # 原子动画操作
│ ├── compounded.ts # 高级动画工具
│ └── ...
│
├── rig/ # 骨骼绑定领域
│ ├── entity.ts # 关节、IKChain、控制等
│ ├── atomic.ts # 原子骨骼绑定操作
│ ├── compounded.ts # 高级骨骼绑定工具
│ └── ...
│
└── rendering/ # 渲染领域
├── entity.ts # 摄像机、灯光、渲染设置等
├── atomic.ts # 原子渲染操作
├── compounded.ts # 高级渲染工具
└── ...
系统实现了一种复杂的实体为中心的方法,其中:
实体作为领域模型:每个领域(建模、动画、骨骼绑定)定义其核心实体,代表其基本概念。这些实体作为带有丰富类型信息的 Zod 模式实现。
CRUD 作为基础:每个实体通过 createCrudOperations 实用工具自动接收一套完整的 CRUD 操作(创建、读取、更新、删除):
// 每个领域从其所有实体的 CRUD 操作开始
const entityCruds = createCrudOperations(ModelEntities);
const modelAtomicTools = {
...entityCruds, // 所有原子工具的基础
// 领域特定的操作在此基础上构建
}
实体复用和继承:在 core/entity.ts 中定义的核心实体被领域特定的实体扩展,促进代码复用和跨领域的设计一致性。
受 DDD 启发的架构:系统遵循领域驱动设计原则,围绕领域实体和聚合组织代码,而不是技术问题。
这种架构提供了几个关键好处:
丰富的实体模型与自动 CRUD 操作相结合,创建了一个强大的基础,简化开发同时保持灵活性以进行领域特定操作。
# 安装依赖
bun install
# 运行服务器
bun run index