diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..b73b7e3 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,260 @@ +# Funplay Cocos MCP — AI Agent Skill + +> Use this skill when operating a Cocos Creator 3.8+ project through the Funplay Cocos MCP server. + +## What This Is + +An MCP server embedded inside the Cocos Creator editor. It exposes tools, resources, and prompts that let you inspect and manipulate a live Cocos project — scene hierarchy, nodes, components, assets, prefabs, scripts, screenshots, runtime state, and more. + +- **Server URL**: `http://127.0.0.1:8765/` (default; may auto-shift if port is taken) +- **MCP server name**: `funplay_cocos` +- **Tool profiles**: `core` (38 tools, default), `full` (110 tools), `custom` +- **Health check**: `GET /health` — verify the server is alive before doing anything + +## Core Philosophy: execute_javascript First + +**`execute_javascript` is the primary tool.** It handles ~80% of all workflows in fewer, higher-leverage calls than chaining many narrow tools. + +**Decision rule**: Start with `execute_javascript`. Only switch to a specialist tool when it is *strictly better* for the task: + +| Task | Best tool | Why | +|---|---|---| +| Scene/node/component inspection & mutation | `execute_javascript` (scene) | One call can inspect, decide, and act | +| Editor automation, file ops, asset-db | `execute_javascript` (editor) | Full access to `Editor`, `fs`, `path`, `helpers` | +| TypeScript compile errors | `run_script_diagnostics` / `get_script_diagnostic_context` | Parsed diagnostics with source snippets | +| Visual verification | `capture_scene_screenshot` / `capture_preview_screenshot` | Image proof of results | +| Exact asset discovery | `list_assets` | Structured asset-db query with type filtering | +| Opening a specific scene | `open_scene` | Direct scene switching | +| Compact editor summary | `get_editor_state` | One-call snapshot of project + selection + windows | +| Validate scene health | `validate_scene` | Combined scene + runtime + diagnostics + logs check | + +**Anti-pattern**: Calling `get_hierarchy` → `inspect_node` → `list_components` → `inspect_component` in 4 separate calls when one `execute_javascript` with `context="scene"` can do all of it and mutate in the same call. + +## The Two Execution Contexts + +### context="scene" — Live scene/runtime + +Runs inside the active Cocos scene via the scene bridge. + +**Injected variables:** +- `cc` — Cocos engine (use `cc.Sprite`, `cc.Node`, `cc.Vec3`, `cc.UITransform`, etc.) +- `scene` — Active scene root node (`cc.Node`, same as `director.getScene()`) +- `director` — `cc.director` +- `require` — Node.js require (with Cocos module paths) +- `Editor` — Editor global (if running in editor) +- `args` — User-passed args object + +**Return patterns (any one):** +```javascript +// 1. Direct return +return { sceneName: scene.name, childCount: scene.children.length }; + +// 2. run function (async supported) +async function run(env) { return result; } + +// 3. module.exports +module.exports = async (env) => result; +``` + +**Critical rules:** +- Always use `cc.Sprite`, `cc.Node` — never bare `Sprite`, `Node` +- Do NOT redeclare `scene`, `director`, `cc` — they are already in scope +- `assetManager.loadAny` must use callback style — it returns `null` without a callback + +### context="editor" — Editor/browser context + +Runs in the Cocos editor main process with full Node.js access. + +**Injected variables:** +- `require`, `Editor`, `args`, `context`, `helpers`, `fs`, `path`, `os` + +**`helpers` object:** +- `helpers.getStatus()` — server status +- `helpers.listTools()` — all exposed MCP tools +- `helpers.readResource(uri)` — read an MCP resource +- `helpers.callTool(name, args)` — call another MCP tool +- `helpers.configureClient(targetId)` — configure an MCP client + +**Common editor-context patterns:** +```javascript +// Query asset-db +const info = await Editor.Message.request("asset-db", "query-asset-info", "ASSET_UUID"); + +// Call a scene method +const result = await Editor.Message.request( + "scene", "execute-scene-script", + { name: "funplay-cocos-mcp", method: "inspectNode", args: { uuid: "NODE_UUID" } } +); + +// Read project context via helper +const ctx = await helpers.readResource("cocos://project/context"); + +// Call another tool from editor context +const diag = await helpers.callTool("run_script_diagnostics", {}); +``` + +## Safety Checks + +`execute_javascript` has safety checks **enabled by default**. The following patterns are blocked: + +- `fs.rm`, `fs.unlink`, `fs.truncate`, `fs.rmdir` and sync variants — **delete/truncate** +- `fs.createWriteStream`, `fs.openSync` — **raw write streams** +- `require("child_process")`, `exec`, `spawn`, etc. — **shell execution** +- `~`, `$HOME`, `%USERPROFILE%` — **user-home path literals** +- `../` — **path traversal** +- Absolute paths outside the Cocos project root + +**To bypass** (only after reviewing the risk): pass `"safety_checks": false` in the tool args. + +File tools and `cocos://asset/path/...` resources are sandboxed to the project root. + +## Common Workflows + +### 1. Orient: Understand the current project state + +```json +// One call for a compact snapshot +{ "context": "editor", "code": "return await helpers.readResource('cocos://project/context');" } +``` + +Or use the specialist tool: +```json +{} +``` +→ `get_editor_state` returns project info, runtime status, selection, scene summary, and windows. + +### 2. Inspect scene hierarchy + +```json +{ + "context": "scene", + "code": "function walk(n, d=0) { const r = { name: n.name, active: n.active, components: n.components.map(c=>c.constructor.name) }; if (d < 3 && n.children.length) r.children = n.children.map(c => walk(c, d+1)); return r; } return walk(scene);" +} +``` + +Or use `get_hierarchy` with `{ "rootPath": "Canvas", "maxDepth": 3, "includeComponents": true }` for a structured snapshot. + +### 3. Create UI (login page example) + +```json +{ + "context": "scene", + "code": "const { Node, UITransform, Sprite, Label, Button, Color, Vec3, find } = cc; const canvas = find('Canvas'); const bg = new Node('LoginBG'); bg.layer = canvas.layer; bg.addComponent(UITransform).setContentSize(720, 1280); bg.addComponent(Sprite).color = new Color(40, 40, 50, 255); canvas.addChild(bg); const title = new Node('Title'); title.layer = canvas.layer; title.addComponent(UITransform).setContentSize(400, 60); const tLabel = title.addComponent(Label); tLabel.string = 'Login'; tLabel.fontSize = 48; tLabel.color = Color.WHITE; title.setPosition(0, 400, 0); bg.addChild(title); return { created: ['LoginBG', 'Title'], canvas: canvas.name };" +} +``` + +After creation, verify: +1. `get_hierarchy` or `execute_javascript` to confirm structure +2. `capture_scene_screenshot` for visual proof + +### 4. Set an asset reference (SpriteFrame, Texture, etc.) + +**Cannot use `set_component_property` for asset references.** Use `execute_javascript` with `loadAny`: + +```json +{ + "context": "scene", + "code": "const { find, assetManager, SpriteFrame } = cc; const node = find('Canvas/Player/Sprite'); const sprite = node.getComponent('cc.Sprite'); const sf = await new Promise((resolve, reject) => { assetManager.loadAny({ uuid: 'SPRITEFRAME_UUID', type: SpriteFrame }, (err, asset) => { if (err) reject(err); else resolve(asset); }); }); sprite.spriteFrame = sf; return { node: node.name, spriteFrame: sf.name };" +} +``` + +### 5. Fix script errors + +1. Run diagnostics: `run_script_diagnostics` → get error list +2. Get context: `get_script_diagnostic_context` → errors with source snippets +3. Fix the file: `execute_javascript` with `context="editor"` using `fs`/`path`, or use `replace_in_file` +4. Refresh assets: `refresh_assets` +5. Re-run diagnostics to confirm clean + +### 6. Prefab workflow + +1. Inspect: `inspect_prefab` with `{ "target": "db://assets/prefabs/Enemy.prefab" }` +2. Validate references: `validate_prefab_references` +3. Edit JSON directly: `edit_prefab_json` with `jsonPath` + `valueJson` or `search`/`replace` +4. Instantiate in scene: `create_prefab_instance` (linked) or `instantiate_prefab` (runtime) +5. After scene edits, apply back: `apply_prefab_instance` + +### 7. Visual verification + +```json +// Scene panel screenshot +{ "fileName": "after-ui-creation" } +``` +→ `capture_scene_screenshot` + +```json +// Preview/game screenshot +{ "fileName": "gameplay-check" } +``` +→ `capture_preview_screenshot` + +## MCP Resources Quick Reference + +| Resource URI | What it gives you | +|---|---| +| `cocos://project/context` | Full project + editor context (project path, version, selection, scene) | +| `cocos://project/summary` | Project path, folder listing, script/prefab/scene counts | +| `cocos://scene/active` | Active scene summary (depth 3) | +| `cocos://selection/current` | Current node + asset selection | +| `cocos://errors/scripts` | Latest TypeScript diagnostics | +| `cocos://logs/editor` | Recent MCP runtime logs + tool interactions | +| `cocos://logs/project` | Tails of common project log files | +| `cocos://mcp/interactions` | Recent MCP tool call history | +| `cocos://mcp/execute-context` | Full execute_javascript variable & pattern guide | + +**Resource templates:** +- `cocos://scene/node/{path}` — inspect a node by hierarchy path +- `cocos://asset/path/{relative_path}` — read a text/asset file by project-relative path +- `cocos://asset/info/{uuid_or_path}` — asset info + metadata by uuid or path + +## MCP Prompts + +Built-in workflow prompts (call via `prompts/get`): + +| Prompt | Use when | +|---|---| +| `fix_script_errors` | Diagnosing and repairing TypeScript compile errors | +| `create_playable_prototype` | Building a gameplay prototype from scratch | +| `scene_validation` | Validating scene health, references, and runtime state | +| `auto_wire_scene` | Wiring up node references, event bindings, and component connections | + +All prompts reinforce the `execute_javascript`-first philosophy. + +## Key Pitfalls + +1. **`set_component_property` cannot set asset references** (SpriteFrame, Texture, Material, Font, AudioClip). Use `execute_javascript` with `cc.assetManager.loadAny({uuid, type}, cb)`. + +2. **`assetManager.loadAny(uuid)` without callback returns `null`** in scene context. Always use callback style: + ```javascript + assetManager.loadAny({ uuid, type: SpriteFrame }, (err, asset) => { ... }); + ``` + +3. **Custom script components require compilation** before `add_component` or `find` can locate them. If a script was just created or modified, wait for Cocos to recompile or trigger a refresh first. + +4. **Node hierarchy paths are slash-separated from scene root**, e.g. `"Canvas/Player/Sprite"`. Use `get_hierarchy` to verify paths before passing them to tools. + +5. **`create_node` accepts `parentPath`, not `parentUuid`**. Resolve the path first with `get_hierarchy` or `find_nodes`. + +6. **Always use `cc.` prefix** in scene context: `cc.Sprite`, `cc.Node`, `cc.UITransform`, `cc.Label`, `cc.Button`, etc. Bare names like `Sprite` or `Node` will fail. + +7. **New nodes need `.layer` set** to match their parent, otherwise they won't render. Set `node.layer = parent.layer` before adding to hierarchy. + +8. **Safety checks block absolute paths outside the project**. If you need to read an external file, use `execute_javascript` with `context="editor"` and pass `safety_checks: false` only after verifying the code is safe. + +## Tool Profile Management + +- **`core`** (default): 38 high-signal tools. Start here. +- **`full`**: All 110 tools including UI creation, node editing, components, animation, camera, input simulation, file I/O, runtime control, and more. +- **`custom`**: Start from `core`, add categories/tools via `enabledToolCategories` / `enabledTools`, remove via `disabledToolCategories` / `disabledTools`. + +Check current exposure: `get_tool_catalog` → see every tool with profile, category, and enabled state. + +If you need a `full`-only tool (e.g. `create_node`, `add_component`, `write_file`), tell the user to switch to `full` profile in the MCP panel (`Funplay > MCP Server`). + +## Quick Start Checklist for Agents + +1. **Verify connection** — call `get_project_info` or `get_editor_state` +2. **Read context** — `cocos://project/context` resource or `get_editor_state` +3. **Do the work** — prefer `execute_javascript` (scene for runtime, editor for automation) +4. **Verify results** — `validate_scene`, `run_script_diagnostics`, or screenshot tools +5. **Report** — summarize what was done, what was verified, and any issues found