Skip to main content
Glama
redcool

SimpleMcpServer

by redcool

SimpleMcpServer

让 AI 代理(Claude Code、OpenCode 等)通过 MCP 协议直接操作 Unity 场景。
必须配合 SimpleMCPBridge(Unity 侧桥接包)使用。

架构

AI Agent (Claude Code / OpenCode)
    │  MCP (stdio)
    ▼
SimpleMcpServer (Node.js/TypeScript)   ← 本仓库
    │  WebSocket
    ▼
SimpleMCPBridge (C#)                   ← 另一个仓库,需单独 clone 到 Unity Assets/
    │
    ▼
Unity Editor / Runtime
  • SimpleMcpServer(本仓库)— 处理 MCP 协议,注册工具,转发请求到 Unity

  • SimpleMCPBridgecompanion repo)— 在 Unity 内运行的 WebSocket 客户端,执行场景操作

除桥外,Server 也能作为 MCP 客户端 接入外部标准 MCP server(如 BlenderMCP), 把它们的工具以 <前缀>.<工具名> 暴露给 AI(如 blender.get_scene_info),见「外部 MCP 适配器」。

Related MCP server: Agent Bridge for Unity

前置条件

  • Node.js 22+

  • Unity 2022.3+ — 项目已安装 SimpleMCPBridge 包

  • npm — 随 Node.js 一起安装

验证 Node.js:

node --version   # 应输出 v22.x.x 或更高
npm --version    # 应输出 10.x.x 或更高

安装与设置

自动安装(推荐)

双击 setup.bat

手动安装

cd SimpleMcpServer
npm install
npm run build

使用

前置:安装 SimpleMCPBridge

cd YourUnityProject/Assets/
git clone https://github.com/redcool/SimpleMCPBridge_Unity.git SimpleMCPBridge

1. 启动 Unity Bridge(prefab 方式)

  1. 用 Unity 打开项目

  2. Assets/SimpleMCPBridge/Prefabs/MCPBridge.prefab 拖入场景(或给任意 GameObject 添加 MCPBridge 组件)

  3. 选中该对象,Inspector 顶部即显示连接状态(● Connected / ○ Disconnected)、ws://ip:port、Bridge ID 与 Connect / Disconnect 按钮

  4. Server IP / Port 默认 127.0.0.1:45678,如需修改见下方 bridge-config.json

Bridge 通过 [ExecuteAlways] 在 Edit Mode、Play Mode、打包运行三态下均工作;默认 isAutoReconnect=true,场景加载、进出 Play Mode、脚本重编译(domain reload)后自动重连,无需手动操作。

bridge-config.json(可选,默认即可用)

Bridge 启动时自动加载配置——配置文件不存在时,首次自动从包内 Resources/bridge-config.json 拷贝生成(已存在则不覆盖),改完需重启生效

环境

路径

Editor

项目 Assets/SimpleMCPBridge-config/bridge-config.json

Player

Application.persistentDataPath/bridge-config.json

兜底

包内 Resources/bridge-config.json(内嵌默认值)

{ "serverIp": "127.0.0.1", "serverPort": 45678, "encryptionKey": "" }
  • serverIp/serverPort — 与 Server 侧 config.jsonip/port 对应

  • encryptionKey — 与 Server 侧 encryptionKey 一致时启用 AES-256-CBC 载荷加密;空 = 透传

  • methodBlocklist / methodAllowlist(可选)— scene.call_component_method 权限控制,详见桥 README

2. 启动 MCP Server

推荐:在独立 cmd 窗口运行(不占用 AI 工具的终端)

# 在 PowerShell 或 cmd 中执行:
Start-Process -FilePath "cmd.exe" -ArgumentList "/K", "cd /d path\to\SimpleMcpServer && start.bat"

或者在文件管理器双击 start.bat 也会弹出 cmd 窗口。

# 编译 + 启动(直接在当前终端)
start.bat

# 跳过编译(代码未改时)
start-quick.bat

连接成功输出:

[Server] Bridge connected
[Server] Registered N tool(s) from bridge [ID: xxxx]
[Server] Ready (ws://127.0.0.1:45678)

3. 配置 AI 代理

{
  "mcpServers": {
    "unity": {
      "command": "node",
      "args": ["path/to/SimpleMcpServer/dist/index.js"]
    }
  }
}

支持的传输端点

传输

端点

说明

Streamable HTTP(推荐)

GET/POST /mcp-stream

MCP 2025-11 规范推荐传输(GET=SSE 事件流 + POST=JSON-RPC),新客户端优先用这个

SSE(legacy)

GET /sse + POST /mcp?sessionId=...

旧版 MCP SSE 传输,为兼容旧客户端保留

直接 JSON-RPC

POST /rpc

非 MCP 会话协议,供脚本/测试直接用(如 autobot)

AI 代理若走网络连接本 Server(非 stdio),urlhttp://<host>:45678/mcp-stream(推荐)或 /sse

4. 验证连通性

node tests/test-e2e.cjs

预期输出:*** TEST PASSED ***

对象寻址

Unity 侧的场景工具同时支持两种方式定位 GameObject:

参数

说明

instanceId

Unity 实例 ID,精确唯一,但 domain reload 后失效

path

Transform 路径(如 "Canvas/Panel/Button"),跨 domain reload 有效

解析优先级:instanceId > pathget_hierarchyget_objects 的返回值同时包含两者。

外部 MCP 适配器(plan C:接入社区 MCP server)

除了直连自家桥(WebSocket wire protocol),Server 还能作为 MCP 客户端 对接外部标准 MCP server,把它们的工具以 <toolsPrefix>.<工具名> 暴露给 AI。社区生态(BlenderMCP、UE MCP 等)无需重写桥即可接入,且与桥工具并存/rpc/mcp 均可用)。

配置(config.jsonmcpServers 段,改后重启生效):

"mcpServers": [
  { "name": "blender", "command": "uvx", "args": ["blender-mcp@1.9.1"], "toolsPrefix": "blender" }
]

mcpServers 条目字段:

字段

必填

说明

name

适配器名(进程名/日志/去重 key)

command

启动外部 MCP server 的命令(如 uvx 的绝对路径;PATH 里可直接写 uvx

args

可选

命令行参数(推荐 pin 版本,如 ["blender-mcp@1.9.1"]

env

可选

注入给子进程的额外环境变量(如 {"BLENDER_PORT":"9877"} 指向第二个 Blender 实例)

toolsPrefix

可选

工具前缀,默认 = name(工具以 <前缀>.<工具名> 暴露)

enabled

可选

false = 不启动该适配器(免删条目临时下线)

  • command / args — 以 stdio 启动外部 MCP server(推荐 pin 具体版本,防上游漂移)

  • 生命周期:服务器启动时 spawn 并 tools/list 拉取工具表;子进程退出后按 10s→30s→60s→120s 指数退避自动重连(外部应用如 Blender 重启后无需重启本 Server)

  • 工具名冲突时 adapter 优先(先于桥工具合并)

  • 危险工具门:名字以 .execute_* 结尾的任意代码执行类工具(如 blender.execute_blender_code)与内置 editor.eval 同策略——evalEnabled=false列表隐藏 + 调用拒绝

  • MCP image 块返回(如视口截图)自动落盘到 mcp-media/ 并返回路径,不塞进文本

接入步骤(以 Blender 为例)

适配层对接的是社区 BlenderMCP(ahujasid/blender-mcp,v1.9.1 实测)。对外部用户来说:AI 客户端接本 Server(MCP),Server 接 Blender(经 blender-mcp),全程只需两步安装 + 配一行配置。

① Blender 侧——安装 MCP addon(一次性,需在本机装过 uvx/uv

uvx blender-mcp install-addon    # 写入 %APPDATA%\Blender Foundation\Blender\<版本>\scripts\addons\

② Server 侧——config.jsonmcpServers(本仓库已内置 config.json.template 示例)

"mcpServers": [
  { "name": "blender", "command": "uvx", "args": ["blender-mcp@1.9.1"], "toolsPrefix": "blender" }
]

版本一致性:addon 与 blender-mcp 的版本建议一致(协议握手 ADDON_PROTOCOL_VERSION 校验,不一致连接会失败)。

③ 启动 Blender 窗口实例:addon 的 Auto-Start Server 选项默认开启——在任何 Blender 窗口的偏好设置里启用一次 addon(保存偏好)后,该实例每次启动都会自动启用 addon 并自动起 socket(默认端口 9876)。如需全自动(首次启用也不用手点),可在 Blender 用户目录 scripts/startup/ 放一个 addon_utils.enable 的小脚本(团队环境做法见 AGENTS.md 相关记录)。本仓库提供了多实例启动脚本:

pwsh scripts\start-blender-instance.ps1 -Instance 1

④ 验证

# /rpc tools/list 应见 blender.* 工具
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"blender.get_scene_info","arguments":{"user_prompt":""}}}

链路(实测通过,2026-09):AI → Server(adapter) → uvx blender-mcp(stdio) → TCP 9876 → Blender addon → bpy。实测全流程:建低多边形树(建模 → smart_project UV → 平滑 + Principled 材质 → 视口截图落盘 mcp-media/)可用。

多 Blender 实例(同时开多个窗口,各自独立控制)

原理:每个实例 = 独立 socket 端口 + 独立的 blender-mcp 进程(适配层本来就按 mcpServers 条目逐条 spawn)+ 独立工具前缀。端口分配:实例 N → 9875+N(实例1=9876,实例2=9877…)。

  1. 起实例(脚本注入 BLENDER_MCP_PORT 环境变量;Blender 的 startup 脚本 blender_mcp_auto.py 据此用对应端口起 addon socket):

pwsh scripts\start-blender-instance.ps1 -Instance 2        # 第 2 个窗口 → 端口 9877
pwsh scripts\start-blender-instance.ps1 -Instance 2 -BlendFile D:\proj\a.blend
  1. config.json 每条实例加一条 mcpServersenv.BLENDER_PORT 与实例端口对应):

"mcpServers": [
  { "name": "blender",  "command": "<uvx>", "args": ["blender-mcp@1.9.1"], "toolsPrefix": "blender" },
  { "name": "blender2", "command": "<uvx>", "args": ["blender-mcp@1.9.1"],
    "env": { "BLENDER_PORT": "9877" }, "toolsPrefix": "blender2" }
]
  1. 重启 Server → tools/list 同时出现 blender.*blender2.*,调用完全隔离(各自查/改的是对应窗口的场景)。

补充:同一实例内切换 .blend 工程不需要任何配置——socket 是进程级的,agent 看到的就是该窗口当前打开的工程。

安全须知(Blender 接入必读)

  1. blender.execute_blender_code = 任意代码执行:可在 Blender 内运行任何 Python(含 os/文件/网络)。它受 evalEnabled 门控(config.json):置 false 后该工具从列表消失且调用被拒。仅在可信环境开启

  2. addon socket 仅监听本机回环BlenderMCPServer 默认 bind localhost:9876,不暴露局域网——不要改 host 为 0.0.0.0 或做端口转发,否则局域网内的 MCP 客户端可直连你的 Blender。

  3. 遥测默认开启:BlenderMCP 的 Allow Telemetry 偏好默认勾选,收集 prompt/代码/截图/轨迹数据。关闭:Blender 偏好面板「MCP for Blender」取消勾选,或调用 blender.disable_telemetry 工具。

  4. 供应链blender-mcp 建议 pin 版本(示例已 pin @1.9.1),addon 同样按该版本安装,避免上游意外更新破坏行为。

  5. 权限边界:AI 对 Blender 的操作 = Blender 进程所属用户的权限(可读写本机文件、调网络)。等同于把"本机 Python 执行权"交给 AI。

  6. 退出接入:删掉/注释 mcpServers 块,或在条目内加 "enabled": false,重启 Server 即断开(不卸载 Blender 侧任何东西)。

  7. 已知坑:Blender 中文界面下默认对象名是本地化的(如 primitive_cube_add 生成 "立方体" 而非 "Cube.001"),脚本建议显式 o.name=...;经 PowerShell 传中文参数需显式 UTF-8 编码。

高层模板工具(本仓库预置的 blender.* 快捷工具)

除透传的 blender-mcp 原生工具外,Server 内置一组高层 Blender 模板工具(建模/骨骼/动画/导出,无需 AI 写 bpy 脚本):blender.rig.humanoidblender.rig.auto_weightsblender.anim.loopblender.anim.quadrupedblender.mesh.primitiveblender.mesh.booleanblender.body.build(参数化四足/人形体块)、blender.scene.export

完整用法、参数表与典型工作流(如"一句话生成会走的四足动物")见 docs/blender-mcp-template-tools.md。所有模板工具均受 evalEnabled 门控,并接受通用参数 adapter 指定目标 Blender 实例。

可用工具

工具由 Unity Bridge 通过 register_tools 动态注册,数量随桥接平台/条件编译变化(当前 Editor 桥实测 127 个桥工具 + 服务端合成 2 个 = 129 个)。下表按类别简述常用工具;完整清单见 SimpleMCPBridge 仓库 README。

场景工具(SceneHandler)

工具

说明

scene.get_hierarchy

获取场景层级树(含 path、instanceId、组件名、位置)

scene.get_objects

查找对象,可选按 nameContains 过滤,返回 path + instanceId

scene.create_object

创建 GameObject,支持 name / parentPath / position / rotation / scale

scene.delete_object

按 instanceId 或 path 删除对象

scene.set_transform

按 instanceId 或 path 设置 position / rotation / scale

scene.set_component_property

修改组件字段/属性,支持 Vector3、Color、Enum 等类型

scene.get_components

按 instanceId 或 path 获取 GameObject 所有组件列表

scene.get_component_properties

获取组件所有可序列化属性名和当前值

scene.set_active

按 instanceId 或 path 启用/禁用 GameObject

scene.duplicate_object

按 instanceId 或 path 复制 GameObject

scene.rename

按 instanceId 或 path 重命名 GameObject

scene.set_parent

按 instanceId/path 设置父级,parentPath/parentId 指定父对象(留空则解除到根)

scene.add_component

按类型名添加组件(如 Rigidbody)

scene.instantiate_prefab

按 assetPath 实例化预制体到场景,支持 transform 和 parent(仅 Editor)

scene.set_material

修改运行时材质颜色/纹理。资产级修改建议直接改 .meta GUID

scene.enter_play_mode

进入播放模式(仅 Editor)

scene.exit_play_mode

退出播放模式(仅 Editor)

scene.pause_play_mode

暂停/继续播放模式 — 传 paused: true/false(仅 Editor)

scene.get_play_mode

获取当前播放模式状态 — 返回 isPlaying/isPaused/mode(仅 Editor)

scene.load_scene

加载场景(按 Assets 路径,支持 .unity 后缀省略)(仅 Editor)

scene.save_prefab

将 GameObject 保存为预制体(仅 Editor)

scene.call_component_method

调用组件公开方法,带黑名单/白名单权限控制

资源工具(AssetHandler,仅 Editor)

工具

说明

asset.find_assets

按名称和/或类型搜索项目 Assets。参数:nameContains(可选)、typeFilter(可选,如 "Prefab""Material")。返回 {path, name, type, guid} 列表

asset.find_references

查找引用了指定资源的所有资源(反向依赖)。参数:assetPath(必填)。扫描文件内容中的 GUID,返回引用者列表。可靠但较慢

asset.create

创建资源(材质/文件夹等)(仅 Editor)

asset.delete

删除资源(带引用预检,force 可跳过)(仅 Editor)

asset.rename

重命名资源(仅 Editor)

asset.move

移动资源到新路径(仅 Editor)

录制工具(RecordingHandler)

工具

说明

recording.start

开始录制 Game 视图画面。仅 Play Mode 可用。可选参数:width/height/fps/videoBitRate/enableAudio/keyframeInterval

recording.stop

停止录制并导出 MP4(异步)。返回后调用 recording.status 轮询完成状态

recording.status

查询录制/导出状态 — 返回 isRecording/elapsedSeconds/state/exported filePath

保存位置:

  • PC: 项目根目录 VideoRecord/(Assets 同级)

  • Android/iOS: app 临时目录 {temporaryCachePath}/VideoRecord/

编辑器工具

工具

说明

editor.request_compile

触发 Unity 脚本重新编译(外部修改 C# 后用)(仅 Editor)

editor.open_window

按菜单路径打开 Unity Editor 窗口,如 "Window/General/Console"(仅 Editor)

PlayerPrefs 工具(PlayerPrefsHandler)

工具

说明

playerprefs.get_all

读取全部 PlayerPrefs(按 key 过滤可选)

playerprefs.get

读取单个 key

playerprefs.set

设置 key(自动类型推断)

playerprefs.delete

删除 key(支持通配符)

UI Toolkit 工具(UIToolkitHandler)

工具

说明

uitk.create_element

在指定面板创建视觉元素

uitk.remove_element

移除视觉元素

配置

编辑 config.json(不存在时首次启动自动从 config.json.template 复制生成,见「首次运行」)。完整字段:

{
    "ip": "0.0.0.0",
    "port": 45678,
    "encryptionKey": "",
    "encryption": false,
    "evalEnabled": true,
    "allowedIps": ["127.0.0.1", "::1"],
    "llm": { "enabled": true, "provider": "agnes", "baseUrl": "https://apihub.agnes-ai.com/v1", "apiKey": "YOUR_API_KEY_HERE", "model": "agnes-2.0-flash", "temperature": 0.7, "maxTokens": 1024 },
    "webSearch": {
        "order": ["serper", "google", "bing", "ddg-html", "ddg-lite"],
        "region": "zh-CN",
        "serper": { "apiKey": "" },
        "google": { "apiKey": "", "cx": "" },
        "providerTimeoutMs": 15000,
        "cooldownMs": 60000
    }
}
  • ip/port:监听地址与端口。本地 127.0.0.1,云端 0.0.0.0

  • encryption/encryptionKey:可选 AES-256-CBC 载荷加密(替代 TLS/wss),Server 与 Bridge 配置需一致;空密钥 = 透传

  • evalEnablededitor.eval 工具开关(默认 true,以用户方便为先 —— 开发调试/快速原型/补救缺口工具时即时可用)。falsetools/list 不暴露 editor.eval 给 agent。风险:eval 执行任意 C# = 完全机器控制,任何能调 /rpc 的 AI 可执行任意代码(读写文件、删资产、网络访问);不可信环境(共享机器/公网暴露)务必关闭或扩 allowedIps 白名单。Editor 侧另有 EditorPrefs SimpleMCPBridge_EvalEnabled 二次 gate,见桥 README「Editor Eval 开关与安全说明」

  • allowedIpsIP 白名单(本版本新增)——只放行白名单内的客户端访问 HTTP /rpc/sse/mcp 端点、WebSocket / 桥接通道以及 /ab 资产端点,其余连接返回 403(WS)或 404(HTTP);默认 ["127.0.0.1","::1"] 仅本机。配置缺失时自动从 config.json.template 复制生成 config.json(首次启动自动创建,见「首次运行」)字段缺失/为空数组/非数组时回退到默认 ["127.0.0.1","::1"](仅本机)

  • llm:LLM 配置(apiKey 用环境变量 LLM_API_KEY 覆盖更安全;config.json 已被 .gitignore 排除,勿提交真实 key)

  • webSearchweb.search 工具的多引擎配置(改动后重启生效)

    • order:引擎优先级(默认 serper → google → bing → ddg-html → ddg-lite),按序尝试,失败自动降级;未配置凭据的引擎自动跳过

    • region:中文查询的语言区域(默认 zh-CN),Serper/Google/必应/DDG 会带上对应 gl/hlmktkl 参数,显著改善中文搜索质量

    • serper可选(推荐)——填 apiKeySerper.dev,Google 搜索结果 API,免费约 2500 次/月、免信用卡、需 Google 可达的网络——公司网络可用)即可启用。服务器启动时会探测 google.serper.dev 可达性——大陆网络(Google 不可达)自动回退 Bing/DDG,无需改配置;成功率/延迟最佳,中文质量 = Google

    • google可选——Programmable Search JSON API(对新用户已关闭,仅老 key 可在 2027-01-01 前使用),留空自动跳过

    • providerTimeoutMs:单引擎请求超时(默认 15s;Serper/Google 探测用其中最多 5s)

    • cooldownMs:某引擎连续失败 ≥2 次后的冷却时间(默认 60s;防止被墙引擎每次拖慢所有搜索)

开发

npm run dev           # tsx 监听模式
node tests/test-e2e.cjs  # E2E 测试

# 目录结构
src/
├── index.ts           # 入口(启动 server)
├── server.ts          # WS Server + MCP handlers(核心)
├── bridgeState.ts     # bridge 连接状态/路由(last-registration-wins、failover)
├── ab.ts              # AssetBundle 上传/部署端点
├── crypto.ts          # AES-256-CBC 载荷加密(#ENC# 前缀)
├── config.ts          # config.json 加载(缺失时从 template 生成)
├── llm.ts             # LLM 代理(ai_request/ai_response)
├── logger.ts          # 日志(stderr + server.log,脱敏)
├── tools.ts           # 服务端合成工具(bridge.list / bridge.call)
└── types.ts           # 类型定义
tests/
├── test-e2e.cjs           # E2E 测试(initialize + tools/list + get_hierarchy)
├── test-playmode-cycle.cjs # Play Mode 循环测试(进出播放验证 bridge 自动重连)
└── auto-test-android.ps1  # Android 全流程自动化测试

故障排查

"WebSocket server error: listen EADDRINUSE" → 端口被占用,杀掉残留进程:

Get-Process -Name "node" | Stop-Process -Force

"Unity not connected" → Unity 没打开,或 SimpleMCPBridge 没启动

Bridge 进出 Play Mode 后断连 → 确认 Unity 菜单 Edit → Project Settings → Editor → Enter Play Mode SettingsReload Domain 已开启。Bridge 依赖 [InitializeOnLoad] 在 domain reload 后重新订阅 EditorApplication.update。如关闭 Domain Reload,Bridge 连接会在 Play Mode 期间保持,但退出后无法自动重连。

测试超时 → E2E 测试会启动自己的 Server 实例,Bridge 需要通过重试循环重连到新 Server

HTTP 调用返回 403 → 请求源 IP 不在 allowedIps 白名单。修改 config.json 的 allowedIps 加来源 IP 后重启服务端。

相关仓库

仓库

说明

SimpleMcpServer

本仓库 — MCP Server,Node.js 端

SimpleMCPBridge

Unity 桥接包,clone 到 Unity 项目的 Assets/

技术说明

  • MCP SDK v1.x 低阶 API(setRequestHandler),不用 registerTool()(该 API 在 connect() 后抛出异常)

  • WebSocket 通信(ws 库),IP/Port 来自 config.json

  • 工具通过 register_tools 消息从 Bridge 动态注册到 Server,Bridge 重连后自动重新注册

  • Unity Bridge 活动传输为 .NET ClientWebSocketNetWebSocketClient 封装,BridgeClient.ConnectToServer() 创建);旧版纯 TCP RFC 6455 实现(WebSocketClient)已标记 [Obsolete] 仅作参考

  • Server 同时暴露 HTTP /rpc 端点用于程序化调用(E2E 测试使用)

  • /health 端点返回 bridge 连接状态、工具列表、播放模式状态

  • HTTP /rpc/sse/mcp 端点受 allowedIps 白名单 gate(403);WebSocket 桥接通道(1008 Forbidden)与 /ab 端点同样受白名单控制

  • 消息负载上限 4MB(maxPayload)

  • 服务端每 ~30s ping、超时未 pong 判定失活并 terminate() 断连(isAlive 心跳)

  • 日志脱敏:工具名 + 参数长度(不打印明文 payload),错误路径保留详情

  • config.json 不存在时首次启动自动从 template 复制生成;改完配置重启生效

  • 进程级安全网:uncaughtException / unhandledRejection handler 记日志后继续运行(不崩进程),防单个坏工具响应或未捕获 rejection 带走整个 relay(丢连接 + retryQueue + 在途调用)

Related MCP Connectors

Related MCP Servers