Bug fixes (verified against Cocos Creator 3.8.8): - diagnostics: shell:true for .cmd/.bat on Windows (T125/T126) - prefabs: duplicatePrefab target resolves under assets/ (T420) - cocos-project: add preview.open candidate for 3.8.8 (T444) - assets-advanced: detect directory assets in inspectAssetDependencies (T110) - scene: improve component-not-found errors with compilation hint (T429) Documentation improvements: - tool-registry: add enum and injected vars to execute_javascript, path format examples, asset ref limitation note - resources: add cocos://mcp/execute-context resource with variables, patterns, pitfalls New tools (core 37->38, full 101->110): - scene-management: create_scene, query_scene_state (core), copy_paste_node, rename_node, reparent_node - scripts: create_script with component/plain templates - prefabs: create_prefab - assets-advanced: batch_asset_ops, find_unused_assets
54 KiB
funplay-cocos-mcp 集成测试文档
目标:AI Agent 读取本文档后,可全程自动循环执行所有测试,输出结构化测试报告,验证 funplay-cocos-mcp 全部 101 个工具、10 个资源、4 个 prompt 在 Cocos Creator 3.8.8 下的兼容性。
测试项目:一次性测试项目,测完丢弃。
调用方式:curl(协议层 + 独立工具)与 execute_javascript(链式编排)结合。
1. 测试环境搭建
1.1 前置条件
| 条件 | 要求 |
|---|---|
| Cocos Creator | 3.8.8 |
| Node.js | >= 18(Cocos 自带即可) |
| 操作系统 | Windows / macOS / Linux 均可 |
| funplay-cocos-mcp | 已 clone 或安装到 Cocos 项目 extensions/ 目录 |
1.2 创建一次性测试项目
- 打开 Cocos Creator 3.8.8,新建一个 Empty(2D) 项目,命名为
mcp-test-disposable - 项目创建后会自动生成一个默认场景
assets/scene.scene,保留它 - 在
assets/下创建文件夹scripts和prefabs
1.3 安装 funplay-cocos-mcp 扩展
# 方式一:符号链接(开发模式)
cd /path/to/mcp-test-disposable/extensions
# Windows: mklink /D funplay-cocos-mcp C:\Users\wangj\data\src\mcp\funplay-cocos-mcp
# macOS/Linux: ln -s /path/to/funplay-cocos-mcp funplay-cocos-mcp
# 方式二:直接复制
cp -r /path/to/funplay-cocos-mcp /path/to/mcp-test-disposable/extensions/funplay-cocos-mcp
回到 Cocos Creator,重新加载扩展(菜单 → 扩展 → 重新载入)。
1.4 启动 MCP 服务器
- 打开菜单:
Funplay > MCP Server - 在面板中确认 Tool Profile 设置为
full(测试全部 101 个工具) - 点击启动服务器
- 确认面板显示服务器运行在
http://127.0.0.1:8765/
1.5 验证连通性
# 健康检查
curl -s http://127.0.0.1:8765/health
# 预期返回:
# {"ok":true,"name":"Funplay Cocos MCP - mcp-test-disposable","version":"0.4.0",...}
如果端口被占用,服务器会自动回退到下一个可用端口。请从 /health 响应中确认实际端口,后续所有测试中使用该端口。
1.6 测试数据初始化
在正式测试前,通过 execute_javascript 在编辑器上下文中创建测试所需的基础数据:
# 设置变量
MCP_URL="http://127.0.0.1:8765"
# 初始化测试数据:创建 Canvas + 测试节点 + 测试脚本文件
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "execute_javascript",
"arguments": {
"context": "scene",
"code": "const { Canvas, UITransform, Label, Button, director, find, Node } = cc; const scene = director.getScene(); let canvas = find(\"Canvas\"); if (!canvas) { canvas = new Node(\"Canvas\"); canvas.addComponent(Canvas); canvas.addComponent(UITransform); scene.addChild(canvas); } let testNode = find(\"Canvas/TestNode\"); if (!testNode) { testNode = new Node(\"TestNode\"); testNode.addComponent(UITransform); testNode.addComponent(Label); testNode.addComponent(Button); canvas.addChild(testNode); } return { canvasUuid: canvas.uuid, testNodeUuid: testNode.uuid, sceneName: scene.name };"
}
}
}'
# 创建测试脚本文件
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "write_file",
"arguments": {
"path": "assets/scripts/TestComponent.ts",
"content": "import { _decorator, Component, Label } from \"cc\";\nconst { ccclass, property } = _decorator;\n\n@ccclass(\"TestComponent\")\nexport class TestComponent extends Component {\n @property({ type: Label })\n label: Label | null = null;\n\n @property\n speed: number = 10;\n\n start() {\n console.log(\"TestComponent started\");\n }\n\n update(dt: number) {\n // test method\n }\n\n public greet(name: string): string {\n return `Hello, ${name}!`;\n }\n}\n"
}
}
}'
# 刷新资源数据库
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "refresh_assets",
"arguments": {}
}
}'
# 保存场景,确保 TestNode 已持久化
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "save_current_scene",
"arguments": {}
}
}'
# 从 TestNode 创建预制体(funplay-cocos-mcp 无 create_prefab 工具,通过 execute_javascript 调用 Editor API)
# 将 <TEST_NODE_UUID> 替换为前面初始化返回的 testNodeUuid
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "execute_javascript",
"arguments": {
"context": "editor",
"code": "const testNodeUuid = \"<TEST_NODE_UUID>\"; const savePath = \"db://assets/prefabs/TestPrefab.prefab\"; const result = await Editor.Message.request(\"scene\", \"create-prefab\", testNodeUuid, savePath); return { result: result, savePath: savePath };"
}
}
}'
# 刷新资源数据库,确保新预制体被索引
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "refresh_assets",
"arguments": {"path": "assets/prefabs"}
}
}'
# 查询预制体 uuid,供后续测试使用
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "list_prefabs",
"arguments": {}
}
}'
AI Agent 注意:记录以下初始化返回值,后续链式测试需要使用:
canvasUuid— Canvas 节点 UUIDtestNodeUuid— TestNode 节点 UUIDprefabUuid— TestPrefab 预制体 UUID(从最后一步 list_prefabs 返回中获取)prefabPath—db://assets/prefabs/TestPrefab.prefab
2. AI Agent 自动化测试框架
2.1 通用变量与辅助函数
AI Agent 在执行测试前,先设置以下变量:
MCP_URL="http://127.0.0.1:8765"
PROTO_VER="2025-11-25"
TEST_ID=0
PASS_COUNT=0
FAIL_COUNT=0
SKIP_COUNT=0
RESULTS_FILE="/tmp/mcp-test-results.json"
辅助函数(AI Agent 可用 shell 函数或等价逻辑实现):
# MCP initialize
mcp_init() {
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d "{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"$PROTO_VER\",\"clientInfo\":{\"name\":\"test-agent\",\"version\":\"1.0\"}}}"
}
# MCP tools/call
mcp_tool() {
local tool_name="$1"
local args="${2:-{}}"
local id="${3:-1}"
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d "{\"jsonrpc\":\"2.0\",\"id\":$id,\"method\":\"tools/call\",\"params\":{\"name\":\"$tool_name\",\"arguments\":$args}}"
}
# MCP resources/read
mcp_resource() {
local uri="$1"
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"resources/read\",\"params\":{\"uri\":\"$uri\"}}"
}
# MCP prompts/get
mcp_prompt() {
local name="$1"
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"prompts/get\",\"params\":{\"name\":\"$name\"}}"
}
# 从 tools/call 响应中提取 structuredContent.data 的 JSON
extract_data() {
local response="$1"
echo "$response" | python3 -c "
import sys, json
resp = json.load(sys.stdin)
sc = resp.get('result', {}).get('structuredContent', {})
print(json.dumps(sc.get('data', {})))
" 2>/dev/null
}
# 从 tools/call 响应中提取 ok 字段
extract_ok() {
local response="$1"
echo "$response" | python3 -c "
import sys, json
resp = json.load(sys.stdin)
sc = resp.get('result', {}).get('structuredContent', {})
print(sc.get('ok', 'missing'))
" 2>/dev/null
}
# 从 tools/call 响应中提取 isError
extract_is_error() {
local response="$1"
echo "$response" | python3 -c "
import sys, json
resp = json.load(sys.stdin)
print(resp.get('result', {}).get('isError', False))
" 2>/dev/null
}
# 记录测试结果
record_result() {
local test_id="$1"
local tool_name="$2"
local status="$3" # pass / fail / skip
local detail="$4"
echo "{\"id\":\"$test_id\",\"tool\":\"$tool_name\",\"status\":\"$status\",\"detail\":\"$detail\"}" >> "$RESULTS_FILE"
if [ "$status" = "pass" ]; then PASS_COUNT=$((PASS_COUNT+1));
elif [ "$status" = "fail" ]; then FAIL_COUNT=$((FAIL_COUNT+1));
else SKIP_COUNT=$((SKIP_COUNT+1)); fi
}
2.2 通用判定规则
每个测试用例的判定遵循以下通用规则,叠加各用例的特定规则:
| 规则编号 | 规则 | 判定方法 |
|---|---|---|
| R1 | HTTP 状态码 200 | curl 退出码为 0 且响应包含 "jsonrpc" |
| R2 | 响应包含 result 字段 |
响应 JSON 有 result 键 |
| R3 | result.isError 不为 true |
extract_is_error 返回 False |
| R4 | structuredContent.ok 为 true |
extract_ok 返回 True |
| R5 | structuredContent.data 存在 |
extract_data 返回非空 JSON |
| R6 | 无 error 顶层字段 |
响应 JSON 无 error 键 |
例外:截图工具返回 image content(data:image/png;base64,...),不适用 R4/R5,改用"content 中包含 image 类型项"判定。
2.3 测试报告格式
测试结果以 JSON 数组形式写入 $RESULTS_FILE:
[
{"id":"T001","tool":"initialize","status":"pass","detail":"protocol 2025-11-25 negotiated"},
{"id":"T101","tool":"get_project_info","status":"pass","detail":"projectPath=/path/to/project, cocosVersion=3.8.8"},
{"id":"T201","tool":"create_node","status":"fail","detail":"ok=false, error=Scene not loaded"}
]
最终汇总报告:
========== funplay-cocos-mcp 集成测试报告 ==========
测试时间: 2026-06-30T12:00:00Z
Cocos Creator 版本: 3.8.8
MCP 服务器版本: 0.4.0
工具配置档: full
================================================
通过: 95 失败: 4 跳过: 2 总计: 101
================================================
失败详情:
T201 create_node: ok=false, error=Scene not loaded
T432 simulate_mouse_click: No visible window found
...
================================================
兼容性结论: [PASS/PARTIAL/FAIL]
2.4 AI Agent 执行循环流程
1. 执行 Phase 0 协议测试
→ 全部通过才继续;失败则中止并报告
2. 执行测试数据初始化(1.6 节)
→ 记录 canvasUuid, testNodeUuid
3. 按顺序执行 Phase 1 → Phase 6
每个测试用例:
a. 检查前置条件(如需要场景已加载、需要 preview 运行等)
b. 执行 curl 命令或 execute_javascript 链式调用
c. 解析响应 JSON
d. 执行判定规则(R1-R6 + 特定规则)
e. 记录结果到 $RESULTS_FILE
f. 如果是链式测试,提取输出数据(uuid 等)供后续测试使用
g. 如果失败,记录详情,继续下一个测试
4. 链式测试特殊处理:
- 前一步失败时,后续依赖步骤标记为 skip
- 提取 uuid 等数据时使用 python3 解析 JSON
5. 全部完成后:
a. 汇总 PASS/FAIL/SKIP 计数
b. 列出所有失败项详情
c. 输出兼容性结论
d. 将 $RESULTS_FILE 内容输出为结构化报告
3. Phase 0: MCP 协议合规性测试
T001: initialize 握手
- 方法: curl
- 前置条件: MCP 服务器已启动
mcp_init
- 判定: R1 + R2 + 响应
result.protocolVersion为受支持版本 +result.capabilities包含tools/resources/prompts+result.serverInfo.name包含Funplay - 记录: 协商出的协议版本
T002: tools/list
- 方法: curl
- 前置条件: T001 通过
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
- 判定: R1 + R2 +
result.tools为数组 + 数组长度 > 0 + 每个工具有name/description/inputSchema - 记录: 工具总数(full 模式应为 101)
T003: resources/list
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d '{"jsonrpc":"2.0","id":1,"method":"resources/list","params":{}}'
- 判定: R1 + R2 +
result.resources为数组 + 长度 >= 10 + 每项有uri/name/description
T004: resources/templates/list
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d '{"jsonrpc":"2.0","id":1,"method":"resources/templates/list","params":{}}'
- 判定: R1 + R2 +
result.resourceTemplates为数组 + 长度 >= 3 + 每项有uriTemplate
T005: prompts/list
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d '{"jsonrpc":"2.0","id":1,"method":"prompts/list","params":{}}'
- 判定: R1 + R2 +
result.prompts为数组 + 长度 >= 4 + 每项有name/description
T006: Accept header 缺失应拒绝
curl -s -o /dev/null -w "%{http_code}" -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
- 判定: HTTP 状态码为 406(Accept header 校验失败)
T007: 不支持的方法应返回 -32601
curl -s -X POST "$MCP_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: $PROTO_VER" \
-d '{"jsonrpc":"2.0","id":1,"method":"nonexistent/method","params":{}}'
- 判定: R1 + 响应包含
error.code为 -32601
T008: GET /tools 调试端点
curl -s "$MCP_URL/tools"
- 判定: R1 + 响应包含
tools数组 +count字段 +ok: true
4. Phase 1: Core 只读工具测试
以下工具均为
core配置档中的只读/安全工具,可独立执行,无副作用。
T101: get_project_info
mcp_tool "get_project_info" '{}'
- 判定: R1-R5 +
data.projectPath非空 +data.cocosVersion包含3.8 - 记录: projectPath, cocosVersion
T102: get_editor_state
mcp_tool "get_editor_state" '{}'
- 判定: R1-R5 +
data包含项目信息
T103: get_tool_catalog
mcp_tool "get_tool_catalog" '{}'
- 判定: R1-R5 +
data为数组 + 长度 > 0 + 每项有name/profile/category
T104: get_scene_info
mcp_tool "get_scene_info" '{}'
- 判定: R1-R5 +
data.sceneName或data.name非空 - 注意: 需要场景已加载,如失败则后续场景相关测试标记 skip
T105: get_hierarchy
mcp_tool "get_hierarchy" '{}'
- 判定: R1-R5 +
data包含节点树结构
T106: list_scenes
mcp_tool "list_scenes" '{}'
- 判定: R1-R5 +
data为数组 + 长度 >= 1 - 记录: 第一个场景的 uuid 和 path,供 T107 使用
T107: open_scene
# 使用 T106 记录的场景 uuid
mcp_tool "open_scene" "{\"uuid\":\"<SCENE_UUID>\"}"
- 判定: R1-R4 + 无
isError - 注意: 替换
<SCENE_UUID>为 T106 获取的实际值
T108: list_assets
mcp_tool "list_assets" '{"pattern":"db://assets/**/*"}'
- 判定: R1-R5 +
data为数组 + 长度 > 0 - 记录: 第一个资产的 uuid,供 T109/T110 使用
T109: inspect_asset
# 使用 T108 记录的 asset uuid
mcp_tool "inspect_asset" "{\"uuid\":\"<ASSET_UUID>\"}"
- 判定: R1-R5 +
data包含资产信息
T110: inspect_asset_dependencies
mcp_tool "inspect_asset_dependencies" "{\"uuid\":\"<ASSET_UUID>\"}"
- 判定: R1-R4 +
data存在(即使无依赖也应返回空数组)
T111: validate_asset_dependencies
mcp_tool "validate_asset_dependencies" "{\"uuid\":\"<ASSET_UUID>\"}"
- 判定: R1-R4 +
data存在
T112: inspect_prefab
# 先列出预制体
mcp_tool "list_assets" '{"pattern":"db://assets/**/*.prefab"}'
- 判定: 如果有预制体,inspect_prefab 返回 R1-R5;如无预制体则 skip
- 注意: AI Agent 应先检查是否有 .prefab 资产,有则取 uuid 调用
inspect_prefab
T113: inspect_prefab_instance
mcp_tool "inspect_prefab_instance" '{"path":"Canvas/TestNode"}'
- 判定: R1-R4(TestNode 非预制体实例,应返回有效响应说明非实例)
T114: validate_prefab_references
# 如果 T112 有预制体 uuid 则使用,否则 skip
mcp_tool "validate_prefab_references" "{\"uuid\":\"<PREFAB_UUID>\"}"
- 判定: R1-R4
T115: validate_scene
mcp_tool "validate_scene" '{}'
- 判定: R1-R5 +
data包含验证结果
T116: get_selection
mcp_tool "get_selection" '{}'
- 判定: R1-R5 +
data存在
T117: set_selection
# 使用初始化时记录的 testNodeUuid
mcp_tool "set_selection" "{\"type\":\"node\",\"uuid\":\"<TEST_NODE_UUID>\"}"
- 判定: R1-R4
T118: get_runtime_state
mcp_tool "get_runtime_state" '{}'
- 判定: R1-R5 +
data存在
T119: get_performance_snapshot
mcp_tool "get_performance_snapshot" '{}'
- 判定: R1-R5 +
data存在
T120: get_build_status
mcp_tool "get_build_status" '{}'
- 判定: R1-R4 +
data存在
T121: list_editor_windows
mcp_tool "list_editor_windows" '{}'
- 判定: R1-R5 +
data为数组 + 长度 > 0 - 记录: 窗口列表,供截图和输入模拟测试使用
T122: get_recent_logs
mcp_tool "get_recent_logs" '{}'
- 判定: R1-R5 +
data存在
T123: search_project_logs
mcp_tool "search_project_logs" '{"query":"error"}'
- 判定: R1-R4 +
data存在
T124: clear_logs
mcp_tool "clear_logs" '{}'
- 判定: R1-R4
T125: run_script_diagnostics
mcp_tool "run_script_diagnostics" '{}'
- 判定: R1-R5 +
data存在(diagnostics数组,即使为空)
T126: get_script_diagnostic_context
mcp_tool "get_script_diagnostic_context" '{}'
- 判定: R1-R5 +
data存在
T127: check_for_updates
mcp_tool "check_for_updates" '{}'
- 判定: R1-R5 +
data存在
T128: list_project_instructions
mcp_tool "list_project_instructions" '{}'
- 判定: R1-R5 +
data为数组
T129: read_project_instruction
# 如果 T128 返回有指令文件则读取第一个,否则 skip
mcp_tool "read_project_instruction" "{\"name\":\"<INSTRUCTION_NAME>\"}"
- 判定: R1-R4(有指令文件时)或 skip(无指令文件时)
T130: capture_editor_screenshot
mcp_tool "capture_editor_screenshot" '{}'
- 判定: R1-R3 +
result.content包含type: "image"项 - 注意: 需要编辑器窗口可见
T131: capture_scene_screenshot
mcp_tool "capture_scene_screenshot" '{}'
- 判定: R1-R3 +
result.content包含type: "image"项
T132: capture_preview_screenshot
mcp_tool "capture_preview_screenshot" '{}'
- 判定: R1-R3 +
result.content包含 image 项 - 注意: 需要 preview 窗口可见;如无 preview 运行则 skip
T133: execute_javascript (scene context)
mcp_tool "execute_javascript" '{"context":"scene","code":"return { sceneName: scene.name, childCount: scene.children.length };"}'
- 判定: R1-R5 +
data.sceneName非空
T134: execute_javascript (editor context)
mcp_tool "execute_javascript" '{"context":"editor","code":"return { projectPath: context.projectPath, toolCount: helpers.listTools().length };"}'
- 判定: R1-R5 +
data.projectPath非空 +data.toolCount> 0
T135: execute_scene_script
mcp_tool "execute_scene_script" '{"code":"return { sceneName: scene.name };"}'
- 判定: R1-R5 +
data.sceneName非空
T136: execute_editor_script
mcp_tool "execute_editor_script" '{"code":"return { projectPath: context.projectPath };"}'
- 判定: R1-R5 +
data.projectPath非空
T137: open_asset
# 使用 T108 记录的 asset uuid
mcp_tool "open_asset" "{\"uuid\":\"<ASSET_UUID>\"}"
- 判定: R1-R4
T138: select_asset
mcp_tool "select_asset" "{\"uuid\":\"<ASSET_UUID>\"}"
- 判定: R1-R4
5. Phase 2: Core 变更工具链式测试
以下测试有副作用,按链式顺序执行。前一步的输出作为后一步的输入。
链 A: 节点创建 → 变换 → 删除
T201: create_node
mcp_tool "create_node" '{"name":"ChainTestNode","parentPath":"Canvas"}'
- 判定: R1-R5 +
data.uuid非空 - 记录:
createdNodeUuid = data.uuid
T202: set_node_transform(依赖 T201)
mcp_tool "set_node_transform" "{\"uuid\":\"<CREATED_NODE_UUID>\",\"position\":{\"x\":100,\"y\":200,\"z\":0},\"scale\":{\"x\":2,\"y\":2,\"z\":1}}"
- 判定: R1-R4
- 前置: T201 通过
T203: delete_node(依赖 T201)
mcp_tool "delete_node" "{\"uuid\":\"<CREATED_NODE_UUID>\"}"
- 判定: R1-R4
- 前置: T201 通过
- 清理: 删除 T201 创建的节点
链 B: 组件添加 → 设置属性 → 移除
T204: add_component(依赖 T201 或使用已有的 TestNode)
# 使用初始化时的 testNodeUuid
mcp_tool "add_component" "{\"path\":\"Canvas/TestNode\",\"componentType\":\"cc.Sprite\"}"
- 判定: R1-R4
T205: set_component_property(依赖 T204)
mcp_tool "set_component_property" "{\"path\":\"Canvas/TestNode\",\"componentType\":\"cc.Sprite\",\"property\":\"color\",\"value\":{\"r\":255,\"g\":0,\"b\":0,\"a\":255}}"
- 判定: R1-R4
- 前置: T204 通过
T206: remove_component(依赖 T204)
mcp_tool "remove_component" "{\"path\":\"Canvas/TestNode\",\"componentType\":\"cc.Sprite\"}"
- 判定: R1-R4
- 前置: T204 通过
- 清理: 移除 T204 添加的组件
T207: save_current_scene
mcp_tool "save_current_scene" '{}'
- 判定: R1-R4
- 注意: 保存前面所有变更
6. Phase 3: Full 额外只读工具测试
以下工具仅在
full配置档中可用。
T301: find_nodes
mcp_tool "find_nodes" '{"name":"TestNode"}'
- 判定: R1-R5 +
data为数组 + 长度 >= 1
T302: inspect_node
mcp_tool "inspect_node" '{"path":"Canvas/TestNode"}'
- 判定: R1-R5 +
data.uuid非空 +data.name为TestNode
T303: list_components
mcp_tool "list_components" '{"path":"Canvas/TestNode"}'
- 判定: R1-R5 +
data为数组 + 长度 >= 1(至少有 UITransform)
T304: inspect_component
mcp_tool "inspect_component" '{"path":"Canvas/TestNode","componentType":"cc.Label"}'
- 判定: R1-R5 +
data存在
T305: list_cameras
mcp_tool "list_cameras" '{}'
- 判定: R1-R5 +
data为数组
T306: list_animations
mcp_tool "list_animations" '{}'
- 判定: R1-R5 +
data为数组
T307: list_prefabs
mcp_tool "list_prefabs" '{}'
- 判定: R1-R5 +
data为数组 - 记录: 如有预制体,记录第一个的 uuid
T308: get_editor_selection
mcp_tool "get_editor_selection" '{}'
- 判定: R1-R5 +
data存在
T309: exists
mcp_tool "exists" '{"path":"assets/scripts/TestComponent.ts"}'
- 判定: R1-R5 +
data.exists为true
T310: read_file
mcp_tool "read_file" '{"path":"assets/scripts/TestComponent.ts"}'
- 判定: R1-R5 +
data.content包含TestComponent
T311: get_file_snippet
mcp_tool "get_file_snippet" '{"path":"assets/scripts/TestComponent.ts","line":3,"context":3}'
- 判定: R1-R5 +
data存在
T312: list_directory
mcp_tool "list_directory" '{"path":"assets/scripts"}'
- 判定: R1-R5 +
data为数组 + 长度 >= 1
T313: search_files
mcp_tool "search_files" '{"pattern":"*.ts"}'
- 判定: R1-R5 +
data为数组 + 长度 >= 1
T314: capture_desktop_screenshot
mcp_tool "capture_desktop_screenshot" '{}'
- 判定: R1-R3 +
result.content包含 image 项
T315: capture_game_screenshot
mcp_tool "capture_game_screenshot" '{}'
- 判定: R1-R3 +
result.content包含 image 项 - 注意: 需要 Game 面板可见
7. Phase 4: Full 额外变更工具测试
以下工具会修改项目状态,按子阶段链式执行。
4a. UI 创建工具
T401: create_canvas
mcp_tool "create_canvas" '{"name":"TestCanvas"}'
- 判定: R1-R5 +
data.uuid非空 - 记录:
canvasUuid = data.uuid
T402: create_label(依赖 T401 或使用已有 Canvas)
mcp_tool "create_label" '{"name":"TestLabel","parentPath":"Canvas","text":"Hello MCP"}'
- 判定: R1-R5 +
data.uuid非空
T403: create_button(依赖 T401)
mcp_tool "create_button" '{"name":"TestButton","parentPath":"Canvas","text":"Click Me"}'
- 判定: R1-R5 +
data.uuid非空 - 记录:
buttonUuid = data.uuid(供 4g 事件测试使用)
T404: create_sprite(依赖 T401)
mcp_tool "create_sprite" '{"name":"TestSprite","parentPath":"Canvas"}'
- 判定: R1-R5 +
data.uuid非空
4b. 摄像机工具
T405: create_camera
mcp_tool "create_camera" '{"name":"TestCamera"}'
- 判定: R1-R5 +
data.uuid非空 - 记录:
cameraUuid = data.uuid
T406: set_camera_properties(依赖 T405)
mcp_tool "set_camera_properties" "{\"uuid\":\"<CAMERA_UUID>\",\"properties\":{\"projection\":1}}"
- 判定: R1-R4
- 前置: T405 通过
4c. 动画工具
T407: add_animation_clip
mcp_tool "add_animation_clip" '{"path":"Canvas/TestNode","clipName":"TestClip"}'
- 判定: R1-R4
- 注意: 如节点无 Animation 组件,工具应自动添加或返回明确错误
T408: play_animation(依赖 T407)
mcp_tool "play_animation" '{"path":"Canvas/TestNode","clipName":"TestClip"}'
- 判定: R1-R4
- 前置: T407 通过
T409: stop_animation(依赖 T407)
mcp_tool "stop_animation" '{"path":"Canvas/TestNode","clipName":"TestClip"}'
- 判定: R1-R4
- 前置: T407 通过
4d. 预制体生命周期测试
前置条件: 1.6 测试数据初始化已创建
TestPrefab.prefab,AI Agent 已记录prefabUuid和prefabPath。本阶段测试完整的预制体生命周期:创建验证 → 实例化 → 修改实例 → 应用回预制体 → 验证保存 → 还原 → JSON编辑 → 复制 → 引用验证。
T410: instantiate_prefab — 实例化预制体到场景
# 使用初始化记录的 prefabUuid
mcp_tool "instantiate_prefab" "{\"prefabUuid\":\"<PREFAB_UUID>\",\"parentPath\":\"Canvas\"}"
- 判定: R1-R5 +
data.uuid非空 - 记录:
instance1Uuid = data.uuid,instance1Path = "Canvas/TestPrefab"(或返回的实际路径)
T411: create_prefab_instance — 创建链接预制体实例
mcp_tool "create_prefab_instance" "{\"prefabUuid\":\"<PREFAB_UUID>\",\"parentPath\":\"Canvas\"}"
- 判定: R1-R5 +
data.uuid非空 - 记录:
instance2Uuid = data.uuid,instance2Path = "Canvas/TestPrefab"(或返回的实际路径) - 注意: 如与 T410 实例名冲突,AI Agent 应使用不同名称或跳过此步
T412: inspect_prefab_instance — 检查实例链接状态(依赖 T410)
mcp_tool "inspect_prefab_instance" "{\"path\":\"<INSTANCE1_PATH>\"}"
- 判定: R1-R5 +
data存在 +data.isPrefabInstance为true或包含预制体关联信息 - 前置: T410 通过
T413: set_node_transform — 修改实例节点属性(依赖 T410)
# 修改实例节点的位置,作为待应用的变更
mcp_tool "set_node_transform" "{\"uuid\":\"<INSTANCE1_UUID>\",\"position\":{\"x\":200,\"y\":300,\"z\":0},\"scale\":{\"x\":1.5,\"y\":1.5,\"z\":1}}"
- 判定: R1-R4
- 前置: T410 通过
- 记录: 修改的位置值
modifiedPosition = {x:200, y:300},供 T415 验证
T414: apply_prefab_instance — 将修改应用回预制体(依赖 T413)
mcp_tool "apply_prefab_instance" "{\"path\":\"<INSTANCE1_PATH>\"}"
- 判定: R1-R5 +
data存在 - 前置: T413 通过
- 说明: 此操作将实例上的变更保存回
.prefab源文件,等同于"保存预制体"
T415: inspect_prefab — 验证修改已保存到预制体(依赖 T410, T414)
mcp_tool "inspect_prefab" "{\"uuid\":\"<PREFAB_UUID>\"}"
- 判定: R1-R5 +
data存在 + 包含预制体序列化信息 - 前置: T414 通过
- 验证点: 预制体数据应反映 T413 的修改(位置/缩放变更)
T416: read_file — 读取 .prefab 文件验证持久化(依赖 T414)
mcp_tool "read_file" '{"path":"assets/prefabs/TestPrefab.prefab"}'
- 判定: R1-R5 +
data.content非空 + 包含有效的 JSON 结构 - 前置: T414 通过
- 验证点: 文件内容应包含 T413 修改的位置值(
"x":200或"y":300) - 说明: 这是验证预制体确实已保存到磁盘的关键步骤
T417: revert_prefab_instance — 还原实例到预制体状态(依赖 T410)
mcp_tool "revert_prefab_instance" "{\"path\":\"<INSTANCE1_PATH>\"}"
- 判定: R1-R5 +
data存在 - 前置: T410 通过
- 验证点: 实例节点应恢复为预制体的原始状态(T413 的修改被撤销)
- 说明: revert 撤销的是实例上的 override,不影响已 apply 的预制体文件
T418: edit_prefab_json — 直接编辑预制体 JSON(依赖 T410)
mcp_tool "edit_prefab_json" '{"prefabPath":"db://assets/prefabs/TestPrefab.prefab","jsonPath":"_name","value":"EditedTestPrefab"}'
- 判定: R1-R5 +
data存在 - 前置: T410 通过
- 说明: 直接修改 .prefab 文件的 JSON 字段,绕过场景编辑
T419: inspect_prefab — 验证 JSON 编辑生效(依赖 T418)
mcp_tool "inspect_prefab" "{\"uuid\":\"<PREFAB_UUID>\"}"
- 判定: R1-R5 +
data存在 - 前置: T418 通过
- 验证点: 预制体名称应反映 T418 的修改(
EditedTestPrefab) - 说明: 也可通过
read_file读取 .prefab 文件验证_name字段已变更
T420: duplicate_prefab — 复制预制体(依赖 T410)
mcp_tool "duplicate_prefab" "{\"prefabUuid\":\"<PREFAB_UUID>\",\"newName\":\"TestPrefabCopy\"}"
- 判定: R1-R5 +
data存在 +data.uuid或data.url非空 - 前置: T410 通过
- 记录:
duplicatedPrefabUuid = data.uuid(如有) - 验证点: 新预制体应存在于
assets/prefabs/目录,且 UUID 与原预制体不同
T421: validate_prefab_references — 验证预制体引用完整性(依赖 T410)
mcp_tool "validate_prefab_references" "{\"uuid\":\"<PREFAB_UUID>\"}"
- 判定: R1-R5 +
data存在 + 无断引错误 - 前置: T410 通过
- 说明: 检查预制体内部的所有 UUID 引用是否有效
T422: validate_prefab_references — 验证复制的预制体引用(依赖 T420)
# 使用 T420 返回的 duplicatedPrefabUuid
mcp_tool "validate_prefab_references" "{\"uuid\":\"<DUPLICATED_PREFAB_UUID>\"}"
- 判定: R1-R5 +
data存在 + 无断引错误 - 前置: T420 通过
- 清理: 测试完成后可删除复制的预制体(
delete_asset)
4e. 文件工具
T423: write_file
mcp_tool "write_file" '{"path":"assets/scripts/test-output.txt","content":"MCP test output\n"}'
- 判定: R1-R4
T424: replace_in_file
mcp_tool "replace_in_file" '{"path":"assets/scripts/test-output.txt","search":"MCP test output","replace":"MCP test output (updated)"}'
- 判定: R1-R4
- 前置: T423 通过
T425: refresh_assets
mcp_tool "refresh_assets" '{"path":"assets/scripts"}'
- 判定: R1-R4
4f. 资源操作工具
T426: open_asset(已在 T137 测试,此处跳过)
T427: select_asset(已在 T138 测试,此处跳过)
T428: delete_asset
# 删除 T423 创建的测试文件
mcp_tool "delete_asset" '{"url":"db://assets/scripts/test-output.txt"}'
- 判定: R1-R4
- 清理: 删除测试文件
4g. 事件工具
T429: bind_button_click_event(依赖 T403)
mcp_tool "bind_button_click_event" "{\"buttonPath\":\"Canvas/TestButton\",\"targetPath\":\"Canvas/TestNode\",\"componentName\":\"TestComponent\",\"handler\":\"greet\"}"
- 判定: R1-R4
- 前置: T403 通过 + TestComponent 脚本已编译
- 注意: 如 TestComponent 未编译完成则 skip
T430: list_button_click_events(依赖 T429)
mcp_tool "list_button_click_events" '{"path":"Canvas/TestButton"}'
- 判定: R1-R5 +
data为数组 - 前置: T429 通过
T431: simulate_button_click(依赖 T403)
mcp_tool "simulate_button_click" '{"path":"Canvas/TestButton"}'
- 判定: R1-R4
- 前置: T403 通过
T432: emit_node_event
mcp_tool "emit_node_event" '{"path":"Canvas/TestNode","eventName":"test-event","data":{"value":42}}'
- 判定: R1-R4
4h. 组件方法调用
T433: invoke_component_method
mcp_tool "invoke_component_method" '{"path":"Canvas/TestNode","componentType":"cc.Label","method":"toString"}'
- 判定: R1-R4
- 注意: 调用 Label 组件的 toString 方法作为安全测试
4i. 运行时控制工具
T434: pause_runtime
mcp_tool "pause_runtime" '{}'
- 判定: R1-R4
- 注意: 需要 preview 运行中;如未运行则 skip
T435: set_time_scale(依赖 T434)
mcp_tool "set_time_scale" '{"scale":0.5}'
- 判定: R1-R4
- 前置: T434 通过或 skip
T436: resume_runtime
mcp_tool "resume_runtime" '{}'
- 判定: R1-R4
T437: run_scene_asset
# 使用 T106 记录的场景 uuid
mcp_tool "run_scene_asset" "{\"uuid\":\"<SCENE_UUID>\"}"
- 判定: R1-R4
- 注意: 会重新加载场景
4j. 输入模拟工具
前置条件: 需要 Cocos Creator 编辑器窗口可见且处于前台。
T438: simulate_mouse_click
mcp_tool "simulate_mouse_click" '{"x":400,"y":300,"windowKind":"editor"}'
- 判定: R1-R4
- 注意: 需要编辑器窗口可见
T439: simulate_mouse_drag
mcp_tool "simulate_mouse_drag" '{"startX":100,"startY":100,"endX":300,"endY":300,"windowKind":"editor"}'
- 判定: R1-R4
T440: simulate_key_press
mcp_tool "simulate_key_press" '{"keyCode":"S","modifiers":["control"],"windowKind":"editor"}'
- 判定: R1-R4
- 注意: Ctrl+S 会触发保存场景
T441: simulate_key_combo
mcp_tool "simulate_key_combo" '{"keyCode":"P","modifiers":["control"],"windowKind":"editor"}'
- 判定: R1-R4
T442: simulate_preview_input
mcp_tool "simulate_preview_input" '{"mode":"click","x":200,"y":200}'
- 判定: R1-R4
- 注意: 需要 preview 窗口运行
4k. 构建与编辑器工具
T443: open_build_panel
mcp_tool "open_build_panel" '{}'
- 判定: R1-R4
- 注意: 会打开构建面板
T444: run_project_preview
mcp_tool "run_project_preview" '{}'
- 判定: R1-R4
- 注意: 会启动预览;后续依赖 preview 的测试(T434-T442)应在此之后执行
4l. 偏好与广播工具
T445: get_editor_preference
mcp_tool "get_editor_preference" '{"name":"general","path":"language"}'
- 判定: R1-R4 +
data存在
T446: set_editor_preference
mcp_tool "set_editor_preference" '{"name":"general","path":"language","value":"zh"}'
- 判定: R1-R4
- 清理: 将语言设回原值
T447: broadcast_editor_message
mcp_tool "broadcast_editor_message" '{"message":"scene:ready","data":{"test":true}}'
- 判定: R1-R4
4m. 项目指令工具
T448: write_project_instruction
mcp_tool "write_project_instruction" '{"name":"AGENTS.md","content":"# Test Instructions\nThis is a test.\n"}'
- 判定: R1-R4
T449: create_project_skill
mcp_tool "create_project_skill" '{"skillName":"test-skill","content":"# Test Skill\nTest content.\n"}'
- 判定: R1-R4
T450: create_cocos_mcp_project_skill
mcp_tool "create_cocos_mcp_project_skill" '{}'
- 判定: R1-R4
T451: reset_component_property
mcp_tool "reset_component_property" '{"path":"Canvas/TestNode","componentType":"cc.Label","property":"string"}'
- 判定: R1-R4
8. Phase 5: MCP Resources 测试
T501: cocos://project/context
mcp_resource "cocos://project/context"
- 判定: R1-R2 +
result.contents为数组 + 首项有text字段 + 非空
T502: cocos://project/summary
mcp_resource "cocos://project/summary"
- 判定: R1-R2 +
result.contents[0].text非空
T503: cocos://scene/active
mcp_resource "cocos://scene/active"
- 判定: R1-R2 +
result.contents[0].text非空
T504: cocos://scene/current
mcp_resource "cocos://scene/current"
- 判定: R1-R2 +
result.contents[0].text非空
T505: cocos://selection/current
mcp_resource "cocos://selection/current"
- 判定: R1-R2 +
result.contents[0].text非空
T506: cocos://selection/asset
mcp_resource "cocos://selection/asset"
- 判定: R1-R2 +
result.contents[0].text非空
T507: cocos://errors/scripts
mcp_resource "cocos://errors/scripts"
- 判定: R1-R2 +
result.contents[0].text非空
T508: cocos://logs/editor
mcp_resource "cocos://logs/editor"
- 判定: R1-R2 +
result.contents[0].text非空
T509: cocos://logs/project
mcp_resource "cocos://logs/project"
- 判定: R1-R2 +
result.contents[0].text非空
T510: cocos://mcp/interactions
mcp_resource "cocos://mcp/interactions"
- 判定: R1-R2 +
result.contents[0].text非空
T511: Resource Template — cocos://scene/node/{path}
mcp_resource "cocos://scene/node/Canvas/TestNode"
- 判定: R1-R2 +
result.contents[0].text非空 + 包含TestNode
T512: Resource Template — cocos://asset/path/{relative_path}
mcp_resource "cocos://asset/path/assets/scripts/TestComponent.ts"
- 判定: R1-R2 +
result.contents[0].text非空 + 包含TestComponent
T513: Resource Template — cocos://asset/info/{uuid_or_path}
mcp_resource "cocos://asset/info/db://assets/scene.scene"
- 判定: R1-R2 +
result.contents[0].text非空
9. Phase 6: MCP Prompts 测试
T601: fix_script_errors
mcp_prompt "fix_script_errors"
- 判定: R1-R2 +
result.messages为数组 + 长度 >= 1 + 首项有content.text+ 包含execute_javascript
T602: create_playable_prototype
mcp_prompt "create_playable_prototype"
- 判定: R1-R2 +
result.messages[0].content.text非空 + 包含execute_javascript
T603: scene_validation
mcp_prompt "scene_validation"
- 判定: R1-R2 +
result.messages[0].content.text非空 + 包含execute_javascript
T604: auto_wire_scene
mcp_prompt "auto_wire_scene"
- 判定: R1-R2 +
result.messages[0].content.text非空 + 包含execute_javascript
10. 测试报告与结论
10.1 汇总统计
测试全部完成后,AI Agent 输出以下汇总:
========== funplay-cocos-mcp 集成测试报告 ==========
测试时间: <ISO_TIMESTAMP>
Cocos Creator 版本: <从 T101 获取>
MCP 服务器版本: <从 T001 获取>
工具配置档: full
测试端口: <实际端口>
====================================================
Phase 0 (协议合规): <X>/8 通过
Phase 1 (Core 只读): <X>/38 通过
Phase 2 (Core 变更): <X>/7 通过
Phase 3 (Full 只读): <X>/15 通过
Phase 4 (Full 变更): <X>/51 通过
Phase 5 (Resources): <X>/13 通过
Phase 6 (Prompts): <X>/4 通过
----------------------------------------------------
总计: <PASS>/<TOTAL> 通过, <FAIL> 失败, <SKIP> 跳过
====================================================
10.2 失败详情格式
每个失败项输出:
[FAIL] <TEST_ID> <tool_name>
调用: <curl 命令摘要>
参数: <arguments JSON>
响应: <response JSON 前 500 字符>
判定: <哪条规则失败>
可能原因: <AI Agent 分析>
10.3 兼容性结论模板
兼容性结论: <PASS / PARTIAL / FAIL>
依据:
- <PASS>: 全部 101 个工具 + 13 个资源 + 4 个 prompt 测试通过
- <PARTIAL>: 核心功能通过,但有 <N> 个工具失败,失败工具列表: <...>
- <FAIL>: 协议层或核心工具大面积失败
3.8.8 特定问题:
- <列出仅在 3.8.8 下出现的问题,如 API 不兼容、方法不存在等>
建议:
- <基于测试结果给出的建议>
10.4 结果文件格式
完整测试结果以 JSON 文件保存:
{
"testDate": "2026-06-30T12:00:00Z",
"cocosVersion": "3.8.8",
"mcpVersion": "0.4.0",
"toolProfile": "full",
"serverPort": 8765,
"summary": {
"total": 136,
"passed": 125,
"failed": 3,
"skipped": 2
},
"results": [
{
"id": "T001",
"phase": 0,
"tool": "initialize",
"status": "pass",
"duration_ms": 120,
"detail": "protocol 2025-11-25 negotiated"
},
{
"id": "T201",
"phase": 2,
"tool": "create_node",
"status": "fail",
"duration_ms": 5000,
"detail": "ok=false, error=Scene not loaded",
"response": "..."
}
],
"conclusion": "PARTIAL",
"issues": [
"T201 create_node: Scene not loaded - 可能需要先 open_scene",
"T432 simulate_mouse_click: No visible window - 需要编辑器窗口在前台"
]
}
附录 A: 测试用例索引
| Phase | 范围 | 用例编号 | 数量 |
|---|---|---|---|
| 0 | MCP 协议合规 | T001-T008 | 8 |
| 1 | Core 只读工具 | T101-T138 | 38 |
| 2 | Core 变更工具(链式) | T201-T207 | 7 |
| 3 | Full 额外只读 | T301-T315 | 15 |
| 4 | Full 额外变更 | T401-T451 | 51 |
| 5 | MCP Resources | T501-T513 | 13 |
| 6 | MCP Prompts | T601-T604 | 4 |
| 总计 | 136 |
附录 B: 工具与测试用例映射
| 工具名 | 配置档 | 测试 ID | 类型 |
|---|---|---|---|
| initialize | — | T001 | 协议 |
| tools/list | — | T002 | 协议 |
| resources/list | — | T003 | 协议 |
| resources/templates/list | — | T004 | 协议 |
| prompts/list | — | T005 | 协议 |
| (Accept header) | — | T006 | 协议 |
| (unknown method) | — | T007 | 协议 |
| GET /tools | — | T008 | 协议 |
| get_project_info | core | T101 | 只读 |
| get_editor_state | core | T102 | 只读 |
| get_tool_catalog | core | T103 | 只读 |
| get_scene_info | core | T104 | 只读 |
| get_hierarchy | core | T105 | 只读 |
| list_scenes | core | T106 | 只读 |
| open_scene | core | T107 | 状态 |
| list_assets | core | T108 | 只读 |
| inspect_asset | core | T109 | 只读 |
| inspect_asset_dependencies | core | T110 | 只读 |
| validate_asset_dependencies | core | T111 | 只读 |
| inspect_prefab | core | T112 | 只读 |
| inspect_prefab_instance | core | T113 | 只读 |
| validate_prefab_references | core | T114 | 只读 |
| validate_scene | core | T115 | 只读 |
| get_selection | core | T116 | 只读 |
| set_selection | core | T117 | 变更 |
| get_runtime_state | core | T118 | 只读 |
| get_performance_snapshot | core | T119 | 只读 |
| get_build_status | core | T120 | 只读 |
| list_editor_windows | core | T121 | 只读 |
| get_recent_logs | core | T122 | 只读 |
| search_project_logs | core | T123 | 只读 |
| clear_logs | core | T124 | 变更 |
| run_script_diagnostics | core | T125 | 只读 |
| get_script_diagnostic_context | core | T126 | 只读 |
| check_for_updates | core | T127 | 只读 |
| list_project_instructions | core | T128 | 只读 |
| read_project_instruction | core | T129 | 只读 |
| capture_editor_screenshot | core | T130 | 只读 |
| capture_scene_screenshot | core | T131 | 只读 |
| capture_preview_screenshot | core | T132 | 只读 |
| execute_javascript (scene) | core | T133 | 执行 |
| execute_javascript (editor) | core | T134 | 执行 |
| execute_scene_script | core | T135 | 执行 |
| execute_editor_script | core | T136 | 执行 |
| open_asset | core | T137 | 状态 |
| select_asset | core | T138 | 状态 |
| create_node | full | T201 | 变更 |
| set_node_transform | full | T202 | 变更 |
| delete_node | full | T203 | 变更 |
| add_component | full | T204 | 变更 |
| set_component_property | full | T205 | 变更 |
| remove_component | full | T206 | 变更 |
| save_current_scene | full | T207 | 状态 |
| find_nodes | full | T301 | 只读 |
| inspect_node | full | T302 | 只读 |
| list_components | full | T303 | 只读 |
| inspect_component | full | T304 | 只读 |
| list_cameras | full | T305 | 只读 |
| list_animations | full | T306 | 只读 |
| list_prefabs | full | T307 | 只读 |
| get_editor_selection | full | T308 | 只读 |
| exists | full | T309 | 只读 |
| read_file | full | T310 | 只读 |
| get_file_snippet | full | T311 | 只读 |
| list_directory | full | T312 | 只读 |
| search_files | full | T313 | 只读 |
| capture_desktop_screenshot | full | T314 | 只读 |
| capture_game_screenshot | full | T315 | 只读 |
| create_canvas | full | T401 | 变更 |
| create_label | full | T402 | 变更 |
| create_button | full | T403 | 变更 |
| create_sprite | full | T404 | 变更 |
| create_camera | full | T405 | 变更 |
| set_camera_properties | full | T406 | 变更 |
| add_animation_clip | full | T407 | 变更 |
| play_animation | full | T408 | 变更 |
| stop_animation | full | T409 | 变更 |
| instantiate_prefab | full | T410 | 变更 |
| create_prefab_instance | full | T411 | 变更 |
| inspect_prefab_instance | full | T412 | 只读 |
| set_node_transform (实例修改) | full | T413 | 变更 |
| apply_prefab_instance | full | T414 | 变更 |
| inspect_prefab (验证保存) | full | T415 | 只读 |
| read_file (验证 .prefab 持久化) | full | T416 | 只读 |
| revert_prefab_instance | full | T417 | 变更 |
| edit_prefab_json | full | T418 | 变更 |
| inspect_prefab (验证 JSON 编辑) | full | T419 | 只读 |
| duplicate_prefab | full | T420 | 变更 |
| validate_prefab_references | full | T421, T422 | 只读 |
| write_file | full | T423 | 变更 |
| replace_in_file | full | T424 | 变更 |
| refresh_assets | full | T425 | 状态 |
| delete_asset | full | T428 | 变更 |
| bind_button_click_event | full | T429 | 变更 |
| list_button_click_events | full | T430 | 只读 |
| simulate_button_click | full | T431 | 变更 |
| emit_node_event | full | T432 | 变更 |
| invoke_component_method | full | T433 | 变更 |
| pause_runtime | full | T434 | 变更 |
| set_time_scale | full | T435 | 变更 |
| resume_runtime | full | T436 | 变更 |
| run_scene_asset | full | T437 | 变更 |
| simulate_mouse_click | full | T438 | 变更 |
| simulate_mouse_drag | full | T439 | 变更 |
| simulate_key_press | full | T440 | 变更 |
| simulate_key_combo | full | T441 | 变更 |
| simulate_preview_input | full | T442 | 变更 |
| open_build_panel | full | T443 | 状态 |
| run_project_preview | full | T444 | 状态 |
| get_editor_preference | full | T445 | 只读 |
| set_editor_preference | full | T446 | 变更 |
| broadcast_editor_message | full | T447 | 状态 |
| write_project_instruction | full | T448 | 变更 |
| create_project_skill | full | T449 | 变更 |
| create_cocos_mcp_project_skill | full | T450 | 变更 |
| reset_component_property | full | T451 | 变更 |
附录 C: AI Agent 执行注意事项
C.1 环境依赖
| 测试阶段 | 环境要求 | 失败处理 |
|---|---|---|
| Phase 0 | MCP 服务器运行 | 全部中止 |
| Phase 1 | 场景已加载 | 场景相关测试 skip |
| Phase 2 | 场景已加载 | 链式 skip |
| Phase 3 | 场景已加载 + 测试脚本已编译 | 脚本相关 skip |
| Phase 4a-4d | 场景已加载 + 预制体已创建 | 链式 skip |
| Phase 4i | preview 运行中 | skip |
| Phase 4j | 编辑器窗口可见且前台 | skip |
| Phase 5 | 服务器运行 | 全部 skip |
| Phase 6 | 服务器运行 | 全部 skip |
C.2 链式测试依赖图
T106 (list_scenes) ──→ T107 (open_scene)
──→ T437 (run_scene_asset)
T108 (list_assets) ──→ T109 (inspect_asset)
──→ T110 (inspect_asset_dependencies)
──→ T111 (validate_asset_dependencies)
──→ T137 (open_asset)
──→ T138 (select_asset)
T201 (create_node) ──→ T202 (set_node_transform)
──→ T203 (delete_node)
T204 (add_component) ──→ T205 (set_component_property)
──→ T206 (remove_component)
T307 (list_prefabs) ──→ T112 (inspect_prefab)
──→ T114 (validate_prefab_references)
T410 (instantiate_prefab) ──→ T412 (inspect_prefab_instance)
──→ T413 (set_node_transform 修改实例)
──→ T414 (apply_prefab_instance 保存回预制体)
│ ──→ T415 (inspect_prefab 验证已保存)
│ ──→ T416 (read_file 验证 .prefab 持久化)
──→ T417 (revert_prefab_instance 还原实例)
T418 (edit_prefab_json) ──→ T419 (inspect_prefab 验证 JSON 编辑)
T420 (duplicate_prefab) ──→ T422 (validate_prefab_references 验证副本)
T421 (validate_prefab_references 验证原件)
T401 (create_canvas) ──→ T402 (create_label)
──→ T403 (create_button) ──→ T429 (bind_button_click_event)
│ ──→ T431 (simulate_button_click)
└──→ T404 (create_sprite)
T405 (create_camera) ──→ T406 (set_camera_properties)
T407 (add_animation_clip) ──→ T408 (play_animation)
──→ T409 (stop_animation)
T423 (write_file) ──→ T424 (replace_in_file)
──→ T428 (delete_asset) [清理]
T434 (pause_runtime) ──→ T435 (set_time_scale)
──→ T436 (resume_runtime)
T444 (run_project_preview) ──→ T434-T442 (需要 preview 运行的测试)
C.3 推荐执行顺序
为最大化测试覆盖并减少 skip,建议按以下顺序执行:
1. Phase 0 (协议) — 必须全部通过
2. 测试数据初始化 (1.6 节) — 含预制体创建
3. Phase 1 (Core 只读) — 先 T106 拿场景 uuid, T108 拿资产 uuid
4. Phase 3 (Full 只读) — T307 验证预制体已创建
5. Phase 2 (Core 变更链式) — T201→T202→T203, T204→T205→T206
6. Phase 4a-4c (UI/摄像机/动画)
7. Phase 4d (预制体生命周期) — T410→T412→T413→T414→T415→T416, T417, T418→T419, T420→T422, T421
8. Phase 4e-4h (文件/资源/事件/组件方法)
9. T444 (run_project_preview) — 启动 preview
10. Phase 4i (Runtime) — 需要 preview 运行
11. Phase 4j (Input) — 需要 preview 运行 + 窗口可见
12. Phase 4k-4m (Build/Preference/Instruction)
13. Phase 5 (Resources)
12. Phase 6 (Prompts)
13. 生成测试报告
C.4 错误处理策略
| 场景 | 策略 |
|---|---|
| 协议测试失败 | 中止全部测试,报告协议不兼容 |
| 场景未加载 | 跳过所有场景相关测试,继续非场景测试 |
| 预制体不存在 | 跳过预制体相关测试,记录 skip |
| preview 未运行 | 先执行 T438 启动 preview,再重试 |
| 窗口不可见 | 跳过截图和输入模拟测试 |
| 链式前驱失败 | 后续依赖步骤标记 skip |
| 超时(>30秒无响应) | 标记 fail,记录超时,继续下一个 |
| HTTP 500 | 标记 fail,记录响应体,继续 |
C.5 execute_javascript 链式编排示例
对于需要多步链式操作且数据传递复杂的场景,可使用 execute_javascript 在编辑器上下文中一次性完成:
# 示例:创建节点 → 添加组件 → 设置属性 → 验证 → 清理,一步完成
mcp_tool "execute_javascript" '{
"context": "editor",
"code": "const createResult = await helpers.callTool(\"create_node\", {name:\"ChainNode\",parentPath:\"Canvas\"}); const createData = JSON.parse(createResult); const nodeUuid = createData.data.uuid; await helpers.callTool(\"add_component\", {path:\"Canvas/ChainNode\",componentType:\"cc.Sprite\"}); await helpers.callTool(\"set_component_property\", {path:\"Canvas/ChainNode\",componentType:\"cc.Sprite\",property:\"color\",value:{r:255,g:0,b:0,a:255}}); const inspectResult = await helpers.callTool(\"inspect_component\", {path:\"Canvas/ChainNode\",componentType:\"cc.Sprite\"}); const inspectData = JSON.parse(inspectResult); await helpers.callTool(\"remove_component\", {path:\"Canvas/ChainNode\",componentType:\"cc.Sprite\"}); await helpers.callTool(\"delete_node\", {uuid:nodeUuid}); return { created: true, inspected: inspectData.ok, cleaned: true };"
}'
- 判定: R1-R5 +
data.created === true+data.inspected === true+data.cleaned === true - 优势: 减少网络往返,原子性更好,适合复杂链式验证