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
2002 lines
54 KiB
Markdown
2002 lines
54 KiB
Markdown
# 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)
|
||
# 将 <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 状态码为 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\":\"<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-R4(TestNode 非预制体实例,应返回有效响应说明非实例)
|
||
|
||
### 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`
|
||
- **优势**: 减少网络往返,原子性更好,适合复杂链式验证
|