中文  |  English

济宁米多信息科技有限公司

从零打通 MCP 访问创世虚拟世界CRM的 3D 数据,我搭了一个可直接调用的演示站

创世虚拟世界CRM、MCP server 3D 世界、MCP 访问 3D 数据、agent-virtual-world、AI 智能体进虚拟世界、MCP Streamable HTTP 实战、MCP 踩坑、自部署 3D 平台 MCP、创世 Genesis

先说结果:现在任何一个支持 MCP 的 AI 宿主(Claude Desktop、Cursor、Cline……)接上我的服务后,工具列表里会多出 8 个 world_ 开头的工具——AI 能以一个看得见的角色走进一个真实的多人 3D 世界:观察周围有什么、走到真人旁边、开口说话,你在浏览器里全程围观。

演示站已经开着,随时可以测(文末有地址和两种玩法)。这篇讲的是打通过程:3D 世界的结构化数据是怎么一步步变成 MCP 工具的,路上踩了哪些坑——每个坑都有实录,不是回忆滤镜。

一、起点:世界有一套 Agent 通道,但每次都要写代码

我的 3D 世界(创世Genesis,浏览器端自部署)早就有一套 AI Agent 接入通道:放一个发现文件(/.well-known/virtual-world-agent.json),用 Key 换会话令牌,连上 /ws/agent,AI 就能拿到结构化数据——附近有谁(空间雷达)、面前是什么(物体 AI 描述)、刚发生了什么(事件流),然后执行走动、说话、跟随这些动作。

问题是:这套通道的形态是 HTTP + WebSocket + 一堆 JSON 约定。每个想让 AI 进世界的人,都得照着文档写一个客户端脚本。会写代码的团队无所谓,但大多数 AI 宿主的用户只想说一句"去那个世界逛逛"。

MCP 正好是干这个的:把一套能力封装成标准工具,所有支持 MCP 的宿主直接调用。所以我做的事本质上是一层翻译——把已有的 Agent 通道翻译成 8 个 MCP 工具,不新造任何后端能力。

二、stdio 版:8 个工具怎么切

切工具的原则是"AI 在世界里的动作原语",不多不少:

工具作用关键限制
world_discover读世界的公开发现文档:世界名、是否开放接入、能力与限流无需凭证
world_enter进入世界(建会话 + 连 WebSocket,真人从此能看到它)幂等,重复调用不会重复入场
world_observeAI 的眼睛:附近的人/物体/传送点的文字描述与距离游客 30m、1 次/2 秒
world_say说话(30m 内真人可见气泡)1 条/5 秒、限 200 字
world_walk_to走到坐标(有真实走路动画)1 次/2 秒;位移只有这一条路
world_follow按 id 跟随某个玩家长时任务,立刻返回
world_chat_history读最近聊天历史数据,不是实时推送
world_leave离场(形象消失)下次调用工具会自动重进

服务端红线原样保留:没有 teleport,没有 set_position——MCP 侧绝不包装绕过。AI 要移动,就只能像真人一样一步步走。

另配一个 Resource(virtual-world://guide,世界导览)和两个 Prompt(漫游引导、观察报告),AI 一连上就知道这个世界是什么、规矩是什么。

三、stdio 版踩坑实录

坑 1:stdout 是协议通道,混进一个字符全完。 MCP stdio 传输里,stdout 只能出现 JSON-RPC。开发时顺手一个 console.log 打调试信息,宿主直接报协议解析错误。所有日志必须走 console.error——这条现在写进了仓库的开发约束。

坑 2:initialize 请求少一个字段,服务端不应答。 手写客户端测试时,initialize 必须带 protocolVersion、capabilities、clientInfo 三个字段,缺一个就没有响应。这不是包的 bug,是 MCP 协议要求——但排查时很容易在应用层找半天。

坑 3:发现文档广播 http://,https 站点踩 Mixed Content。 反向代理没透传 X-Forwarded-Proto 时,线上发现文档里的端点可能是 http://。MCP 客户端要是盲信发现文档,在 https 环境里就会因为 Mixed Content 连不上。修法是协议以 AGENT_HOST 配置为准,发现文档只提供路径。

坑 4:会话到期要换票,但不能重连。 Key 档会话 15 分钟,到期自动换新票。这里有个容易忽略的体验细节:如果换票时重连 WebSocket,世界里那个角色的形象会闪烁一下,真人看得见。所以换票只换 token、绝不重连。

坑 5:游客被空闲超时踢掉后的"瞬移"。 5 分钟无动作被服务端踢出,下次工具调用自动重进,位置从上次落库位置恢复——观感上就是"瞬移"。这其实是正常行为,但如果不写进文档,用户一定当 bug 报。

四、再做 Remote 端点:平台只收 HTTP

stdio 版发到 npm(agent-virtual-world,已进官方 MCP Registry)之后,接目录站和国内平台时撞上新要求:Smithery、扣子、Dify、千帆、元器只收 Remote (HTTP) 形态的 MCP。而且 Remote 版对测试者更友好——不用装任何东西,填一个 URL 就能用。

于是有了 https://miduo100.com/mcp(Streamable HTTP,MCP 2025-03-26 规范)。

关于依赖的教训:最初一版用官方 SDK 实现,结果它拖进来 34 个包。我的部署方式是"直接上传依赖目录"(服务器跑不了 npm install),"传哪些包"变成一件容易漏、难排查的事——实测就出过事故:清理时 npm prune 和手工删目录撞车,把 qs 删残了,express 加载失败,整个服务起不来。

最后干脆手写,零新增依赖:HTTP 用项目里已有的 express,会话 ID 用 Node 自带的 crypto.randomUUID(),业务逻辑直调已有的 Agent 服务层。package.json 一个字没改。MCP Streamable HTTP 剥掉包装就是 JSON-RPC over HTTP 加一个会话头,500 行左右就覆盖了我要的全部能力(initialize / tools / resources / prompts / ping)。

五、Remote 端点踩坑实录

坑 6:GET /mcp 无会话时返回 400,被目录站误判。 原实现直接回 JSON-RPC 错误。但 Smithery、Glama、PulseMCP 这些目录站收录前都会先 GET 试一下端点可达性——收到 400 就可能判"端点无效"打回提交。修法:无会话时返回 200 + 端点自述 JSON(server / version / tools / hint / health),浏览器打开也能看到一段说明而不是报错。

坑 7:POST 不带 Content-Type 时 body 不被解析。 全局的 express.json() 只解析 application/json,而部分 MCP 客户端和探测器发 POST 时就是不带这个头,于是 body 为空,被误判成 parse error。修法是给 /mcp 路由单独挂宽容解析器:express.json({ type: () => true, limit: '1mb' })。

坑 8:每 IP 并发 1 个,平台用户集体 429。 游客档原来每 IP 只允许 1 个连接——stdio 时代没问题(每个用户是自己电脑的 IP)。但 Smithery、扣子这些平台代所有用户转发请求,从服务端看共用一个出口 IP,卡 1 个等于平台上同时只有 1 个用户能用。改成 10,另有签票限流和全局会话上限兜底。

坑 9:排查时的假线索——curl 引号转义。 有一轮排障,服务端日志一直报 JSON parse error、body 只有 {\ 两个字符,看起来像服务端坏了。折腾半天发现是 PowerShell 里 curl.exe -d "{\"jsonrpc\":...}" 的转义被吃掉了,发出去的本来就是残缺的请求。现象在服务端,锅在测试命令——body 写进文件用 --data-binary "@file.json" 才是可靠做法。

六、完整调用步骤

方式 A:宿主配置(零凭证,30 秒)

{
  "mcpServers": {
    "virtual-world": {
      "command": "npx",
      "args": ["-y", "agent-virtual-world"],
      "env": { "AGENT_HOST": "https://miduo100.com" }
    }
  }
}

方式 B:Remote 端点(零安装)——在支持 Streamable HTTP 的宿主里直接填 https://miduo100.com/mcp,无需任何凭证。

接好之后,AI 的一次完整世界漫游大致是这条链:

world_discover   → 确认世界开放接入、看能力与限流
world_enter      → 进入世界(真人的世界里出现一个 🤖 角色)
world_observe    → 看附近:有谁、多远、物体是什么(带 AI 描述)
world_walk_to    → 走过去(真实走路动画,不是瞬移)
world_say        → 开口打招呼(30m 内真人头顶弹气泡)
world_chat_history → 看有没有人回话(游客档是拉模式)
world_leave      → 离场

想看协议层的话,Remote 端点的最小调用是三步——initialize 拿会话头、tools/list 看清单、tools/call 调工具:

# 1) 健康检查
curl -s https://miduo100.com/mcp/health
# {"ok":true,"server":"agent-virtual-world","version":"0.1.2","tools":8,...}

# 2) initialize(响应头里拿 Mcp-Session-Id,后续请求都带上)
curl -s -X POST https://miduo100.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data-binary '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"demo","version":"0.0.1"}}}'

# 3) 调工具(带 Mcp-Session-Id)
curl -s -X POST https://miduo100.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Mcp-Session-Id: <上一步返回的会话ID>" \
  --data-binary '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"world_discover","arguments":{}}}'

七、实测结果

本地独立实例与线上各跑一遍,结果一致:/mcp/health 返回 {"ok":true,"tools":8,"version":"0.1.2"};initialize → tools/list 出 8 个工具;world_discover 读到世界「创世虚拟世界」;world_observe 返回附近真人 2.9 米、约百个物体带描述;会话复用同一 sid;DELETE /mcp 后旧会话再用于 404(正确拒绝)。第三方验证:Smithery 自动探测 SUCCESS,8 tools, 2 prompts, 1 resource,与本地数字一致。

要如实交代的限制:游客档是拉模式(收不到实时推送,只能用 world_chat_history 主动拉)、观察半径 30 米、会话 30 分钟且不可续期;world_observe 输出有约 2KB 预算,物体太多时远处的会降级成"仅名称";物体的 AI 描述没填时就老老实实写"(无 AI 描述)",绝不用名字猜内容。填了 API Key(Key 档)才有 200 米雷达和实时推送。

八、来测吧:两种玩法

玩法一:你自己当"被观察对象"。 浏览器打开演示站 https://miduo100.com,以游客身份走进世界;再让接入 MCP 的 AI(按方式 A 或 B 配好)执行一句"进那个世界,找个人,打个招呼"。然后看着你的浏览器:一个 🤖 角色出现,朝你走过来,头顶弹出气泡跟你说话。

玩法二:只看协议层。 按第六节的 curl 三步走一遍,或者直接打开 https://miduo100.com/mcp(无会话时返回端点自述),/mcp/health 看健康状态。

已知现象先说明,免得当 bug 报:气泡只覆盖 30 米,AI 离你远时先让它走过来;同 IP 游客并发与签票有限流;游客档下它听不到你的实时说话(拉模式),配 Key 才有完整对话体验。

三个仓库地址内容一致,国内访问用前两个更快:

  • Gitee(MCP 包):https://gitee.com/miduoxinxijeji/miduo.git
  • GitCode(镜像):https://gitcode.com/qq_35054471/virtual-world
  • GitHub:https://github.com/miduo100/3d-virtual-world

关于创世Genesis

创世Genesis是一套基于Three.js+WebGL构建的自部署3D虚拟世界系统,帮助个人与企业搭建属于自己的3D空间。浏览器直接访问,PC和手机双端兼容,支持多人在线、联邦传送、商铺系统,并支持Agent接入——AI能以具身角色进入你部署的世界。数据运行在你自己的服务器上,不经过第三方平台——让每个世界都真正属于它的主人。

想让你的 AI 走进一个真实的 3D 世界? 创世Genesis(创世虚拟世界CRM系统)是自部署的 Three.js 3D 虚拟世界基底,MCP 接入与演示站均已开放。官网(搜「创世虚拟世界CRM」即可找到)有完整介绍。

关于名字:本文说的创世Genesis,即创世虚拟世界CRM系统,两者是同一个自部署 3D 虚拟世界产品。若你通过「创世Genesis」没搜到我们,直接搜「创世虚拟世界CRM」即可。
← 返回文章列表