Release v0.1.3
This commit is contained in:
@@ -6,6 +6,20 @@ This project follows a simple changelog format inspired by [Keep a Changelog](ht
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.1.3] - 2026-05-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `get_editor_state` as a compact structured editor-state summary tool.
|
||||||
|
- Added `get_selection` and `set_selection` as explicit selection workflow tools for editor-side automation.
|
||||||
|
- Added persistence for the selected one-click MCP client target in the Cocos panel configuration.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Expanded the default `core` profile from 19 tools to 22 tools by promoting editor-state and selection workflows.
|
||||||
|
- Expanded the `full` profile from 67 tools to 70 tools.
|
||||||
|
- Updated panel config persistence so changing the selected MCP client target no longer restarts the server unnecessarily.
|
||||||
|
|
||||||
## [0.1.2] - 2026-04-30
|
## [0.1.2] - 2026-04-30
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ Try a higher-level prompt in your AI client:
|
|||||||
- This extension is **Editor-only**. It is meant to automate Cocos Creator, not to add runtime dependencies to your final game build.
|
- This extension is **Editor-only**. It is meant to automate Cocos Creator, not to add runtime dependencies to your final game build.
|
||||||
- The MCP server listens on `http://127.0.0.1:8765/` by default.
|
- The MCP server listens on `http://127.0.0.1:8765/` by default.
|
||||||
- If the configured port is busy, the server automatically falls back to the next available port and the panel/client config use the actual running port.
|
- If the configured port is busy, the server automatically falls back to the next available port and the panel/client config use the actual running port.
|
||||||
- The default `core` profile exposes 19 high-signal tools. Switch to `full` in the panel if you want all 67 tools exposed.
|
- The default `core` profile exposes 22 high-signal tools. Switch to `full` in the panel if you want all 70 tools exposed.
|
||||||
- All exposed MCP tools execute directly. There is no extra approval toggle inside the Cocos extension.
|
- All exposed MCP tools execute directly. There is no extra approval toggle inside the Cocos extension.
|
||||||
- File tools and `cocos://asset/path/...` resources are restricted to the active Cocos project root.
|
- File tools and `cocos://asset/path/...` resources are restricted to the active Cocos project root.
|
||||||
- The recommended workflow is `execute_javascript` first, then focused helper tools for screenshots, diagnostics, assets, and inspection.
|
- The recommended workflow is `execute_javascript` first, then focused helper tools for screenshots, diagnostics, assets, and inspection.
|
||||||
@@ -214,7 +214,7 @@ Try a higher-level prompt in your AI client:
|
|||||||
|
|
||||||
## Highlights
|
## Highlights
|
||||||
|
|
||||||
- **67 Built-in Tools** — Scene hierarchy, assets, UI creation, components, files, script diagnostics, screenshots, runtime control, and input simulation
|
- **70 Built-in Tools** — Scene hierarchy, editor state, selection workflows, assets, UI creation, components, files, script diagnostics, screenshots, runtime control, and input simulation
|
||||||
- **Primary Unified Tool** — `execute_javascript` supports both `scene` and `editor` contexts
|
- **Primary Unified Tool** — `execute_javascript` supports both `scene` and `editor` contexts
|
||||||
- **Resources & Prompts** — Live project resources plus reusable workflows like script fixing, scene validation, and playable prototype creation
|
- **Resources & Prompts** — Live project resources plus reusable workflows like script fixing, scene validation, and playable prototype creation
|
||||||
- **Cocos Panel UI** — A minimal `Funplay > MCP Server` panel for service management and MCP client setup
|
- **Cocos Panel UI** — A minimal `Funplay > MCP Server` panel for service management and MCP client setup
|
||||||
@@ -231,20 +231,20 @@ Funplay MCP for Cocos follows the same design principles as Funplay MCP for Unit
|
|||||||
| Embedded server | Built-in HTTP MCP server | Built-in HTTP MCP server |
|
| Embedded server | Built-in HTTP MCP server | Built-in HTTP MCP server |
|
||||||
| Primary execution tool | `execute_javascript` | `execute_code` |
|
| Primary execution tool | `execute_javascript` | `execute_code` |
|
||||||
| Primary language | JavaScript in scene/editor contexts | C# in Unity editor/runtime contexts |
|
| Primary language | JavaScript in scene/editor contexts | C# in Unity editor/runtime contexts |
|
||||||
| Default profile | `core` with 19 tools | `core` focused tool profile |
|
| Default profile | `core` with 22 tools | `core` focused tool profile |
|
||||||
| Full profile | 67 tools | 79 tools |
|
| Full profile | 70 tools | 79 tools |
|
||||||
| Client setup | One-click config panel | One-click config window |
|
| Client setup | One-click config panel | One-click config window |
|
||||||
|
|
||||||
## MCP Capabilities
|
## MCP Capabilities
|
||||||
|
|
||||||
The current package exposes four capability layers:
|
The current package exposes four capability layers:
|
||||||
|
|
||||||
- **Tools** — 19 tools in `core`, 67 tools in `full`
|
- **Tools** — 22 tools in `core`, 70 tools in `full`
|
||||||
- **Primary execution** — `execute_javascript` for scene/runtime and editor/browser automation
|
- **Primary execution** — `execute_javascript` for scene/runtime and editor/browser automation
|
||||||
- **Prompts** — `fix_script_errors`, `create_playable_prototype`, `scene_validation`, and `auto_wire_scene`
|
- **Prompts** — `fix_script_errors`, `create_playable_prototype`, `scene_validation`, and `auto_wire_scene`
|
||||||
- **Resources** — project context, scene summaries, current selection, script diagnostics, asset selection, and MCP interaction history
|
- **Resources** — project context, scene summaries, current selection, script diagnostics, asset selection, and MCP interaction history
|
||||||
|
|
||||||
The default `core` set is intentionally small: `execute_javascript`, `execute_scene_script`, `execute_editor_script`, `get_project_info`, `get_scene_info`, `get_hierarchy`, `list_scenes`, `open_scene`, `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `run_script_diagnostics`, `get_script_diagnostic_context`, `get_runtime_state`, `capture_editor_screenshot`, `capture_scene_screenshot`, `capture_preview_screenshot`, and `list_editor_windows`.
|
The default `core` set is intentionally small: `execute_javascript`, `execute_scene_script`, `execute_editor_script`, `get_editor_state`, `get_selection`, `set_selection`, `get_project_info`, `get_scene_info`, `get_hierarchy`, `list_scenes`, `open_scene`, `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `run_script_diagnostics`, `get_script_diagnostic_context`, `get_runtime_state`, `capture_editor_screenshot`, `capture_scene_screenshot`, `capture_preview_screenshot`, and `list_editor_windows`.
|
||||||
|
|
||||||
## Built-in Resources
|
## Built-in Resources
|
||||||
|
|
||||||
@@ -261,11 +261,12 @@ The default `core` set is intentionally small: `execute_javascript`, `execute_sc
|
|||||||
|
|
||||||
## Built-in Tools
|
## Built-in Tools
|
||||||
|
|
||||||
Funplay MCP for Cocos currently ships with **67 tool functions** in the `full` profile:
|
Funplay MCP for Cocos currently ships with **70 tool functions** in the `full` profile:
|
||||||
|
|
||||||
| Category | Tools |
|
| Category | Tools |
|
||||||
|----------|-------|
|
|----------|-------|
|
||||||
| **Script Execution** | `execute_javascript`, `execute_scene_script`, `execute_editor_script` |
|
| **Script Execution** | `execute_javascript`, `execute_scene_script`, `execute_editor_script` |
|
||||||
|
| **Editor State** | `get_editor_state`, `get_selection`, `set_selection`, `get_editor_selection` |
|
||||||
| **Project & Scene** | `get_project_info`, `get_scene_info`, `get_hierarchy`, `find_nodes`, `inspect_node`, `list_scenes`, `open_scene`, `run_scene_asset` |
|
| **Project & Scene** | `get_project_info`, `get_scene_info`, `get_hierarchy`, `find_nodes`, `inspect_node`, `list_scenes`, `open_scene`, `run_scene_asset` |
|
||||||
| **Node Editing** | `create_node`, `delete_node`, `set_node_transform` |
|
| **Node Editing** | `create_node`, `delete_node`, `set_node_transform` |
|
||||||
| **Assets & Prefabs** | `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `delete_asset`, `list_prefabs`, `instantiate_prefab`, `get_editor_selection` |
|
| **Assets & Prefabs** | `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `delete_asset`, `list_prefabs`, `instantiate_prefab`, `get_editor_selection` |
|
||||||
|
|||||||
+8
-7
@@ -197,7 +197,7 @@ url = "http://127.0.0.1:8765/"
|
|||||||
- 这是一个 **仅限 Editor** 的扩展,用于自动化 Cocos Creator,不会给最终游戏包添加运行时依赖。
|
- 这是一个 **仅限 Editor** 的扩展,用于自动化 Cocos Creator,不会给最终游戏包添加运行时依赖。
|
||||||
- MCP Server 默认监听 `http://127.0.0.1:8765/`。
|
- MCP Server 默认监听 `http://127.0.0.1:8765/`。
|
||||||
- 如果配置端口被占用,服务会自动回退到下一个可用端口,面板与一键客户端配置会使用实际运行端口。
|
- 如果配置端口被占用,服务会自动回退到下一个可用端口,面板与一键客户端配置会使用实际运行端口。
|
||||||
- 默认 `core` profile 暴露 19 个高频工具;如果需要完整工具集,可在面板切到 `full`,暴露全部 67 个工具。
|
- 默认 `core` profile 暴露 22 个高频工具;如果需要完整工具集,可在面板切到 `full`,暴露全部 70 个工具。
|
||||||
- 所有已暴露的 MCP 工具都会直接执行,Cocos 扩展里没有额外 approval 开关。
|
- 所有已暴露的 MCP 工具都会直接执行,Cocos 扩展里没有额外 approval 开关。
|
||||||
- 文件工具和 `cocos://asset/path/...` 资源默认只能访问当前 Cocos 项目根目录内的路径。
|
- 文件工具和 `cocos://asset/path/...` 资源默认只能访问当前 Cocos 项目根目录内的路径。
|
||||||
- 推荐工作流是优先使用 `execute_javascript`,再配合截图、诊断、资产、检查类工具。
|
- 推荐工作流是优先使用 `execute_javascript`,再配合截图、诊断、资产、检查类工具。
|
||||||
@@ -214,7 +214,7 @@ url = "http://127.0.0.1:8765/"
|
|||||||
|
|
||||||
## 核心特性
|
## 核心特性
|
||||||
|
|
||||||
- **67 个内置工具** — 覆盖场景层级、资产、UI 创建、组件、文件、脚本诊断、截图、运行态控制和输入模拟
|
- **70 个内置工具** — 覆盖场景层级、编辑器状态、选择工作流、资产、UI 创建、组件、文件、脚本诊断、截图、运行态控制和输入模拟
|
||||||
- **统一主工具** — `execute_javascript` 同时支持 `scene` 和 `editor` 两种上下文
|
- **统一主工具** — `execute_javascript` 同时支持 `scene` 和 `editor` 两种上下文
|
||||||
- **Resources 与 Prompts** — 实时项目资源,以及脚本修复、场景验证、可玩原型等可复用工作流
|
- **Resources 与 Prompts** — 实时项目资源,以及脚本修复、场景验证、可玩原型等可复用工作流
|
||||||
- **Cocos 图形面板** — `Funplay > MCP Server` 提供极简服务管理与 MCP 客户端配置
|
- **Cocos 图形面板** — `Funplay > MCP Server` 提供极简服务管理与 MCP 客户端配置
|
||||||
@@ -231,20 +231,20 @@ Funplay MCP for Cocos 延续 Funplay MCP for Unity 的设计原则,并针对 C
|
|||||||
| 内置服务 | 内嵌 HTTP MCP Server | 内嵌 HTTP MCP Server |
|
| 内置服务 | 内嵌 HTTP MCP Server | 内嵌 HTTP MCP Server |
|
||||||
| 主执行工具 | `execute_javascript` | `execute_code` |
|
| 主执行工具 | `execute_javascript` | `execute_code` |
|
||||||
| 主语言 | 场景/编辑器上下文中的 JavaScript | Unity 编辑器/运行态中的 C# |
|
| 主语言 | 场景/编辑器上下文中的 JavaScript | Unity 编辑器/运行态中的 C# |
|
||||||
| 默认工具集 | `core`,19 个工具 | 聚焦版 `core` 工具集 |
|
| 默认工具集 | `core`,22 个工具 | 聚焦版 `core` 工具集 |
|
||||||
| 完整工具集 | 67 个工具 | 79 个工具 |
|
| 完整工具集 | 70 个工具 | 79 个工具 |
|
||||||
| 客户端配置 | 一键配置面板 | 一键配置窗口 |
|
| 客户端配置 | 一键配置面板 | 一键配置窗口 |
|
||||||
|
|
||||||
## MCP 能力结构
|
## MCP 能力结构
|
||||||
|
|
||||||
当前包提供四层能力:
|
当前包提供四层能力:
|
||||||
|
|
||||||
- **Tools** — `core` 下 19 个工具,`full` 下 67 个工具
|
- **Tools** — `core` 下 22 个工具,`full` 下 70 个工具
|
||||||
- **Primary execution** — `execute_javascript` 用于场景/运行态和编辑器/browser 自动化
|
- **Primary execution** — `execute_javascript` 用于场景/运行态和编辑器/browser 自动化
|
||||||
- **Prompts** — `fix_script_errors`、`create_playable_prototype`、`scene_validation`、`auto_wire_scene`
|
- **Prompts** — `fix_script_errors`、`create_playable_prototype`、`scene_validation`、`auto_wire_scene`
|
||||||
- **Resources** — 项目上下文、场景摘要、当前选择、脚本诊断、资产选择和 MCP 交互历史
|
- **Resources** — 项目上下文、场景摘要、当前选择、脚本诊断、资产选择和 MCP 交互历史
|
||||||
|
|
||||||
当前默认 `core` 工具集刻意保持精简,只包含:`execute_javascript`、`execute_scene_script`、`execute_editor_script`、`get_project_info`、`get_scene_info`、`get_hierarchy`、`list_scenes`、`open_scene`、`list_assets`、`inspect_asset`、`open_asset`、`select_asset`、`run_script_diagnostics`、`get_script_diagnostic_context`、`get_runtime_state`、`capture_editor_screenshot`、`capture_scene_screenshot`、`capture_preview_screenshot`、`list_editor_windows`。
|
当前默认 `core` 工具集刻意保持精简,只包含:`execute_javascript`、`execute_scene_script`、`execute_editor_script`、`get_editor_state`、`get_selection`、`set_selection`、`get_project_info`、`get_scene_info`、`get_hierarchy`、`list_scenes`、`open_scene`、`list_assets`、`inspect_asset`、`open_asset`、`select_asset`、`run_script_diagnostics`、`get_script_diagnostic_context`、`get_runtime_state`、`capture_editor_screenshot`、`capture_scene_screenshot`、`capture_preview_screenshot`、`list_editor_windows`。
|
||||||
|
|
||||||
## 内置 Resources
|
## 内置 Resources
|
||||||
|
|
||||||
@@ -261,11 +261,12 @@ Funplay MCP for Cocos 延续 Funplay MCP for Unity 的设计原则,并针对 C
|
|||||||
|
|
||||||
## 内置工具
|
## 内置工具
|
||||||
|
|
||||||
Funplay MCP for Cocos 当前在 `full` profile 下提供 **67 个工具函数**:
|
Funplay MCP for Cocos 当前在 `full` profile 下提供 **70 个工具函数**:
|
||||||
|
|
||||||
| 分类 | 工具 |
|
| 分类 | 工具 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| **脚本执行** | `execute_javascript`, `execute_scene_script`, `execute_editor_script` |
|
| **脚本执行** | `execute_javascript`, `execute_scene_script`, `execute_editor_script` |
|
||||||
|
| **编辑器状态** | `get_editor_state`, `get_selection`, `set_selection`, `get_editor_selection` |
|
||||||
| **项目与场景** | `get_project_info`, `get_scene_info`, `get_hierarchy`, `find_nodes`, `inspect_node`, `list_scenes`, `open_scene`, `run_scene_asset` |
|
| **项目与场景** | `get_project_info`, `get_scene_info`, `get_hierarchy`, `find_nodes`, `inspect_node`, `list_scenes`, `open_scene`, `run_scene_asset` |
|
||||||
| **节点编辑** | `create_node`, `delete_node`, `set_node_transform` |
|
| **节点编辑** | `create_node`, `delete_node`, `set_node_transform` |
|
||||||
| **资产与 Prefab** | `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `delete_asset`, `list_prefabs`, `instantiate_prefab`, `get_editor_selection` |
|
| **资产与 Prefab** | `list_assets`, `inspect_asset`, `open_asset`, `select_asset`, `delete_asset`, `list_prefabs`, `instantiate_prefab`, `get_editor_selection` |
|
||||||
|
|||||||
+11
-2
@@ -87,6 +87,7 @@ class ExtensionService {
|
|||||||
|
|
||||||
this.toolRegistry = createToolRegistry({
|
this.toolRegistry = createToolRegistry({
|
||||||
getRuntimeContext: runtimeContext,
|
getRuntimeContext: runtimeContext,
|
||||||
|
getStatus: () => this.getStatus(),
|
||||||
interactionLog: this.interactionLog,
|
interactionLog: this.interactionLog,
|
||||||
sceneBridge,
|
sceneBridge,
|
||||||
editorExecutor: async (payload) => await this.executeEditorScript(payload, runtimeContext),
|
editorExecutor: async (payload) => await this.executeEditorScript(payload, runtimeContext),
|
||||||
@@ -315,16 +316,24 @@ class ExtensionService {
|
|||||||
maxInteractionLogEntries: Number.isInteger(nextMaxEntries)
|
maxInteractionLogEntries: Number.isInteger(nextMaxEntries)
|
||||||
? Math.max(10, Math.min(500, nextMaxEntries))
|
? Math.max(10, Math.min(500, nextMaxEntries))
|
||||||
: this.config.maxInteractionLogEntries,
|
: this.config.maxInteractionLogEntries,
|
||||||
|
lastClientTargetId: partialConfig && partialConfig.lastClientTargetId
|
||||||
|
? String(partialConfig.lastClientTargetId)
|
||||||
|
: this.config.lastClientTargetId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const configPath = this.config.configPath;
|
const configPath = this.config.configPath;
|
||||||
fs.writeFileSync(configPath, JSON.stringify(nextConfig, null, 2) + '\n', 'utf8');
|
fs.writeFileSync(configPath, JSON.stringify(nextConfig, null, 2) + '\n', 'utf8');
|
||||||
const wasRunning = Boolean(this.server && this.server.isRunning());
|
const wasRunning = Boolean(this.server && this.server.isRunning());
|
||||||
if (wasRunning) {
|
const requiresRestart = wasRunning && (
|
||||||
|
nextConfig.host !== this.config.host ||
|
||||||
|
nextConfig.port !== this.config.port ||
|
||||||
|
nextConfig.toolProfile !== this.config.toolProfile
|
||||||
|
);
|
||||||
|
if (requiresRestart) {
|
||||||
await this.stopServer();
|
await this.stopServer();
|
||||||
}
|
}
|
||||||
this.reloadRuntime();
|
this.reloadRuntime();
|
||||||
if (wasRunning) {
|
if (requiresRestart) {
|
||||||
await this.startServer();
|
await this.startServer();
|
||||||
}
|
}
|
||||||
return this.getPanelState();
|
return this.getPanelState();
|
||||||
|
|||||||
@@ -157,6 +157,32 @@ function selectAsset(uuid) {
|
|||||||
return { selected: true, uuid };
|
return { selected: true, uuid };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectNode(uuid) {
|
||||||
|
if (!global.Editor || !Editor.Selection || typeof Editor.Selection.select !== 'function') {
|
||||||
|
throw new Error('Editor.Selection.select is unavailable in this Cocos environment.');
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.Selection.clear('node');
|
||||||
|
Editor.Selection.select('node', uuid);
|
||||||
|
return { selected: true, uuid };
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSelection(type) {
|
||||||
|
if (!global.Editor || !Editor.Selection || typeof Editor.Selection.clear !== 'function') {
|
||||||
|
throw new Error('Editor.Selection.clear is unavailable in this Cocos environment.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = String(type || 'all').trim().toLowerCase();
|
||||||
|
if (normalized === 'asset' || normalized === 'node') {
|
||||||
|
Editor.Selection.clear(normalized);
|
||||||
|
return { cleared: true, type: normalized };
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.Selection.clear('asset');
|
||||||
|
Editor.Selection.clear('node');
|
||||||
|
return { cleared: true, type: 'all' };
|
||||||
|
}
|
||||||
|
|
||||||
function getCurrentSelection() {
|
function getCurrentSelection() {
|
||||||
if (!global.Editor || !Editor.Selection || typeof Editor.Selection.getSelected !== 'function') {
|
if (!global.Editor || !Editor.Selection || typeof Editor.Selection.getSelected !== 'function') {
|
||||||
throw new Error('Editor.Selection API is unavailable in this Cocos environment.');
|
throw new Error('Editor.Selection API is unavailable in this Cocos environment.');
|
||||||
@@ -170,6 +196,7 @@ function getCurrentSelection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
clearSelection,
|
||||||
deleteAsset,
|
deleteAsset,
|
||||||
getCurrentSelection,
|
getCurrentSelection,
|
||||||
listAssets,
|
listAssets,
|
||||||
@@ -179,4 +206,5 @@ module.exports = {
|
|||||||
queryAssetMeta,
|
queryAssetMeta,
|
||||||
queryAssetUrl,
|
queryAssetUrl,
|
||||||
selectAsset,
|
selectAsset,
|
||||||
|
selectNode,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const DEFAULTS = {
|
|||||||
toolProfile: 'core',
|
toolProfile: 'core',
|
||||||
autostart: true,
|
autostart: true,
|
||||||
maxInteractionLogEntries: 50,
|
maxInteractionLogEntries: 50,
|
||||||
|
lastClientTargetId: 'claude_code',
|
||||||
};
|
};
|
||||||
|
|
||||||
function getProjectPath() {
|
function getProjectPath() {
|
||||||
@@ -60,6 +61,11 @@ function normalizeProfile(value) {
|
|||||||
return String(value || DEFAULTS.toolProfile).toLowerCase() === 'full' ? 'full' : 'core';
|
return String(value || DEFAULTS.toolProfile).toLowerCase() === 'full' ? 'full' : 'core';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeClientTargetId(value) {
|
||||||
|
const normalized = String(value || '').trim();
|
||||||
|
return normalized || DEFAULTS.lastClientTargetId;
|
||||||
|
}
|
||||||
|
|
||||||
function loadConfig() {
|
function loadConfig() {
|
||||||
const projectPath = getProjectPath();
|
const projectPath = getProjectPath();
|
||||||
const configPath = path.join(projectPath, 'funplay-cocos-mcp.config.json');
|
const configPath = path.join(projectPath, 'funplay-cocos-mcp.config.json');
|
||||||
@@ -75,6 +81,7 @@ function loadConfig() {
|
|||||||
maxInteractionLogEntries: Number.isInteger(fileConfig.maxInteractionLogEntries)
|
maxInteractionLogEntries: Number.isInteger(fileConfig.maxInteractionLogEntries)
|
||||||
? Math.max(10, Math.min(500, fileConfig.maxInteractionLogEntries))
|
? Math.max(10, Math.min(500, fileConfig.maxInteractionLogEntries))
|
||||||
: DEFAULTS.maxInteractionLogEntries,
|
: DEFAULTS.maxInteractionLogEntries,
|
||||||
|
lastClientTargetId: normalizeClientTargetId(fileConfig.lastClientTargetId),
|
||||||
configPath,
|
configPath,
|
||||||
configError: fileConfig.__error || '',
|
configError: fileConfig.__error || '',
|
||||||
};
|
};
|
||||||
|
|||||||
+85
-2
@@ -3,6 +3,7 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const {
|
const {
|
||||||
|
clearSelection,
|
||||||
deleteAsset,
|
deleteAsset,
|
||||||
getCurrentSelection,
|
getCurrentSelection,
|
||||||
listAssets,
|
listAssets,
|
||||||
@@ -11,6 +12,7 @@ const {
|
|||||||
queryAssetInfo,
|
queryAssetInfo,
|
||||||
queryAssetMeta,
|
queryAssetMeta,
|
||||||
selectAsset,
|
selectAsset,
|
||||||
|
selectNode,
|
||||||
} = require('./assets');
|
} = require('./assets');
|
||||||
const { runScriptDiagnostics } = require('./diagnostics');
|
const { runScriptDiagnostics } = require('./diagnostics');
|
||||||
const { listWindows, sendKeyCombo, sendKeyPress, sendMouseClick, sendMouseDrag } = require('./input');
|
const { listWindows, sendKeyCombo, sendKeyPress, sendMouseClick, sendMouseDrag } = require('./input');
|
||||||
@@ -121,7 +123,7 @@ async function refreshAssets(projectPath, targetPath) {
|
|||||||
return 'File written outside assets directory; no asset-db refresh was needed.';
|
return 'File written outside assets directory; no asset-db refresh was needed.';
|
||||||
}
|
}
|
||||||
|
|
||||||
function createToolRegistry({ getRuntimeContext, interactionLog, sceneBridge, editorExecutor }) {
|
function createToolRegistry({ getRuntimeContext, getStatus, interactionLog, sceneBridge, editorExecutor }) {
|
||||||
const tools = [
|
const tools = [
|
||||||
{
|
{
|
||||||
name: 'execute_javascript',
|
name: 'execute_javascript',
|
||||||
@@ -180,6 +182,87 @@ function createToolRegistry({ getRuntimeContext, interactionLog, sceneBridge, ed
|
|||||||
return await editorExecutor({ code: args.code, args: args.args || {} });
|
return await editorExecutor({ code: args.code, args: args.args || {} });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'get_editor_state',
|
||||||
|
profile: 'core',
|
||||||
|
description: '[specialist] Return a structured editor-state snapshot including project info, runtime server status, current selection, and visible Electron windows. Prefer this when you want one compact editor summary.',
|
||||||
|
inputSchema: createSchema({}, []),
|
||||||
|
handler: async () => {
|
||||||
|
const runtimeContext = getRuntimeContext();
|
||||||
|
const status = typeof getStatus === 'function' ? getStatus() : null;
|
||||||
|
let scene = null;
|
||||||
|
try {
|
||||||
|
const sceneInfo = await sceneBridge.call('getSceneInfo', { maxDepth: 1, includeComponents: false });
|
||||||
|
scene = sceneInfo
|
||||||
|
? {
|
||||||
|
sceneName: sceneInfo.sceneName,
|
||||||
|
uuid: sceneInfo.uuid,
|
||||||
|
childCount: sceneInfo.childCount,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
} catch (error) {
|
||||||
|
scene = { error: error.message };
|
||||||
|
}
|
||||||
|
|
||||||
|
let windows = [];
|
||||||
|
try {
|
||||||
|
windows = listWindows();
|
||||||
|
} catch (error) {
|
||||||
|
windows = [{ error: error.message }];
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
extensionName: runtimeContext.extensionName,
|
||||||
|
version: runtimeContext.version,
|
||||||
|
projectName: runtimeContext.projectName,
|
||||||
|
projectPath: runtimeContext.projectPath,
|
||||||
|
cocosVersion: runtimeContext.cocosVersion,
|
||||||
|
toolProfile: runtimeContext.config ? runtimeContext.config.toolProfile : 'core',
|
||||||
|
status,
|
||||||
|
selection: getCurrentSelection(),
|
||||||
|
scene,
|
||||||
|
windows,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_selection',
|
||||||
|
profile: 'core',
|
||||||
|
description: '[specialist] Return the current editor selection in a compact structured form. Prefer this when selection state matters for the next action.',
|
||||||
|
inputSchema: createSchema({}, []),
|
||||||
|
handler: async () => getCurrentSelection(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'set_selection',
|
||||||
|
profile: 'core',
|
||||||
|
description: '[specialist] Set or clear the current editor selection for an asset or node. Use this when downstream editor workflows depend on selection state.',
|
||||||
|
inputSchema: createSchema(
|
||||||
|
{
|
||||||
|
type: { type: 'string', description: 'Selection target type: asset, node, or clear.' },
|
||||||
|
target: { type: 'string', description: 'Asset uuid/path/db url, or node uuid when type=node.' },
|
||||||
|
clearMode: { type: 'string', description: 'When type=clear, choose asset, node, or all.' },
|
||||||
|
},
|
||||||
|
['type']
|
||||||
|
),
|
||||||
|
handler: async (args) => {
|
||||||
|
const type = String(args.type || '').trim().toLowerCase();
|
||||||
|
if (type === 'clear') {
|
||||||
|
return clearSelection(args.clearMode || 'all');
|
||||||
|
}
|
||||||
|
if (type === 'asset') {
|
||||||
|
const info = await queryAssetInfo(args.target);
|
||||||
|
return selectAsset(info.uuid || args.target);
|
||||||
|
}
|
||||||
|
if (type === 'node') {
|
||||||
|
const target = String(args.target || '').trim();
|
||||||
|
if (!target) {
|
||||||
|
throw new Error('target is required when type=node.');
|
||||||
|
}
|
||||||
|
return selectNode(target);
|
||||||
|
}
|
||||||
|
throw new Error(`Unknown selection type '${args.type}'. Expected asset, node, or clear.`);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'get_scene_info',
|
name: 'get_scene_info',
|
||||||
profile: 'core',
|
profile: 'core',
|
||||||
@@ -441,7 +524,7 @@ function createToolRegistry({ getRuntimeContext, interactionLog, sceneBridge, ed
|
|||||||
{
|
{
|
||||||
name: 'get_editor_selection',
|
name: 'get_editor_selection',
|
||||||
profile: 'full',
|
profile: 'full',
|
||||||
description: '[core] Return the current node and asset selection in the Cocos editor.',
|
description: '[compat] Return the current node and asset selection in the Cocos editor. Prefer get_selection as the primary structured selection read tool.',
|
||||||
inputSchema: createSchema({}, []),
|
inputSchema: createSchema({}, []),
|
||||||
handler: async () => getCurrentSelection(),
|
handler: async () => getCurrentSelection(),
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "funplay-cocos-mcp",
|
"name": "funplay-cocos-mcp",
|
||||||
"package_version": 2,
|
"package_version": 2,
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"description": "Embedded MCP server for Cocos Creator with scene script execution, project resources, prompts, and file/scene tools.",
|
"description": "Embedded MCP server for Cocos Creator with scene script execution, project resources, prompts, and file/scene tools.",
|
||||||
"author": "Funplay",
|
"author": "Funplay",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
+7
-2
@@ -248,7 +248,8 @@ module.exports = Editor.Panel.define({
|
|||||||
},
|
},
|
||||||
renderClientTargets() {
|
renderClientTargets() {
|
||||||
const targets = (this.state && this.state.clientTargets) || [];
|
const targets = (this.state && this.state.clientTargets) || [];
|
||||||
const selected = this.$.clientTargetSelect.value || (targets[0] && targets[0].id);
|
const preferred = this.state && this.state.config ? this.state.config.lastClientTargetId : '';
|
||||||
|
const selected = this.$.clientTargetSelect.value || preferred || (targets[0] && targets[0].id);
|
||||||
this.$.clientTargetSelect.innerHTML = targets
|
this.$.clientTargetSelect.innerHTML = targets
|
||||||
.map((target) => `<option value="${target.id}">${target.name}</option>`)
|
.map((target) => `<option value="${target.id}">${target.name}</option>`)
|
||||||
.join('');
|
.join('');
|
||||||
@@ -300,6 +301,7 @@ module.exports = Editor.Panel.define({
|
|||||||
toolProfile: this.$.profileSelect.value || 'core',
|
toolProfile: this.$.profileSelect.value || 'core',
|
||||||
autostart: Boolean(this.$.enabledInput.value),
|
autostart: Boolean(this.$.enabledInput.value),
|
||||||
maxInteractionLogEntries: this.state && this.state.config ? this.state.config.maxInteractionLogEntries : 50,
|
maxInteractionLogEntries: this.state && this.state.config ? this.state.config.maxInteractionLogEntries : 50,
|
||||||
|
lastClientTargetId: this.$.clientTargetSelect.value || 'claude_code',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async handleEnableToggle() {
|
async handleEnableToggle() {
|
||||||
@@ -333,7 +335,10 @@ module.exports = Editor.Panel.define({
|
|||||||
this.$.portInput.addEventListener('change', () => this.persistConfig({ showOutput: true }));
|
this.$.portInput.addEventListener('change', () => this.persistConfig({ showOutput: true }));
|
||||||
this.$.profileSelect.addEventListener('change', () => this.persistConfig({ showOutput: true }));
|
this.$.profileSelect.addEventListener('change', () => this.persistConfig({ showOutput: true }));
|
||||||
this.$.clientTargetSelect.addEventListener('confirm', () => this.renderClientTargetStatus());
|
this.$.clientTargetSelect.addEventListener('confirm', () => this.renderClientTargetStatus());
|
||||||
this.$.clientTargetSelect.addEventListener('change', () => this.renderClientTargetStatus());
|
this.$.clientTargetSelect.addEventListener('change', () => {
|
||||||
|
this.renderClientTargetStatus();
|
||||||
|
this.persistConfig();
|
||||||
|
});
|
||||||
this.$.configureClientBtn.addEventListener('click', () => {
|
this.$.configureClientBtn.addEventListener('click', () => {
|
||||||
const targetId = this.$.clientTargetSelect.value;
|
const targetId = this.$.clientTargetSelect.value;
|
||||||
if (!targetId) {
|
if (!targetId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user