# 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 创建一次性测试项目 1. 打开 Cocos Creator 3.8.8,新建一个 **Empty(2D)** 项目,命名为 `mcp-test-disposable` 2. 项目创建后会自动生成一个默认场景 `assets/scene.scene`,保留它 3. 在 `assets/` 下创建文件夹 `scripts` 和 `prefabs` ### 1.3 安装 funplay-cocos-mcp 扩展 ```bash # 方式一:符号链接(开发模式) 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 服务器 1. 打开菜单:`Funplay > MCP Server` 2. 在面板中确认 Tool Profile 设置为 `full`(测试全部 101 个工具) 3. 点击启动服务器 4. 确认面板显示服务器运行在 `http://127.0.0.1:8765/` ### 1.5 验证连通性 ```bash # 健康检查 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` 在编辑器上下文中创建测试所需的基础数据: ```bash # 设置变量 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 };" } } }' ``` ```bash # 创建测试脚本文件 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" } } }' ``` ```bash # 刷新资源数据库 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": {} } }' ``` ```bash # 保存场景,确保 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": {} } }' ``` ```bash # 从 TestNode 创建预制体(funplay-cocos-mcp 无 create_prefab 工具,通过 execute_javascript 调用 Editor API) # 将 替换为前面初始化返回的 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 = \"\"; const savePath = \"db://assets/prefabs/TestPrefab.prefab\"; const result = await Editor.Message.request(\"scene\", \"create-prefab\", testNodeUuid, savePath); return { result: result, savePath: savePath };" } } }' ``` ```bash # 刷新资源数据库,确保新预制体被索引 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"} } }' ``` ```bash # 查询预制体 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 节点 UUID - `testNodeUuid` — TestNode 节点 UUID - `prefabUuid` — TestPrefab 预制体 UUID(从最后一步 list_prefabs 返回中获取) - `prefabPath` — `db://assets/prefabs/TestPrefab.prefab` --- ## 2. AI Agent 自动化测试框架 ### 2.1 通用变量与辅助函数 AI Agent 在执行测试前,先设置以下变量: ```bash 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 函数或等价逻辑实现): ```bash # 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`: ```json [ {"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 服务器已启动 ```bash mcp_init ``` - **判定**: R1 + R2 + 响应 `result.protocolVersion` 为受支持版本 + `result.capabilities` 包含 `tools`/`resources`/`prompts` + `result.serverInfo.name` 包含 `Funplay` - **记录**: 协商出的协议版本 ### T002: tools/list - **方法**: curl - **前置条件**: T001 通过 ```bash 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 ```bash 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 ```bash 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 ```bash 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 缺失应拒绝 ```bash 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 ```bash 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 调试端点 ```bash curl -s "$MCP_URL/tools" ``` - **判定**: R1 + 响应包含 `tools` 数组 + `count` 字段 + `ok: true` --- ## 4. Phase 1: Core 只读工具测试 > 以下工具均为 `core` 配置档中的只读/安全工具,可独立执行,无副作用。 ### T101: get_project_info ```bash mcp_tool "get_project_info" '{}' ``` - **判定**: R1-R5 + `data.projectPath` 非空 + `data.cocosVersion` 包含 `3.8` - **记录**: projectPath, cocosVersion ### T102: get_editor_state ```bash mcp_tool "get_editor_state" '{}' ``` - **判定**: R1-R5 + `data` 包含项目信息 ### T103: get_tool_catalog ```bash mcp_tool "get_tool_catalog" '{}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 > 0 + 每项有 `name`/`profile`/`category` ### T104: get_scene_info ```bash mcp_tool "get_scene_info" '{}' ``` - **判定**: R1-R5 + `data.sceneName` 或 `data.name` 非空 - **注意**: 需要场景已加载,如失败则后续场景相关测试标记 skip ### T105: get_hierarchy ```bash mcp_tool "get_hierarchy" '{}' ``` - **判定**: R1-R5 + `data` 包含节点树结构 ### T106: list_scenes ```bash mcp_tool "list_scenes" '{}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 >= 1 - **记录**: 第一个场景的 uuid 和 path,供 T107 使用 ### T107: open_scene ```bash # 使用 T106 记录的场景 uuid mcp_tool "open_scene" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 + 无 `isError` - **注意**: 替换 `` 为 T106 获取的实际值 ### T108: list_assets ```bash mcp_tool "list_assets" '{"pattern":"db://assets/**/*"}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 > 0 - **记录**: 第一个资产的 uuid,供 T109/T110 使用 ### T109: inspect_asset ```bash # 使用 T108 记录的 asset uuid mcp_tool "inspect_asset" "{\"uuid\":\"\"}" ``` - **判定**: R1-R5 + `data` 包含资产信息 ### T110: inspect_asset_dependencies ```bash mcp_tool "inspect_asset_dependencies" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 + `data` 存在(即使无依赖也应返回空数组) ### T111: validate_asset_dependencies ```bash mcp_tool "validate_asset_dependencies" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 + `data` 存在 ### T112: inspect_prefab ```bash # 先列出预制体 mcp_tool "list_assets" '{"pattern":"db://assets/**/*.prefab"}' ``` - **判定**: 如果有预制体,inspect_prefab 返回 R1-R5;如无预制体则 skip - **注意**: AI Agent 应先检查是否有 .prefab 资产,有则取 uuid 调用 `inspect_prefab` ### T113: inspect_prefab_instance ```bash mcp_tool "inspect_prefab_instance" '{"path":"Canvas/TestNode"}' ``` - **判定**: R1-R4(TestNode 非预制体实例,应返回有效响应说明非实例) ### T114: validate_prefab_references ```bash # 如果 T112 有预制体 uuid 则使用,否则 skip mcp_tool "validate_prefab_references" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 ### T115: validate_scene ```bash mcp_tool "validate_scene" '{}' ``` - **判定**: R1-R5 + `data` 包含验证结果 ### T116: get_selection ```bash mcp_tool "get_selection" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T117: set_selection ```bash # 使用初始化时记录的 testNodeUuid mcp_tool "set_selection" "{\"type\":\"node\",\"uuid\":\"\"}" ``` - **判定**: R1-R4 ### T118: get_runtime_state ```bash mcp_tool "get_runtime_state" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T119: get_performance_snapshot ```bash mcp_tool "get_performance_snapshot" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T120: get_build_status ```bash mcp_tool "get_build_status" '{}' ``` - **判定**: R1-R4 + `data` 存在 ### T121: list_editor_windows ```bash mcp_tool "list_editor_windows" '{}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 > 0 - **记录**: 窗口列表,供截图和输入模拟测试使用 ### T122: get_recent_logs ```bash mcp_tool "get_recent_logs" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T123: search_project_logs ```bash mcp_tool "search_project_logs" '{"query":"error"}' ``` - **判定**: R1-R4 + `data` 存在 ### T124: clear_logs ```bash mcp_tool "clear_logs" '{}' ``` - **判定**: R1-R4 ### T125: run_script_diagnostics ```bash mcp_tool "run_script_diagnostics" '{}' ``` - **判定**: R1-R5 + `data` 存在(`diagnostics` 数组,即使为空) ### T126: get_script_diagnostic_context ```bash mcp_tool "get_script_diagnostic_context" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T127: check_for_updates ```bash mcp_tool "check_for_updates" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T128: list_project_instructions ```bash mcp_tool "list_project_instructions" '{}' ``` - **判定**: R1-R5 + `data` 为数组 ### T129: read_project_instruction ```bash # 如果 T128 返回有指令文件则读取第一个,否则 skip mcp_tool "read_project_instruction" "{\"name\":\"\"}" ``` - **判定**: R1-R4(有指令文件时)或 skip(无指令文件时) ### T130: capture_editor_screenshot ```bash mcp_tool "capture_editor_screenshot" '{}' ``` - **判定**: R1-R3 + `result.content` 包含 `type: "image"` 项 - **注意**: 需要编辑器窗口可见 ### T131: capture_scene_screenshot ```bash mcp_tool "capture_scene_screenshot" '{}' ``` - **判定**: R1-R3 + `result.content` 包含 `type: "image"` 项 ### T132: capture_preview_screenshot ```bash mcp_tool "capture_preview_screenshot" '{}' ``` - **判定**: R1-R3 + `result.content` 包含 image 项 - **注意**: 需要 preview 窗口可见;如无 preview 运行则 skip ### T133: execute_javascript (scene context) ```bash mcp_tool "execute_javascript" '{"context":"scene","code":"return { sceneName: scene.name, childCount: scene.children.length };"}' ``` - **判定**: R1-R5 + `data.sceneName` 非空 ### T134: execute_javascript (editor context) ```bash 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 ```bash mcp_tool "execute_scene_script" '{"code":"return { sceneName: scene.name };"}' ``` - **判定**: R1-R5 + `data.sceneName` 非空 ### T136: execute_editor_script ```bash mcp_tool "execute_editor_script" '{"code":"return { projectPath: context.projectPath };"}' ``` - **判定**: R1-R5 + `data.projectPath` 非空 ### T137: open_asset ```bash # 使用 T108 记录的 asset uuid mcp_tool "open_asset" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 ### T138: select_asset ```bash mcp_tool "select_asset" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 --- ## 5. Phase 2: Core 变更工具链式测试 > 以下测试有副作用,按链式顺序执行。前一步的输出作为后一步的输入。 ### 链 A: 节点创建 → 变换 → 删除 #### T201: create_node ```bash mcp_tool "create_node" '{"name":"ChainTestNode","parentPath":"Canvas"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `createdNodeUuid = data.uuid` #### T202: set_node_transform(依赖 T201) ```bash mcp_tool "set_node_transform" "{\"uuid\":\"\",\"position\":{\"x\":100,\"y\":200,\"z\":0},\"scale\":{\"x\":2,\"y\":2,\"z\":1}}" ``` - **判定**: R1-R4 - **前置**: T201 通过 #### T203: delete_node(依赖 T201) ```bash mcp_tool "delete_node" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 - **前置**: T201 通过 - **清理**: 删除 T201 创建的节点 ### 链 B: 组件添加 → 设置属性 → 移除 #### T204: add_component(依赖 T201 或使用已有的 TestNode) ```bash # 使用初始化时的 testNodeUuid mcp_tool "add_component" "{\"path\":\"Canvas/TestNode\",\"componentType\":\"cc.Sprite\"}" ``` - **判定**: R1-R4 #### T205: set_component_property(依赖 T204) ```bash 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) ```bash mcp_tool "remove_component" "{\"path\":\"Canvas/TestNode\",\"componentType\":\"cc.Sprite\"}" ``` - **判定**: R1-R4 - **前置**: T204 通过 - **清理**: 移除 T204 添加的组件 ### T207: save_current_scene ```bash mcp_tool "save_current_scene" '{}' ``` - **判定**: R1-R4 - **注意**: 保存前面所有变更 --- ## 6. Phase 3: Full 额外只读工具测试 > 以下工具仅在 `full` 配置档中可用。 ### T301: find_nodes ```bash mcp_tool "find_nodes" '{"name":"TestNode"}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 >= 1 ### T302: inspect_node ```bash mcp_tool "inspect_node" '{"path":"Canvas/TestNode"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 + `data.name` 为 `TestNode` ### T303: list_components ```bash mcp_tool "list_components" '{"path":"Canvas/TestNode"}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 >= 1(至少有 UITransform) ### T304: inspect_component ```bash mcp_tool "inspect_component" '{"path":"Canvas/TestNode","componentType":"cc.Label"}' ``` - **判定**: R1-R5 + `data` 存在 ### T305: list_cameras ```bash mcp_tool "list_cameras" '{}' ``` - **判定**: R1-R5 + `data` 为数组 ### T306: list_animations ```bash mcp_tool "list_animations" '{}' ``` - **判定**: R1-R5 + `data` 为数组 ### T307: list_prefabs ```bash mcp_tool "list_prefabs" '{}' ``` - **判定**: R1-R5 + `data` 为数组 - **记录**: 如有预制体,记录第一个的 uuid ### T308: get_editor_selection ```bash mcp_tool "get_editor_selection" '{}' ``` - **判定**: R1-R5 + `data` 存在 ### T309: exists ```bash mcp_tool "exists" '{"path":"assets/scripts/TestComponent.ts"}' ``` - **判定**: R1-R5 + `data.exists` 为 `true` ### T310: read_file ```bash mcp_tool "read_file" '{"path":"assets/scripts/TestComponent.ts"}' ``` - **判定**: R1-R5 + `data.content` 包含 `TestComponent` ### T311: get_file_snippet ```bash mcp_tool "get_file_snippet" '{"path":"assets/scripts/TestComponent.ts","line":3,"context":3}' ``` - **判定**: R1-R5 + `data` 存在 ### T312: list_directory ```bash mcp_tool "list_directory" '{"path":"assets/scripts"}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 >= 1 ### T313: search_files ```bash mcp_tool "search_files" '{"pattern":"*.ts"}' ``` - **判定**: R1-R5 + `data` 为数组 + 长度 >= 1 ### T314: capture_desktop_screenshot ```bash mcp_tool "capture_desktop_screenshot" '{}' ``` - **判定**: R1-R3 + `result.content` 包含 image 项 ### T315: capture_game_screenshot ```bash mcp_tool "capture_game_screenshot" '{}' ``` - **判定**: R1-R3 + `result.content` 包含 image 项 - **注意**: 需要 Game 面板可见 --- ## 7. Phase 4: Full 额外变更工具测试 > 以下工具会修改项目状态,按子阶段链式执行。 ### 4a. UI 创建工具 #### T401: create_canvas ```bash mcp_tool "create_canvas" '{"name":"TestCanvas"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `canvasUuid = data.uuid` #### T402: create_label(依赖 T401 或使用已有 Canvas) ```bash mcp_tool "create_label" '{"name":"TestLabel","parentPath":"Canvas","text":"Hello MCP"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 #### T403: create_button(依赖 T401) ```bash mcp_tool "create_button" '{"name":"TestButton","parentPath":"Canvas","text":"Click Me"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `buttonUuid = data.uuid`(供 4g 事件测试使用) #### T404: create_sprite(依赖 T401) ```bash mcp_tool "create_sprite" '{"name":"TestSprite","parentPath":"Canvas"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 ### 4b. 摄像机工具 #### T405: create_camera ```bash mcp_tool "create_camera" '{"name":"TestCamera"}' ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `cameraUuid = data.uuid` #### T406: set_camera_properties(依赖 T405) ```bash mcp_tool "set_camera_properties" "{\"uuid\":\"\",\"properties\":{\"projection\":1}}" ``` - **判定**: R1-R4 - **前置**: T405 通过 ### 4c. 动画工具 #### T407: add_animation_clip ```bash mcp_tool "add_animation_clip" '{"path":"Canvas/TestNode","clipName":"TestClip"}' ``` - **判定**: R1-R4 - **注意**: 如节点无 Animation 组件,工具应自动添加或返回明确错误 #### T408: play_animation(依赖 T407) ```bash mcp_tool "play_animation" '{"path":"Canvas/TestNode","clipName":"TestClip"}' ``` - **判定**: R1-R4 - **前置**: T407 通过 #### T409: stop_animation(依赖 T407) ```bash 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 — 实例化预制体到场景 ```bash # 使用初始化记录的 prefabUuid mcp_tool "instantiate_prefab" "{\"prefabUuid\":\"\",\"parentPath\":\"Canvas\"}" ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `instance1Uuid = data.uuid`,`instance1Path = "Canvas/TestPrefab"`(或返回的实际路径) #### T411: create_prefab_instance — 创建链接预制体实例 ```bash mcp_tool "create_prefab_instance" "{\"prefabUuid\":\"\",\"parentPath\":\"Canvas\"}" ``` - **判定**: R1-R5 + `data.uuid` 非空 - **记录**: `instance2Uuid = data.uuid`,`instance2Path = "Canvas/TestPrefab"`(或返回的实际路径) - **注意**: 如与 T410 实例名冲突,AI Agent 应使用不同名称或跳过此步 #### T412: inspect_prefab_instance — 检查实例链接状态(依赖 T410) ```bash mcp_tool "inspect_prefab_instance" "{\"path\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 + `data.isPrefabInstance` 为 `true` 或包含预制体关联信息 - **前置**: T410 通过 #### T413: set_node_transform — 修改实例节点属性(依赖 T410) ```bash # 修改实例节点的位置,作为待应用的变更 mcp_tool "set_node_transform" "{\"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) ```bash mcp_tool "apply_prefab_instance" "{\"path\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 - **前置**: T413 通过 - **说明**: 此操作将实例上的变更保存回 `.prefab` 源文件,等同于"保存预制体" #### T415: inspect_prefab — 验证修改已保存到预制体(依赖 T410, T414) ```bash mcp_tool "inspect_prefab" "{\"uuid\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 + 包含预制体序列化信息 - **前置**: T414 通过 - **验证点**: 预制体数据应反映 T413 的修改(位置/缩放变更) #### T416: read_file — 读取 .prefab 文件验证持久化(依赖 T414) ```bash 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) ```bash mcp_tool "revert_prefab_instance" "{\"path\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 - **前置**: T410 通过 - **验证点**: 实例节点应恢复为预制体的原始状态(T413 的修改被撤销) - **说明**: revert 撤销的是实例上的 override,不影响已 apply 的预制体文件 #### T418: edit_prefab_json — 直接编辑预制体 JSON(依赖 T410) ```bash 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) ```bash mcp_tool "inspect_prefab" "{\"uuid\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 - **前置**: T418 通过 - **验证点**: 预制体名称应反映 T418 的修改(`EditedTestPrefab`) - **说明**: 也可通过 `read_file` 读取 .prefab 文件验证 `_name` 字段已变更 #### T420: duplicate_prefab — 复制预制体(依赖 T410) ```bash mcp_tool "duplicate_prefab" "{\"prefabUuid\":\"\",\"newName\":\"TestPrefabCopy\"}" ``` - **判定**: R1-R5 + `data` 存在 + `data.uuid` 或 `data.url` 非空 - **前置**: T410 通过 - **记录**: `duplicatedPrefabUuid = data.uuid`(如有) - **验证点**: 新预制体应存在于 `assets/prefabs/` 目录,且 UUID 与原预制体不同 #### T421: validate_prefab_references — 验证预制体引用完整性(依赖 T410) ```bash mcp_tool "validate_prefab_references" "{\"uuid\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 + 无断引错误 - **前置**: T410 通过 - **说明**: 检查预制体内部的所有 UUID 引用是否有效 #### T422: validate_prefab_references — 验证复制的预制体引用(依赖 T420) ```bash # 使用 T420 返回的 duplicatedPrefabUuid mcp_tool "validate_prefab_references" "{\"uuid\":\"\"}" ``` - **判定**: R1-R5 + `data` 存在 + 无断引错误 - **前置**: T420 通过 - **清理**: 测试完成后可删除复制的预制体(`delete_asset`) ### 4e. 文件工具 #### T423: write_file ```bash mcp_tool "write_file" '{"path":"assets/scripts/test-output.txt","content":"MCP test output\n"}' ``` - **判定**: R1-R4 #### T424: replace_in_file ```bash 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 ```bash mcp_tool "refresh_assets" '{"path":"assets/scripts"}' ``` - **判定**: R1-R4 ### 4f. 资源操作工具 #### T426: open_asset(已在 T137 测试,此处跳过) #### T427: select_asset(已在 T138 测试,此处跳过) #### T428: delete_asset ```bash # 删除 T423 创建的测试文件 mcp_tool "delete_asset" '{"url":"db://assets/scripts/test-output.txt"}' ``` - **判定**: R1-R4 - **清理**: 删除测试文件 ### 4g. 事件工具 #### T429: bind_button_click_event(依赖 T403) ```bash 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) ```bash mcp_tool "list_button_click_events" '{"path":"Canvas/TestButton"}' ``` - **判定**: R1-R5 + `data` 为数组 - **前置**: T429 通过 #### T431: simulate_button_click(依赖 T403) ```bash mcp_tool "simulate_button_click" '{"path":"Canvas/TestButton"}' ``` - **判定**: R1-R4 - **前置**: T403 通过 #### T432: emit_node_event ```bash mcp_tool "emit_node_event" '{"path":"Canvas/TestNode","eventName":"test-event","data":{"value":42}}' ``` - **判定**: R1-R4 ### 4h. 组件方法调用 #### T433: invoke_component_method ```bash mcp_tool "invoke_component_method" '{"path":"Canvas/TestNode","componentType":"cc.Label","method":"toString"}' ``` - **判定**: R1-R4 - **注意**: 调用 Label 组件的 toString 方法作为安全测试 ### 4i. 运行时控制工具 #### T434: pause_runtime ```bash mcp_tool "pause_runtime" '{}' ``` - **判定**: R1-R4 - **注意**: 需要 preview 运行中;如未运行则 skip #### T435: set_time_scale(依赖 T434) ```bash mcp_tool "set_time_scale" '{"scale":0.5}' ``` - **判定**: R1-R4 - **前置**: T434 通过或 skip #### T436: resume_runtime ```bash mcp_tool "resume_runtime" '{}' ``` - **判定**: R1-R4 #### T437: run_scene_asset ```bash # 使用 T106 记录的场景 uuid mcp_tool "run_scene_asset" "{\"uuid\":\"\"}" ``` - **判定**: R1-R4 - **注意**: 会重新加载场景 ### 4j. 输入模拟工具 > **前置条件**: 需要 Cocos Creator 编辑器窗口可见且处于前台。 #### T438: simulate_mouse_click ```bash mcp_tool "simulate_mouse_click" '{"x":400,"y":300,"windowKind":"editor"}' ``` - **判定**: R1-R4 - **注意**: 需要编辑器窗口可见 #### T439: simulate_mouse_drag ```bash mcp_tool "simulate_mouse_drag" '{"startX":100,"startY":100,"endX":300,"endY":300,"windowKind":"editor"}' ``` - **判定**: R1-R4 #### T440: simulate_key_press ```bash mcp_tool "simulate_key_press" '{"keyCode":"S","modifiers":["control"],"windowKind":"editor"}' ``` - **判定**: R1-R4 - **注意**: Ctrl+S 会触发保存场景 #### T441: simulate_key_combo ```bash mcp_tool "simulate_key_combo" '{"keyCode":"P","modifiers":["control"],"windowKind":"editor"}' ``` - **判定**: R1-R4 #### T442: simulate_preview_input ```bash mcp_tool "simulate_preview_input" '{"mode":"click","x":200,"y":200}' ``` - **判定**: R1-R4 - **注意**: 需要 preview 窗口运行 ### 4k. 构建与编辑器工具 #### T443: open_build_panel ```bash mcp_tool "open_build_panel" '{}' ``` - **判定**: R1-R4 - **注意**: 会打开构建面板 #### T444: run_project_preview ```bash mcp_tool "run_project_preview" '{}' ``` - **判定**: R1-R4 - **注意**: 会启动预览;后续依赖 preview 的测试(T434-T442)应在此之后执行 ### 4l. 偏好与广播工具 #### T445: get_editor_preference ```bash mcp_tool "get_editor_preference" '{"name":"general","path":"language"}' ``` - **判定**: R1-R4 + `data` 存在 #### T446: set_editor_preference ```bash mcp_tool "set_editor_preference" '{"name":"general","path":"language","value":"zh"}' ``` - **判定**: R1-R4 - **清理**: 将语言设回原值 #### T447: broadcast_editor_message ```bash mcp_tool "broadcast_editor_message" '{"message":"scene:ready","data":{"test":true}}' ``` - **判定**: R1-R4 ### 4m. 项目指令工具 #### T448: write_project_instruction ```bash mcp_tool "write_project_instruction" '{"name":"AGENTS.md","content":"# Test Instructions\nThis is a test.\n"}' ``` - **判定**: R1-R4 #### T449: create_project_skill ```bash mcp_tool "create_project_skill" '{"skillName":"test-skill","content":"# Test Skill\nTest content.\n"}' ``` - **判定**: R1-R4 #### T450: create_cocos_mcp_project_skill ```bash mcp_tool "create_cocos_mcp_project_skill" '{}' ``` - **判定**: R1-R4 #### T451: reset_component_property ```bash mcp_tool "reset_component_property" '{"path":"Canvas/TestNode","componentType":"cc.Label","property":"string"}' ``` - **判定**: R1-R4 --- ## 8. Phase 5: MCP Resources 测试 ### T501: cocos://project/context ```bash mcp_resource "cocos://project/context" ``` - **判定**: R1-R2 + `result.contents` 为数组 + 首项有 `text` 字段 + 非空 ### T502: cocos://project/summary ```bash mcp_resource "cocos://project/summary" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T503: cocos://scene/active ```bash mcp_resource "cocos://scene/active" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T504: cocos://scene/current ```bash mcp_resource "cocos://scene/current" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T505: cocos://selection/current ```bash mcp_resource "cocos://selection/current" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T506: cocos://selection/asset ```bash mcp_resource "cocos://selection/asset" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T507: cocos://errors/scripts ```bash mcp_resource "cocos://errors/scripts" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T508: cocos://logs/editor ```bash mcp_resource "cocos://logs/editor" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T509: cocos://logs/project ```bash mcp_resource "cocos://logs/project" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T510: cocos://mcp/interactions ```bash mcp_resource "cocos://mcp/interactions" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 ### T511: Resource Template — cocos://scene/node/{path} ```bash mcp_resource "cocos://scene/node/Canvas/TestNode" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 + 包含 `TestNode` ### T512: Resource Template — cocos://asset/path/{relative_path} ```bash 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} ```bash mcp_resource "cocos://asset/info/db://assets/scene.scene" ``` - **判定**: R1-R2 + `result.contents[0].text` 非空 --- ## 9. Phase 6: MCP Prompts 测试 ### T601: fix_script_errors ```bash mcp_prompt "fix_script_errors" ``` - **判定**: R1-R2 + `result.messages` 为数组 + 长度 >= 1 + 首项有 `content.text` + 包含 `execute_javascript` ### T602: create_playable_prototype ```bash mcp_prompt "create_playable_prototype" ``` - **判定**: R1-R2 + `result.messages[0].content.text` 非空 + 包含 `execute_javascript` ### T603: scene_validation ```bash mcp_prompt "scene_validation" ``` - **判定**: R1-R2 + `result.messages[0].content.text` 非空 + 包含 `execute_javascript` ### T604: auto_wire_scene ```bash mcp_prompt "auto_wire_scene" ``` - **判定**: R1-R2 + `result.messages[0].content.text` 非空 + 包含 `execute_javascript` --- ## 10. 测试报告与结论 ### 10.1 汇总统计 测试全部完成后,AI Agent 输出以下汇总: ``` ========== funplay-cocos-mcp 集成测试报告 ========== 测试时间: Cocos Creator 版本: <从 T101 获取> MCP 服务器版本: <从 T001 获取> 工具配置档: full 测试端口: <实际端口> ==================================================== Phase 0 (协议合规): /8 通过 Phase 1 (Core 只读): /38 通过 Phase 2 (Core 变更): /7 通过 Phase 3 (Full 只读): /15 通过 Phase 4 (Full 变更): /51 通过 Phase 5 (Resources): /13 通过 Phase 6 (Prompts): /4 通过 ---------------------------------------------------- 总计: / 通过, 失败, 跳过 ==================================================== ``` ### 10.2 失败详情格式 每个失败项输出: ``` [FAIL] 调用: 参数: 响应: 判定: <哪条规则失败> 可能原因: ``` ### 10.3 兼容性结论模板 ``` 兼容性结论: 依据: - : 全部 101 个工具 + 13 个资源 + 4 个 prompt 测试通过 - : 核心功能通过,但有 个工具失败,失败工具列表: <...> - : 协议层或核心工具大面积失败 3.8.8 特定问题: - <列出仅在 3.8.8 下出现的问题,如 API 不兼容、方法不存在等> 建议: - <基于测试结果给出的建议> ``` ### 10.4 结果文件格式 完整测试结果以 JSON 文件保存: ```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 在编辑器上下文中一次性完成: ```bash # 示例:创建节点 → 添加组件 → 设置属性 → 验证 → 清理,一步完成 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` - **优势**: 减少网络往返,原子性更好,适合复杂链式验证