#
tokens: 49118/50000 27/37 files (page 1/3)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 3. Use http://codebase.md/daxianlee/cocos-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── @types
│   └── schema
│       └── package
│           ├── base
│           │   └── panels.json
│           ├── contributions
│           │   └── index.json
│           └── index.json
├── base.tsconfig.json
├── dist
│   ├── examples
│   │   └── prefab-instantiation-example.js
│   ├── main.js
│   ├── mcp-server.js
│   ├── panels
│   │   ├── default
│   │   │   └── index.js
│   │   └── tool-manager
│   │       └── index.js
│   ├── scene.js
│   ├── settings.js
│   ├── test
│   │   ├── manual-test.js
│   │   ├── mcp-tool-tester.js
│   │   ├── prefab-tools-test.js
│   │   └── tool-tester.js
│   ├── tools
│   │   ├── asset-advanced-tools.js
│   │   ├── broadcast-tools.js
│   │   ├── component-tools.js
│   │   ├── debug-tools.js
│   │   ├── node-tools.js
│   │   ├── prefab-tools.js
│   │   ├── preferences-tools.js
│   │   ├── project-tools.js
│   │   ├── reference-image-tools.js
│   │   ├── scene-advanced-tools.js
│   │   ├── scene-tools.js
│   │   ├── scene-view-tools.js
│   │   ├── server-tools.js
│   │   ├── tool-manager.js
│   │   └── validation-tools.js
│   └── types
│       └── index.js
├── FEATURE_GUIDE_CN.md
├── FEATURE_GUIDE_EN.md
├── i18n
│   ├── en.js
│   └── zh.js
├── image
│   ├── iamge2.png
│   └── image-20250717174157957.png
├── package-lock.json
├── package.json
├── README.EN.md
├── README.md
├── scripts
│   └── preinstall.js
├── source
│   ├── main.ts
│   ├── mcp-server.ts
│   ├── panels
│   │   ├── default
│   │   │   └── index.ts
│   │   └── tool-manager
│   │       └── index.ts
│   ├── scene.ts
│   ├── settings.ts
│   ├── test
│   │   ├── manual-test.ts
│   │   ├── mcp-tool-tester.ts
│   │   ├── prefab-tools-test.ts
│   │   └── tool-tester.ts
│   ├── tools
│   │   ├── asset-advanced-tools.ts
│   │   ├── broadcast-tools.ts
│   │   ├── component-tools.ts
│   │   ├── debug-tools.ts
│   │   ├── node-tools.ts
│   │   ├── prefab-tools.ts
│   │   ├── preferences-tools.ts
│   │   ├── project-tools.ts
│   │   ├── reference-image-tools.ts
│   │   ├── scene-advanced-tools.ts
│   │   ├── scene-tools.ts
│   │   ├── scene-view-tools.ts
│   │   ├── server-tools.ts
│   │   ├── tool-manager.ts
│   │   └── validation-tools.ts
│   └── types
│       └── index.ts
├── static
│   ├── icon.png
│   ├── style
│   │   └── default
│   │       └── index.css
│   └── template
│       ├── default
│       │   ├── index.html
│       │   └── tool-manager.html
│       └── vue
│           └── mcp-server-app.html
├── TestScript.js
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
node_modules/
```

--------------------------------------------------------------------------------
/README.EN.md:
--------------------------------------------------------------------------------

```markdown
# Cocos Creator MCP Server Plugin

**[📖 English](README.EN.md)**  **[📖 中文](README.md)**

A comprehensive MCP (Model Context Protocol) server plugin for Cocos Creator 3.8+, enabling AI assistants to interact with the Cocos Creator editor through standardized protocols. One-click installation and use, eliminating all cumbersome environments and configurations. Claude clients Claude CLI and Cursor have been tested, and other editors are also perfectly supported in theory.

**🚀 Now provides 50 powerful integrated tools, achieving 99% editor control!**

## Video Demonstrations and Tutorials

[<img width="503" height="351" alt="image" src="https://github.com/user-attachments/assets/f186ce14-9ffc-4a29-8761-48bdd7c1ea16" />](https://www.bilibili.com/video/BV1mB8dzfEw8?spm_id_from=333.788.recommend_more_video.0&vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)



## Quick Links

- **[📖 Complete Feature Guide (English)](FEATURE_GUIDE_EN.md)** - Detailed documentation for all 50 tools (to be completed)
- **[📖 完整功能指南 (中文)](FEATURE_GUIDE_CN.md)** - All 50 tools detailed documentation (to be completed)


## Changelog

## 🚀 Major Update v1.5.0 (July 29, 2024) (Already updated in Cocos Store, GitHub version will be synchronized in next version)

Cocos store: https://store.cocos.com/app/detail/7941
If you don't want to purchase, join the communication group and I can send you the latest version directly!

- **Tool Streamlining and Refactoring**: Condensed the original 150+ tools into 50 high-reuse, high-coverage core tools, removing all invalid redundant code, greatly improving usability and maintainability.
- **Unified Operation Codes**: All tools adopt "operation code + parameters" mode, greatly simplifying AI calling process, improving AI calling success rate, reducing AI calling times, and lowering 50% token consumption.
- **Comprehensive Prefab Function Upgrade**: Completely fixed and perfected all core prefab functions including creation, instantiation, synchronization, references, etc., supporting complex reference relationships, 100% aligned with official format.
- **Event Binding and Legacy Function Completion**: Added and implemented event binding, node/component/asset legacy functions, all methods completely aligned with official implementation.
- **Interface Optimization**: All interface parameters are clearer, documentation is more complete, AI can understand and call more easily.
- **Plugin Panel Optimization**: Panel UI is more concise, operations are more intuitive.
- **Performance and Compatibility Improvements**: Overall architecture is more efficient, compatible with Cocos Creator 3.8.6 and all versions above.


## Tool System and Operation Codes

- All tools are named with "category_operation", parameters use unified Schema, support multiple operation code (action) switching, greatly improving flexibility and extensibility.
- 50 core tools cover scene, node, component, prefab, asset, project, debugging, preferences, server, message broadcasting and all other editor operations.
- Tool calling example:

```json
{
  "tool": "node_lifecycle",
  "arguments": {
    "action": "create",
    "name": "MyNode",
    "parentUuid": "parent-uuid",
    "nodeType": "2DNode"
  }
}
```

---

## Main Function Categories (Partial Examples)

- **scene_management**: Scene management (get/open/save/create/close scenes)
- **node_query / node_lifecycle / node_transform**: Node query, creation, deletion, property changes
- **component_manage / component_script / component_query**: Component add/remove, script mounting, component information
- **prefab_browse / prefab_lifecycle / prefab_instance**: Prefab browsing, creation, instantiation, synchronization
- **asset_manage / asset_analyze**: Asset import, deletion, dependency analysis
- **project_manage / project_build_system**: Project running, building, configuration information
- **debug_console / debug_logs**: Console and log management
- **preferences_manage**: Preferences settings
- **server_info**: Server information
- **broadcast_message**: Message broadcasting


### v1.4.0 - July 26, 2025 (Current github version)

#### 🎯 Major Functionality Fixes
- **Complete Prefab Creation Fix**: Thoroughly resolved the issue of component/node/resource type reference loss during prefab creation
- **Proper Reference Handling**: Implemented reference formats completely consistent with manually created prefabs
  - **Internal References**: Node and component references within prefabs correctly converted to `{"__id__": x}` format
  - **External References**: Node and component references outside prefabs correctly set to `null`
  - **Resource References**: Prefab, texture, sprite frame and other resource references fully preserved in UUID format
- **Component/Script Removal API Standardization**: Now, when removing a component or script, you must provide the component's cid (type field), not the script name or class name. AI and users should first use getComponents to get the type field (cid), then pass it to removeComponent. This ensures 100% accurate removal of all component and script types, compatible with all Cocos Creator versions.

#### 🔧 Core Improvements
- **Index Order Optimization**: Adjusted prefab object creation order to ensure consistency with Cocos Creator standard format
- **Component Type Support**: Extended component reference detection to support all cc. prefixed component types (Label, Button, Sprite, etc.)
- **UUID Mapping Mechanism**: Perfected internal UUID to index mapping system, ensuring correct reference relationships
- **Property Format Standardization**: Fixed component property order and format, eliminating engine parsing errors

#### 🐛 Bug Fixes
- **Fixed Prefab Import Errors**: Resolved `Cannot read properties of undefined (reading '_name')` error
- **Fixed Engine Compatibility**: Resolved `placeHolder.initDefault is not a function` error
- **Fixed Property Overwriting**: Prevented critical properties like `_objFlags` from being overwritten by component data
- **Fixed Reference Loss**: Ensured all types of references are correctly saved and loaded

#### 📈 Feature Enhancements
- **Complete Component Property Preservation**: All component properties including private properties (like _group, _density, etc.)
- **Child Node Structure Support**: Proper handling of prefab hierarchical structures and child node relationships
- **Transform Property Processing**: Preserved node position, rotation, scale, and layer information
- **Debug Information Optimization**: Added detailed reference processing logs for easier issue tracking

#### 💡 Technical Breakthroughs
- **Reference Type Identification**: Intelligently distinguish between internal and external references, avoiding invalid references
- **Format Compatibility**: Generated prefabs are 100% compatible with manually created prefab formats
- **Engine Integration**: Prefabs can be properly mounted to scenes without any runtime errors
- **Performance Optimization**: Optimized prefab creation workflow, improving processing efficiency for large prefabs

**🎉 Prefab creation functionality is now fully operational, supporting complex component reference relationships and complete prefab structures!**

### v1.3.0 - July 25, 2024

#### 🆕 New Features
- **Integrated Tool Management Panel**: Added comprehensive tool management functionality directly into the main control panel
- **Tool Configuration System**: Implemented selective tool enabling/disabling with persistent configurations
- **Dynamic Tool Loading**: Enhanced tool discovery to dynamically load all 158 available tools from the MCP server
- **Real-time Tool State Management**: Added real-time updates for tool counts and status when individual tools are toggled
- **Configuration Persistence**: Automatic saving and loading of tool configurations across editor sessions

#### 🔧 Improvements
- **Unified Panel Interface**: Merged tool management into the main MCP server panel as a tab, eliminating the need for separate panels
- **Enhanced Server Settings**: Improved server configuration management with better persistence and loading
- **Vue 3 Integration**: Upgraded to Vue 3 Composition API for better reactivity and performance
- **Better Error Handling**: Added comprehensive error handling with rollback mechanisms for failed operations
- **Improved UI/UX**: Enhanced visual design with proper dividers, distinct block styles, and non-transparent modal backgrounds

#### 🐛 Bug Fixes
- **Fixed Tool State Persistence**: Resolved issues where tool states would reset upon tab switching or panel re-opening
- **Fixed Configuration Loading**: Corrected server settings loading issues and message registration problems
- **Fixed Checkbox Interactions**: Resolved checkbox unchecking issues and improved reactivity
- **Fixed Panel Scrolling**: Ensured proper scrolling functionality in the tool management panel
- **Fixed IPC Communication**: Resolved various IPC communication issues between frontend and backend

#### 🏗️ Technical Improvements
- **Simplified Architecture**: Removed multi-configuration complexity, focusing on single configuration management
- **Better Type Safety**: Enhanced TypeScript type definitions and interfaces
- **Improved Data Synchronization**: Better synchronization between frontend UI state and backend tool manager
- **Enhanced Debugging**: Added comprehensive logging and debugging capabilities

#### 📊 Statistics
- **Total Tools**: Increased from 151 to 158 tools
- **Categories**: 13 tool categories with comprehensive coverage
- **Editor Control**: Achieved 98% editor functionality coverage

### v1.2.0 - Previous Version
- Initial release with 151 tools
- Basic MCP server functionality
- Scene, node, component, and prefab operations
- Project control and debugging tools



## Quick Usage

**Claude CLI configuration:**

```
claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp (use your configured port number)
```

**Claude client configuration:**

```
{

  "mcpServers": {

		"cocos-creator": {

 		"type": "http",

		"url": "http://127.0.0.1:3000/mcp"

		 }

	  }

}
```

**Cursor or VS class MCP configuration**

```
{

  "mcpServers": { 

   "cocos-creator": {
      "url": "http://localhost:3000/mcp"
   }
  }

}
```

## Features

### 🎯 Scene Operations (scene_*)
- **scene_management**: Scene management - Get current scene, open/save/create/close scenes, support scene list query
- **scene_hierarchy**: Scene hierarchy - Get complete scene structure, support component information inclusion
- **scene_execution_control**: Execution control - Execute component methods, scene scripts, prefab synchronization

### 🎮 Node Operations (node_*)
- **node_query**: Node query - Find nodes by name/pattern, get node information, detect 2D/3D types
- **node_lifecycle**: Node lifecycle - Create/delete nodes, support component pre-installation, prefab instantiation
- **node_transform**: Node transform - Modify node name, position, rotation, scale, visibility and other properties
- **node_hierarchy**: Node hierarchy - Move, copy, paste nodes, support hierarchical structure operations
- **node_clipboard**: Node clipboard - Copy/paste/cut node operations
- **node_property_management**: Property management - Reset node properties, component properties, transform properties

### 🔧 Component Operations (component_*)
- **component_manage**: Component management - Add/remove engine components (cc.Sprite, cc.Button, etc.)
- **component_script**: Script components - Mount/remove custom script components
- **component_query**: Component query - Get component list, detailed information, available component types
- **set_component_property**: Property setting - Set single or multiple component property values

### 📦 Prefab Operations (prefab_*)
- **prefab_browse**: Prefab browsing - List prefabs, view information, validate files
- **prefab_lifecycle**: Prefab lifecycle - Create prefabs from nodes, delete prefabs
- **prefab_instance**: Prefab instances - Instantiate to scene, unlink, apply changes, restore original
- **prefab_edit**: Prefab editing - Enter/exit edit mode, save prefabs, test changes

### 🚀 Project Control (project_*)
- **project_manage**: Project management - Run project, build project, get project information and settings
- **project_build_system**: Build system - Control build panel, check build status, preview server management

### 🔍 Debug Tools (debug_*)
- **debug_console**: Console management - Get/clear console logs, support filtering and limiting
- **debug_logs**: Log analysis - Read/search/analyze project log files, support pattern matching
- **debug_system**: System debugging - Get editor information, performance statistics, environment information

### 📁 Asset Management (asset_*)
- **asset_manage**: Asset management - Batch import/delete assets, save metadata, generate URLs
- **asset_analyze**: Asset analysis - Get dependency relationships, export asset manifests
- **asset_system**: Asset system - Refresh assets, query asset database status
- **asset_query**: Asset query - Query assets by type/folder, get detailed information
- **asset_operations**: Asset operations - Create/copy/move/delete/save/re-import assets

### ⚙️ Preferences (preferences_*)
- **preferences_manage**: Preferences management - Get/set editor preferences
- **preferences_global**: Global settings - Manage global configuration and system settings

### 🌐 Server and Broadcasting (server_* / broadcast_*)
- **server_info**: Server information - Get server status, project details, environment information
- **broadcast_message**: Message broadcasting - Listen and broadcast custom messages

### 🖼️ Reference Images (referenceImage_*)
- **reference_image_manage**: Reference image management - Add/delete/manage reference images in scene view
- **reference_image_view**: Reference image view - Control reference image display and editing

### 🎨 Scene View (sceneView_*)
- **scene_view_control**: Scene view control - Control Gizmo tools, coordinate systems, view modes
- **scene_view_tools**: Scene view tools - Manage various scene view tools and options

### ✅ Validation Tools (validation_*)
- **validation_scene**: Scene validation - Validate scene integrity, check missing assets
- **validation_asset**: Asset validation - Validate asset references, check asset integrity

### 🛠️ Tool Management
- **Tool Configuration System**: Selectively enable/disable tools, support multiple configurations
- **Configuration Persistence**: Automatically save and load tool configurations
- **Configuration Import/Export**: Support tool configuration import/export functionality
- **Real-time State Management**: Real-time tool state updates and synchronization

### 🚀 Core Advantages
- **Unified Operation Codes**: All tools adopt "category_operation" naming, unified parameter Schema
- **High Reusability**: 50 core tools cover 99% editor functionality
- **AI-Friendly**: Clear parameters, complete documentation, simple calling
- **Performance Optimization**: Reduce 50% token consumption, improve AI calling success rate
- **Complete Compatibility**: 100% aligned with Cocos Creator official API

## Installation

### 1. Copy Plugin Files

Copy the entire `cocos-mcp-server` folder to your Cocos Creator project's `extensions` directory, or you can directly import the project in the extension manager:

```
YourProject/
├── assets/
├── extensions/
│   └── cocos-mcp-server/          <- Place plugin here
│       ├── source/
│       ├── dist/
│       ├── package.json
│       └── ...
├── settings/
└── ...
```

### 2. Install Dependencies

```bash
cd extensions/cocos-mcp-server
npm install
```

### 3. Build the Plugin

```bash
npm run build
```

### 4. Enable Plugin

1. Restart Cocos Creator or refresh extensions
2. The plugin will appear in the Extension menu
3. Click `Extension > Cocos MCP Server` to open the control panel

## Usage

### Starting the Server

1. Open the MCP Server panel from `Extension > Cocos MCP Server`
2. Configure settings:
   - **Port**: HTTP server port (default: 3000)
   - **Auto Start**: Automatically start server when editor opens
   - **Debug Logging**: Enable detailed logging for development
   - **Max Connections**: Maximum concurrent connections allowed

3. Click "Start Server" to begin accepting connections

### Connecting AI Assistants

The server exposes an HTTP endpoint at `http://localhost:3000/mcp` (or your configured port).

AI assistants can connect using the MCP protocol and access all available tools.


## Development

### Project Structure
```
cocos-mcp-server/
├── source/                    # TypeScript source files
│   ├── main.ts               # Plugin entry point
│   ├── mcp-server.ts         # MCP server implementation
│   ├── settings.ts           # Settings management
│   ├── types/                # TypeScript type definitions
│   ├── tools/                # Tool implementations
│   │   ├── scene-tools.ts
│   │   ├── node-tools.ts
│   │   ├── component-tools.ts
│   │   ├── prefab-tools.ts
│   │   ├── project-tools.ts
│   │   ├── debug-tools.ts
│   │   ├── preferences-tools.ts
│   │   ├── server-tools.ts
│   │   ├── broadcast-tools.ts
│   │   ├── scene-advanced-tools.ts (integrated into node-tools.ts and scene-tools.ts)
│   │   ├── scene-view-tools.ts
│   │   ├── reference-image-tools.ts
│   │   └── asset-advanced-tools.ts
│   ├── panels/               # UI panel implementation
│   └── test/                 # Test files
├── dist/                     # Compiled JavaScript output
├── static/                   # Static assets (icons, etc.)
├── i18n/                     # Internationalization files
├── package.json              # Plugin configuration
└── tsconfig.json             # TypeScript configuration
```

### Building from Source

```bash
# Install dependencies
npm install

# Build for development with watch mode
npm run watch

# Build for production
npm run build
```

### Adding New Tools

1. Create a new tool class in `source/tools/`
2. Implement the `ToolExecutor` interface
3. Add tool to `mcp-server.ts` initialization
4. Tools are automatically exposed via MCP protocol

### TypeScript Support

The plugin is fully written in TypeScript with:
- Strict type checking enabled
- Comprehensive type definitions for all APIs
- IntelliSense support for development
- Automatic compilation to JavaScript

## Troubleshooting

### Common Issues

1. **Server won't start**: Check port availability and firewall settings
2. **Tools not working**: Ensure scene is loaded and UUIDs are valid
3. **Build errors**: Run `npm run build` to check for TypeScript errors
4. **Connection issues**: Verify HTTP URL and server status

### Debug Mode

Enable debug logging in the plugin panel for detailed operation logs.

### Using Debug Tools

```json
{
  "tool": "debug_get_console_logs",
  "arguments": {"limit": 50, "filter": "error"}
}
```

```json
{
  "tool": "debug_validate_scene",
  "arguments": {"checkMissingAssets": true}
}
```

## Requirements

- Cocos Creator 3.8.6 or later
- Node.js (bundled with Cocos Creator)
- TypeScript (installed as dev dependency)

## License

This plug-in is for Cocos Creator project use, and the source code is packaged together, which can be used for learning and communication. It is not encrypted. It can support your own secondary development and optimization. Any code of this project or its derivative code cannot be used for any commercial purpose or resale. If you need commercial use, please contact me.

## Contact me to join the group
<img src="https://github.com/user-attachments/assets/2e3f043a-0b03-4b27-a175-e9c31fbed981" width="400" height="400"/>

<img src="https://github.com/user-attachments/assets/5ef6172c-2968-499e-9edf-7da133016cd2" width="400" height="400"/>
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
    "extends": "./base.tsconfig.json",
    "compilerOptions": {
        "outDir": "./dist",
        "rootDir": "./source",
        "types": [
            "node",
            "@cocos/creator-types/editor",
        ]
    }
}
```

--------------------------------------------------------------------------------
/base.tsconfig.json:
--------------------------------------------------------------------------------

```json
{
    "$schema": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json",
    "compilerOptions": {
        "target": "ES2017",
        "module": "CommonJS",
        "moduleResolution": "node",
        "inlineSourceMap": true,
        "inlineSources": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "strict": true,
        "experimentalDecorators": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "outDir": "./dist",
        "rootDir": "./source",
        "types": [
            "node",
            "@cocos/creator-types/editor",
        ]
    }
}
```

--------------------------------------------------------------------------------
/@types/schema/package/contributions/index.json:
--------------------------------------------------------------------------------

```json
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "description": "其他扩展插件的扩展配置 / Extended configuration for other extension plugins",
    "properties": {
        "menu": {
            "type": "array",
            "description": "菜单配置 / Menu configuration",
            "items": {
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "菜单路径 / Menu path"
                    },
                    "label": {
                        "type": "string",
                        "description": "菜单标签 / Menu label"
                    },
                    "message": {
                        "type": "string",
                        "description": "菜单消息 / Menu message"
                    }
                }
            }
        },
        "messages": {
            "type": "object",
            "description": "消息配置 / Message configuration",
            "additionalProperties": {
                "type": "object",
                "properties": {
                    "methods": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "panels": {
            "$ref": "../base/panels.json"
        }
    },
    "required": []
}

```

--------------------------------------------------------------------------------
/source/types/index.ts:
--------------------------------------------------------------------------------

```typescript
export interface MCPServerSettings {
    port: number;
    autoStart: boolean;
    enableDebugLog: boolean;
    allowedOrigins: string[];
    maxConnections: number;
}

export interface ServerStatus {
    running: boolean;
    port: number;
    clients: number;
}

export interface ToolDefinition {
    name: string;
    description: string;
    inputSchema: any;
}

export interface ToolResponse {
    success: boolean;
    data?: any;
    message?: string;
    error?: string;
    instruction?: string;
    warning?: string;
    verificationData?: any;
    updatedProperties?: string[];
}

export interface NodeInfo {
    uuid: string;
    name: string;
    active: boolean;
    position?: { x: number; y: number; z: number };
    rotation?: { x: number; y: number; z: number };
    scale?: { x: number; y: number; z: number };
    parent?: string;
    children?: string[];
    components?: ComponentInfo[];
    layer?: number;
    mobility?: number;
}

export interface ComponentInfo {
    type: string;
    enabled: boolean;
    properties?: Record<string, any>;
}

export interface SceneInfo {
    name: string;
    uuid: string;
    path: string;
}

export interface PrefabInfo {
    name: string;
    uuid: string;
    path: string;
    folder: string;
    createTime?: string;
    modifyTime?: string;
    dependencies?: string[];
}

export interface AssetInfo {
    name: string;
    uuid: string;
    path: string;
    type: string;
    size?: number;
    isDirectory: boolean;
    meta?: {
        ver: string;
        importer: string;
    };
}

export interface ProjectInfo {
    name: string;
    path: string;
    uuid: string;
    version: string;
    cocosVersion: string;
}

export interface ConsoleMessage {
    timestamp: string;
    type: 'log' | 'warn' | 'error' | 'info';
    message: string;
    stack?: string;
}

export interface PerformanceStats {
    nodeCount: number;
    componentCount: number;
    drawCalls: number;
    triangles: number;
    memory: Record<string, any>;
}

export interface ValidationIssue {
    type: 'error' | 'warning' | 'info';
    category: string;
    message: string;
    details?: any;
    suggestion?: string;
}

export interface ValidationResult {
    valid: boolean;
    issueCount: number;
    issues: ValidationIssue[];
}

export interface MCPClient {
    id: string;
    lastActivity: Date;
    userAgent?: string;
}

export interface ToolExecutor {
    getTools(): ToolDefinition[];
    execute(toolName: string, args: any): Promise<ToolResponse>;
}

// 工具配置管理相关接口
export interface ToolConfig {
    category: string;
    name: string;
    enabled: boolean;
    description: string;
}

export interface ToolConfiguration {
    id: string;
    name: string;
    description?: string;
    tools: ToolConfig[];
    createdAt: string;
    updatedAt: string;
}

export interface ToolManagerSettings {
    configurations: ToolConfiguration[];
    currentConfigId: string;
    maxConfigSlots: number;
}

export interface ToolManagerState {
    availableTools: ToolConfig[];
    currentConfiguration: ToolConfiguration | null;
    configurations: ToolConfiguration[];
}
```

--------------------------------------------------------------------------------
/source/settings.ts:
--------------------------------------------------------------------------------

```typescript
import * as fs from 'fs';
import * as path from 'path';
import { MCPServerSettings, ToolManagerSettings, ToolConfiguration, ToolConfig } from './types';

const DEFAULT_SETTINGS: MCPServerSettings = {
    port: 3000,
    autoStart: false,
    enableDebugLog: false,
    allowedOrigins: ['*'],
    maxConnections: 10
};

const DEFAULT_TOOL_MANAGER_SETTINGS: ToolManagerSettings = {
    configurations: [],
    currentConfigId: '',
    maxConfigSlots: 5
};

function getSettingsPath(): string {
    return path.join(Editor.Project.path, 'settings', 'mcp-server.json');
}

function getToolManagerSettingsPath(): string {
    return path.join(Editor.Project.path, 'settings', 'tool-manager.json');
}

function ensureSettingsDir(): void {
    const settingsDir = path.dirname(getSettingsPath());
    if (!fs.existsSync(settingsDir)) {
        fs.mkdirSync(settingsDir, { recursive: true });
    }
}

export function readSettings(): MCPServerSettings {
    try {
        ensureSettingsDir();
        const settingsFile = getSettingsPath();
        if (fs.existsSync(settingsFile)) {
            const content = fs.readFileSync(settingsFile, 'utf8');
            return { ...DEFAULT_SETTINGS, ...JSON.parse(content) };
        }
    } catch (e) {
        console.error('Failed to read settings:', e);
    }
    return DEFAULT_SETTINGS;
}

export function saveSettings(settings: MCPServerSettings): void {
    try {
        ensureSettingsDir();
        const settingsFile = getSettingsPath();
        fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
    } catch (e) {
        console.error('Failed to save settings:', e);
        throw e;
    }
}

// 工具管理器设置相关函数
export function readToolManagerSettings(): ToolManagerSettings {
    try {
        ensureSettingsDir();
        const settingsFile = getToolManagerSettingsPath();
        if (fs.existsSync(settingsFile)) {
            const content = fs.readFileSync(settingsFile, 'utf8');
            return { ...DEFAULT_TOOL_MANAGER_SETTINGS, ...JSON.parse(content) };
        }
    } catch (e) {
        console.error('Failed to read tool manager settings:', e);
    }
    return DEFAULT_TOOL_MANAGER_SETTINGS;
}

export function saveToolManagerSettings(settings: ToolManagerSettings): void {
    try {
        ensureSettingsDir();
        const settingsFile = getToolManagerSettingsPath();
        fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
    } catch (e) {
        console.error('Failed to save tool manager settings:', e);
        throw e;
    }
}

export function exportToolConfiguration(config: ToolConfiguration): string {
    return JSON.stringify(config, null, 2);
}

export function importToolConfiguration(configJson: string): ToolConfiguration {
    try {
        const config = JSON.parse(configJson);
        // 验证配置格式
        if (!config.id || !config.name || !Array.isArray(config.tools)) {
            throw new Error('Invalid configuration format');
        }
        return config;
    } catch (e) {
        console.error('Failed to parse tool configuration:', e);
        throw new Error('Invalid JSON format or configuration structure');
    }
}

export { DEFAULT_SETTINGS, DEFAULT_TOOL_MANAGER_SETTINGS };
```

--------------------------------------------------------------------------------
/@types/schema/package/base/panels.json:
--------------------------------------------------------------------------------

```json
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "description": "面板数据 / Panel data",
    "additionalProperties": false,
    "patternProperties": {
        "^[a-zA-Z0-9_-]+$": {
            "type": "object",
            "description": "面板名 / Panel name",
            "properties": {
                "title": {
                    "type": "string",
                    "default": "Default Panel",
                    "description": "面板标题,支持 i18n:key / Panel title, support for i18n:key (required)"
                },
                "main": {
                    "type": "string",
                    "default": "dist/panels/default/index.js",
                    "description": "入口函数 / Entry function (required)"
                },
                "icon": {
                    "type": "string",
                    "description": "面板图标存放相对目录 / Relative directory for panel icon storage"
                },
                "type": {
                    "type": "string",
                    "enum": ["dockable", "simple"],
                    "default": "dockable",
                    "description": "面板类型(dockable | simple) / Panel type (dockable | simple)"
                },
                "flags": {
                    "type": "object",
                    "properties": {
                        "resizable": {
                            "type": "boolean",
                            "default": true,
                            "description": "是否可以改变大小,默认 true / Whether the size can be changed, default true"
                        },
                        "save": {
                            "type": "boolean",
                            "default": true,
                            "description": "是否需要保存,默认 false / Whether to save, default false"
                        },
                        "alwaysOnTop": {
                            "type": "boolean",
                            "default": true,
                            "description": "是否保持顶层显示,默认 false / Whether to keep the top level display, default false"
                        }
                    }
                },
                "size": {
                    "type": "object",
                    "description": "面板大小信息 / Panel size information",
                    "properties": {
                        "min-width": {
                            "type": "number",
                            "default": 200,
                            "description": "面板最小宽度 / Minimum panel width"
                        },
                        "min-height": {
                            "type": "number",
                            "default": 200,
                            "description": "面板最小高度 / Minimum panel height"
                        },
                        "width": {
                            "type": "number",
                            "default": 400,
                            "description": " 面板默认宽度 / Panel Default Width"
                        },
                        "height": {
                            "type": "number",
                            "default": 600,
                            "description": "面板默认高度 / Panel Default Height"
                        }
                    }
                }
            },
            "required": ["title", "main"]
        }
    }
}

```

--------------------------------------------------------------------------------
/i18n/en.js:
--------------------------------------------------------------------------------

```javascript
"use strict";

module.exports = {
    "extension_name": "Cocos MCP Server",
    "description": "AI MCP Server for Cocos Creator 3.8",
    "panel_title": "MCP Server",
    "open_panel": "Open MCP Panel",
    "start_server": "Start Server",
    "stop_server": "Stop Server",
    "server_status": "Server Status",
    "port": "Port",
    "settings": "Settings",
    "connected": "Connected",
    "disconnected": "Disconnected",
    "server_running": "Server is running on port {0}",
    "server_stopped": "Server has stopped",
    "auto_start": "Auto Start",
    "debug_log": "Debug Logging",
    "max_connections": "Max Connections",
    "connection_info": "Connection Info",
    "http_url": "HTTP URL",
    "copy": "Copy",
    "save_settings": "Save Settings",
    "settings_saved": "Settings saved successfully",
    "server_started": "MCP Server Started",
    "server_stopped_msg": "MCP Server Stopped",
    "failed_to_start": "Failed to start server",
    "failed_to_stop": "Failed to stop server",
    "failed_to_save": "Failed to save settings",
    "url_copied": "HTTP URL copied to clipboard",
    "tool_manager": "Tool Manager",
    "open_tool_manager": "Open Tool Manager",
    "create_config": "Create Configuration",
    "edit_config": "Edit Configuration",
    "delete_config": "Delete Configuration",
    "import_config": "Import Configuration",
    "export_config": "Export Configuration",
    "apply_config": "Apply Configuration",
    "select_all": "Select All",
    "deselect_all": "Deselect All",
    "save_changes": "Save Changes",
    "config_name": "Configuration Name",
    "config_description": "Configuration Description",
    "current_config": "Current Configuration",
    "tool_management": "Tool Management",
    "total_tools": "Total Tools",
    "enabled_tools": "Enabled",
    "disabled_tools": "Disabled",
    "no_config_selected": "No Configuration Selected",
    "select_config_first": "Please select a configuration or create a new one first",
    "config_created": "Configuration created successfully",
    "config_updated": "Configuration updated successfully",
    "config_deleted": "Configuration deleted successfully",
    "config_applied": "Configuration applied successfully",
    "config_exported": "Configuration exported successfully",
    "config_imported": "Configuration imported successfully",
    "confirm_delete": "Confirm Delete",
    "delete_config_confirm": "Are you sure you want to delete configuration \"{0}\"? This action cannot be undone.",
    "max_config_slots_reached": "Maximum configuration slots reached ({0})",
    "invalid_config_format": "Invalid configuration format",
    "invalid_json_format": "Invalid JSON format or configuration structure",
    "server_tab": "Server",
    "tools_tab": "Tool Management",
    "available_tools": "Available Tools",
    "scene_tools": "Scene Tools",
    "node_tools": "Node Tools",
    "component_tools": "Component Tools",
    "prefab_tools": "Prefab Tools",
    "project_tools": "Project Tools",
    "debug_tools": "Debug Tools",
    "preferences_tools": "Preferences",
    "server_tools": "Server Tools",
    "broadcast_tools": "Broadcast Tools",
    "scene_advanced_tools": "Advanced Scene Tools",
    "scene_view_tools": "Scene View Tools",
    "reference_image_tools": "Reference Image Tools",
    "asset_advanced_tools": "Advanced Asset Tools",
    "validation_tools": "Validation Tools"
};
```

--------------------------------------------------------------------------------
/source/test/manual-test.ts:
--------------------------------------------------------------------------------

```typescript
declare const Editor: any;

/**
 * 手动测试脚本
 * 可以在 Cocos Creator 控制台中执行测试
 */

export async function testSceneTools() {
    console.log('=== Testing Scene Tools ===');
    
    try {
        // 1. 获取场景信息
        console.log('1. Getting scene info...');
        const sceneInfo = await Editor.Message.request('scene', 'get-scene-info');
        console.log('Scene info:', sceneInfo);
        
        // 2. 创建节点
        console.log('\n2. Creating test node...');
        const createResult = await Editor.Message.request('scene', 'create-node', {
            name: 'TestNode_' + Date.now(),
            type: 'cc.Node'
        });
        console.log('Create result:', createResult);
        
        if (createResult && createResult.uuid) {
            const nodeUuid = createResult.uuid;
            
            // 3. 查询节点
            console.log('\n3. Querying node...');
            const nodeInfo = await Editor.Message.request('scene', 'query-node', {
                uuid: nodeUuid
            });
            console.log('Node info:', nodeInfo);
            
            // 4. 设置节点属性
            console.log('\n4. Setting node position...');
            await Editor.Message.request('scene', 'set-node-property', {
                uuid: nodeUuid,
                path: 'position',
                value: { x: 100, y: 200, z: 0 }
            });
            console.log('Position set successfully');
            
            // 5. 添加组件
            console.log('\n5. Adding Sprite component...');
            const addCompResult = await Editor.Message.request('scene', 'add-component', {
                uuid: nodeUuid,
                component: 'cc.Sprite'
            });
            console.log('Component added:', addCompResult);
            
            // 6. 查询组件
            console.log('\n6. Querying component...');
            const compInfo = await Editor.Message.request('scene', 'query-node-component', {
                uuid: nodeUuid,
                component: 'cc.Sprite'
            });
            console.log('Component info:', compInfo);
            
            // 7. 删除节点
            console.log('\n7. Removing test node...');
            await Editor.Message.request('scene', 'remove-node', {
                uuid: nodeUuid
            });
            console.log('Node removed successfully');
        }
        
    } catch (error) {
        console.error('Test failed:', error);
    }
}

export async function testAssetTools() {
    console.log('\n=== Testing Asset Tools ===');
    
    try {
        // 1. 查询资源
        console.log('1. Querying image assets...');
        const assets = await Editor.Message.request('asset-db', 'query-assets', {
            pattern: '**/*.png',
            ccType: 'cc.ImageAsset'
        });
        console.log('Found assets:', assets?.length || 0);
        
        // 2. 获取资源信息
        console.log('\n2. Getting asset database info...');
        const assetInfo = await Editor.Message.request('asset-db', 'query-asset-info', {
            uuid: 'db://assets'
        });
        console.log('Asset info:', assetInfo);
        
    } catch (error) {
        console.error('Test failed:', error);
    }
}

export async function testProjectTools() {
    console.log('\n=== Testing Project Tools ===');
    
    try {
        // 1. 获取项目信息
        console.log('1. Getting project info...');
        const projectInfo = await Editor.Message.request('project', 'query-info');
        console.log('Project info:', projectInfo);
        
        // 2. 检查构建能力
        console.log('\n2. Checking build capability...');
        const canBuild = await Editor.Message.request('project', 'can-build');
        console.log('Can build:', canBuild);
        
    } catch (error) {
        console.error('Test failed:', error);
    }
}

export async function runAllTests() {
    console.log('Starting MCP Server Tools Test...\n');
    
    await testSceneTools();
    await testAssetTools();
    await testProjectTools();
    
    console.log('\n=== All tests completed ===');
}

// 导出到全局,方便在控制台调用
(global as any).MCPTest = {
    testSceneTools,
    testAssetTools,
    testProjectTools,
    runAllTests
};
```

--------------------------------------------------------------------------------
/TestScript.js:
--------------------------------------------------------------------------------

```javascript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestScript = void 0;
const cc_1 = require("cc");
const { ccclass, property } = cc_1._decorator;
let TestScript = class TestScript extends cc_1.Component {
    constructor() {
        super(...arguments);
        this.testString = "Hello World";
        this.testNumber = 100;
        this.testBoolean = true;
        this.targetNode = null;
    }
    start() {
        console.log('TestScript started with:', {
            testString: this.testString,
            testNumber: this.testNumber,
            testBoolean: this.testBoolean,
            targetNode: this.targetNode
        });
    }
    update(deltaTime) {
    }
};
exports.TestScript = TestScript;
__decorate([
    property({
        displayName: "测试字符串"
    })
], TestScript.prototype, "testString", void 0);
__decorate([
    property({
        displayName: "测试数字"
    })
], TestScript.prototype, "testNumber", void 0);
__decorate([
    property({
        displayName: "测试布尔值"
    })
], TestScript.prototype, "testBoolean", void 0);
__decorate([
    property(cc_1.Node)
], TestScript.prototype, "targetNode", void 0);
exports.TestScript = TestScript = __decorate([
    ccclass('TestScript')
], TestScript);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGVzdFNjcmlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIlRlc3RTY3JpcHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUEsMkJBQWlEO0FBQ2pELE1BQU0sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsZUFBVSxDQUFDO0FBR2xDLElBQU0sVUFBVSxHQUFoQixNQUFNLFVBQVcsU0FBUSxjQUFTO0lBQWxDOztRQUlJLGVBQVUsR0FBVyxhQUFhLENBQUM7UUFLbkMsZUFBVSxHQUFXLEdBQUcsQ0FBQztRQUt6QixnQkFBVyxHQUFZLElBQUksQ0FBQztRQUc1QixlQUFVLEdBQWdCLElBQUksQ0FBQztJQWMxQyxDQUFDO0lBWkcsS0FBSztRQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLEVBQUU7WUFDcEMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1lBQzNCLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVTtZQUMzQixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQzlCLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxNQUFNLENBQUMsU0FBaUI7SUFFeEIsQ0FBQztDQUNKLENBQUE7QUEvQlksZ0NBQVU7QUFJWjtJQUhOLFFBQVEsQ0FBQztRQUNOLFdBQVcsRUFBRSxPQUFPO0tBQ3ZCLENBQUM7OENBQ3dDO0FBS25DO0lBSE4sUUFBUSxDQUFDO1FBQ04sV0FBVyxFQUFFLE1BQU07S0FDdEIsQ0FBQzs4Q0FDOEI7QUFLekI7SUFITixRQUFRLENBQUM7UUFDTixXQUFXLEVBQUUsT0FBTztLQUN2QixDQUFDOytDQUNpQztBQUc1QjtJQUROLFFBQVEsQ0FBQyxTQUFJLENBQUM7OENBQ3VCO3FCQWpCN0IsVUFBVTtJQUR0QixPQUFPLENBQUMsWUFBWSxDQUFDO0dBQ1QsVUFBVSxDQStCdEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBfZGVjb3JhdG9yLCBDb21wb25lbnQsIE5vZGUgfSBmcm9tICdjYyc7XG5jb25zdCB7IGNjY2xhc3MsIHByb3BlcnR5IH0gPSBfZGVjb3JhdG9yO1xuXG5AY2NjbGFzcygnVGVzdFNjcmlwdCcpXG5leHBvcnQgY2xhc3MgVGVzdFNjcmlwdCBleHRlbmRzIENvbXBvbmVudCB7XG4gICAgQHByb3BlcnR5KHtcbiAgICAgICAgZGlzcGxheU5hbWU6IFwi5rWL6K+V5a2X56ym5LiyXCJcbiAgICB9KVxuICAgIHB1YmxpYyB0ZXN0U3RyaW5nOiBzdHJpbmcgPSBcIkhlbGxvIFdvcmxkXCI7XG4gICAgXG4gICAgQHByb3BlcnR5KHtcbiAgICAgICAgZGlzcGxheU5hbWU6IFwi5rWL6K+V5pWw5a2XXCJcbiAgICB9KVxuICAgIHB1YmxpYyB0ZXN0TnVtYmVyOiBudW1iZXIgPSAxMDA7XG4gICAgXG4gICAgQHByb3BlcnR5KHtcbiAgICAgICAgZGlzcGxheU5hbWU6IFwi5rWL6K+V5biD5bCU5YC8XCJcbiAgICB9KVxuICAgIHB1YmxpYyB0ZXN0Qm9vbGVhbjogYm9vbGVhbiA9IHRydWU7XG4gICAgXG4gICAgQHByb3BlcnR5KE5vZGUpXG4gICAgcHVibGljIHRhcmdldE5vZGU6IE5vZGUgfCBudWxsID0gbnVsbDtcblxuICAgIHN0YXJ0KCkge1xuICAgICAgICBjb25zb2xlLmxvZygnVGVzdFNjcmlwdCBzdGFydGVkIHdpdGg6Jywge1xuICAgICAgICAgICAgdGVzdFN0cmluZzogdGhpcy50ZXN0U3RyaW5nLFxuICAgICAgICAgICAgdGVzdE51bWJlcjogdGhpcy50ZXN0TnVtYmVyLFxuICAgICAgICAgICAgdGVzdEJvb2xlYW46IHRoaXMudGVzdEJvb2xlYW4sXG4gICAgICAgICAgICB0YXJnZXROb2RlOiB0aGlzLnRhcmdldE5vZGVcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdXBkYXRlKGRlbHRhVGltZTogbnVtYmVyKSB7XG4gICAgICAgIFxuICAgIH1cbn0iXX0=
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
    "$schema": "./@types/schema/package/index.json",
    "package_version": 2,
    "name": "cocos-mcp-server",
    "version": "1.4.0",
    "author": "LiDaxian",
    "editor": ">=3.8.6",
    "scripts": {
        "preinstall": "node ./scripts/preinstall.js",
        "build": "tsc",
        "watch": "tsc -w"
    },
    "description": "i18n:cocos-mcp-server.description",
    "main": "./dist/main.js",
    "dependencies": {
        "fs-extra": "^11.3.0",
        "uuid": "^9.0.1",
        "vue": "^3.1.4"
    },
    "devDependencies": {
        "@cocos/creator-types": "^3.8.6",
        "@types/fs-extra": "^9.0.5",
        "@types/node": "^18.17.1",
        "@types/uuid": "^9.0.8",
        "typescript": "^5.8.2"
    },
    "panels": {
        "default": {
            "title": "i18n:cocos-mcp-server.panel_title",
            "type": "dockable",
            "main": "dist/panels/default",
            "icon": "./static/icon.png",
            "size": {
                "min-width": 400,
                "min-height": 300,
                "width": 600,
                "height": 500
            }
        }
    },
    "contributions": {
                "menu": [
            {
                "path": "i18n:menu.extension/Cocos MCP Server",
                "label": "i18n:cocos-mcp-server.open_panel",
                "message": "open-panel"
            }
        ],
        "messages": {
            "open-panel": {
                "methods": [
                    "openPanel"
                ]
            },
            "open-tool-manager": {
                "methods": [
                    "openToolManager"
                ]
            },
            "start-server": {
                "methods": [
                    "startServer"
                ]
            },
            "stop-server": {
                "methods": [
                    "stopServer"
                ]
            },
            "get-server-status": {
                "methods": [
                    "getServerStatus"
                ]
            },
            "update-settings": {
                "methods": [
                    "updateSettings"
                ]
            },
            "getToolsList": {
                "methods": [
                    "getToolsList"
                ]
            },
            "get-server-settings": {
                "methods": [
                    "getServerSettings"
                ]
            },
            "getToolManagerState": {
                "methods": [
                    "getToolManagerState"
                ]
            },
            "createToolConfiguration": {
                "methods": [
                    "createToolConfiguration"
                ]
            },
            "updateToolConfiguration": {
                "methods": [
                    "updateToolConfiguration"
                ]
            },
            "deleteToolConfiguration": {
                "methods": [
                    "deleteToolConfiguration"
                ]
            },
            "setCurrentToolConfiguration": {
                "methods": [
                    "setCurrentToolConfiguration"
                ]
            },
            "updateToolStatus": {
                "methods": [
                    "updateToolStatus"
                ]
            },
            "updateToolStatusBatch": {
                "methods": [
                    "updateToolStatusBatch"
                ]
            },
            "exportToolConfiguration": {
                "methods": [
                    "exportToolConfiguration"
                ]
            },
            "importToolConfiguration": {
                "methods": [
                    "importToolConfiguration"
                ]
            },
            "getEnabledTools": {
                "methods": [
                    "getEnabledTools"
                ]
            }
        },
        "scene": {
            "script": "./dist/scene.js",
            "methods": [
                "createNewScene",
                "addComponentToNode",
                "removeComponentFromNode",
                "getNodeInfo",
                "getAllNodes",
                "findNodeByName",
                "setNodeProperty",
                "setComponentProperty",
                "getCurrentSceneInfo",
                "getSceneHierarchy",
                "createPrefabFromNode"
            ]
        }
    }
}

```

--------------------------------------------------------------------------------
/source/test/tool-tester.ts:
--------------------------------------------------------------------------------

```typescript
declare const Editor: any;

interface TestResult {
    tool: string;
    method: string;
    success: boolean;
    result?: any;
    error?: string;
    time: number;
}

export class ToolTester {
    private results: TestResult[] = [];

    async runTest(tool: string, method: string, params: any): Promise<TestResult> {
        const startTime = Date.now();
        const result: TestResult = {
            tool,
            method,
            success: false,
            time: 0
        };

        try {
            const response = await Editor.Message.request(tool, method, params);
            result.success = true;
            result.result = response;
        } catch (error) {
            result.success = false;
            result.error = error instanceof Error ? error.message : String(error);
        }

        result.time = Date.now() - startTime;
        this.results.push(result);
        return result;
    }

    async testSceneOperations() {
        console.log('Testing Scene Operations...');
        
        // Test node creation (this is the main scene operation that works)
        const createResult = await this.runTest('scene', 'create-node', {
            name: 'TestNode',
            type: 'cc.Node'
        });
        
        if (createResult.success && createResult.result) {
            const nodeUuid = createResult.result;
            
            // Test query node info
            await this.runTest('scene', 'query-node-info', nodeUuid);
            
            // Test remove node
            await this.runTest('scene', 'remove-node', nodeUuid);
        }
        
        // Test execute scene script
        await this.runTest('scene', 'execute-scene-script', {
            name: 'cocos-mcp-server',
            method: 'test-method',
            args: []
        });
    }

    async testNodeOperations() {
        console.log('Testing Node Operations...');
        
        // Create a test node first
        const createResult = await this.runTest('scene', 'create-node', {
            name: 'TestNodeForOps',
            type: 'cc.Node'
        });
        
        if (createResult.success && createResult.result) {
            const nodeUuid = createResult.result;
            
            // Test set property
            await this.runTest('scene', 'set-property', {
                uuid: nodeUuid,
                path: 'position',
                dump: {
                    type: 'cc.Vec3',
                    value: { x: 100, y: 200, z: 0 }
                }
            });
            
            // Test add component
            await this.runTest('scene', 'add-component', {
                uuid: nodeUuid,
                component: 'cc.Sprite'
            });
            
            // Clean up
            await this.runTest('scene', 'remove-node', nodeUuid);
        }
    }

    async testAssetOperations() {
        console.log('Testing Asset Operations...');
        
        // Test asset list
        await this.runTest('asset-db', 'query-assets', {
            pattern: '**/*.png',
            ccType: 'cc.ImageAsset'
        });
        
        // Test query asset by path
        await this.runTest('asset-db', 'query-path', 'db://assets');
        
        // Test query asset by uuid (using a valid uuid format)
        await this.runTest('asset-db', 'query-uuid', 'db://assets');
    }

    async testProjectOperations() {
        console.log('Testing Project Operations...');
        
        // Test open project settings
        await this.runTest('project', 'open-settings', {});
        
        // Test query project settings
        const projectName = await this.runTest('project', 'query-setting', 'name');
        
        if (projectName.success) {
            console.log('Project name:', projectName.result);
        }
    }

    async runAllTests() {
        this.results = [];
        
        await this.testSceneOperations();
        await this.testNodeOperations();
        await this.testAssetOperations();
        await this.testProjectOperations();
        
        return this.getTestReport();
    }

    getTestReport() {
        const total = this.results.length;
        const passed = this.results.filter(r => r.success).length;
        const failed = total - passed;
        
        return {
            summary: {
                total,
                passed,
                failed,
                passRate: total > 0 ? (passed / total * 100).toFixed(2) + '%' : '0%'
            },
            results: this.results,
            grouped: this.groupResultsByTool()
        };
    }

    private groupResultsByTool() {
        const grouped: Record<string, TestResult[]> = {};
        
        for (const result of this.results) {
            if (!grouped[result.tool]) {
                grouped[result.tool] = [];
            }
            grouped[result.tool].push(result);
        }
        
        return grouped;
    }
}
```

--------------------------------------------------------------------------------
/static/template/vue/mcp-server-app.html:
--------------------------------------------------------------------------------

```html
<div class="mcp-app">
    <!-- 选项卡导航 -->
    <div class="tab-navigation">
        <button class="tab-button" :class="{ active: activeTab === 'server' }" @click="switchTab('server')">
            <span>服务器</span>
        </button>
        <button class="tab-button" :class="{ active: activeTab === 'tools' }" @click="switchTab('tools')">
            <span>工具管理</span>
        </button>
    </div>
    
    <!-- 服务器选项卡 -->
    <div class="tab-content" v-show="activeTab === 'server'">
        <section class="server-status">
            <h3>服务器状态</h3>
            <div class="status-info">
                <ui-prop>
                    <ui-label slot="label">状态</ui-label>
                    <ui-label slot="content" class="status-value" :class="statusClass">{{ serverStatus }}</ui-label>
                </ui-prop>
                <ui-prop v-if="serverRunning">
                    <ui-label slot="label">连接数</ui-label>
                    <ui-label slot="content">{{ connectedClients }}</ui-label>
                </ui-prop>
            </div>
        </section>

        <section class="server-controls">
            <ui-button @click="toggleServer" :disabled="isProcessing" class="primary">
                {{ serverRunning ? '停止服务器' : '启动服务器' }}
            </ui-button>
        </section>

        <section class="server-settings">
            <h3>服务器设置</h3>
            <ui-prop>
                <ui-label slot="label">端口</ui-label>
                <ui-num-input slot="content" v-model="settings.port" :min="1024" :max="65535" :step="1" :disabled="serverRunning">
                </ui-num-input>
            </ui-prop>
            <ui-prop>
                <ui-label slot="label">自动启动</ui-label>
                <ui-checkbox slot="content" v-model="settings.autoStart"></ui-checkbox>
            </ui-prop>
            <ui-prop>
                <ui-label slot="label">调试日志</ui-label>
                <ui-checkbox slot="content" v-model="settings.debugLog"></ui-checkbox>
            </ui-prop>
            <ui-prop>
                <ui-label slot="label">最大连接数</ui-label>
                <ui-num-input slot="content" v-model="settings.maxConnections" :min="1" :max="100" :step="1">
                </ui-num-input>
            </ui-prop>
        </section>

        <section class="server-info" v-if="serverRunning">
            <h3>连接信息</h3>
            <div class="connection-details">
                <ui-prop>
                    <ui-label slot="label">HTTP URL</ui-label>
                    <ui-input slot="content" :value="httpUrl" readonly>
                        <ui-button slot="suffix" @click="copyUrl">复制</ui-button>
                    </ui-input>
                </ui-prop>
            </div>
        </section>

        <footer>
            <ui-button @click="saveSettings" :disabled="!settingsChanged">保存设置</ui-button>
        </footer>
    </div>
    
    <!-- 工具管理选项卡 -->
    <div class="tab-content" v-show="activeTab === 'tools'">
        <section class="tool-manager">
            <div class="tool-manager-header">
                <h3>工具管理</h3>
            </div>
            
            <div class="tools-section">
                <div class="tools-section-header">
                    <div class="tools-section-title">
                        <h4>可用工具</h4>
                        <div class="tools-stats">
                            {{ totalTools }} 个工具
                            ({{ enabledTools }} 启用 / {{ disabledTools }} 禁用)
                        </div>
                    </div>
                    <div class="tools-section-controls">
                        <ui-button @click="selectAllTools" class="small">全选</ui-button>
                        <ui-button @click="deselectAllTools" class="small">取消全选</ui-button>
                        <ui-button @click="saveChanges" class="primary">保存更改</ui-button>
                    </div>
                </div>
                
                <div class="tools-container">
                    <div v-for="category in toolCategories" :key="category" class="tool-category">
                        <div class="category-header">
                            <h5>{{ getCategoryDisplayName(category) }}</h5>
                            <div class="category-controls">
                                <ui-button @click="toggleCategoryTools(category, true)" class="small">全选</ui-button>
                                <ui-button @click="toggleCategoryTools(category, false)" class="small">取消全选</ui-button>
                            </div>
                        </div>
                        <div class="tool-items">
                            <div v-for="tool in getToolsByCategory(category)" :key="tool.name" class="tool-item">
                                <ui-checkbox 
                                    :value="tool.enabled"
                                    @change="(event) => updateToolStatus(category, tool.name, event.target.checked)"
                                ></ui-checkbox>
                                <div class="tool-info">
                                    <div class="tool-name">{{ tool.name }}</div>
                                    <div class="tool-description">{{ tool.description }}</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            

        </section>
    </div>
</div>

 
```

--------------------------------------------------------------------------------
/static/style/default/index.css:
--------------------------------------------------------------------------------

```css
.mcp-server-panel {
    padding: 20px;
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 100%;
    max-height: 100%;
    overflow-y: auto;
    box-sizing: border-box;
}

header h2 {
    margin: 0 0 20px 0;
    font-size: 18px;
}

/* Vue3 应用样式 */
.mcp-app {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

/* 选项卡导航样式 */
.tab-navigation {
    display: flex;
    border-bottom: 1px solid var(--color-normal-border);
    margin-bottom: 20px;
    background: var(--color-panel);
}

.tab-button {
    background: none;
    border: none;
    padding: 10px 20px;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    color: var(--color-normal-text);
    font-size: 14px;
    transition: all 0.2s ease;
    border-radius: 4px 4px 0 0;
}

.tab-button:hover {
    background: var(--color-normal-fill-emphasis);
}

.tab-button.active {
    border-bottom-color: var(--color-primary);
    color: var(--color-primary);
    font-weight: 600;
    background: var(--color-panel);
}

/* 选项卡内容样式 */
.tab-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow-y: auto;
    padding: 20px;
}

section {
    margin-bottom: 20px;
    padding: 15px;
    background: var(--color-normal-fill-emphasis);
    border-radius: 4px;
}

section h3 {
    margin: 0 0 15px 0;
    font-size: 14px;
    font-weight: 600;
}

.status-value {
    font-weight: 600;
}

.status-value.running {
    color: var(--color-success-fill);
}

.status-value.stopped {
    color: var(--color-warn-fill);
}

.server-controls {
    display: flex;
    justify-content: center;
    padding: 20px;
}

.server-controls ui-button {
    min-width: 150px;
}

.connection-details {
    margin-top: 10px;
}

footer {
    margin-top: auto;
    padding-top: 20px;
    display: flex;
    justify-content: flex-end;
}

ui-prop {
    margin-bottom: 10px;
}

/* 工具管理器样式 */
.tool-manager {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.tool-manager-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.tool-manager-controls {
    display: flex;
    gap: 10px;
}

.config-selector-section {
    margin-bottom: 20px;
}

.tools-section {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.tools-section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--color-normal-border);
}

.tools-section-title {
    display: flex;
    flex-direction: column;
    gap: 5px;
}

.tools-section-title h4 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
}

.tools-stats {
    font-size: 12px;
    color: var(--color-normal-text-secondary);
}

.tools-section-controls {
    display: flex;
    gap: 10px;
    align-items: center;
}

.tools-container {
    flex: 1;
    overflow-y: auto;
    padding-right: 8px;
    max-height: 400px;
}

.tools-container::-webkit-scrollbar {
    width: 6px;
}

.tools-container::-webkit-scrollbar-track {
    background: var(--color-normal-fill-emphasis);
    border-radius: 3px;
}

.tools-container::-webkit-scrollbar-thumb {
    background: var(--color-normal-border);
    border-radius: 3px;
}

.tools-container::-webkit-scrollbar-thumb:hover {
    background: var(--color-normal-text-secondary);
}

.tool-category {
    margin-bottom: 20px;
    background: var(--color-normal-fill);
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.category-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 15px;
    background: linear-gradient(135deg, var(--color-primary-fill) 0%, var(--color-primary-fill-emphasis) 100%);
    color: var(--color-primary-text);
    font-weight: 600;
}

.category-name {
    font-size: 14px;
}

.category-toggle {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
}

.tool-list {
    padding: 10px 15px;
}

.tool-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid var(--color-normal-border);
}

.tool-item:last-child {
    border-bottom: none;
}

.tool-info {
    flex: 1;
}

.tool-name {
    font-size: 13px;
    font-weight: 500;
    color: var(--color-normal-text);
}

.tool-description {
    font-size: 11px;
    color: var(--color-normal-text-secondary);
    margin-top: 2px;
}

.tool-toggle {
    display: flex;
    align-items: center;
}

.checkbox {
    width: 16px;
    height: 16px;
    cursor: pointer;
}

.tool-manager-footer {
    margin-top: 20px;
    padding-top: 15px;
    border-top: 1px solid var(--color-normal-border);
}

.config-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* 模态框样式 */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.modal-content {
    background: var(--color-normal-fill);
    border-radius: 8px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    backdrop-filter: blur(8px);
    min-width: 400px;
    max-width: 600px;
    max-height: 80vh;
    overflow-y: auto;
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20px 20px 0 20px;
    border-bottom: 1px solid var(--color-normal-border);
    padding-bottom: 15px;
}

.modal-header h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
}

.modal-close {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: var(--color-normal-text-secondary);
    padding: 0;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
}

.modal-close:hover {
    background: var(--color-normal-fill-emphasis);
    color: var(--color-normal-text);
}

.modal-body {
    padding: 20px;
}

.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 0 20px 20px 20px;
    border-top: 1px solid var(--color-normal-border);
    padding-top: 15px;
}

/* 按钮样式 */
ui-button.small {
    font-size: 12px;
    padding: 4px 8px;
    min-width: auto;
}

ui-button.secondary {
    background: var(--color-normal-fill-emphasis);
    color: var(--color-normal-text);
    border: 1px solid var(--color-normal-border);
}

ui-button.secondary:hover {
    background: var(--color-normal-fill);
}

/* 空状态样式 */
.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--color-normal-text-secondary);
}

.empty-state h3 {
    margin: 0 0 10px 0;
    font-size: 16px;
}

.empty-state p {
    margin: 0;
    font-size: 14px;
}
```

--------------------------------------------------------------------------------
/source/test/mcp-tool-tester.ts:
--------------------------------------------------------------------------------

```typescript
declare const Editor: any;

/**
 * MCP 工具测试器 - 直接测试通过 WebSocket 的 MCP 工具
 */
export class MCPToolTester {
    private ws: WebSocket | null = null;
    private messageId = 0;
    private responseHandlers = new Map<number, (response: any) => void>();

    async connect(port: number): Promise<boolean> {
        return new Promise((resolve) => {
            try {
                this.ws = new WebSocket(`ws://localhost:${port}`);
                
                this.ws.onopen = () => {
                    console.log('WebSocket 连接成功');
                    resolve(true);
                };
                
                this.ws.onerror = (error) => {
                    console.error('WebSocket 连接错误:', error);
                    resolve(false);
                };
                
                this.ws.onmessage = (event) => {
                    try {
                        const response = JSON.parse(event.data);
                        if (response.id && this.responseHandlers.has(response.id)) {
                            const handler = this.responseHandlers.get(response.id);
                            this.responseHandlers.delete(response.id);
                            handler?.(response);
                        }
                    } catch (error) {
                        console.error('处理响应时出错:', error);
                    }
                };
            } catch (error) {
                console.error('创建 WebSocket 时出错:', error);
                resolve(false);
            }
        });
    }

    async callTool(tool: string, args: any = {}): Promise<any> {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            throw new Error('WebSocket 未连接');
        }

        return new Promise((resolve, reject) => {
            const id = ++this.messageId;
            const request = {
                jsonrpc: '2.0',
                id,
                method: 'tools/call',
                params: {
                    name: tool,
                    arguments: args
                }
            };

            const timeout = setTimeout(() => {
                this.responseHandlers.delete(id);
                reject(new Error('请求超时'));
            }, 10000);

            this.responseHandlers.set(id, (response) => {
                clearTimeout(timeout);
                if (response.error) {
                    reject(new Error(response.error.message));
                } else {
                    resolve(response.result);
                }
            });

            this.ws!.send(JSON.stringify(request));
        });
    }

    async listTools(): Promise<any> {
        if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
            throw new Error('WebSocket 未连接');
        }

        return new Promise((resolve, reject) => {
            const id = ++this.messageId;
            const request = {
                jsonrpc: '2.0',
                id,
                method: 'tools/list'
            };

            const timeout = setTimeout(() => {
                this.responseHandlers.delete(id);
                reject(new Error('请求超时'));
            }, 10000);

            this.responseHandlers.set(id, (response) => {
                clearTimeout(timeout);
                if (response.error) {
                    reject(new Error(response.error.message));
                } else {
                    resolve(response.result);
                }
            });

            this.ws!.send(JSON.stringify(request));
        });
    }

    async testMCPTools() {
        console.log('\n=== 测试 MCP 工具(通过 WebSocket)===');
        
        try {
            // 0. 获取工具列表
            console.log('\n0. 获取工具列表...');
            const toolsList = await this.listTools();
            console.log(`找到 ${toolsList.tools?.length || 0} 个工具:`);
            if (toolsList.tools) {
                for (const tool of toolsList.tools.slice(0, 10)) { // 只显示前10个
                    console.log(`  - ${tool.name}: ${tool.description}`);
                }
                if (toolsList.tools.length > 10) {
                    console.log(`  ... 还有 ${toolsList.tools.length - 10} 个工具`);
                }
            }
            
            // 1. 测试场景工具
            console.log('\n1. 测试当前场景信息...');
            const sceneInfo = await this.callTool('scene_get_current_scene');
            console.log('场景信息:', JSON.stringify(sceneInfo).substring(0, 100) + '...');
            
            // 2. 测试场景列表
            console.log('\n2. 测试场景列表...');
            const sceneList = await this.callTool('scene_get_scene_list');
            console.log('场景列表:', JSON.stringify(sceneList).substring(0, 100) + '...');
            
            // 3. 测试节点创建
            console.log('\n3. 测试创建节点...');
            const createResult = await this.callTool('node_create_node', {
                name: 'MCPTestNode_' + Date.now(),
                nodeType: 'cc.Node',
                position: { x: 0, y: 0, z: 0 }
            });
            console.log('创建节点结果:', createResult);
            
            // 解析创建节点的结果
            let nodeUuid: string | null = null;
            if (createResult.content && createResult.content[0] && createResult.content[0].text) {
                try {
                    const resultData = JSON.parse(createResult.content[0].text);
                    if (resultData.success && resultData.data && resultData.data.uuid) {
                        nodeUuid = resultData.data.uuid;
                        console.log('成功获取节点UUID:', nodeUuid);
                    }
                } catch (e) {
                }
            }
            
            if (nodeUuid) {
                // 4. 测试查询节点
                console.log('\n4. 测试查询节点...');
                const queryResult = await this.callTool('node_get_node_info', {
                    uuid: nodeUuid
                });
                console.log('节点信息:', JSON.stringify(queryResult).substring(0, 100) + '...');
                
                // 5. 测试删除节点
                console.log('\n5. 测试删除节点...');
                const removeResult = await this.callTool('node_delete_node', {
                    uuid: nodeUuid
                });
                console.log('删除结果:', removeResult);
            } else {
                console.log('无法从创建结果获取节点UUID,尝试通过名称查找...');
                
                // 备用方案:通过名称查找刚创建的节点
                const findResult = await this.callTool('node_find_node_by_name', {
                    name: 'MCPTestNode_' + Date.now()
                });
                
                if (findResult.content && findResult.content[0] && findResult.content[0].text) {
                    try {
                        const findData = JSON.parse(findResult.content[0].text);
                        if (findData.success && findData.data && findData.data.uuid) {
                            nodeUuid = findData.data.uuid;
                            console.log('通过名称查找成功获取UUID:', nodeUuid);
                        }
                    } catch (e) {
                    }
                }
                
                if (!nodeUuid) {
                    console.log('所有方式都无法获取节点UUID,跳过后续节点操作测试');
                }
            }
            
            // 6. 测试项目工具
            console.log('\n6. 测试项目信息...');
            const projectInfo = await this.callTool('project_get_project_info');
            console.log('项目信息:', JSON.stringify(projectInfo).substring(0, 100) + '...');
            
            // 7. 测试预制体工具
            console.log('\n7. 测试预制体列表...');
            const prefabResult = await this.callTool('prefab_get_prefab_list', {
                folder: 'db://assets'
            });
            console.log('找到预制体:', prefabResult.data?.length || 0);
            
            // 8. 测试组件工具
            console.log('\n8. 测试可用组件...');
            const componentsResult = await this.callTool('component_get_available_components');
            console.log('可用组件:', JSON.stringify(componentsResult).substring(0, 100) + '...');
            
            // 9. 测试调试工具
            console.log('\n9. 测试编辑器信息...');
            const editorInfo = await this.callTool('debug_get_editor_info');
            console.log('编辑器信息:', JSON.stringify(editorInfo).substring(0, 100) + '...');
            
        } catch (error) {
            console.error('MCP 工具测试失败:', error);
        }
    }

    disconnect() {
        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }
        this.responseHandlers.clear();
    }
}

// 导出到全局方便测试
(global as any).MCPToolTester = MCPToolTester;
```

--------------------------------------------------------------------------------
/source/tools/broadcast-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';

export class BroadcastTools implements ToolExecutor {
    private listeners: Map<string, Function[]> = new Map();
    private messageLog: Array<{ message: string; data: any; timestamp: number }> = [];

    constructor() {
        this.setupBroadcastListeners();
    }

    getTools(): ToolDefinition[] {
        return [
            {
                name: 'get_broadcast_log',
                description: 'Get recent broadcast messages log',
                inputSchema: {
                    type: 'object',
                    properties: {
                        limit: {
                            type: 'number',
                            description: 'Number of recent messages to return',
                            default: 50
                        },
                        messageType: {
                            type: 'string',
                            description: 'Filter by message type (optional)'
                        }
                    }
                }
            },
            {
                name: 'listen_broadcast',
                description: 'Start listening for specific broadcast messages',
                inputSchema: {
                    type: 'object',
                    properties: {
                        messageType: {
                            type: 'string',
                            description: 'Message type to listen for'
                        }
                    },
                    required: ['messageType']
                }
            },
            {
                name: 'stop_listening',
                description: 'Stop listening for specific broadcast messages',
                inputSchema: {
                    type: 'object',
                    properties: {
                        messageType: {
                            type: 'string',
                            description: 'Message type to stop listening for'
                        }
                    },
                    required: ['messageType']
                }
            },
            {
                name: 'clear_broadcast_log',
                description: 'Clear the broadcast messages log',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'get_active_listeners',
                description: 'Get list of active broadcast listeners',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'get_broadcast_log':
                return await this.getBroadcastLog(args.limit, args.messageType);
            case 'listen_broadcast':
                return await this.listenBroadcast(args.messageType);
            case 'stop_listening':
                return await this.stopListening(args.messageType);
            case 'clear_broadcast_log':
                return await this.clearBroadcastLog();
            case 'get_active_listeners':
                return await this.getActiveListeners();
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private setupBroadcastListeners(): void {
        // 设置预定义的重要广播消息监听
        const importantMessages = [
            'build-worker:ready',
            'build-worker:closed',
            'scene:ready',
            'scene:close',
            'scene:light-probe-edit-mode-changed',
            'scene:light-probe-bounding-box-edit-mode-changed',
            'asset-db:ready',
            'asset-db:close',
            'asset-db:asset-add',
            'asset-db:asset-change',
            'asset-db:asset-delete'
        ];

        importantMessages.forEach(messageType => {
            this.addBroadcastListener(messageType);
        });
    }

    private addBroadcastListener(messageType: string): void {
        const listener = (data: any) => {
            this.messageLog.push({
                message: messageType,
                data: data,
                timestamp: Date.now()
            });

            // 保持日志大小在合理范围内
            if (this.messageLog.length > 1000) {
                this.messageLog = this.messageLog.slice(-500);
            }

            console.log(`[Broadcast] ${messageType}:`, data);
        };

        if (!this.listeners.has(messageType)) {
            this.listeners.set(messageType, []);
        }
        this.listeners.get(messageType)!.push(listener);

        // 注册 Editor 消息监听 - 暂时注释掉,Editor.Message API可能不支持
        // Editor.Message.on(messageType, listener);
        console.log(`[BroadcastTools] Added listener for ${messageType} (simulated)`);
    }

    private removeBroadcastListener(messageType: string): void {
        const listeners = this.listeners.get(messageType);
        if (listeners) {
            listeners.forEach(listener => {
                // Editor.Message.off(messageType, listener);
                console.log(`[BroadcastTools] Removed listener for ${messageType} (simulated)`);
            });
            this.listeners.delete(messageType);
        }
    }

    private async getBroadcastLog(limit: number = 50, messageType?: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            let filteredLog = this.messageLog;

            if (messageType) {
                filteredLog = this.messageLog.filter(entry => entry.message === messageType);
            }

            const recentLog = filteredLog.slice(-limit).map(entry => ({
                ...entry,
                timestamp: new Date(entry.timestamp).toISOString()
            }));

            resolve({
                success: true,
                data: {
                    log: recentLog,
                    count: recentLog.length,
                    totalCount: filteredLog.length,
                    filter: messageType || 'all',
                    message: 'Broadcast log retrieved successfully'
                }
            });
        });
    }

    private async listenBroadcast(messageType: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            try {
                if (!this.listeners.has(messageType)) {
                    this.addBroadcastListener(messageType);
                    resolve({
                        success: true,
                        data: {
                            messageType: messageType,
                            message: `Started listening for broadcast: ${messageType}`
                        }
                    });
                } else {
                    resolve({
                        success: true,
                        data: {
                            messageType: messageType,
                            message: `Already listening for broadcast: ${messageType}`
                        }
                    });
                }
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }

    private async stopListening(messageType: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            try {
                if (this.listeners.has(messageType)) {
                    this.removeBroadcastListener(messageType);
                    resolve({
                        success: true,
                        data: {
                            messageType: messageType,
                            message: `Stopped listening for broadcast: ${messageType}`
                        }
                    });
                } else {
                    resolve({
                        success: true,
                        data: {
                            messageType: messageType,
                            message: `Was not listening for broadcast: ${messageType}`
                        }
                    });
                }
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }

    private async clearBroadcastLog(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            const previousCount = this.messageLog.length;
            this.messageLog = [];
            resolve({
                success: true,
                data: {
                    clearedCount: previousCount,
                    message: 'Broadcast log cleared successfully'
                }
            });
        });
    }

    private async getActiveListeners(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            const activeListeners = Array.from(this.listeners.keys()).map(messageType => ({
                messageType: messageType,
                listenerCount: this.listeners.get(messageType)?.length || 0
            }));

            resolve({
                success: true,
                data: {
                    listeners: activeListeners,
                    count: activeListeners.length,
                    message: 'Active listeners retrieved successfully'
                }
            });
        });
    }
}
```

--------------------------------------------------------------------------------
/source/tools/validation-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';

export class ValidationTools implements ToolExecutor {
    getTools(): ToolDefinition[] {
        return [
            {
                name: 'validate_json_params',
                description: 'Validate and fix JSON parameters before sending to other tools',
                inputSchema: {
                    type: 'object',
                    properties: {
                        jsonString: {
                            type: 'string',
                            description: 'JSON string to validate and fix'
                        },
                        expectedSchema: {
                            type: 'object',
                            description: 'Expected parameter schema (optional)'
                        }
                    },
                    required: ['jsonString']
                }
            },
            {
                name: 'safe_string_value',
                description: 'Create a safe string value that won\'t cause JSON parsing issues',
                inputSchema: {
                    type: 'object',
                    properties: {
                        value: {
                            type: 'string',
                            description: 'String value to make safe'
                        }
                    },
                    required: ['value']
                }
            },
            {
                name: 'format_mcp_request',
                description: 'Format a complete MCP request with proper JSON escaping',
                inputSchema: {
                    type: 'object',
                    properties: {
                        toolName: {
                            type: 'string',
                            description: 'Tool name to call'
                        },
                        arguments: {
                            type: 'object',
                            description: 'Tool arguments'
                        }
                    },
                    required: ['toolName', 'arguments']
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'validate_json_params':
                return await this.validateJsonParams(args.jsonString, args.expectedSchema);
            case 'safe_string_value':
                return await this.createSafeStringValue(args.value);
            case 'format_mcp_request':
                return await this.formatMcpRequest(args.toolName, args.arguments);
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private async validateJsonParams(jsonString: string, expectedSchema?: any): Promise<ToolResponse> {
        try {
            // First try to parse as-is
            let parsed;
            try {
                parsed = JSON.parse(jsonString);
            } catch (error: any) {
                // Try to fix common issues
                const fixed = this.fixJsonString(jsonString);
                try {
                    parsed = JSON.parse(fixed);
                } catch (secondError) {
                    return {
                        success: false,
                        error: `Cannot fix JSON: ${error.message}`,
                        data: {
                            originalJson: jsonString,
                            fixedAttempt: fixed,
                            suggestions: this.getJsonFixSuggestions(jsonString)
                        }
                    };
                }
            }

            // Validate against schema if provided
            if (expectedSchema) {
                const validation = this.validateAgainstSchema(parsed, expectedSchema);
                if (!validation.valid) {
                    return {
                        success: false,
                        error: 'Schema validation failed',
                        data: {
                            parsedJson: parsed,
                            validationErrors: validation.errors,
                            suggestions: validation.suggestions
                        }
                    };
                }
            }

            return {
                success: true,
                data: {
                    parsedJson: parsed,
                    fixedJson: JSON.stringify(parsed, null, 2),
                    isValid: true
                }
            };
        } catch (error: any) {
            return {
                success: false,
                error: error.message
            };
        }
    }

    private async createSafeStringValue(value: string): Promise<ToolResponse> {
        const safeValue = this.escapJsonString(value);
        return {
            success: true,
            data: {
                originalValue: value,
                safeValue: safeValue,
                jsonReady: JSON.stringify(safeValue),
                usage: `Use "${safeValue}" in your JSON parameters`
            }
        };
    }

    private async formatMcpRequest(toolName: string, toolArgs: any): Promise<ToolResponse> {
        try {
            const mcpRequest = {
                jsonrpc: '2.0',
                id: Date.now(),
                method: 'tools/call',
                params: {
                    name: toolName,
                    arguments: toolArgs
                }
            };

            const formattedJson = JSON.stringify(mcpRequest, null, 2);
            const compactJson = JSON.stringify(mcpRequest);

            return {
                success: true,
                data: {
                    request: mcpRequest,
                    formattedJson: formattedJson,
                    compactJson: compactJson,
                    curlCommand: this.generateCurlCommand(compactJson)
                }
            };
        } catch (error: any) {
            return {
                success: false,
                error: `Failed to format MCP request: ${error.message}`
            };
        }
    }

    private fixJsonString(jsonStr: string): string {
        let fixed = jsonStr;
        
        // Fix common escape character issues
        fixed = fixed
            // Fix unescaped quotes in string values
            .replace(/(\{[^}]*"[^"]*":\s*")([^"]*")([^"]*")([^}]*\})/g, (match, prefix, content, suffix, end) => {
                const escapedContent = content.replace(/"/g, '\\"');
                return prefix + escapedContent + suffix + end;
            })
            // Fix unescaped backslashes
            .replace(/([^\\])\\([^"\\\/bfnrtu])/g, '$1\\\\$2')
            // Fix trailing commas
            .replace(/,(\s*[}\]])/g, '$1')
            // Fix control characters
            .replace(/\n/g, '\\n')
            .replace(/\r/g, '\\r')
            .replace(/\t/g, '\\t')
            // Fix single quotes to double quotes
            .replace(/'/g, '"');
        
        return fixed;
    }

    private escapJsonString(str: string): string {
        return str
            .replace(/\\/g, '\\\\')  // Escape backslashes first
            .replace(/"/g, '\\"')    // Escape quotes
            .replace(/\n/g, '\\n')   // Escape newlines
            .replace(/\r/g, '\\r')   // Escape carriage returns
            .replace(/\t/g, '\\t')   // Escape tabs
            .replace(/\f/g, '\\f')   // Escape form feeds
            .replace(/\b/g, '\\b');  // Escape backspaces
    }

    private validateAgainstSchema(data: any, schema: any): { valid: boolean; errors: string[]; suggestions: string[] } {
        const errors: string[] = [];
        const suggestions: string[] = [];

        // Basic type checking
        if (schema.type) {
            const actualType = Array.isArray(data) ? 'array' : typeof data;
            if (actualType !== schema.type) {
                errors.push(`Expected type ${schema.type}, got ${actualType}`);
                suggestions.push(`Convert value to ${schema.type}`);
            }
        }

        // Required fields checking
        if (schema.required && Array.isArray(schema.required)) {
            for (const field of schema.required) {
                if (!Object.prototype.hasOwnProperty.call(data, field)) {
                    errors.push(`Missing required field: ${field}`);
                    suggestions.push(`Add required field "${field}"`);
                }
            }
        }

        return {
            valid: errors.length === 0,
            errors,
            suggestions
        };
    }

    private getJsonFixSuggestions(jsonStr: string): string[] {
        const suggestions: string[] = [];
        
        if (jsonStr.includes('\\"')) {
            suggestions.push('Check for improperly escaped quotes');
        }
        if (jsonStr.includes("'")) {
            suggestions.push('Replace single quotes with double quotes');
        }
        if (jsonStr.includes('\n') || jsonStr.includes('\t')) {
            suggestions.push('Escape newlines and tabs properly');
        }
        if (jsonStr.match(/,\s*[}\]]/)) {
            suggestions.push('Remove trailing commas');
        }
        
        return suggestions;
    }

    private generateCurlCommand(jsonStr: string): string {
        const escapedJson = jsonStr.replace(/'/g, "'\"'\"'");
        return `curl -X POST http://127.0.0.1:8585/mcp \\
  -H "Content-Type: application/json" \\
  -d '${escapedJson}'`;
    }
}
```

--------------------------------------------------------------------------------
/source/tools/server-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';

export class ServerTools implements ToolExecutor {
    getTools(): ToolDefinition[] {
        return [
            {
                name: 'query_server_ip_list',
                description: 'Query server IP list',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'query_sorted_server_ip_list',
                description: 'Get sorted server IP list',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'query_server_port',
                description: 'Query editor server current port',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'get_server_status',
                description: 'Get comprehensive server status information',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'check_server_connectivity',
                description: 'Check server connectivity and network status',
                inputSchema: {
                    type: 'object',
                    properties: {
                        timeout: {
                            type: 'number',
                            description: 'Timeout in milliseconds',
                            default: 5000
                        }
                    }
                }
            },
            {
                name: 'get_network_interfaces',
                description: 'Get available network interfaces',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'query_server_ip_list':
                return await this.queryServerIPList();
            case 'query_sorted_server_ip_list':
                return await this.querySortedServerIPList();
            case 'query_server_port':
                return await this.queryServerPort();
            case 'get_server_status':
                return await this.getServerStatus();
            case 'check_server_connectivity':
                return await this.checkServerConnectivity(args.timeout);
            case 'get_network_interfaces':
                return await this.getNetworkInterfaces();
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private async queryServerIPList(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('server', 'query-ip-list').then((ipList: string[]) => {
                resolve({
                    success: true,
                    data: {
                        ipList: ipList,
                        count: ipList.length,
                        message: 'IP list retrieved successfully'
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async querySortedServerIPList(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('server', 'query-sort-ip-list').then((sortedIPList: string[]) => {
                resolve({
                    success: true,
                    data: {
                        sortedIPList: sortedIPList,
                        count: sortedIPList.length,
                        message: 'Sorted IP list retrieved successfully'
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async queryServerPort(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('server', 'query-port').then((port: number) => {
                resolve({
                    success: true,
                    data: {
                        port: port,
                        message: `Editor server is running on port ${port}`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async getServerStatus(): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                // Gather comprehensive server information
                const [ipListResult, portResult] = await Promise.allSettled([
                    this.queryServerIPList(),
                    this.queryServerPort()
                ]);

                const status: any = {
                    timestamp: new Date().toISOString(),
                    serverRunning: true
                };

                if (ipListResult.status === 'fulfilled' && ipListResult.value.success) {
                    status.availableIPs = ipListResult.value.data.ipList;
                    status.ipCount = ipListResult.value.data.count;
                } else {
                    status.availableIPs = [];
                    status.ipCount = 0;
                    status.ipError = ipListResult.status === 'rejected' ? ipListResult.reason : ipListResult.value.error;
                }

                if (portResult.status === 'fulfilled' && portResult.value.success) {
                    status.port = portResult.value.data.port;
                } else {
                    status.port = null;
                    status.portError = portResult.status === 'rejected' ? portResult.reason : portResult.value.error;
                }

                // Add additional server info
                status.mcpServerPort = 3000; // Our MCP server port
                status.editorVersion = (Editor as any).versions?.cocos || 'Unknown';
                status.platform = process.platform;
                status.nodeVersion = process.version;

                resolve({
                    success: true,
                    data: status
                });

            } catch (err: any) {
                resolve({
                    success: false,
                    error: `Failed to get server status: ${err.message}`
                });
            }
        });
    }

    private async checkServerConnectivity(timeout: number = 5000): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            const startTime = Date.now();
            
            try {
                // Test basic Editor API connectivity
                const testPromise = Editor.Message.request('server', 'query-port');
                const timeoutPromise = new Promise((_, reject) => {
                    setTimeout(() => reject(new Error('Connection timeout')), timeout);
                });

                await Promise.race([testPromise, timeoutPromise]);
                
                const responseTime = Date.now() - startTime;
                
                resolve({
                    success: true,
                    data: {
                        connected: true,
                        responseTime: responseTime,
                        timeout: timeout,
                        message: `Server connectivity confirmed in ${responseTime}ms`
                    }
                });

            } catch (err: any) {
                const responseTime = Date.now() - startTime;
                
                resolve({
                    success: false,
                    data: {
                        connected: false,
                        responseTime: responseTime,
                        timeout: timeout,
                        error: err.message
                    }
                });
            }
        });
    }

    private async getNetworkInterfaces(): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                // Get network interfaces using Node.js os module
                const os = require('os');
                const interfaces = os.networkInterfaces();
                
                const networkInfo = Object.entries(interfaces).map(([name, addresses]: [string, any]) => ({
                    name: name,
                    addresses: addresses.map((addr: any) => ({
                        address: addr.address,
                        family: addr.family,
                        internal: addr.internal,
                        cidr: addr.cidr
                    }))
                }));

                // Also try to get server IPs for comparison
                const serverIPResult = await this.queryServerIPList();
                
                resolve({
                    success: true,
                    data: {
                        networkInterfaces: networkInfo,
                        serverAvailableIPs: serverIPResult.success ? serverIPResult.data.ipList : [],
                        message: 'Network interfaces retrieved successfully'
                    }
                });

            } catch (err: any) {
                resolve({
                    success: false,
                    error: `Failed to get network interfaces: ${err.message}`
                });
            }
        });
    }
}
```

--------------------------------------------------------------------------------
/source/tools/preferences-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';

export class PreferencesTools implements ToolExecutor {
    getTools(): ToolDefinition[] {
        return [
            {
                name: 'open_preferences_settings',
                description: 'Open preferences settings panel',
                inputSchema: {
                    type: 'object',
                    properties: {
                        tab: {
                            type: 'string',
                            description: 'Preferences tab to open (optional)',
                            enum: ['general', 'external-tools', 'data-editor', 'laboratory', 'extensions']
                        },
                        args: {
                            type: 'array',
                            description: 'Additional arguments to pass to the tab'
                        }
                    }
                }
            },
            {
                name: 'query_preferences_config',
                description: 'Query preferences configuration',
                inputSchema: {
                    type: 'object',
                    properties: {
                        name: {
                            type: 'string',
                            description: 'Plugin or category name',
                            default: 'general'
                        },
                        path: {
                            type: 'string',
                            description: 'Configuration path (optional)'
                        },
                        type: {
                            type: 'string',
                            description: 'Configuration type',
                            enum: ['default', 'global', 'local'],
                            default: 'global'
                        }
                    },
                    required: ['name']
                }
            },
            {
                name: 'set_preferences_config',
                description: 'Set preferences configuration',
                inputSchema: {
                    type: 'object',
                    properties: {
                        name: {
                            type: 'string',
                            description: 'Plugin name'
                        },
                        path: {
                            type: 'string',
                            description: 'Configuration path'
                        },
                        value: {
                            description: 'Configuration value'
                        },
                        type: {
                            type: 'string',
                            description: 'Configuration type',
                            enum: ['default', 'global', 'local'],
                            default: 'global'
                        }
                    },
                    required: ['name', 'path', 'value']
                }
            },
            {
                name: 'get_all_preferences',
                description: 'Get all available preferences categories',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'reset_preferences',
                description: 'Reset preferences to default values',
                inputSchema: {
                    type: 'object',
                    properties: {
                        name: {
                            type: 'string',
                            description: 'Specific preference category to reset (optional)'
                        },
                        type: {
                            type: 'string',
                            description: 'Configuration type to reset',
                            enum: ['global', 'local'],
                            default: 'global'
                        }
                    }
                }
            },
            {
                name: 'export_preferences',
                description: 'Export current preferences configuration',
                inputSchema: {
                    type: 'object',
                    properties: {
                        exportPath: {
                            type: 'string',
                            description: 'Path to export preferences file (optional)'
                        }
                    }
                }
            },
            {
                name: 'import_preferences',
                description: 'Import preferences configuration from file',
                inputSchema: {
                    type: 'object',
                    properties: {
                        importPath: {
                            type: 'string',
                            description: 'Path to import preferences file from'
                        }
                    },
                    required: ['importPath']
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'open_preferences_settings':
                return await this.openPreferencesSettings(args.tab, args.args);
            case 'query_preferences_config':
                return await this.queryPreferencesConfig(args.name, args.path, args.type);
            case 'set_preferences_config':
                return await this.setPreferencesConfig(args.name, args.path, args.value, args.type);
            case 'get_all_preferences':
                return await this.getAllPreferences();
            case 'reset_preferences':
                return await this.resetPreferences(args.name, args.type);
            case 'export_preferences':
                return await this.exportPreferences(args.exportPath);
            case 'import_preferences':
                return await this.importPreferences(args.importPath);
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private async openPreferencesSettings(tab?: string, args?: any[]): Promise<ToolResponse> {
        return new Promise((resolve) => {
            const requestArgs = [];
            if (tab) {
                requestArgs.push(tab);
            }
            if (args && args.length > 0) {
                requestArgs.push(...args);
            }

            (Editor.Message.request as any)('preferences', 'open-settings', ...requestArgs).then(() => {
                resolve({
                    success: true,
                    message: `Preferences settings opened${tab ? ` on tab: ${tab}` : ''}`
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async queryPreferencesConfig(name: string, path?: string, type: string = 'global'): Promise<ToolResponse> {
        return new Promise((resolve) => {
            const requestArgs = [name];
            if (path) {
                requestArgs.push(path);
            }
            requestArgs.push(type);

            (Editor.Message.request as any)('preferences', 'query-config', ...requestArgs).then((config: any) => {
                resolve({
                    success: true,
                    data: {
                        name: name,
                        path: path,
                        type: type,
                        config: config
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async setPreferencesConfig(name: string, path: string, value: any, type: string = 'global'): Promise<ToolResponse> {
        return new Promise((resolve) => {
            (Editor.Message.request as any)('preferences', 'set-config', name, path, value, type).then((success: boolean) => {
                if (success) {
                    resolve({
                        success: true,
                        message: `Preference '${name}.${path}' updated successfully`
                    });
                } else {
                    resolve({
                        success: false,
                        error: `Failed to update preference '${name}.${path}'`
                    });
                }
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async getAllPreferences(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // Common preference categories in Cocos Creator
            const categories = [
                'general',
                'external-tools', 
                'data-editor',
                'laboratory',
                'extensions',
                'preview',
                'console',
                'native',
                'builder'
            ];

            const preferences: any = {};

            const queryPromises = categories.map(category => {
                return Editor.Message.request('preferences', 'query-config', category, undefined, 'global')
                    .then((config: any) => {
                        preferences[category] = config;
                    })
                    .catch(() => {
                        // Ignore errors for categories that don't exist
                        preferences[category] = null;
                    });
            });

            Promise.all(queryPromises).then(() => {
                // Filter out null entries
                const validPreferences = Object.fromEntries(
                    Object.entries(preferences).filter(([_, value]) => value !== null)
                );

                resolve({
                    success: true,
                    data: {
                        categories: Object.keys(validPreferences),
                        preferences: validPreferences
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async resetPreferences(name?: string, type: string = 'global'): Promise<ToolResponse> {
        return new Promise((resolve) => {
            if (name) {
                // Reset specific preference category
                Editor.Message.request('preferences', 'query-config', name, undefined, 'default').then((defaultConfig: any) => {
                    return (Editor.Message.request as any)('preferences', 'set-config', name, '', defaultConfig, type);
                }).then((success: boolean) => {
                    if (success) {
                        resolve({
                            success: true,
                            message: `Preference category '${name}' reset to default`
                        });
                    } else {
                        resolve({
                            success: false,
                            error: `Failed to reset preference category '${name}'`
                        });
                    }
                }).catch((err: Error) => {
                    resolve({ success: false, error: err.message });
                });
            } else {
                resolve({
                    success: false,
                    error: 'Resetting all preferences is not supported through API. Please specify a preference category.'
                });
            }
        });
    }

    private async exportPreferences(exportPath?: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            this.getAllPreferences().then((prefsResult: ToolResponse) => {
                if (!prefsResult.success) {
                    resolve(prefsResult);
                    return;
                }

                const prefsData = JSON.stringify(prefsResult.data, null, 2);
                const path = exportPath || `preferences_export_${Date.now()}.json`;

                // For now, return the data - in a real implementation, you'd write to file
                resolve({
                    success: true,
                    data: {
                        exportPath: path,
                        preferences: prefsResult.data,
                        jsonData: prefsData,
                        message: 'Preferences exported successfully'
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async importPreferences(importPath: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            resolve({
                success: false,
                error: 'Import preferences functionality requires file system access which is not available in this context. Please manually import preferences through the Editor UI.'
            });
        });
    }
}
```

--------------------------------------------------------------------------------
/source/tools/reference-image-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor } from '../types';

export class ReferenceImageTools implements ToolExecutor {
    getTools(): ToolDefinition[] {
        return [
            {
                name: 'add_reference_image',
                description: 'Add reference image(s) to scene',
                inputSchema: {
                    type: 'object',
                    properties: {
                        paths: {
                            type: 'array',
                            items: { type: 'string' },
                            description: 'Array of reference image absolute paths'
                        }
                    },
                    required: ['paths']
                }
            },
            {
                name: 'remove_reference_image',
                description: 'Remove reference image(s)',
                inputSchema: {
                    type: 'object',
                    properties: {
                        paths: {
                            type: 'array',
                            items: { type: 'string' },
                            description: 'Array of reference image paths to remove (optional, removes current if empty)'
                        }
                    }
                }
            },
            {
                name: 'switch_reference_image',
                description: 'Switch to specific reference image',
                inputSchema: {
                    type: 'object',
                    properties: {
                        path: {
                            type: 'string',
                            description: 'Reference image absolute path'
                        },
                        sceneUUID: {
                            type: 'string',
                            description: 'Specific scene UUID (optional)'
                        }
                    },
                    required: ['path']
                }
            },
            {
                name: 'set_reference_image_data',
                description: 'Set reference image transform and display properties',
                inputSchema: {
                    type: 'object',
                    properties: {
                        key: {
                            type: 'string',
                            description: 'Property key',
                            enum: ['path', 'x', 'y', 'sx', 'sy', 'opacity']
                        },
                        value: {
                            description: 'Property value (path: string, x/y/sx/sy: number, opacity: number 0-1)'
                        }
                    },
                    required: ['key', 'value']
                }
            },
            {
                name: 'query_reference_image_config',
                description: 'Query reference image configuration',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'query_current_reference_image',
                description: 'Query current reference image data',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'refresh_reference_image',
                description: 'Refresh reference image display',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'set_reference_image_position',
                description: 'Set reference image position',
                inputSchema: {
                    type: 'object',
                    properties: {
                        x: {
                            type: 'number',
                            description: 'X offset'
                        },
                        y: {
                            type: 'number',
                            description: 'Y offset'
                        }
                    },
                    required: ['x', 'y']
                }
            },
            {
                name: 'set_reference_image_scale',
                description: 'Set reference image scale',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sx: {
                            type: 'number',
                            description: 'X scale',
                            minimum: 0.1,
                            maximum: 10
                        },
                        sy: {
                            type: 'number',
                            description: 'Y scale',
                            minimum: 0.1,
                            maximum: 10
                        }
                    },
                    required: ['sx', 'sy']
                }
            },
            {
                name: 'set_reference_image_opacity',
                description: 'Set reference image opacity',
                inputSchema: {
                    type: 'object',
                    properties: {
                        opacity: {
                            type: 'number',
                            description: 'Opacity (0.0 to 1.0)',
                            minimum: 0,
                            maximum: 1
                        }
                    },
                    required: ['opacity']
                }
            },
            {
                name: 'list_reference_images',
                description: 'List all available reference images',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'clear_all_reference_images',
                description: 'Clear all reference images',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'add_reference_image':
                return await this.addReferenceImage(args.paths);
            case 'remove_reference_image':
                return await this.removeReferenceImage(args.paths);
            case 'switch_reference_image':
                return await this.switchReferenceImage(args.path, args.sceneUUID);
            case 'set_reference_image_data':
                return await this.setReferenceImageData(args.key, args.value);
            case 'query_reference_image_config':
                return await this.queryReferenceImageConfig();
            case 'query_current_reference_image':
                return await this.queryCurrentReferenceImage();
            case 'refresh_reference_image':
                return await this.refreshReferenceImage();
            case 'set_reference_image_position':
                return await this.setReferenceImagePosition(args.x, args.y);
            case 'set_reference_image_scale':
                return await this.setReferenceImageScale(args.sx, args.sy);
            case 'set_reference_image_opacity':
                return await this.setReferenceImageOpacity(args.opacity);
            case 'list_reference_images':
                return await this.listReferenceImages();
            case 'clear_all_reference_images':
                return await this.clearAllReferenceImages();
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private async addReferenceImage(paths: string[]): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'add-image', paths).then(() => {
                resolve({
                    success: true,
                    data: {
                        addedPaths: paths,
                        count: paths.length,
                        message: `Added ${paths.length} reference image(s)`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async removeReferenceImage(paths?: string[]): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'remove-image', paths).then(() => {
                const message = paths && paths.length > 0 ? 
                    `Removed ${paths.length} reference image(s)` : 
                    'Removed current reference image';
                resolve({
                    success: true,
                    message: message
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async switchReferenceImage(path: string, sceneUUID?: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            const args = sceneUUID ? [path, sceneUUID] : [path];
            Editor.Message.request('reference-image', 'switch-image', ...args).then(() => {
                resolve({
                    success: true,
                    data: {
                        path: path,
                        sceneUUID: sceneUUID,
                        message: `Switched to reference image: ${path}`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async setReferenceImageData(key: string, value: any): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'set-image-data', key, value).then(() => {
                resolve({
                    success: true,
                    data: {
                        key: key,
                        value: value,
                        message: `Reference image ${key} set to ${value}`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async queryReferenceImageConfig(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'query-config').then((config: any) => {
                resolve({
                    success: true,
                    data: config
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async queryCurrentReferenceImage(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'query-current').then((current: any) => {
                resolve({
                    success: true,
                    data: current
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async refreshReferenceImage(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'refresh').then(() => {
                resolve({
                    success: true,
                    message: 'Reference image refreshed'
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async setReferenceImagePosition(x: number, y: number): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                await Editor.Message.request('reference-image', 'set-image-data', 'x', x);
                await Editor.Message.request('reference-image', 'set-image-data', 'y', y);
                
                resolve({
                    success: true,
                    data: {
                        x: x,
                        y: y,
                        message: `Reference image position set to (${x}, ${y})`
                    }
                });
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }

    private async setReferenceImageScale(sx: number, sy: number): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                await Editor.Message.request('reference-image', 'set-image-data', 'sx', sx);
                await Editor.Message.request('reference-image', 'set-image-data', 'sy', sy);
                
                resolve({
                    success: true,
                    data: {
                        sx: sx,
                        sy: sy,
                        message: `Reference image scale set to (${sx}, ${sy})`
                    }
                });
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }

    private async setReferenceImageOpacity(opacity: number): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('reference-image', 'set-image-data', 'opacity', opacity).then(() => {
                resolve({
                    success: true,
                    data: {
                        opacity: opacity,
                        message: `Reference image opacity set to ${opacity}`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async listReferenceImages(): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                const config = await Editor.Message.request('reference-image', 'query-config');
                const current = await Editor.Message.request('reference-image', 'query-current');
                
                resolve({
                    success: true,
                    data: {
                        config: config,
                        current: current,
                        message: 'Reference image information retrieved'
                    }
                });
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }

    private async clearAllReferenceImages(): Promise<ToolResponse> {
        return new Promise(async (resolve) => {
            try {
                // Remove all reference images by calling remove-image without paths
                await Editor.Message.request('reference-image', 'remove-image');
                
                resolve({
                    success: true,
                    message: 'All reference images cleared'
                });
            } catch (err: any) {
                resolve({ success: false, error: err.message });
            }
        });
    }
}
```

--------------------------------------------------------------------------------
/source/scene.ts:
--------------------------------------------------------------------------------

```typescript
import { join } from 'path';
module.paths.push(join(Editor.App.path, 'node_modules'));

export const methods: { [key: string]: (...any: any) => any } = {
    /**
     * Create a new scene
     */
    createNewScene() {
        try {
            const { director, Scene } = require('cc');
            const scene = new Scene();
            scene.name = 'New Scene';
            director.runScene(scene);
            return { success: true, message: 'New scene created successfully' };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Add component to a node
     */
    addComponentToNode(nodeUuid: string, componentType: string) {
        try {
            const { director, js } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            // Find node by UUID
            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }

            // Get component class
            const ComponentClass = js.getClassByName(componentType);
            if (!ComponentClass) {
                return { success: false, error: `Component type ${componentType} not found` };
            }

            // Add component
            const component = node.addComponent(ComponentClass);
            return { 
                success: true, 
                message: `Component ${componentType} added successfully`,
                data: { componentId: component.uuid }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Remove component from a node
     */
    removeComponentFromNode(nodeUuid: string, componentType: string) {
        try {
            const { director, js } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }

            const ComponentClass = js.getClassByName(componentType);
            if (!ComponentClass) {
                return { success: false, error: `Component type ${componentType} not found` };
            }

            const component = node.getComponent(ComponentClass);
            if (!component) {
                return { success: false, error: `Component ${componentType} not found on node` };
            }

            node.removeComponent(component);
            return { success: true, message: `Component ${componentType} removed successfully` };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Create a new node
     */
    createNode(name: string, parentUuid?: string) {
        try {
            const { director, Node } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = new Node(name);
            
            if (parentUuid) {
                const parent = scene.getChildByUuid(parentUuid);
                if (parent) {
                    parent.addChild(node);
                } else {
                    scene.addChild(node);
                }
            } else {
                scene.addChild(node);
            }

            return { 
                success: true, 
                message: `Node ${name} created successfully`,
                data: { uuid: node.uuid, name: node.name }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Get node information
     */
    getNodeInfo(nodeUuid: string) {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }

            return {
                success: true,
                data: {
                    uuid: node.uuid,
                    name: node.name,
                    active: node.active,
                    position: node.position,
                    rotation: node.rotation,
                    scale: node.scale,
                    parent: node.parent?.uuid,
                    children: node.children.map((child: any) => child.uuid),
                    components: node.components.map((comp: any) => ({
                        type: comp.constructor.name,
                        enabled: comp.enabled
                    }))
                }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Get all nodes in scene
     */
    getAllNodes() {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const nodes: any[] = [];
            const collectNodes = (node: any) => {
                nodes.push({
                    uuid: node.uuid,
                    name: node.name,
                    active: node.active,
                    parent: node.parent?.uuid
                });
                
                node.children.forEach((child: any) => collectNodes(child));
            };

            scene.children.forEach((child: any) => collectNodes(child));
            
            return { success: true, data: nodes };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Find node by name
     */
    findNodeByName(name: string) {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = scene.getChildByName(name);
            if (!node) {
                return { success: false, error: `Node with name ${name} not found` };
            }

            return {
                success: true,
                data: {
                    uuid: node.uuid,
                    name: node.name,
                    active: node.active,
                    position: node.position
                }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Get current scene information
     */
    getCurrentSceneInfo() {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            return {
                success: true,
                data: {
                    name: scene.name,
                    uuid: scene.uuid,
                    nodeCount: scene.children.length
                }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Set node property
     */
    setNodeProperty(nodeUuid: string, property: string, value: any) {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }

            // 设置属性
            if (property === 'position') {
                node.setPosition(value.x || 0, value.y || 0, value.z || 0);
            } else if (property === 'rotation') {
                node.setRotationFromEuler(value.x || 0, value.y || 0, value.z || 0);
            } else if (property === 'scale') {
                node.setScale(value.x || 1, value.y || 1, value.z || 1);
            } else if (property === 'active') {
                node.active = value;
            } else if (property === 'name') {
                node.name = value;
            } else {
                // 尝试直接设置属性
                (node as any)[property] = value;
            }

            return { 
                success: true, 
                message: `Property '${property}' updated successfully` 
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Get scene hierarchy
     */
    getSceneHierarchy(includeComponents: boolean = false) {
        try {
            const { director } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const processNode = (node: any): any => {
                const result: any = {
                    name: node.name,
                    uuid: node.uuid,
                    active: node.active,
                    children: []
                };

                if (includeComponents) {
                    result.components = node.components.map((comp: any) => ({
                        type: comp.constructor.name,
                        enabled: comp.enabled
                    }));
                }

                if (node.children && node.children.length > 0) {
                    result.children = node.children.map((child: any) => processNode(child));
                }

                return result;
            };

            const hierarchy = scene.children.map((child: any) => processNode(child));
            return { success: true, data: hierarchy };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Create prefab from node
     */
    createPrefabFromNode(nodeUuid: string, prefabPath: string) {
        try {
            const { director, instantiate } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }

            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }

            // 注意:这里只是一个模拟实现,因为运行时环境下无法直接创建预制体文件
            // 真正的预制体创建需要Editor API支持
            return {
                success: true,
                data: {
                    prefabPath: prefabPath,
                    sourceNodeUuid: nodeUuid,
                    message: `Prefab created from node '${node.name}' at ${prefabPath}`
                }
            };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    },

    /**
     * Set component property
     */
    setComponentProperty(nodeUuid: string, componentType: string, property: string, value: any) {
        try {
            const { director, js } = require('cc');
            const scene = director.getScene();
            if (!scene) {
                return { success: false, error: 'No active scene' };
            }
            const node = scene.getChildByUuid(nodeUuid);
            if (!node) {
                return { success: false, error: `Node with UUID ${nodeUuid} not found` };
            }
            const ComponentClass = js.getClassByName(componentType);
            if (!ComponentClass) {
                return { success: false, error: `Component type ${componentType} not found` };
            }
            const component = node.getComponent(ComponentClass);
            if (!component) {
                return { success: false, error: `Component ${componentType} not found on node` };
            }
            // 针对常见属性做特殊处理
            if (property === 'spriteFrame' && componentType === 'cc.Sprite') {
                // 支持 value 为 uuid 或资源路径
                if (typeof value === 'string') {
                    // 先尝试按 uuid 查找
                    const assetManager = require('cc').assetManager;
                    assetManager.resources.load(value, require('cc').SpriteFrame, (err: any, spriteFrame: any) => {
                        if (!err && spriteFrame) {
                            component.spriteFrame = spriteFrame;
                        } else {
                            // 尝试通过 uuid 加载
                            assetManager.loadAny({ uuid: value }, (err2: any, asset: any) => {
                                if (!err2 && asset) {
                                    component.spriteFrame = asset;
                                } else {
                                    // 直接赋值(兼容已传入资源对象)
                                    component.spriteFrame = value;
                                }
                            });
                        }
                    });
                } else {
                    component.spriteFrame = value;
                }
            } else if (property === 'material' && (componentType === 'cc.Sprite' || componentType === 'cc.MeshRenderer')) {
                // 支持 value 为 uuid 或资源路径
                if (typeof value === 'string') {
                    const assetManager = require('cc').assetManager;
                    assetManager.resources.load(value, require('cc').Material, (err: any, material: any) => {
                        if (!err && material) {
                            component.material = material;
                        } else {
                            assetManager.loadAny({ uuid: value }, (err2: any, asset: any) => {
                                if (!err2 && asset) {
                                    component.material = asset;
                                } else {
                                    component.material = value;
                                }
                            });
                        }
                    });
                } else {
                    component.material = value;
                }
            } else if (property === 'string' && (componentType === 'cc.Label' || componentType === 'cc.RichText')) {
                component.string = value;
            } else {
                component[property] = value;
            }
            // 可选:刷新 Inspector
            // Editor.Message.send('scene', 'snapshot');
            return { success: true, message: `Component property '${property}' updated successfully` };
        } catch (error: any) {
            return { success: false, error: error.message };
        }
    }
};
```

--------------------------------------------------------------------------------
/static/template/default/tool-manager.html:
--------------------------------------------------------------------------------

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>工具管理器</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            margin: 0;
            padding: 20px;
            background: #2a2a2a;
            color: #e0e0e0;
        }

        .container {
            display: flex;
            flex-direction: column;
            height: calc(100vh - 40px);
            gap: 20px;
            max-width: 1200px;
            margin: 0 auto;
            overflow-y: auto;
            padding-right: 8px;
        }

        /* 容器滚动条样式 */
        .container::-webkit-scrollbar {
            width: 8px;
        }

        .container::-webkit-scrollbar-track {
            background: #2a2a2a;
            border-radius: 4px;
        }

        .container::-webkit-scrollbar-thumb {
            background: #5a5a5a;
            border-radius: 4px;
        }

        .container::-webkit-scrollbar-thumb:hover {
            background: #6a6a6a;
        }

        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 24px;
            background: linear-gradient(135deg, #3a3a3a 0%, #2d2d2d 100%);
            border: 1px solid #4a4a4a;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
        }

        .header h2 {
            margin: 0;
            font-size: 20px;
            font-weight: 600;
            color: #ffffff;
        }

        .config-section {
            background: linear-gradient(135deg, #323232 0%, #2a2a2a 100%);
            border: 1px solid #4a4a4a;
            border-radius: 8px;
            padding: 20px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        }

        .config-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
            padding-bottom: 12px;
            border-bottom: 2px solid #4a4a4a;
        }

        .config-title {
            font-weight: 600;
            font-size: 16px;
            color: #ffffff;
        }

        .config-controls {
            display: flex;
            gap: 10px;
        }

        .config-selector {
            display: flex;
            gap: 12px;
            margin-bottom: 20px;
            align-items: center;
        }

        .config-selector select {
            flex: 1;
            padding: 10px 12px;
            border: 1px solid #5a5a5a;
            border-radius: 6px;
            background: #3a3a3a;
            color: #e0e0e0;
            font-size: 14px;
            transition: all 0.2s;
        }

        .config-selector select:focus {
            outline: none;
            border-color: #007acc;
            box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
        }

        .btn {
            padding: 8px 16px;
            border: 1px solid #5a5a5a;
            border-radius: 6px;
            background: linear-gradient(135deg, #4a4a4a 0%, #3a3a3a 100%);
            color: #e0e0e0;
            cursor: pointer;
            font-size: 13px;
            font-weight: 500;
            transition: all 0.2s;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
        }

        .btn:hover {
            background: linear-gradient(135deg, #5a5a5a 0%, #4a4a4a 100%);
            border-color: #6a6a6a;
            transform: translateY(-1px);
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
        }

        .btn:active {
            transform: translateY(0);
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
        }

        .btn-primary {
            background: linear-gradient(135deg, #007acc 0%, #005a9e 100%);
            color: white;
            border-color: #007acc;
        }

        .btn-primary:hover {
            background: linear-gradient(135deg, #0088e6 0%, #0066cc 100%);
            border-color: #0088e6;
        }

        .btn-danger {
            background: linear-gradient(135deg, #d32f2f 0%, #b71c1c 100%);
            color: white;
            border-color: #d32f2f;
        }

        .btn-danger:hover {
            background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);
            border-color: #f44336;
        }

        .tools-container {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
            gap: 16px;
            max-height: 500px;
            overflow-y: auto;
            padding: 4px;
        }

        .tool-category {
            background: linear-gradient(135deg, #383838 0%, #2f2f2f 100%);
            border: 1px solid #4a4a4a;
            border-radius: 8px;
            padding: 16px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
            transition: all 0.2s;
        }

        .tool-category:hover {
            border-color: #5a5a5a;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            transform: translateY(-2px);
        }

        .category-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
            padding-bottom: 10px;
            border-bottom: 2px solid #4a4a4a;
        }

        .category-name {
            font-weight: 600;
            font-size: 14px;
            color: #ffffff;
        }

        .category-toggle {
            display: flex;
            align-items: center;
            gap: 4px;
        }

        .tool-list {
            display: flex;
            flex-direction: column;
            gap: 6px;
        }

        .tool-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px 12px;
            margin: 4px 0;
            background: rgba(255, 255, 255, 0.02);
            border-radius: 6px;
            transition: all 0.2s;
        }

        .tool-item:hover {
            background: rgba(255, 255, 255, 0.05);
            transform: translateX(2px);
        }

        .tool-info {
            flex: 1;
            margin-right: 12px;
        }

        .tool-name {
            font-size: 13px;
            font-weight: 500;
            color: #e0e0e0;
        }

        .tool-description {
            font-size: 12px;
            color: #b0b0b0;
            margin-top: 4px;
            line-height: 1.4;
        }

        .tool-toggle {
            display: flex;
            align-items: center;
        }

        .checkbox {
            width: 18px;
            height: 18px;
            cursor: pointer;
            accent-color: #007acc;
        }

        .status-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 16px 20px;
            background: linear-gradient(135deg, #323232 0%, #2a2a2a 100%);
            border: 1px solid #4a4a4a;
            border-radius: 8px;
            font-size: 13px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        }

        .status-info {
            display: flex;
            gap: 20px;
            color: #b0b0b0;
        }

        .status-info span {
            font-weight: 500;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            backdrop-filter: blur(4px);
            z-index: 1000;
        }

        .modal-content {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: linear-gradient(135deg, #3a3a3a 0%, #2d2d2d 100%);
            border: 1px solid #5a5a5a;
            border-radius: 12px;
            padding: 24px;
            min-width: 400px;
            max-width: 600px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
            backdrop-filter: blur(8px);
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 12px;
            border-bottom: 2px solid #4a4a4a;
        }

        .modal-title {
            font-weight: 600;
            font-size: 18px;
            color: #ffffff;
        }

        .modal-close {
            background: none;
            border: none;
            font-size: 20px;
            cursor: pointer;
            color: #b0b0b0;
            padding: 4px;
            border-radius: 4px;
            transition: all 0.2s;
        }

        .modal-close:hover {
            color: #ffffff;
            background: rgba(255, 255, 255, 0.1);
        }

        .form-group {
            margin-bottom: 16px;
        }

        .form-label {
            display: block;
            margin-bottom: 6px;
            font-size: 13px;
            font-weight: 500;
            color: #e0e0e0;
        }

        .form-input {
            width: 100%;
            padding: 10px 12px;
            border: 1px solid #5a5a5a;
            border-radius: 6px;
            background: #3a3a3a;
            color: #e0e0e0;
            font-size: 14px;
            transition: all 0.2s;
            box-sizing: border-box;
        }

        .form-input:focus {
            outline: none;
            border-color: #007acc;
            box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
        }

        .form-textarea {
            width: 100%;
            padding: 10px 12px;
            border: 1px solid #5a5a5a;
            border-radius: 6px;
            background: #3a3a3a;
            color: #e0e0e0;
            font-size: 14px;
            resize: vertical;
            min-height: 80px;
            transition: all 0.2s;
            box-sizing: border-box;
        }

        .form-textarea:focus {
            outline: none;
            border-color: #007acc;
            box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2);
        }

        .modal-actions {
            display: flex;
            justify-content: flex-end;
            gap: 8px;
            margin-top: 16px;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #b0b0b0;
            background: linear-gradient(135deg, #383838 0%, #2f2f2f 100%);
            border: 2px dashed #4a4a4a;
            border-radius: 12px;
            margin: 20px 0;
        }

        .empty-state h3 {
            margin: 0 0 12px 0;
            font-size: 18px;
            color: #e0e0e0;
            font-weight: 600;
        }

        .empty-state p {
            margin: 0;
            font-size: 14px;
            line-height: 1.5;
        }

        /* 滚动条样式 */
        .tools-container::-webkit-scrollbar {
            width: 8px;
        }

        .tools-container::-webkit-scrollbar-track {
            background: #2a2a2a;
            border-radius: 4px;
        }

        .tools-container::-webkit-scrollbar-thumb {
            background: #5a5a5a;
            border-radius: 4px;
        }

        .tools-container::-webkit-scrollbar-thumb:hover {
            background: #6a6a6a;
        }

        /* 工具管理区域标题 */
        .tools-section-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
            padding: 16px 20px;
            background: linear-gradient(135deg, #323232 0%, #2a2a2a 100%);
            border: 1px solid #4a4a4a;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        }

        .tools-section-title {
            font-weight: 600;
            font-size: 16px;
            color: #ffffff;
        }

        .tools-section-controls {
            display: flex;
            gap: 10px;
        }

        .loading {
            text-align: center;
            padding: 40px 20px;
            color: #b0b0b0;
            font-size: 14px;
        }

        .error {
            background: linear-gradient(135deg, #d32f2f 0%, #b71c1c 100%);
            color: white;
            padding: 12px 16px;
            border-radius: 6px;
            font-size: 13px;
            margin-bottom: 16px;
            border: 1px solid #f44336;
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 头部 -->
        <div class="header">
            <h2 id="panelTitle">工具管理器</h2>
            <div class="config-controls">
                <button class="btn btn-primary" id="createConfigBtn">新建配置</button>
                <button class="btn" id="importConfigBtn">导入配置</button>
                <button class="btn" id="exportConfigBtn">导出配置</button>
            </div>
        </div>

        <!-- 配置选择器 -->
        <div class="config-section">
            <div class="config-header">
                <div class="config-title">当前配置</div>
                <div class="config-controls">
                    <button class="btn" id="editConfigBtn">编辑</button>
                    <button class="btn btn-danger" id="deleteConfigBtn">删除</button>
                </div>
            </div>
            <div class="config-selector">
                <select id="configSelector">
                    <option value="">选择配置...</option>
                </select>
                <button class="btn btn-primary" id="applyConfigBtn">应用</button>
            </div>
        </div>

        <!-- 工具列表 -->
        <div class="config-section">
            <div class="tools-section-header">
                <div class="tools-section-title">工具管理</div>
                <div class="tools-section-controls">
                    <button class="btn" id="selectAllBtn">全选</button>
                    <button class="btn" id="deselectAllBtn">取消全选</button>
                </div>
            </div>
            <div id="toolsContainer" class="tools-container">
                <div class="loading">加载中...</div>
            </div>
        </div>

        <!-- 状态栏 -->
        <div class="status-bar">
            <div class="status-info">
                <span>总工具数: <span id="totalToolsCount">0</span></span>
                <span>已启用: <span id="enabledToolsCount">0</span></span>
                <span>已禁用: <span id="disabledToolsCount">0</span></span>
            </div>
            <div>
                <button class="btn" id="saveChangesBtn">保存更改</button>
            </div>
        </div>
    </div>

    <!-- 新建/编辑配置模态框 -->
    <div id="configModal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <div class="modal-title" id="modalTitle">新建配置</div>
                <button class="modal-close" id="closeModal">&times;</button>
            </div>
            <form id="configForm">
                <div class="form-group">
                    <label class="form-label" for="configName">配置名称 *</label>
                    <input type="text" id="configName" class="form-input" required>
                </div>
                <div class="form-group">
                    <label class="form-label" for="configDescription">描述</label>
                    <textarea id="configDescription" class="form-textarea" placeholder="可选:添加配置描述"></textarea>
                </div>
                <div class="modal-actions">
                    <button type="button" class="btn" id="cancelConfigBtn">取消</button>
                    <button type="submit" class="btn btn-primary" id="saveConfigBtn">保存</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 导入配置模态框 -->
    <div id="importModal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <div class="modal-title">导入配置</div>
                <button class="modal-close" id="closeImportModal">&times;</button>
            </div>
            <div class="form-group">
                <label class="form-label" for="importConfigJson">配置JSON</label>
                <textarea id="importConfigJson" class="form-textarea" placeholder="粘贴配置JSON内容"></textarea>
            </div>
            <div class="modal-actions">
                <button type="button" class="btn" id="cancelImportBtn">取消</button>
                <button type="button" class="btn btn-primary" id="confirmImportBtn">导入</button>
            </div>
        </div>
    </div>

    <script>
        // 这里将包含面板的JavaScript逻辑
    </script>
</body>
</html> 
```

--------------------------------------------------------------------------------
/source/tools/tool-manager.ts:
--------------------------------------------------------------------------------

```typescript
import { v4 as uuidv4 } from 'uuid';
import { ToolConfig, ToolConfiguration, ToolManagerSettings, ToolDefinition } from '../types';
import * as fs from 'fs';
import * as path from 'path';

export class ToolManager {
    private settings: ToolManagerSettings;
    private availableTools: ToolConfig[] = [];

    constructor() {
        this.settings = this.readToolManagerSettings();
        this.initializeAvailableTools();
        
        // 如果没有配置,自动创建一个默认配置
        if (this.settings.configurations.length === 0) {
            console.log('[ToolManager] No configurations found, creating default configuration...');
            this.createConfiguration('默认配置', '自动创建的默认工具配置');
        }
    }

    private getToolManagerSettingsPath(): string {
        return path.join(Editor.Project.path, 'settings', 'tool-manager.json');
    }

    private ensureSettingsDir(): void {
        const settingsDir = path.dirname(this.getToolManagerSettingsPath());
        if (!fs.existsSync(settingsDir)) {
            fs.mkdirSync(settingsDir, { recursive: true });
        }
    }

    private readToolManagerSettings(): ToolManagerSettings {
        const DEFAULT_TOOL_MANAGER_SETTINGS: ToolManagerSettings = {
            configurations: [],
            currentConfigId: '',
            maxConfigSlots: 5
        };

        try {
            this.ensureSettingsDir();
            const settingsFile = this.getToolManagerSettingsPath();
            if (fs.existsSync(settingsFile)) {
                const content = fs.readFileSync(settingsFile, 'utf8');
                return { ...DEFAULT_TOOL_MANAGER_SETTINGS, ...JSON.parse(content) };
            }
        } catch (e) {
            console.error('Failed to read tool manager settings:', e);
        }
        return DEFAULT_TOOL_MANAGER_SETTINGS;
    }

    private saveToolManagerSettings(settings: ToolManagerSettings): void {
        try {
            this.ensureSettingsDir();
            const settingsFile = this.getToolManagerSettingsPath();
            fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
        } catch (e) {
            console.error('Failed to save tool manager settings:', e);
            throw e;
        }
    }

    private exportToolConfiguration(config: ToolConfiguration): string {
        return JSON.stringify(config, null, 2);
    }

    private importToolConfiguration(configJson: string): ToolConfiguration {
        try {
            const config = JSON.parse(configJson);
            // 验证配置格式
            if (!config.id || !config.name || !Array.isArray(config.tools)) {
                throw new Error('Invalid configuration format');
            }
            return config;
        } catch (e) {
            console.error('Failed to parse tool configuration:', e);
            throw new Error('Invalid JSON format or configuration structure');
        }
    }

    private initializeAvailableTools(): void {
        // 从MCP服务器获取真实的工具列表
        try {
            // 导入所有工具类
            const { SceneTools } = require('./scene-tools');
            const { NodeTools } = require('./node-tools');
            const { ComponentTools } = require('./component-tools');
            const { PrefabTools } = require('./prefab-tools');
            const { ProjectTools } = require('./project-tools');
            const { DebugTools } = require('./debug-tools');
            const { PreferencesTools } = require('./preferences-tools');
            const { ServerTools } = require('./server-tools');
            const { BroadcastTools } = require('./broadcast-tools');
            const { SceneAdvancedTools } = require('./scene-advanced-tools');
            const { SceneViewTools } = require('./scene-view-tools');
            const { ReferenceImageTools } = require('./reference-image-tools');
            const { AssetAdvancedTools } = require('./asset-advanced-tools');
            const { ValidationTools } = require('./validation-tools');

            // 初始化工具实例
            const tools = {
                scene: new SceneTools(),
                node: new NodeTools(),
                component: new ComponentTools(),
                prefab: new PrefabTools(),
                project: new ProjectTools(),
                debug: new DebugTools(),
                preferences: new PreferencesTools(),
                server: new ServerTools(),
                broadcast: new BroadcastTools(),
                sceneAdvanced: new SceneAdvancedTools(),
                sceneView: new SceneViewTools(),
                referenceImage: new ReferenceImageTools(),
                assetAdvanced: new AssetAdvancedTools(),
                validation: new ValidationTools()
            };

            // 从每个工具类获取工具列表
            this.availableTools = [];
            for (const [category, toolSet] of Object.entries(tools)) {
                const toolDefinitions = toolSet.getTools();
                toolDefinitions.forEach((tool: any) => {
                    this.availableTools.push({
                        category: category,
                        name: tool.name,
                        enabled: true, // 默认启用
                        description: tool.description
                    });
                });
            }

            console.log(`[ToolManager] Initialized ${this.availableTools.length} tools from MCP server`);
        } catch (error) {
            console.error('[ToolManager] Failed to initialize tools from MCP server:', error);
            // 如果获取失败,使用默认工具列表作为后备
            this.initializeDefaultTools();
        }
    }

    private initializeDefaultTools(): void {
        // 默认工具列表作为后备方案
        const toolCategories = [
            { category: 'scene', name: '场景工具', tools: [
                { name: 'getCurrentSceneInfo', description: '获取当前场景信息' },
                { name: 'getSceneHierarchy', description: '获取场景层级结构' },
                { name: 'createNewScene', description: '创建新场景' },
                { name: 'saveScene', description: '保存场景' },
                { name: 'loadScene', description: '加载场景' }
            ]},
            { category: 'node', name: '节点工具', tools: [
                { name: 'getAllNodes', description: '获取所有节点' },
                { name: 'findNodeByName', description: '根据名称查找节点' },
                { name: 'createNode', description: '创建节点' },
                { name: 'deleteNode', description: '删除节点' },
                { name: 'setNodeProperty', description: '设置节点属性' },
                { name: 'getNodeInfo', description: '获取节点信息' }
            ]},
            { category: 'component', name: '组件工具', tools: [
                { name: 'addComponentToNode', description: '添加组件到节点' },
                { name: 'removeComponentFromNode', description: '从节点移除组件' },
                { name: 'setComponentProperty', description: '设置组件属性' },
                { name: 'getComponentInfo', description: '获取组件信息' }
            ]},
            { category: 'prefab', name: '预制体工具', tools: [
                { name: 'createPrefabFromNode', description: '从节点创建预制体' },
                { name: 'instantiatePrefab', description: '实例化预制体' },
                { name: 'getPrefabInfo', description: '获取预制体信息' },
                { name: 'savePrefab', description: '保存预制体' }
            ]},
            { category: 'project', name: '项目工具', tools: [
                { name: 'getProjectInfo', description: '获取项目信息' },
                { name: 'getAssetList', description: '获取资源列表' },
                { name: 'createAsset', description: '创建资源' },
                { name: 'deleteAsset', description: '删除资源' }
            ]},
            { category: 'debug', name: '调试工具', tools: [
                { name: 'getConsoleLogs', description: '获取控制台日志' },
                { name: 'getPerformanceStats', description: '获取性能统计' },
                { name: 'validateScene', description: '验证场景' },
                { name: 'getErrorLogs', description: '获取错误日志' }
            ]},
            { category: 'preferences', name: '偏好设置工具', tools: [
                { name: 'getPreferences', description: '获取偏好设置' },
                { name: 'setPreferences', description: '设置偏好设置' },
                { name: 'resetPreferences', description: '重置偏好设置' }
            ]},
            { category: 'server', name: '服务器工具', tools: [
                { name: 'getServerStatus', description: '获取服务器状态' },
                { name: 'getConnectedClients', description: '获取连接的客户端' },
                { name: 'getServerLogs', description: '获取服务器日志' }
            ]},
            { category: 'broadcast', name: '广播工具', tools: [
                { name: 'broadcastMessage', description: '广播消息' },
                { name: 'getBroadcastHistory', description: '获取广播历史' }
            ]},
            { category: 'sceneAdvanced', name: '高级场景工具', tools: [
                { name: 'optimizeScene', description: '优化场景' },
                { name: 'analyzeScene', description: '分析场景' },
                { name: 'batchOperation', description: '批量操作' }
            ]},
            { category: 'sceneView', name: '场景视图工具', tools: [
                { name: 'getViewportInfo', description: '获取视口信息' },
                { name: 'setViewportCamera', description: '设置视口相机' },
                { name: 'focusOnNode', description: '聚焦到节点' }
            ]},
            { category: 'referenceImage', name: '参考图片工具', tools: [
                { name: 'addReferenceImage', description: '添加参考图片' },
                { name: 'removeReferenceImage', description: '移除参考图片' },
                { name: 'getReferenceImages', description: '获取参考图片列表' }
            ]},
            { category: 'assetAdvanced', name: '高级资源工具', tools: [
                { name: 'importAsset', description: '导入资源' },
                { name: 'exportAsset', description: '导出资源' },
                { name: 'processAsset', description: '处理资源' }
            ]},
            { category: 'validation', name: '验证工具', tools: [
                { name: 'validateProject', description: '验证项目' },
                { name: 'validateAssets', description: '验证资源' },
                { name: 'generateReport', description: '生成报告' }
            ]}
        ];

        this.availableTools = [];
        toolCategories.forEach(category => {
            category.tools.forEach(tool => {
                this.availableTools.push({
                    category: category.category,
                    name: tool.name,
                    enabled: true, // 默认启用
                    description: tool.description
                });
            });
        });

        console.log(`[ToolManager] Initialized ${this.availableTools.length} default tools`);
    }

    public getAvailableTools(): ToolConfig[] {
        return [...this.availableTools];
    }

    public getConfigurations(): ToolConfiguration[] {
        return [...this.settings.configurations];
    }

    public getCurrentConfiguration(): ToolConfiguration | null {
        if (!this.settings.currentConfigId) {
            return null;
        }
        return this.settings.configurations.find(config => config.id === this.settings.currentConfigId) || null;
    }

    public createConfiguration(name: string, description?: string): ToolConfiguration {
        if (this.settings.configurations.length >= this.settings.maxConfigSlots) {
            throw new Error(`已达到最大配置槽位数量 (${this.settings.maxConfigSlots})`);
        }

        const config: ToolConfiguration = {
            id: uuidv4(),
            name,
            description,
            tools: this.availableTools.map(tool => ({ ...tool })),
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString()
        };

        this.settings.configurations.push(config);
        this.settings.currentConfigId = config.id;
        this.saveSettings();

        return config;
    }

    public updateConfiguration(configId: string, updates: Partial<ToolConfiguration>): ToolConfiguration {
        const configIndex = this.settings.configurations.findIndex(config => config.id === configId);
        if (configIndex === -1) {
            throw new Error('配置不存在');
        }

        const config = this.settings.configurations[configIndex];
        const updatedConfig: ToolConfiguration = {
            ...config,
            ...updates,
            updatedAt: new Date().toISOString()
        };

        this.settings.configurations[configIndex] = updatedConfig;
        this.saveSettings();

        return updatedConfig;
    }

    public deleteConfiguration(configId: string): void {
        const configIndex = this.settings.configurations.findIndex(config => config.id === configId);
        if (configIndex === -1) {
            throw new Error('配置不存在');
        }

        this.settings.configurations.splice(configIndex, 1);
        
        // 如果删除的是当前配置,清空当前配置ID
        if (this.settings.currentConfigId === configId) {
            this.settings.currentConfigId = this.settings.configurations.length > 0 
                ? this.settings.configurations[0].id 
                : '';
        }

        this.saveSettings();
    }

    public setCurrentConfiguration(configId: string): void {
        const config = this.settings.configurations.find(config => config.id === configId);
        if (!config) {
            throw new Error('配置不存在');
        }

        this.settings.currentConfigId = configId;
        this.saveSettings();
    }

    public updateToolStatus(configId: string, category: string, toolName: string, enabled: boolean): void {
        console.log(`Backend: Updating tool status - configId: ${configId}, category: ${category}, toolName: ${toolName}, enabled: ${enabled}`);
        
        const config = this.settings.configurations.find(config => config.id === configId);
        if (!config) {
            console.error(`Backend: Config not found with ID: ${configId}`);
            throw new Error('配置不存在');
        }

        console.log(`Backend: Found config: ${config.name}`);

        const tool = config.tools.find(t => t.category === category && t.name === toolName);
        if (!tool) {
            console.error(`Backend: Tool not found - category: ${category}, name: ${toolName}`);
            throw new Error('工具不存在');
        }

        console.log(`Backend: Found tool: ${tool.name}, current enabled: ${tool.enabled}, new enabled: ${enabled}`);
        
        tool.enabled = enabled;
        config.updatedAt = new Date().toISOString();
        
        console.log(`Backend: Tool updated, saving settings...`);
        this.saveSettings();
        console.log(`Backend: Settings saved successfully`);
    }

    public updateToolStatusBatch(configId: string, updates: { category: string; name: string; enabled: boolean }[]): void {
        console.log(`Backend: updateToolStatusBatch called with configId: ${configId}`);
        console.log(`Backend: Current configurations count: ${this.settings.configurations.length}`);
        console.log(`Backend: Current config IDs:`, this.settings.configurations.map(c => c.id));
        
        const config = this.settings.configurations.find(config => config.id === configId);
        if (!config) {
            console.error(`Backend: Config not found with ID: ${configId}`);
            console.error(`Backend: Available config IDs:`, this.settings.configurations.map(c => c.id));
            throw new Error('配置不存在');
        }

        console.log(`Backend: Found config: ${config.name}, updating ${updates.length} tools`);

        updates.forEach(update => {
            const tool = config.tools.find(t => t.category === update.category && t.name === update.name);
            if (tool) {
                tool.enabled = update.enabled;
            }
        });

        config.updatedAt = new Date().toISOString();
        this.saveSettings();
        console.log(`Backend: Batch update completed successfully`);
    }

    public exportConfiguration(configId: string): string {
        const config = this.settings.configurations.find(config => config.id === configId);
        if (!config) {
            throw new Error('配置不存在');
        }

        return this.exportToolConfiguration(config);
    }

    public importConfiguration(configJson: string): ToolConfiguration {
        const config = this.importToolConfiguration(configJson);
        
        // 生成新的ID和时间戳
        config.id = uuidv4();
        config.createdAt = new Date().toISOString();
        config.updatedAt = new Date().toISOString();

        if (this.settings.configurations.length >= this.settings.maxConfigSlots) {
            throw new Error(`已达到最大配置槽位数量 (${this.settings.maxConfigSlots})`);
        }

        this.settings.configurations.push(config);
        this.saveSettings();

        return config;
    }

    public getEnabledTools(): ToolConfig[] {
        const currentConfig = this.getCurrentConfiguration();
        if (!currentConfig) {
            return this.availableTools.filter(tool => tool.enabled);
        }
        return currentConfig.tools.filter(tool => tool.enabled);
    }

    public getToolManagerState() {
        const currentConfig = this.getCurrentConfiguration();
        return {
            success: true,
            availableTools: currentConfig ? currentConfig.tools : this.getAvailableTools(),
            selectedConfigId: this.settings.currentConfigId,
            configurations: this.getConfigurations(),
            maxConfigSlots: this.settings.maxConfigSlots
        };
    }

    private saveSettings(): void {
        console.log(`Backend: Saving settings, current configs count: ${this.settings.configurations.length}`);
        this.saveToolManagerSettings(this.settings);
        console.log(`Backend: Settings saved to file`);
    }
} 
```

--------------------------------------------------------------------------------
/source/mcp-server.ts:
--------------------------------------------------------------------------------

```typescript
import * as http from 'http';
import * as url from 'url';
import { v4 as uuidv4 } from 'uuid';
import { MCPServerSettings, ServerStatus, MCPClient, ToolDefinition } from './types';
import { SceneTools } from './tools/scene-tools';
import { NodeTools } from './tools/node-tools';
import { ComponentTools } from './tools/component-tools';
import { PrefabTools } from './tools/prefab-tools';
import { ProjectTools } from './tools/project-tools';
import { DebugTools } from './tools/debug-tools';
import { PreferencesTools } from './tools/preferences-tools';
import { ServerTools } from './tools/server-tools';
import { BroadcastTools } from './tools/broadcast-tools';
import { SceneAdvancedTools } from './tools/scene-advanced-tools';
import { SceneViewTools } from './tools/scene-view-tools';
import { ReferenceImageTools } from './tools/reference-image-tools';
import { AssetAdvancedTools } from './tools/asset-advanced-tools';
import { ValidationTools } from './tools/validation-tools';

export class MCPServer {
    private settings: MCPServerSettings;
    private httpServer: http.Server | null = null;
    private clients: Map<string, MCPClient> = new Map();
    private tools: Record<string, any> = {};
    private toolsList: ToolDefinition[] = [];
    private enabledTools: any[] = []; // 存储启用的工具列表

    constructor(settings: MCPServerSettings) {
        this.settings = settings;
        this.initializeTools();
    }

    private initializeTools(): void {
        try {
            console.log('[MCPServer] Initializing tools...');
            this.tools.scene = new SceneTools();
            this.tools.node = new NodeTools();
            this.tools.component = new ComponentTools();
            this.tools.prefab = new PrefabTools();
            this.tools.project = new ProjectTools();
            this.tools.debug = new DebugTools();
            this.tools.preferences = new PreferencesTools();
            this.tools.server = new ServerTools();
            this.tools.broadcast = new BroadcastTools();
            this.tools.sceneAdvanced = new SceneAdvancedTools();
            this.tools.sceneView = new SceneViewTools();
            this.tools.referenceImage = new ReferenceImageTools();
            this.tools.assetAdvanced = new AssetAdvancedTools();
            this.tools.validation = new ValidationTools();
            console.log('[MCPServer] Tools initialized successfully');
        } catch (error) {
            console.error('[MCPServer] Error initializing tools:', error);
            throw error;
        }
    }

    public async start(): Promise<void> {
        if (this.httpServer) {
            console.log('[MCPServer] Server is already running');
            return;
        }

        try {
            console.log(`[MCPServer] Starting HTTP server on port ${this.settings.port}...`);
            this.httpServer = http.createServer(this.handleHttpRequest.bind(this));

            await new Promise<void>((resolve, reject) => {
                this.httpServer!.listen(this.settings.port, '127.0.0.1', () => {
                    console.log(`[MCPServer] ✅ HTTP server started successfully on http://127.0.0.1:${this.settings.port}`);
                    console.log(`[MCPServer] Health check: http://127.0.0.1:${this.settings.port}/health`);
                    console.log(`[MCPServer] MCP endpoint: http://127.0.0.1:${this.settings.port}/mcp`);
                    resolve();
                });
                this.httpServer!.on('error', (err: any) => {
                    console.error('[MCPServer] ❌ Failed to start server:', err);
                    if (err.code === 'EADDRINUSE') {
                        console.error(`[MCPServer] Port ${this.settings.port} is already in use. Please change the port in settings.`);
                    }
                    reject(err);
                });
            });

            this.setupTools();
            console.log('[MCPServer] 🚀 MCP Server is ready for connections');
        } catch (error) {
            console.error('[MCPServer] ❌ Failed to start server:', error);
            throw error;
        }
    }

    private setupTools(): void {
        this.toolsList = [];
        
        // 如果没有启用工具配置,返回所有工具
        if (!this.enabledTools || this.enabledTools.length === 0) {
            for (const [category, toolSet] of Object.entries(this.tools)) {
                const tools = toolSet.getTools();
                for (const tool of tools) {
                    this.toolsList.push({
                        name: `${category}_${tool.name}`,
                        description: tool.description,
                        inputSchema: tool.inputSchema
                    });
                }
            }
        } else {
            // 根据启用的工具配置过滤
            const enabledToolNames = new Set(this.enabledTools.map(tool => `${tool.category}_${tool.name}`));
            
            for (const [category, toolSet] of Object.entries(this.tools)) {
                const tools = toolSet.getTools();
                for (const tool of tools) {
                    const toolName = `${category}_${tool.name}`;
                    if (enabledToolNames.has(toolName)) {
                        this.toolsList.push({
                            name: toolName,
                            description: tool.description,
                            inputSchema: tool.inputSchema
                        });
                    }
                }
            }
        }
        
        console.log(`[MCPServer] Setup tools: ${this.toolsList.length} tools available`);
    }

    public getFilteredTools(enabledTools: any[]): ToolDefinition[] {
        if (!enabledTools || enabledTools.length === 0) {
            return this.toolsList; // 如果没有过滤配置,返回所有工具
        }

        const enabledToolNames = new Set(enabledTools.map(tool => `${tool.category}_${tool.name}`));
        return this.toolsList.filter(tool => enabledToolNames.has(tool.name));
    }

    public async executeToolCall(toolName: string, args: any): Promise<any> {
        const parts = toolName.split('_');
        const category = parts[0];
        const toolMethodName = parts.slice(1).join('_');
        
        if (this.tools[category]) {
            return await this.tools[category].execute(toolMethodName, args);
        }
        
        throw new Error(`Tool ${toolName} not found`);
    }

    public getClients(): MCPClient[] {
        return Array.from(this.clients.values());
    }
    public getAvailableTools(): ToolDefinition[] {
        return this.toolsList;
    }

    public updateEnabledTools(enabledTools: any[]): void {
        console.log(`[MCPServer] Updating enabled tools: ${enabledTools.length} tools`);
        this.enabledTools = enabledTools;
        this.setupTools(); // 重新设置工具列表
    }

    public getSettings(): MCPServerSettings {
        return this.settings;
    }

    private async handleHttpRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
        const parsedUrl = url.parse(req.url || '', true);
        const pathname = parsedUrl.pathname;
        
        // Set CORS headers
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
        res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
        res.setHeader('Content-Type', 'application/json');
        
        if (req.method === 'OPTIONS') {
            res.writeHead(200);
            res.end();
            return;
        }
        
        try {
            if (pathname === '/mcp' && req.method === 'POST') {
                await this.handleMCPRequest(req, res);
            } else if (pathname === '/health' && req.method === 'GET') {
                res.writeHead(200);
                res.end(JSON.stringify({ status: 'ok', tools: this.toolsList.length }));
            } else if (pathname?.startsWith('/api/') && req.method === 'POST') {
                await this.handleSimpleAPIRequest(req, res, pathname);
            } else if (pathname === '/api/tools' && req.method === 'GET') {
                res.writeHead(200);
                res.end(JSON.stringify({ tools: this.getSimplifiedToolsList() }));
            } else {
                res.writeHead(404);
                res.end(JSON.stringify({ error: 'Not found' }));
            }
        } catch (error) {
            console.error('HTTP request error:', error);
            res.writeHead(500);
            res.end(JSON.stringify({ error: 'Internal server error' }));
        }
    }
    
    private async handleMCPRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
        let body = '';
        
        req.on('data', (chunk) => {
            body += chunk.toString();
        });
        
        req.on('end', async () => {
            try {
                // Enhanced JSON parsing with better error handling
                let message;
                try {
                    message = JSON.parse(body);
                } catch (parseError: any) {
                    // Try to fix common JSON issues
                    const fixedBody = this.fixCommonJsonIssues(body);
                    try {
                        message = JSON.parse(fixedBody);
                        console.log('[MCPServer] Fixed JSON parsing issue');
                    } catch (secondError) {
                        throw new Error(`JSON parsing failed: ${parseError.message}. Original body: ${body.substring(0, 500)}...`);
                    }
                }
                
                const response = await this.handleMessage(message);
                res.writeHead(200);
                res.end(JSON.stringify(response));
            } catch (error: any) {
                console.error('Error handling MCP request:', error);
                res.writeHead(400);
                res.end(JSON.stringify({
                    jsonrpc: '2.0',
                    id: null,
                    error: {
                        code: -32700,
                        message: `Parse error: ${error.message}`
                    }
                }));
            }
        });
    }

    private async handleMessage(message: any): Promise<any> {
        const { id, method, params } = message;

        try {
            let result: any;

            switch (method) {
                case 'tools/list':
                    result = { tools: this.getAvailableTools() };
                    break;
                case 'tools/call':
                    const { name, arguments: args } = params;
                    const toolResult = await this.executeToolCall(name, args);
                    result = { content: [{ type: 'text', text: JSON.stringify(toolResult) }] };
                    break;
                case 'initialize':
                    // MCP initialization
                    result = {
                        protocolVersion: '2024-11-05',
                        capabilities: {
                            tools: {}
                        },
                        serverInfo: {
                            name: 'cocos-mcp-server',
                            version: '1.0.0'
                        }
                    };
                    break;
                default:
                    throw new Error(`Unknown method: ${method}`);
            }

            return {
                jsonrpc: '2.0',
                id,
                result
            };
        } catch (error: any) {
            return {
                jsonrpc: '2.0',
                id,
                error: {
                    code: -32603,
                    message: error.message
                }
            };
        }
    }

    private fixCommonJsonIssues(jsonStr: string): string {
        let fixed = jsonStr;
        
        // Fix common escape character issues
        fixed = fixed
            // Fix unescaped quotes in strings
            .replace(/([^\\])"([^"]*[^\\])"([^,}\]:])/g, '$1\\"$2\\"$3')
            // Fix unescaped backslashes
            .replace(/([^\\])\\([^"\\\/bfnrt])/g, '$1\\\\$2')
            // Fix trailing commas
            .replace(/,(\s*[}\]])/g, '$1')
            // Fix single quotes (should be double quotes)
            .replace(/'/g, '"')
            // Fix common control characters
            .replace(/\n/g, '\\n')
            .replace(/\r/g, '\\r')
            .replace(/\t/g, '\\t');
        
        return fixed;
    }

    public stop(): void {
        if (this.httpServer) {
            this.httpServer.close();
            this.httpServer = null;
            console.log('[MCPServer] HTTP server stopped');
        }

        this.clients.clear();
    }

    public getStatus(): ServerStatus {
        return {
            running: !!this.httpServer,
            port: this.settings.port,
            clients: 0 // HTTP is stateless, no persistent clients
        };
    }

    private async handleSimpleAPIRequest(req: http.IncomingMessage, res: http.ServerResponse, pathname: string): Promise<void> {
        let body = '';
        
        req.on('data', (chunk) => {
            body += chunk.toString();
        });
        
        req.on('end', async () => {
            try {
                // Extract tool name from path like /api/node/set_position
                const pathParts = pathname.split('/').filter(p => p);
                if (pathParts.length < 3) {
                    res.writeHead(400);
                    res.end(JSON.stringify({ error: 'Invalid API path. Use /api/{category}/{tool_name}' }));
                    return;
                }
                
                const category = pathParts[1];
                const toolName = pathParts[2];
                const fullToolName = `${category}_${toolName}`;
                
                // Parse parameters with enhanced error handling
                let params;
                try {
                    params = body ? JSON.parse(body) : {};
                } catch (parseError: any) {
                    // Try to fix JSON issues
                    const fixedBody = this.fixCommonJsonIssues(body);
                    try {
                        params = JSON.parse(fixedBody);
                        console.log('[MCPServer] Fixed API JSON parsing issue');
                    } catch (secondError: any) {
                        res.writeHead(400);
                        res.end(JSON.stringify({
                            error: 'Invalid JSON in request body',
                            details: parseError.message,
                            receivedBody: body.substring(0, 200)
                        }));
                        return;
                    }
                }
                
                // Execute tool
                const result = await this.executeToolCall(fullToolName, params);
                
                res.writeHead(200);
                res.end(JSON.stringify({
                    success: true,
                    tool: fullToolName,
                    result: result
                }));
                
            } catch (error: any) {
                console.error('Simple API error:', error);
                res.writeHead(500);
                res.end(JSON.stringify({
                    success: false,
                    error: error.message,
                    tool: pathname
                }));
            }
        });
    }

    private getSimplifiedToolsList(): any[] {
        return this.toolsList.map(tool => {
            const parts = tool.name.split('_');
            const category = parts[0];
            const toolName = parts.slice(1).join('_');
            
            return {
                name: tool.name,
                category: category,
                toolName: toolName,
                description: tool.description,
                apiPath: `/api/${category}/${toolName}`,
                curlExample: this.generateCurlExample(category, toolName, tool.inputSchema)
            };
        });
    }

    private generateCurlExample(category: string, toolName: string, schema: any): string {
        // Generate sample parameters based on schema
        const sampleParams = this.generateSampleParams(schema);
        const jsonString = JSON.stringify(sampleParams, null, 2);
        
        return `curl -X POST http://127.0.0.1:8585/api/${category}/${toolName} \\
  -H "Content-Type: application/json" \\
  -d '${jsonString}'`;
    }

    private generateSampleParams(schema: any): any {
        if (!schema || !schema.properties) return {};
        
        const sample: any = {};
        for (const [key, prop] of Object.entries(schema.properties as any)) {
            const propSchema = prop as any;
            switch (propSchema.type) {
                case 'string':
                    sample[key] = propSchema.default || 'example_string';
                    break;
                case 'number':
                    sample[key] = propSchema.default || 42;
                    break;
                case 'boolean':
                    sample[key] = propSchema.default || true;
                    break;
                case 'object':
                    sample[key] = propSchema.default || { x: 0, y: 0, z: 0 };
                    break;
                default:
                    sample[key] = 'example_value';
            }
        }
        return sample;
    }

    public updateSettings(settings: MCPServerSettings) {
        this.settings = settings;
        if (this.httpServer) {
            this.stop();
            this.start();
        }
    }
}

// HTTP transport doesn't need persistent connections
// MCP over HTTP uses request-response pattern
```

--------------------------------------------------------------------------------
/source/panels/default/index.ts:
--------------------------------------------------------------------------------

```typescript
/* eslint-disable vue/one-component-per-file */

import { readFileSync } from 'fs-extra';
import { join } from 'path';
import { createApp, App, defineComponent, ref, computed, onMounted, watch, nextTick } from 'vue';

const panelDataMap = new WeakMap<any, App>();

// 定义工具配置接口
interface ToolConfig {
    category: string;
    name: string;
    enabled: boolean;
    description: string;
}

// 定义配置接口
interface Configuration {
    id: string;
    name: string;
    description: string;
    tools: ToolConfig[];
    createdAt: string;
    updatedAt: string;
}

// 定义服务器设置接口
interface ServerSettings {
    port: number;
    autoStart: boolean;
    debugLog: boolean;
    maxConnections: number;
}

module.exports = Editor.Panel.define({
    listeners: {
        show() { 
            console.log('[MCP Panel] Panel shown'); 
        },
        hide() { 
            console.log('[MCP Panel] Panel hidden'); 
        },
    },
    template: readFileSync(join(__dirname, '../../../static/template/default/index.html'), 'utf-8'),
    style: readFileSync(join(__dirname, '../../../static/style/default/index.css'), 'utf-8'),
    $: {
        app: '#app',
        panelTitle: '#panelTitle',
    },
    ready() {
        if (this.$.app) {
            const app = createApp({});
            app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('ui-');
            
            // 创建主应用组件
            app.component('McpServerApp', defineComponent({
                setup() {
                    // 响应式数据
                    const activeTab = ref('server');
                    const serverRunning = ref(false);
                    const serverStatus = ref('已停止');
                    const connectedClients = ref(0);
                    const httpUrl = ref('');
                    const isProcessing = ref(false);
                    
                    const settings = ref<ServerSettings>({
                        port: 3000,
                        autoStart: false,
                        debugLog: false,
                        maxConnections: 10
                    });
                    
                    const availableTools = ref<ToolConfig[]>([]);
                    const toolCategories = ref<string[]>([]);
                    

                    
                    // 计算属性
                    const statusClass = computed(() => ({
                        'status-running': serverRunning.value,
                        'status-stopped': !serverRunning.value
                    }));
                    
                    const totalTools = computed(() => availableTools.value.length);
                    const enabledTools = computed(() => availableTools.value.filter(t => t.enabled).length);
                    const disabledTools = computed(() => totalTools.value - enabledTools.value);
                    

                    
                    const settingsChanged = ref(false);
                    
                    // 方法
                    const switchTab = (tabName: string) => {
                        activeTab.value = tabName;
                        if (tabName === 'tools') {
                            loadToolManagerState();
                        }
                    };
                    
                    const toggleServer = async () => {
                        try {
                            if (serverRunning.value) {
                                await Editor.Message.request('cocos-mcp-server', 'stop-server');
                            } else {
                                // 启动服务器时使用当前面板设置
                                const currentSettings = {
                                    port: settings.value.port,
                                    autoStart: settings.value.autoStart,
                                    enableDebugLog: settings.value.debugLog,
                                    maxConnections: settings.value.maxConnections
                                };
                                await Editor.Message.request('cocos-mcp-server', 'update-settings', currentSettings);
                                await Editor.Message.request('cocos-mcp-server', 'start-server');
                            }
                            console.log('[Vue App] Server toggled');
                        } catch (error) {
                            console.error('[Vue App] Failed to toggle server:', error);
                        }
                    };
                    
                    const saveSettings = async () => {
                        try {
                            // 创建一个简单的对象,避免克隆错误
                            const settingsData = {
                                port: settings.value.port,
                                autoStart: settings.value.autoStart,
                                debugLog: settings.value.debugLog,
                                maxConnections: settings.value.maxConnections
                            };
                            
                            const result = await Editor.Message.request('cocos-mcp-server', 'update-settings', settingsData);
                            console.log('[Vue App] Save settings result:', result);
                            settingsChanged.value = false;
                        } catch (error) {
                            console.error('[Vue App] Failed to save settings:', error);
                        }
                    };
                    
                    const copyUrl = async () => {
                        try {
                            await navigator.clipboard.writeText(httpUrl.value);
                            console.log('[Vue App] URL copied to clipboard');
                        } catch (error) {
                            console.error('[Vue App] Failed to copy URL:', error);
                        }
                    };
                    
                    const loadToolManagerState = async () => {
                        try {
                            const result = await Editor.Message.request('cocos-mcp-server', 'getToolManagerState');
                            if (result && result.success) {
                                // 总是加载后端状态,确保数据是最新的
                                availableTools.value = result.availableTools || [];
                                console.log('[Vue App] Loaded tools:', availableTools.value.length);
                                
                                // 更新工具分类
                                const categories = new Set(availableTools.value.map(tool => tool.category));
                                toolCategories.value = Array.from(categories);
                            }
                        } catch (error) {
                            console.error('[Vue App] Failed to load tool manager state:', error);
                        }
                    };
                    
                    const updateToolStatus = async (category: string, name: string, enabled: boolean) => {
                        try {
                            console.log('[Vue App] updateToolStatus called:', category, name, enabled);
                            
                            // 先更新本地状态
                            const toolIndex = availableTools.value.findIndex(t => t.category === category && t.name === name);
                            if (toolIndex !== -1) {
                                availableTools.value[toolIndex].enabled = enabled;
                                // 强制触发响应式更新
                                availableTools.value = [...availableTools.value];
                                console.log('[Vue App] Local state updated, tool enabled:', availableTools.value[toolIndex].enabled);
                            }
                            
                            // 调用后端更新
                            const result = await Editor.Message.request('cocos-mcp-server', 'updateToolStatus', category, name, enabled);
                            if (!result || !result.success) {
                                // 如果后端更新失败,回滚本地状态
                                if (toolIndex !== -1) {
                                    availableTools.value[toolIndex].enabled = !enabled;
                                    availableTools.value = [...availableTools.value];
                                }
                                console.error('[Vue App] Backend update failed, rolled back local state');
                            } else {
                                console.log('[Vue App] Backend update successful');
                            }
                        } catch (error) {
                            // 如果发生错误,回滚本地状态
                            const toolIndex = availableTools.value.findIndex(t => t.category === category && t.name === name);
                            if (toolIndex !== -1) {
                                availableTools.value[toolIndex].enabled = !enabled;
                                availableTools.value = [...availableTools.value];
                            }
                            console.error('[Vue App] Failed to update tool status:', error);
                        }
                    };
                    
                    const selectAllTools = async () => {
                        try {
                            // 直接更新本地状态,然后保存
                            availableTools.value.forEach(tool => tool.enabled = true);
                            await saveChanges();
                        } catch (error) {
                            console.error('[Vue App] Failed to select all tools:', error);
                        }
                    };
                    
                    const deselectAllTools = async () => {
                        try {
                            // 直接更新本地状态,然后保存
                            availableTools.value.forEach(tool => tool.enabled = false);
                            await saveChanges();
                        } catch (error) {
                            console.error('[Vue App] Failed to deselect all tools:', error);
                        }
                    };
                    
                                        const saveChanges = async () => {
                        try {
                            // 创建普通对象,避免Vue3响应式对象克隆错误
                            const updates = availableTools.value.map(tool => ({
                                category: String(tool.category),
                                name: String(tool.name),
                                enabled: Boolean(tool.enabled)
                            }));
                            
                            console.log('[Vue App] Sending updates:', updates.length, 'tools');
                            
                            const result = await Editor.Message.request('cocos-mcp-server', 'updateToolStatusBatch', updates);
                            
                            if (result && result.success) {
                                console.log('[Vue App] Tool changes saved successfully');
                            }
                        } catch (error) {
                            console.error('[Vue App] Failed to save tool changes:', error);
                        }
                    };
                    

                    
                    const toggleCategoryTools = async (category: string, enabled: boolean) => {
                        try {
                            // 直接更新本地状态,然后保存
                            availableTools.value.forEach(tool => {
                                if (tool.category === category) {
                                    tool.enabled = enabled;
                                }
                            });
                            await saveChanges();
                        } catch (error) {
                            console.error('[Vue App] Failed to toggle category tools:', error);
                        }
                    };
                    
                    const getToolsByCategory = (category: string) => {
                        return availableTools.value.filter(tool => tool.category === category);
                    };
                    
                    const getCategoryDisplayName = (category: string): string => {
                        const categoryNames: { [key: string]: string } = {
                            'scene': '场景工具',
                            'node': '节点工具',
                            'component': '组件工具',
                            'prefab': '预制体工具',
                            'project': '项目工具',
                            'debug': '调试工具',
                            'preferences': '偏好设置工具',
                            'server': '服务器工具',
                            'broadcast': '广播工具',
                            'sceneAdvanced': '高级场景工具',
                            'sceneView': '场景视图工具',
                            'referenceImage': '参考图片工具',
                            'assetAdvanced': '高级资源工具',
                            'validation': '验证工具'
                        };
                        return categoryNames[category] || category;
                    };
                    

                    

                    
                    // 监听设置变化
                    watch(settings, () => {
                        settingsChanged.value = true;
                    }, { deep: true });
                    

                    
                    // 组件挂载时加载数据
                    onMounted(async () => {
                        // 加载工具管理器状态
                        await loadToolManagerState();
                        
                        // 从服务器状态获取设置信息
                        try {
                            const serverStatus = await Editor.Message.request('cocos-mcp-server', 'get-server-status');
                            if (serverStatus && serverStatus.settings) {
                                settings.value = {
                                    port: serverStatus.settings.port || 3000,
                                    autoStart: serverStatus.settings.autoStart || false,
                                    debugLog: serverStatus.settings.enableDebugLog || false,
                                    maxConnections: serverStatus.settings.maxConnections || 10
                                };
                                console.log('[Vue App] Server settings loaded from status:', serverStatus.settings);
                            } else if (serverStatus && serverStatus.port) {
                                // 兼容旧版本,只获取端口信息
                                settings.value.port = serverStatus.port;
                                console.log('[Vue App] Port loaded from server status:', serverStatus.port);
                            }
                        } catch (error) {
                            console.error('[Vue App] Failed to get server status:', error);
                            console.log('[Vue App] Using default server settings');
                        }
                        
                        // 定期更新服务器状态
                        setInterval(async () => {
                            try {
                                const result = await Editor.Message.request('cocos-mcp-server', 'get-server-status');
                                if (result) {
                                    serverRunning.value = result.running;
                                    serverStatus.value = result.running ? '运行中' : '已停止';
                                    connectedClients.value = result.clients || 0;
                                    httpUrl.value = result.running ? `http://localhost:${result.port}` : '';
                                    isProcessing.value = false;
                                }
                            } catch (error) {
                                console.error('[Vue App] Failed to get server status:', error);
                            }
                        }, 2000);
                    });
                    
                    return {
                        // 数据
                        activeTab,
                        serverRunning,
                        serverStatus,
                        connectedClients,
                        httpUrl,
                        isProcessing,
                        settings,
                        availableTools,
                        toolCategories,
                        settingsChanged,
                        
                        // 计算属性
                        statusClass,
                        totalTools,
                        enabledTools,
                        disabledTools,
                        
                        // 方法
                        switchTab,
                        toggleServer,
                        saveSettings,
                        copyUrl,
                        loadToolManagerState,
                        updateToolStatus,
                        selectAllTools,
                        deselectAllTools,
                        saveChanges,
                        toggleCategoryTools,
                        getToolsByCategory,
                        getCategoryDisplayName
                    };
                },
                template: readFileSync(join(__dirname, '../../../static/template/vue/mcp-server-app.html'), 'utf-8'),
            }));
            
            app.mount(this.$.app);
            panelDataMap.set(this, app);
            
            console.log('[MCP Panel] Vue3 app mounted successfully');
        }
    },
    beforeClose() { },
    close() {
        const app = panelDataMap.get(this);
        if (app) {
            app.unmount();
        }
    },
});
```

--------------------------------------------------------------------------------
/source/tools/scene-tools.ts:
--------------------------------------------------------------------------------

```typescript
import { ToolDefinition, ToolResponse, ToolExecutor, SceneInfo } from '../types';

export class SceneTools implements ToolExecutor {
    getTools(): ToolDefinition[] {
        return [
            {
                name: 'get_current_scene',
                description: 'Get current scene information',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'get_scene_list',
                description: 'Get all scenes in the project',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'open_scene',
                description: 'Open a scene by path',
                inputSchema: {
                    type: 'object',
                    properties: {
                        scenePath: {
                            type: 'string',
                            description: 'The scene file path'
                        }
                    },
                    required: ['scenePath']
                }
            },
            {
                name: 'save_scene',
                description: 'Save current scene',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'create_scene',
                description: 'Create a new scene asset',
                inputSchema: {
                    type: 'object',
                    properties: {
                        sceneName: {
                            type: 'string',
                            description: 'Name of the new scene'
                        },
                        savePath: {
                            type: 'string',
                            description: 'Path to save the scene (e.g., db://assets/scenes/NewScene.scene)'
                        }
                    },
                    required: ['sceneName', 'savePath']
                }
            },
            {
                name: 'save_scene_as',
                description: 'Save scene as new file',
                inputSchema: {
                    type: 'object',
                    properties: {
                        path: {
                            type: 'string',
                            description: 'Path to save the scene'
                        }
                    },
                    required: ['path']
                }
            },
            {
                name: 'close_scene',
                description: 'Close current scene',
                inputSchema: {
                    type: 'object',
                    properties: {}
                }
            },
            {
                name: 'get_scene_hierarchy',
                description: 'Get the complete hierarchy of current scene',
                inputSchema: {
                    type: 'object',
                    properties: {
                        includeComponents: {
                            type: 'boolean',
                            description: 'Include component information',
                            default: false
                        }
                    }
                }
            }
        ];
    }

    async execute(toolName: string, args: any): Promise<ToolResponse> {
        switch (toolName) {
            case 'get_current_scene':
                return await this.getCurrentScene();
            case 'get_scene_list':
                return await this.getSceneList();
            case 'open_scene':
                return await this.openScene(args.scenePath);
            case 'save_scene':
                return await this.saveScene();
            case 'create_scene':
                return await this.createScene(args.sceneName, args.savePath);
            case 'save_scene_as':
                return await this.saveSceneAs(args.path);
            case 'close_scene':
                return await this.closeScene();
            case 'get_scene_hierarchy':
                return await this.getSceneHierarchy(args.includeComponents);
            default:
                throw new Error(`Unknown tool: ${toolName}`);
        }
    }

    private async getCurrentScene(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // 直接使用 query-node-tree 来获取场景信息(这个方法已经验证可用)
            Editor.Message.request('scene', 'query-node-tree').then((tree: any) => {
                if (tree && tree.uuid) {
                    resolve({
                        success: true,
                        data: {
                            name: tree.name || 'Current Scene',
                            uuid: tree.uuid,
                            type: tree.type || 'cc.Scene',
                            active: tree.active !== undefined ? tree.active : true,
                            nodeCount: tree.children ? tree.children.length : 0
                        }
                    });
                } else {
                    resolve({ success: false, error: 'No scene data available' });
                }
            }).catch((err: Error) => {
                // 备用方案:使用场景脚本
                const options = {
                    name: 'cocos-mcp-server',
                    method: 'getCurrentSceneInfo',
                    args: []
                };
                
                Editor.Message.request('scene', 'execute-scene-script', options).then((result: any) => {
                    resolve(result);
                }).catch((err2: Error) => {
                    resolve({ success: false, error: `Direct API failed: ${err.message}, Scene script failed: ${err2.message}` });
                });
            });
        });
    }

    private async getSceneList(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // Note: query-assets API corrected with proper parameters
            Editor.Message.request('asset-db', 'query-assets', {
                pattern: 'db://assets/**/*.scene'
            }).then((results: any[]) => {
                const scenes: SceneInfo[] = results.map(asset => ({
                    name: asset.name,
                    path: asset.url,
                    uuid: asset.uuid
                }));
                resolve({ success: true, data: scenes });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async openScene(scenePath: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // 首先获取场景的UUID
            Editor.Message.request('asset-db', 'query-uuid', scenePath).then((uuid: string | null) => {
                if (!uuid) {
                    throw new Error('Scene not found');
                }
                
                // 使用正确的 scene API 打开场景 (需要UUID)
                return Editor.Message.request('scene', 'open-scene', uuid);
            }).then(() => {
                resolve({ success: true, message: `Scene opened: ${scenePath}` });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async saveScene(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('scene', 'save-scene').then(() => {
                resolve({ success: true, message: 'Scene saved successfully' });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async createScene(sceneName: string, savePath: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // 确保路径以.scene结尾
            const fullPath = savePath.endsWith('.scene') ? savePath : `${savePath}/${sceneName}.scene`;
            
            // 使用正确的Cocos Creator 3.8场景格式
            const sceneContent = JSON.stringify([
                {
                    "__type__": "cc.SceneAsset",
                    "_name": sceneName,
                    "_objFlags": 0,
                    "__editorExtras__": {},
                    "_native": "",
                    "scene": {
                        "__id__": 1
                    }
                },
                {
                    "__type__": "cc.Scene",
                    "_name": sceneName,
                    "_objFlags": 0,
                    "__editorExtras__": {},
                    "_parent": null,
                    "_children": [],
                    "_active": true,
                    "_components": [],
                    "_prefab": null,
                    "_lpos": {
                        "__type__": "cc.Vec3",
                        "x": 0,
                        "y": 0,
                        "z": 0
                    },
                    "_lrot": {
                        "__type__": "cc.Quat",
                        "x": 0,
                        "y": 0,
                        "z": 0,
                        "w": 1
                    },
                    "_lscale": {
                        "__type__": "cc.Vec3",
                        "x": 1,
                        "y": 1,
                        "z": 1
                    },
                    "_mobility": 0,
                    "_layer": 1073741824,
                    "_euler": {
                        "__type__": "cc.Vec3",
                        "x": 0,
                        "y": 0,
                        "z": 0
                    },
                    "autoReleaseAssets": false,
                    "_globals": {
                        "__id__": 2
                    },
                    "_id": "scene"
                },
                {
                    "__type__": "cc.SceneGlobals",
                    "ambient": {
                        "__id__": 3
                    },
                    "skybox": {
                        "__id__": 4
                    },
                    "fog": {
                        "__id__": 5
                    },
                    "octree": {
                        "__id__": 6
                    }
                },
                {
                    "__type__": "cc.AmbientInfo",
                    "_skyColorHDR": {
                        "__type__": "cc.Vec4",
                        "x": 0.2,
                        "y": 0.5,
                        "z": 0.8,
                        "w": 0.520833
                    },
                    "_skyColor": {
                        "__type__": "cc.Vec4",
                        "x": 0.2,
                        "y": 0.5,
                        "z": 0.8,
                        "w": 0.520833
                    },
                    "_skyIllumHDR": 20000,
                    "_skyIllum": 20000,
                    "_groundAlbedoHDR": {
                        "__type__": "cc.Vec4",
                        "x": 0.2,
                        "y": 0.2,
                        "z": 0.2,
                        "w": 1
                    },
                    "_groundAlbedo": {
                        "__type__": "cc.Vec4",
                        "x": 0.2,
                        "y": 0.2,
                        "z": 0.2,
                        "w": 1
                    }
                },
                {
                    "__type__": "cc.SkyboxInfo",
                    "_envLightingType": 0,
                    "_envmapHDR": null,
                    "_envmap": null,
                    "_envmapLodCount": 0,
                    "_diffuseMapHDR": null,
                    "_diffuseMap": null,
                    "_enabled": false,
                    "_useHDR": true,
                    "_editableMaterial": null,
                    "_reflectionHDR": null,
                    "_reflectionMap": null,
                    "_rotationAngle": 0
                },
                {
                    "__type__": "cc.FogInfo",
                    "_type": 0,
                    "_fogColor": {
                        "__type__": "cc.Color",
                        "r": 200,
                        "g": 200,
                        "b": 200,
                        "a": 255
                    },
                    "_enabled": false,
                    "_fogDensity": 0.3,
                    "_fogStart": 0.5,
                    "_fogEnd": 300,
                    "_fogAtten": 5,
                    "_fogTop": 1.5,
                    "_fogRange": 1.2,
                    "_accurate": false
                },
                {
                    "__type__": "cc.OctreeInfo",
                    "_enabled": false,
                    "_minPos": {
                        "__type__": "cc.Vec3",
                        "x": -1024,
                        "y": -1024,
                        "z": -1024
                    },
                    "_maxPos": {
                        "__type__": "cc.Vec3",
                        "x": 1024,
                        "y": 1024,
                        "z": 1024
                    },
                    "_depth": 8
                }
            ], null, 2);
            
            Editor.Message.request('asset-db', 'create-asset', fullPath, sceneContent).then((result: any) => {
                // Verify scene creation by checking if it exists
                this.getSceneList().then((sceneList) => {
                    const createdScene = sceneList.data?.find((scene: any) => scene.uuid === result.uuid);
                    resolve({
                        success: true,
                        data: {
                            uuid: result.uuid,
                            url: result.url,
                            name: sceneName,
                            message: `Scene '${sceneName}' created successfully`,
                            sceneVerified: !!createdScene
                        },
                        verificationData: createdScene
                    });
                }).catch(() => {
                    resolve({
                        success: true,
                        data: {
                            uuid: result.uuid,
                            url: result.url,
                            name: sceneName,
                            message: `Scene '${sceneName}' created successfully (verification failed)`
                        }
                    });
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async getSceneHierarchy(includeComponents: boolean = false): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // 优先尝试使用 Editor API 查询场景节点树
            Editor.Message.request('scene', 'query-node-tree').then((tree: any) => {
                if (tree) {
                    const hierarchy = this.buildHierarchy(tree, includeComponents);
                    resolve({
                        success: true,
                        data: hierarchy
                    });
                } else {
                    resolve({ success: false, error: 'No scene hierarchy available' });
                }
            }).catch((err: Error) => {
                // 备用方案:使用场景脚本
                const options = {
                    name: 'cocos-mcp-server',
                    method: 'getSceneHierarchy',
                    args: [includeComponents]
                };
                
                Editor.Message.request('scene', 'execute-scene-script', options).then((result: any) => {
                    resolve(result);
                }).catch((err2: Error) => {
                    resolve({ success: false, error: `Direct API failed: ${err.message}, Scene script failed: ${err2.message}` });
                });
            });
        });
    }

    private buildHierarchy(node: any, includeComponents: boolean): any {
        const nodeInfo: any = {
            uuid: node.uuid,
            name: node.name,
            type: node.type,
            active: node.active,
            children: []
        };

        if (includeComponents && node.__comps__) {
            nodeInfo.components = node.__comps__.map((comp: any) => ({
                type: comp.__type__ || 'Unknown',
                enabled: comp.enabled !== undefined ? comp.enabled : true
            }));
        }

        if (node.children) {
            nodeInfo.children = node.children.map((child: any) => 
                this.buildHierarchy(child, includeComponents)
            );
        }

        return nodeInfo;
    }

    private async saveSceneAs(path: string): Promise<ToolResponse> {
        return new Promise((resolve) => {
            // save-as-scene API 不接受路径参数,会弹出对话框让用户选择
            (Editor.Message.request as any)('scene', 'save-as-scene').then(() => {
                resolve({
                    success: true,
                    data: {
                        path: path,
                        message: `Scene save-as dialog opened`
                    }
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }

    private async closeScene(): Promise<ToolResponse> {
        return new Promise((resolve) => {
            Editor.Message.request('scene', 'close-scene').then(() => {
                resolve({
                    success: true,
                    message: 'Scene closed successfully'
                });
            }).catch((err: Error) => {
                resolve({ success: false, error: err.message });
            });
        });
    }
}
```
Page 1/3FirstPrevNextLast