Files
mingyuansi b65a4f22c3 fix: Windows spawn, prefab path, preview API, asset deps, error messages; add execute-context resource, tool descriptions, scene/script/asset tools
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
2026-06-30 21:53:06 +08:00

2002 lines
54 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 | >= 18Cocos 自带即可) |
| 操作系统 | 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
# 将 <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 };"
}
}
}'
```
```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 状态码为 406Accept 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\":\"<SCENE_UUID>\"}"
```
- **判定**: R1-R4 + 无 `isError`
- **注意**: 替换 `<SCENE_UUID>` 为 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\":\"<ASSET_UUID>\"}"
```
- **判定**: R1-R5 + `data` 包含资产信息
### T110: inspect_asset_dependencies
```bash
mcp_tool "inspect_asset_dependencies" "{\"uuid\":\"<ASSET_UUID>\"}"
```
- **判定**: R1-R4 + `data` 存在(即使无依赖也应返回空数组)
### T111: validate_asset_dependencies
```bash
mcp_tool "validate_asset_dependencies" "{\"uuid\":\"<ASSET_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-R4TestNode 非预制体实例,应返回有效响应说明非实例)
### T114: validate_prefab_references
```bash
# 如果 T112 有预制体 uuid 则使用,否则 skip
mcp_tool "validate_prefab_references" "{\"uuid\":\"<PREFAB_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\":\"<TEST_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\":\"<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\":\"<ASSET_UUID>\"}"
```
- **判定**: R1-R4
### T138: select_asset
```bash
mcp_tool "select_asset" "{\"uuid\":\"<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\":\"<CREATED_NODE_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\":\"<CREATED_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\":\"<CAMERA_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\":\"<PREFAB_UUID>\",\"parentPath\":\"Canvas\"}"
```
- **判定**: R1-R5 + `data.uuid` 非空
- **记录**: `instance1Uuid = data.uuid``instance1Path = "Canvas/TestPrefab"`(或返回的实际路径)
#### T411: create_prefab_instance — 创建链接预制体实例
```bash
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)
```bash
mcp_tool "inspect_prefab_instance" "{\"path\":\"<INSTANCE1_PATH>\"}"
```
- **判定**: R1-R5 + `data` 存在 + `data.isPrefabInstance``true` 或包含预制体关联信息
- **前置**: T410 通过
#### T413: set_node_transform — 修改实例节点属性(依赖 T410)
```bash
# 修改实例节点的位置,作为待应用的变更
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)
```bash
mcp_tool "apply_prefab_instance" "{\"path\":\"<INSTANCE1_PATH>\"}"
```
- **判定**: R1-R5 + `data` 存在
- **前置**: T413 通过
- **说明**: 此操作将实例上的变更保存回 `.prefab` 源文件,等同于"保存预制体"
#### T415: inspect_prefab — 验证修改已保存到预制体(依赖 T410, T414)
```bash
mcp_tool "inspect_prefab" "{\"uuid\":\"<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\":\"<INSTANCE1_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\":\"<PREFAB_UUID>\"}"
```
- **判定**: R1-R5 + `data` 存在
- **前置**: T418 通过
- **验证点**: 预制体名称应反映 T418 的修改(`EditedTestPrefab`
- **说明**: 也可通过 `read_file` 读取 .prefab 文件验证 `_name` 字段已变更
#### T420: duplicate_prefab — 复制预制体(依赖 T410)
```bash
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)
```bash
mcp_tool "validate_prefab_references" "{\"uuid\":\"<PREFAB_UUID>\"}"
```
- **判定**: R1-R5 + `data` 存在 + 无断引错误
- **前置**: T410 通过
- **说明**: 检查预制体内部的所有 UUID 引用是否有效
#### T422: validate_prefab_references — 验证复制的预制体引用(依赖 T420)
```bash
# 使用 T420 返回的 duplicatedPrefabUuid
mcp_tool "validate_prefab_references" "{\"uuid\":\"<DUPLICATED_PREFAB_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\":\"<SCENE_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 集成测试报告 ==========
测试时间: <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 文件保存:
```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`
- **优势**: 减少网络往返,原子性更好,适合复杂链式验证