# u-space MCP

`u-space-mcp` 是面向 `u-space` 文档的 Model Context Protocol（MCP）服务器。它把当前文档打包成只读 MCP 工具，方便 Mastra、Claude Desktop、Cursor 等 MCP 客户端在回答 `u-space` API、插件和示例问题时直接检索官方文档，包括实验性 `u-space/worker` OffscreenCanvas runtime、`OffscreenViewerHost`、top-level await `createWorkerViewer()`、Worker command/事件桥接、`ModelLoaderManager.setDecodeWorker()` + `u-space/worker/model-decoder` 嵌套静态模型解码、transferable/ACK backpressure、普通图片超过 WebGPU `8192` 上限时的解码前缩放、Three.js 原生静态场景矩阵策略及其与 `setEditableBatching()` 的组合；核心 `src/batches` 导出的 `ModelInstancedLayer` 与 `EditableGeometryBatchLayer`；`TSLEffects.outline()` 可组合描边和 `InstanceObject` bounds proxy；`u-manager` 的 `UManagerLoader` 一体化加载入口、`SceneLoader` 语义去重、path-based model instancing 和 scene-specific editable batching adapter、Semantic/Facilities API，以及 atmosphere 和 fire 插件的 WebGPU 效果。

## 安装与启动

推荐通过 `npx` 使用已发布的 npm 包：

```json
{
  "mcpServers": {
    "uSpace": {
      "command": "npx",
      "args": ["-y", "u-space-mcp@latest"]
    }
  }
}
```

本地开发文档时，可以通过 `--docs` 指向仓库里的 docs 目录：

```json
{
  "mcpServers": {
    "uSpace": {
      "command": "npx",
      "args": [
        "-y",
        "u-space-mcp@latest",
        "--docs",
        "/Users/jiangqi/Desktop/xunwei/SoonSpace/u-space/docs"
      ]
    }
  }
}
```

也可以使用环境变量：

```bash
U_SPACE_DOCS_PATH=/path/to/u-space/docs npx -y u-space-mcp@latest
```

## Mastra 接入

在 Mastra 中通过 `MCPClient` 使用 stdio 形式接入：

```typescript
import { MCPClient } from '@mastra/mcp';

export const uSpaceMcpClient = new MCPClient({
  id: 'u-space-mcp-client',
  servers: {
    uSpace: {
      command: 'npx',
      args: ['-y', 'u-space-mcp@latest'],
      stderr: 'pipe',
    },
  },
});
```

然后把工具挂到 Agent 上：

```typescript
export const codingAgent = new Agent({
  // ...
  tools: {
    ...(await uSpaceMcpClient.listTools()),
  },
});
```

## 工具列表

`u-space-mcp` 只提供只读工具：

| 工具 | 说明 |
| :--- | :--- |
| `list_docs` | 列出可用文档页 |
| `search_docs` | 按关键词、API 名、插件名或概念检索文档 |
| `get_doc` | 按 path 或 id 读取单篇文档 |
| `get_api_reference` | 面向 API / 类 / 方法 / 插件的检索 |
| `find_examples` | 查找示例和用法相关文档 |
| `get_changelog` | 读取更新日志 |

## 示例检索

MCP 文档索引包含 `examples/test_outline.html`、`examples/test_umanager_loader.html`、`examples/test_umanager_dynamic_instances.html`、`examples/test_umanager2.html` 和 `examples/offscreen/test_umanager2_offscreen.html` 的说明。检索 `TSLEffects.outline`、`outline effect`、`instanceBoundsProxy` 或 `test_outline` 可以找到描边 API 与交互示例；检索 `UManagerLoader example`、`test_umanager_loader` 或 `UManagerLoader 用法` 可以找到一体化加载示例；检索 `dynamic instances`、`getInstanceById` 或 `test_umanager_dynamic_instances` 可以找到运行时实例编辑示例；检索 `setEditableBatching`、`SceneEditableBatchLayer`、`SceneEditableBatchFallback`、`editable batching`、`materialize` 或 `test_umanager2` 可以找到大型静态场景合批及其与 `SceneInstancedLayer` fallback 的关系；检索 `OffscreenCanvas`、`OffscreenViewerHost`、`host.init`、`initialized`、`ready`、`createWorkerViewer`、`ModelLoaderManager.setDecodeWorker`、`model-decoder`、`decode Worker`、`transferable`、`ACK backpressure`、`ImageBitmapLoader`、`maxTextureDimension2D`、`oversized texture`、`top-level await`、`u-space/worker`、`Worker WebGPU` 或 `test_umanager2_offscreen` 可以找到 Worker 渲染、嵌套静态模型解码、生命周期、事件/command 桥接、超大贴图缩放、editable batching、pipeline 预热和主线程/GPU 性能边界。

## OffscreenCanvas Worker 检索范围

| 关键词 / API | 可检索内容 |
| :----------- | :--------- |
| `OffscreenViewerHost` | 主线程 canvas 所有权、完整构造选项/方法/事件、`transferControlToOffscreen()`、pointer/wheel/resize 转发、renderer 滚动统计和 `request()` command 调用；`host.init()` / `initialized` 只等待 `viewer.init()`，业务资源完成由一次性 `ready` 表示。还包括 init canvas transfer/post 失败或初始化期间 dispose 的 Promise rejection/资源清理，以及 dispose 后忽略迟到业务消息的语义。 |
| `createWorkerViewer` | module Worker 顶层可直接 await 的命令式入口；同步安装 host 消息监听，完成 OffscreenCanvas/`viewer.init()` 后返回 `WorkerViewerRuntime`，提供状态、事件、command、逆序 dispose 和一次性业务 ready 生命周期、ready 前 fatal cleanup、去重 ArrayBuffer transfer，以及内置 `getStats` / `getViewpoint` / `setViewpoint` / `render` 命令。 |
| `ModelLoaderManager.setDecodeWorker` / `u-space/worker/model-decoder` | render Worker 创建第二个模型 decode Worker 的接线方式；静态 glTF/GLB/SBMX 支持范围，fetch/cache/SBMX/JSON/base64/ImageBitmap 工作边界，transferable 数据包、串行 ACK backpressure、有界贴图内容身份复用、LoadingManager URL/item 生命周期、跨域凭据隔离、节点图安全校验、完整 AbortSignal、故障回退，以及实例绑定的 Worker disposer。 |
| `test_umanager2_offscreen` | UManager Worker 示例启动方式、HDR/语义/场景加载、默认启用嵌套模型 decode Worker、`?modelDecodeWorker=off` A/B 开关、`setEditableBatching()`、`compileAsync()` 首帧预热、滚动帧率 HUD、标准透明合成、静态场景矩阵冻结/显式提交，以及默认显示全部语义对象且设备选择/飞向/高亮不改变其他对象显隐的调试策略。 |
| `ImageLoader` / `ImageBitmapLoader` / `maxTextureDimension2D` | Worker 普通图片加载兼容层、JPEG/PNG/GIF/WebP 编码尺寸预读、超过默认 `8192` limit 时的首次解码等比缩放、未知格式 fallback、源 bitmap 释放，以及 loader options/cache/request headers/abort 语义。 |
| `matrixWorldAutoUpdate` / `updateMatrixWorld` / `updateWorldMatrix` | 使用 Three.js 原生 API 冻结静态 Scene，按需提交单个对象或新增子树，并通过 `viewer.invalidate()` 请求新帧；单个 `InstanceObject.updateWorldMatrix(true, false)` 或父 Group 的 `updateWorldMatrix(true, true)` 仍会触发 dirty callback、instanced buffer 同步和 editable-batch materialize，相机矩阵继续独立更新。 |
| `OffscreenCanvas` + `setEditableBatching` | Offscreen 移走主线程解析/合并/渲染提交，editable batching 减少 draw submission；Three.js 对象必须留在 Worker，业务对象操作通过 structured-clone command 调用。 |

## InstanceObject 与 u-manager 检索范围

MCP 文档索引会同步 `docs/api-objects.md` 中的核心 `InstanceObject` API，以及 `docs/api-plugin-u-manager.md` 中的 u-manager 子类、加载器和合批层 API。客户端可以直接检索以下关键词：

| 关键词 / API | 可检索内容 |
| :----------- | :--------- |
| `UManagerLoader` | 同时加载 `SemanticLoader` 和 `SceneLoader`、自动复用 semantic id 去重、返回带 `semanticGroup` / `sceneGroup` 直接属性的 `UManagerSceneGroup`；可通过 `semanticGroup.getDefaultFacilityLayer()` 和 `sceneGroup.getDefaultSceneLayer()` 直接访问默认合批层。 |
| `InstanceObject` | 核心 `u-space` 导出 `InstanceObject`、`InstanceStyle`、`InstanceObjectOptions`、`InstanceIdentity`、`InstanceMaterializer`、`INSTANCE_COLOR_MODE_*` 和 `isInstanceObject()` 类型守卫；包括身份、样式、bounds、dirty、fallback render object，以及公共 `setInstanceMaterializer()` / ownership-aware `clearInstanceMaterializer()` / `materialize()` 协议；默认自动矩阵遍历和冻结根 Scene 后显式 `updateWorldMatrix()` 都会同步 batching 状态。实例可直接用于 `controls.flyToObject()`。 |
| `ModelInstancedLayer` | `SceneInstancedLayer` 与 `FacilityInstancedLayer` 的共享实现：模板 mesh 保持独立以保留透明排序和局部包围体，复杂静态几何在射线通过实例包围体后按需建立并复用 `three-mesh-bvh`；普通静态模型可对明确的热点 root 显式调用 `enableMeshBVHRaycast(root)`，不对整个大场景自动建树；同时提供合法 material groups、多材质 instancing、`getInstances()`、`getInstanceById()`、运行时实例新增/删除、capacity 预分配与扩容、重复 `instanceId` 拒绝加入、身份字段变化后按需刷新 id 索引、dirty-driven buffer sync、transform 变化后渲染前同步 instance matrix、raycast hit remap 和可选相机实例裁剪；内部索引使用实例独立字段，不依赖 `userData`。 |
| `EditableGeometryBatchLayer` | 核心 `src/batches` one-shot 公共类，接收 `Model` 模板和不重复的 `InstanceObject[]` source，按材质/Geometry 布局/阴影/renderOrder 烘焙合并静态 Geometry；每个 layer 独立维护矩阵状态，使用 `batchObjectIndex` + Float `DataTexture` + TSL 立即同步 dirty CPU 状态，返回带 `reasons` 的 unsupported source，支持同帧世界矩阵提交、跨 layer 旧副本隐藏、独立材质 materialize、typed event、materialized BVH hit 过滤、按实例 negative-scale fallback、安全 ownership dispose 和统计。 |
| `SceneLoader` | 场景树加载、语义 `ID` 去重、返回 `SceneGroup`、默认重复 3D 模型 path instancing，以及 opt-in `setEditableBatching({ maxVerticesPerBatch, maxIndicesPerBatch, freezeAnimations })` 静态 Geometry 合批；unsupported template/子 Mesh 安全 fallback，负缩放实例绕过 `InstancedMesh`，build 期间已 materialize 的实例不会重复进入透明 fallback。 |
| `SceneGroup` | `SceneLoader.loadAsync()` 返回根组，保留原始场景树层级，并通过 `sceneLayer` / `getDefaultSceneLayer()` 暴露主渲染层：默认是 `SceneInstancedLayer`，opt-in editable batching 且存在 merged Mesh 时是与其没有继承关系的 `SceneEditableBatchLayer`；只有 fallback 而无 merged Mesh 时返回 `null`。editable batch 统计位于 `userData.editableBatch`。 |
| `SceneInstanceObject` | `SceneLoader` 的单模型逻辑引用、`id` / `sid` 检索、`instanceKind = 'SceneInstances'`、统一显隐/颜色/透明度/高亮/bounds/dirty API，以及 editable batch 的 `materialize()`；世界 transform 或半透明变化时可只恢复当前普通 `Model`。 |
| `SceneInstancedLayer` | `SceneLoader` 内部批量渲染层、共享 `ModelInstancedLayer`、dirty-driven instance buffer 同步、raycast hit remap。 |
| `SceneEditableBatchLayer` | `EditableGeometryBatchLayer<SceneInstanceObject>` 的 u-manager 薄适配层，作为 opt-in 静态 Geometry 合并主层；通用 batching、materialize、内部 `BaseMesh`、不可见 raycast 短路和 lazy BVH 由核心层实现。`SceneLoader` 负责 URL source 与同级 `SceneEditableBatchFallback`（`SceneInstancedLayer`）/普通 `Model` fallback，并监听 typed `materialize` 事件移除对应 fallback instance。 |
| `FacilityInstanceObject` | 楼层下的设备引用、`objectManager.getById()` 全局检索、对象级包围盒缓存 + `controls.flyToObject()` 飞向单设备、统一 `setInstance*` 控制、fallback `Model` wrapper 和事件目标。 |
| `FacilityInstancedLayer` | `SemanticGroup.facilityLayer` / `SemanticGroup.getDefaultFacilityLayer()`、`getInstances()`、`getInstanceById()`、`reserveBatch()`、`addInstance()` / `addInstances()`、`removeInstance()` / `removeInstances()`（支持单个 `instanceId` 字符串）、`removeBatch()`、`clearBatches()`、batch 创建条件、`setInstanceCulling()`、动态 Facilities batch、可选按相机视锥压缩 active instances、可选 `minScreenRadius` 屏幕尺寸裁剪、dirty-driven instance buffer 同步和 raycast hit remap。 |
| `Facilities` | `SemanticLoader` 解析、`FloorMesh.getFacilityById()`、`FacilityInstanceObject.setInstanceOpacity()`、普通 `Model` fallback wrapper 与 scene-level instancing 的一致 API；`SemanticGroup` / `BuildingGroup` / `FloorMesh` 查询使用对象语义 ID、实例 `instanceId` 或显式别名，不扫描 `userData` ID。 |

## Effects 检索范围

MCP 文档索引会同步 `docs/api-effects.md` 中的 `MaterialEffects` / `TSLEffects` API，以及 `docs/examples-guide.md` 中的 Outline 示例。客户端可以直接检索以下关键词：

| 关键词 / API | 可检索内容 |
| :----------- | :--------- |
| `TSLEffects.outline` / `TSLOutlineEffect` | 通过 `RenderPipeline.addOutputEffect()` 接入描边、`setSelectedObjects()` 替换选择、`update()` 动态调参，以及 `removeOutputEffect()` 后 `dispose()` 的完整生命周期。 |
| `TSLOutlineOptions` | 可见/隐藏边缘颜色、强度、厚度、Glow、降采样比例，以及 `instanceBoundsProxy`、padding 和最小尺寸默认值。 |
| `InstanceObject outline` / `instanceBoundsProxy` | 优先使用实例的实际渲染对象或逻辑对象渲染子树；都不存在时由世界包围盒创建不可见代理，并随 dirty callback 更新。 |
| `test_outline` | Box、Sphere 与核心 `InstanceObject` 的交互选择、实时参数调整和 output-effect 资源释放示例。 |

## fire 检索范围

MCP 文档索引会同步 `docs/api-plugin-fire.md` 中的 FireEffect API、参数和示例。客户端可以直接检索以下关键词：

| 关键词 / API | 可检索内容 |
| :----------- | :--------- |
| `FireEffect` | 插件创建、`enable()`、`update()`、`setEmitter()`、`reset()`、`disable()` 和 `dispose()`。 |
| `fire` / `volumetric fire` | WebGPU 体积火焰、烟雾散射、curl noise、buoyancy、Jacobi pressure projection 和 raymarch 输出。 |
| `emitterGeometry` / `emitterRadius` | 默认 `TeapotGeometry(0.8, 28)`、自定义 emitter 几何、业务 `Object3D` matrix 驱动和移动扰动半径。 |
| `size` / `gridSize` | 体积盒世界范围、烟雾扩散边界和 3D 模拟网格尺寸。 |
| `addOutputEffect` | `FireEffect` 通过 RenderPipeline output effect 叠加体积 pass，不占用业务 `setOutputComposer()`。 |
| `keyLight` / `pointLight` | 体积阴影 spot light、跟随火焰核心的动态点光源和可关闭的内置光源。 |

## 包结构

源码位于 `packages/u-space-mcp`。本地兼容发布入口会先递增 `u-space-mcp` 的 patch 版本，再从 `docs/*.md` 生成内置文档索引、编译并通过当前 npm 登录态发布，因此启用 npm 2FA 时仍会请求 OTP：

```bash
pnpm publish:mcp
```

维护者发布完整版本时应使用 [`pnpm release:all`](./release)。该命令触发 GitHub Actions，通过 npm Trusted Publishing/OIDC 同时发布 `u-space` 与 `u-space-mcp`，不需要 `NPM_TOKEN` 或每次输入 OTP，并继续部署 docs 与 examples。

发布后的包不依赖本机绝对路径；只有在传入 `--docs` 或设置 `U_SPACE_DOCS_PATH` 时，才会读取本地文档目录。
