This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user