#
tokens: 19810/50000 28/28 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .vscode
│   └── settings.json
├── addons
│   └── godot_mcp
│       ├── command_handler.gd
│       ├── command_handler.gd.uid
│       ├── commands
│       │   ├── base_command_processor.gd
│       │   ├── base_command_processor.gd.uid
│       │   ├── editor_commands.gd
│       │   ├── editor_commands.gd.uid
│       │   ├── editor_script_commands.gd
│       │   ├── editor_script_commands.gd.uid
│       │   ├── node_commands.gd
│       │   ├── node_commands.gd.uid
│       │   ├── project_commands.gd
│       │   ├── project_commands.gd.uid
│       │   ├── scene_commands.gd
│       │   ├── scene_commands.gd.uid
│       │   ├── script_commands.gd
│       │   └── script_commands.gd.uid
│       ├── mcp_server.gd
│       ├── mcp_server.gd.uid
│       ├── plugin.cfg
│       ├── ui
│       │   ├── mcp_panel.gd
│       │   ├── mcp_panel.gd.uid
│       │   └── mcp_panel.tscn
│       ├── utils
│       │   ├── node_utils.gd
│       │   ├── node_utils.gd.uid
│       │   ├── resource_utils.gd
│       │   ├── resource_utils.gd.uid
│       │   ├── script_utils.gd
│       │   └── script_utils.gd.uid
│       ├── websocket_server.gd
│       └── websocket_server.gd.uid
├── claude_desktop_config.json
├── CLAUDE.md
├── docs
│   ├── architecture.md
│   ├── command-reference.md
│   ├── getting-started.md
│   ├── godot-addon-readme.md
│   ├── implementation-plan.md
│   ├── installation-guide.md
│   └── mcp-server-readme.md
├── icon.svg
├── icon.svg.import
├── LICENSE
├── package-lock.json
├── project.godot
├── README.md
├── server
│   ├── dist
│   │   └── index.js
│   ├── package-lock.json
│   ├── package.json
│   ├── simple_client.js
│   ├── src
│   │   ├── index.ts
│   │   ├── resources
│   │   │   ├── editor_resources.ts
│   │   │   ├── project_resources.ts
│   │   │   ├── scene_resources.ts
│   │   │   └── script_resources.ts
│   │   ├── tools
│   │   │   ├── editor_tools.ts
│   │   │   ├── node_tools.ts
│   │   │   ├── scene_tools.ts
│   │   │   └── script_tools.ts
│   │   └── utils
│   │       ├── godot_connection.ts
│   │       └── types.ts
│   └── tsconfig.json
└── TestScene.tscn
```

# Files

--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------

```
root = true

[*]
charset = utf-8

```

--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------

```
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

```

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

```
# Godot-specific ignores
.godot/
.import/
export.cfg
export_presets.cfg

# Imported translations (automatically generated from CSV files)
*.translation

# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

# Node.js and npm
node_modules/
npm-debug.log
dist/

# System files
.DS_Store
Thumbs.db

# Build artifacts
*.o
*.os
*.obj
*.bc
*.pyc
*.pyo
__pycache__/

# Various temporary files
*.swp
*~
.~lock.*

```

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

```markdown
# Godot MCP (Model Context Protocol)

A comprehensive integration between Godot Engine and AI assistants using the Model Context Protocol (MCP). This plugin allows AI assistants to interact with your Godot projects, providing powerful capabilities for code assistance, scene manipulation, and project management.

## Features

- **Full Godot Project Access**: AI assistants can access and modify scripts, scenes, nodes, and project resources
- **Two-way Communication**: Send project data to AI and apply suggested changes directly in the editor
- **Command Categories**:
  - **Node Commands**: Create, modify, and manage nodes in your scenes
  - **Script Commands**: Edit, analyze, and create GDScript files
  - **Scene Commands**: Manipulate scenes and their structure
  - **Project Commands**: Access project settings and resources
  - **Editor Commands**: Control various editor functionality

## Quick Setup

### 1. Clone the Repository

```bash
git clone https://github.com/ee0pdt/godot-mcp.git
cd godot-mcp
```

### 2. Set Up the MCP Server

```bash
cd server
npm install
npm run build
# Return to project root
cd ..
```

### 3. Set Up Claude Desktop

1. Edit or create the Claude Desktop config file:
   ```bash
   # For macOS
   nano ~/Library/Application\ Support/Claude/claude_desktop_config.json
   ```

2. Add the following configuration (or use the included `claude_desktop_config.json` as a reference):
   ```json
   {
	 "mcpServers": {
	   "godot-mcp": {
		 "command": "node",
		 "args": [
		   "PATH_TO_YOUR_PROJECT/server/dist/index.js"
		 ],
		 "env": {
		   "MCP_TRANSPORT": "stdio"
		 }
	   }
	 }
   }
   ```
   > **Note**: Replace `PATH_TO_YOUR_PROJECT` with the absolute path to where you have this repository stored.

3. Restart Claude Desktop

### 4. Open the Example Project in Godot

1. Open Godot Engine
2. Select "Import" and navigate to the cloned repository
3. Open the `project.godot` file
4. The MCP plugin is already enabled in this example project

## Using MCP with Claude

After setup, you can work with your Godot project directly from Claude using natural language. Here are some examples:

### Example Prompts

```
@mcp godot-mcp read godot://script/current

I need help optimizing my player movement code. Can you suggest improvements?
```

```
@mcp godot-mcp run get-scene-tree

Add a cube in the middle of the scene and then make a camera that is looking at the cube.
```

```
@mcp godot-mcp read godot://scene/current

Create an enemy AI that patrols between waypoints and attacks the player when in range.
```

### Natural Language Tasks Claude Can Perform

- "Create a main menu with play, options, and quit buttons"
- "Add collision detection to the player character"
- "Implement a day/night cycle system"
- "Refactor this code to use signals instead of direct references"
- "Debug why my player character falls through the floor sometimes"

## Available Resources and Commands

### Resource Endpoints:
- `godot://script/current` - The currently open script
- `godot://scene/current` - The currently open scene
- `godot://project/info` - Project metadata and settings

### Command Categories:

#### Node Commands
- `get-scene-tree` - Returns the scene tree structure
- `get-node-properties` - Gets properties of a specific node
- `create-node` - Creates a new node
- `delete-node` - Deletes a node
- `modify-node` - Updates node properties

#### Script Commands
- `list-project-scripts` - Lists all scripts in the project
- `read-script` - Reads a specific script
- `modify-script` - Updates script content
- `create-script` - Creates a new script
- `analyze-script` - Provides analysis of a script

#### Scene Commands
- `list-project-scenes` - Lists all scenes in the project
- `read-scene` - Reads scene structure
- `create-scene` - Creates a new scene
- `save-scene` - Saves current scene

#### Project Commands
- `get-project-settings` - Gets project settings
- `list-project-resources` - Lists project resources

#### Editor Commands
- `get-editor-state` - Gets current editor state
- `run-project` - Runs the project
- `stop-project` - Stops the running project

## Troubleshooting

### Connection Issues
- Ensure the plugin is enabled in Godot's Project Settings
- Check the Godot console for any error messages
- Verify the server is running when Claude Desktop launches it


### Plugin Not Working
- Reload Godot project after any configuration changes
- Check for error messages in the Godot console
- Make sure all paths in your Claude Desktop config are absolute and correct

## Adding the Plugin to Your Own Godot Project

If you want to use the MCP plugin in your own Godot project:

1. Copy the `addons/godot_mcp` folder to your Godot project's `addons` directory
2. Open your project in Godot
3. Go to Project > Project Settings > Plugins
4. Enable the "Godot MCP" plugin

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Documentation

For more detailed information, check the documentation in the `docs` folder:

- [Getting Started](docs/getting-started.md)
- [Installation Guide](docs/installation-guide.md)
- [Command Reference](docs/command-reference.md)
- [Architecture](docs/architecture.md)

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

```

--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------

```markdown
# CLAUDE.md - Godot MCP Project Guidelines

## Build & Run Commands
- **Server Build**: `cd server && npm run build`
- **Server Start**: `cd server && npm run start`
- **Server Dev Mode**: `cd server && npm run dev` (auto-rebuild on changes)
- **Run Godot Project**: Open project.godot in Godot Editor

## Code Style Guidelines

### TypeScript (Server)
- Use camelCase for variables, methods, and function names
- Use PascalCase for classes/interfaces
- Strong typing: avoid `any` type
- Prefer async/await over Promise chains
- Import structure: Node modules first, then local modules

### GDScript (Godot)
- Use snake_case for variables, methods, and function names
- Use PascalCase for classes
- Use type hints where possible: `var player: Player`
- Follow Godot singleton conventions (e.g., `Engine`, `OS`)
- Prefer signals for communication between nodes

### General
- Use descriptive names
- Keep functions small and focused
- Add comments for complex logic
- Error handling: prefer try/catch in TS, use assertions in GDScript

```

--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------

```json
{
    "godotTools.editorPath.godot4": "/Applications/Godot.app"
}
```

--------------------------------------------------------------------------------
/claude_desktop_config.json:
--------------------------------------------------------------------------------

```json
{
  "mcpServers": {
	"godot-mcp": {
	  "command": "node",
	  "args": [
		"--experimental-modules",
		"/Users/Shared/Godot/godot-mcp/server/dist/index.js"
	  ],
	  "env": {
		"MCP_TRANSPORT": "stdio"
	  }
	}
  }
}

```

--------------------------------------------------------------------------------
/server/src/utils/types.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';

/**
 * Interface for FastMCP tool definition
 */
export interface MCPTool<T = any> {
  name: string;
  description: string;
  parameters: z.ZodType<T>;
  execute: (args: T) => Promise<string>;
}

/**
 * Generic response from a Godot command
 */
export interface CommandResult {
  [key: string]: any;
}
```

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

```json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "rootDir": "src",
    "sourceMap": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.test.ts"]
}
```

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

```json
{
  "name": "godot-mcp-server",
  "version": "1.0.0",
  "description": "Godot MCP Server using FastMCP",
  "type": "module",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "nodemon --watch src --exec \"tsc && node dist/index.js\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "godot",
    "mcp",
    "fastmcp",
    "claude",
    "ai"
  ],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "fastmcp": "^1.20.4",
    "websocket": "^1.0.35",
    "ws": "^8.13.0",
    "zod": "^3.21.4"
  },
  "devDependencies": {
    "@types/node": "^20.3.1",
    "@types/ws": "^8.5.5",
    "nodemon": "^2.0.22",
    "typescript": "^5.1.3"
  }
}

```

--------------------------------------------------------------------------------
/server/simple_client.js:
--------------------------------------------------------------------------------

```javascript
// The simplest possible WebSocket client
const WebSocket = require('ws');

console.log('=== STARTING ULTRA SIMPLE WEBSOCKET CLIENT ===');

const ws = new WebSocket('ws://localhost:9080');

ws.on('open', function() {
  console.log('Connected successfully!');
  ws.send('Hello from Node.js client!');
  console.log('Message sent');
});

ws.on('message', function(data) {
  console.log('Received:', data.toString());
  console.log('Test successful! Closing...');
  ws.close();
});

ws.on('error', function(error) {
  console.error('ERROR:', error.message);
});

ws.on('close', function(code, reason) {
  console.log('Connection closed. Code:', code, 'Reason:', reason || 'No reason');
  process.exit(0);
});

console.log('Client initialized, waiting for connection...');

// Exit after 10 seconds if nothing happens
setTimeout(() => {
  console.log('Timeout reached, exiting...');
  process.exit(1);
}, 10000);
```

--------------------------------------------------------------------------------
/icon.svg:
--------------------------------------------------------------------------------

```
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
```

--------------------------------------------------------------------------------
/server/src/tools/editor_tools.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';
import { getGodotConnection } from '../utils/godot_connection.js';
import { MCPTool } from '../utils/types.js';

interface ExecuteEditorScriptParams {
  code: string;
}

export const editorTools: MCPTool[] = [
  {
    name: 'execute_editor_script',
    description: 'Executes arbitrary GDScript code in the Godot editor',
    parameters: z.object({
      code: z.string()
        .describe('GDScript code to execute in the editor context'),
    }),
    execute: async ({ code }: ExecuteEditorScriptParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand('execute_editor_script', { code });
        
        // Format output for display
        let outputText = 'Script executed successfully';
        
        if (result.output && Array.isArray(result.output) && result.output.length > 0) {
          outputText += '\n\nOutput:\n' + result.output.join('\n');
        }
        
        if (result.result) {
          outputText += '\n\nResult:\n' + JSON.stringify(result.result, null, 2);
        }
        
        return outputText;
      } catch (error) {
        throw new Error(`Script execution failed: ${(error as Error).message}`);
      }
    },
  },
];
```

--------------------------------------------------------------------------------
/server/src/resources/scene_resources.ts:
--------------------------------------------------------------------------------

```typescript
import { Resource, ResourceTemplate } from 'fastmcp';
import { getGodotConnection } from '../utils/godot_connection.js';
import { z } from 'zod';

/**
 * Resource that provides a list of all scenes in the project
 */
export const sceneListResource: Resource = {
  uri: 'godot/scenes',
  name: 'Godot Scene List',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to list all scenes
      const result = await godot.sendCommand('list_project_files', {
        extensions: ['.tscn', '.scn']
      });
      
      if (result && result.files) {
        return {
          text: JSON.stringify({
            scenes: result.files,
            count: result.files.length
          })
        };
      } else {
        return {
          text: JSON.stringify({
            scenes: [],
            count: 0
          })
        };
      }
    } catch (error) {
      console.error('Error fetching scene list:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides detailed information about a specific scene
 */
export const sceneStructureResource: Resource = {
    uri: 'godot/scene/current',
    name: 'Godot Scene Structure',
    mimeType: 'application/json',
    async load() {
        const godot = getGodotConnection();
        
        try {
            // Call a command on the Godot side to get current scene structure
            const result = await godot.sendCommand('get_current_scene_structure', {});
            
            return {
                text: JSON.stringify(result)
            };
        } catch (error) {
            console.error('Error fetching scene structure:', error);
            throw error;
        }
    }
};

```

--------------------------------------------------------------------------------
/server/src/resources/project_resources.ts:
--------------------------------------------------------------------------------

```typescript
import { Resource } from 'fastmcp';
import { getGodotConnection } from '../utils/godot_connection.js';

/**
 * Resource that provides information about the Godot project structure
 */
export const projectStructureResource: Resource = {
  uri: 'godot/project/structure',
  name: 'Godot Project Structure',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get project structure
      const result = await godot.sendCommand('get_project_structure');
      
      return {
        text: JSON.stringify(result)
      };
    } catch (error) {
      console.error('Error fetching project structure:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides project settings
 */
export const projectSettingsResource: Resource = {
  uri: 'godot/project/settings',
  name: 'Godot Project Settings',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get project settings
      const result = await godot.sendCommand('get_project_settings');
      
      return {
        text: JSON.stringify(result)
      };
    } catch (error) {
      console.error('Error fetching project settings:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides a list of all project resources
 */
export const projectResourcesResource: Resource = {
  uri: 'godot/project/resources',
  name: 'Godot Project Resources',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get a list of all resources
      const result = await godot.sendCommand('list_project_resources');
      
      return {
        text: JSON.stringify(result)
      };
    } catch (error) {
      console.error('Error fetching project resources:', error);
      throw error;
    }
  }
};
```

--------------------------------------------------------------------------------
/docs/installation-guide.md:
--------------------------------------------------------------------------------

```markdown
# Godot MCP Installation Guide

This guide walks you through installing and setting up the Godot MCP integration to use Claude with your Godot projects.

## Prerequisites

- Godot 4.x installed
- Node.js 18+ and npm installed
- Claude desktop application with MCP enabled

## Installation Steps

### 1. Install the Godot Addon

1. Copy the `godot_mcp` folder from the `addons` directory to your Godot project's `addons` folder
2. In your Godot project, go to "Project > Project Settings > Plugins"
3. Find the "Godot MCP" plugin and enable it
4. You should now see a "Godot MCP Server" panel in your editor's right dock

### 2. Set up the MCP Server

1. Navigate to the `server` directory in your terminal
2. Install dependencies:
   ```bash
   npm install
   ```
3. Build the TypeScript code:
   ```bash
   npm run build
   ```

## Usage

### 1. Start the Godot WebSocket Server

1. Open your Godot project
2. In the "Godot MCP Server" panel, set the port (default: 9080)
3. Click "Start Server"
4. You should see a message confirming the server is running

### 2. Start the MCP Server

1. In the `server` directory, run:
   ```bash
   npm start
   ```
2. The server will automatically connect to the Godot WebSocket server

### 3. Connect Claude

1. In Claude desktop app, go to Settings > Developer
2. Enable Model Context Protocol
3. Add a new MCP tool with the following configuration:
   - Name: Godot MCP
   - Command: `node /path/to/godot-mcp/server/dist/index.js`
   - Working directory: `/path/to/your/project`
4. Save the configuration
5. When chatting with Claude, you can now access Godot tools

## Troubleshooting

### Connection Issues

If the MCP Server can't connect to Godot:
1. Make sure the Godot WebSocket server is running (check the panel)
2. Verify that the port numbers match in both the Godot panel and `godot_connection.ts`
3. Check for any firewall issues blocking localhost connections

### Command Errors

If commands are failing:
1. Check the logs in both the Godot panel and terminal running the MCP server
2. Make sure your Godot project is properly set up and has an active scene
3. Verify that paths used in commands follow the correct format (usually starting with "res://")
```

--------------------------------------------------------------------------------
/server/src/resources/editor_resources.ts:
--------------------------------------------------------------------------------

```typescript
import { Resource } from 'fastmcp';
import { getGodotConnection } from '../utils/godot_connection.js';

/**
 * Resource that provides information about the current state of the Godot editor
 */
export const editorStateResource: Resource = {
  uri: 'godot/editor/state',
  name: 'Godot Editor State',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get editor state
      const result = await godot.sendCommand('get_editor_state');
      
      return {
        text: JSON.stringify(result)
      };
    } catch (error) {
      console.error('Error fetching editor state:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides information about the currently selected node
 */
export const selectedNodeResource: Resource = {
  uri: 'godot/editor/selected_node',
  name: 'Godot Selected Node',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get selected node
      const result = await godot.sendCommand('get_selected_node');
      
      return {
        text: JSON.stringify(result)
      };
    } catch (error) {
      console.error('Error fetching selected node:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides information about the currently edited script
 */
export const currentScriptResource: Resource = {
  uri: 'godot/editor/current_script',
  name: 'Current Script in Editor',
  mimeType: 'text/plain',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to get current script
      const result = await godot.sendCommand('get_current_script');
      
      // If we got a script path, return script content and metadata
      if (result && result.script_found && result.content) {
        return {
          text: result.content,
          metadata: {
            path: result.script_path,
            language: result.script_path.endsWith('.gd') ? 'gdscript' : 
                     result.script_path.endsWith('.cs') ? 'csharp' : 'unknown'
          }
        };
      } else {
        return {
          text: '',
          metadata: {
            error: 'No script currently being edited',
            script_found: false
          }
        };
      }
    } catch (error) {
      console.error('Error fetching current script:', error);
      throw error;
    }
  }
};
```

--------------------------------------------------------------------------------
/server/src/index.ts:
--------------------------------------------------------------------------------

```typescript
import { FastMCP } from 'fastmcp';
import { nodeTools } from './tools/node_tools.js';
import { scriptTools } from './tools/script_tools.js';
import { sceneTools } from './tools/scene_tools.js';
import { editorTools } from './tools/editor_tools.js';
import { getGodotConnection } from './utils/godot_connection.js';

// Import resources
import { 
  sceneListResource, 
  sceneStructureResource 
} from './resources/scene_resources.js';
import { 
  scriptResource, 
  scriptListResource,
  scriptMetadataResource 
} from './resources/script_resources.js';
import { 
  projectStructureResource,
  projectSettingsResource,
  projectResourcesResource 
} from './resources/project_resources.js';
import { 
  editorStateResource,
  selectedNodeResource,
  currentScriptResource 
} from './resources/editor_resources.js';

/**
 * Main entry point for the Godot MCP server
 */
async function main() {
  console.error('Starting Godot MCP server...');

  // Create FastMCP instance
  const server = new FastMCP({
    name: 'GodotMCP',
    version: '1.0.0',
  });

  // Register all tools
  [...nodeTools, ...scriptTools, ...sceneTools, ...editorTools].forEach(tool => {
    server.addTool(tool);
  });

  // Register all resources
  // Static resources
  server.addResource(sceneListResource);
  server.addResource(scriptListResource);
  server.addResource(projectStructureResource);
  server.addResource(projectSettingsResource);
  server.addResource(projectResourcesResource);
  server.addResource(editorStateResource);
  server.addResource(selectedNodeResource);
  server.addResource(currentScriptResource);
  server.addResource(sceneStructureResource);
  server.addResource(scriptResource);
  server.addResource(scriptMetadataResource);

  // Try to connect to Godot
  try {
    const godot = getGodotConnection();
    await godot.connect();
    console.error('Successfully connected to Godot WebSocket server');
  } catch (error) {
    const err = error as Error;
    console.warn(`Could not connect to Godot: ${err.message}`);
    console.warn('Will retry connection when commands are executed');
  }

  // Start the server
  server.start({
    transportType: 'stdio',
  });

  console.error('Godot MCP server started');

  // Handle cleanup
  const cleanup = () => {
    console.error('Shutting down Godot MCP server...');
    const godot = getGodotConnection();
    godot.disconnect();
    process.exit(0);
  };

  process.on('SIGINT', cleanup);
  process.on('SIGTERM', cleanup);
}

// Start the server
main().catch(error => {
  console.error('Failed to start Godot MCP server:', error);
  process.exit(1);
});

```

--------------------------------------------------------------------------------
/server/src/resources/script_resources.ts:
--------------------------------------------------------------------------------

```typescript
import { Resource, ResourceTemplate } from 'fastmcp';
import { getGodotConnection } from '../utils/godot_connection.js';
import { z } from 'zod';

/**
 * Resource that provides the content of a specific script
 * Note: As a Resource (not ResourceTemplate), it cannot handle dynamic paths
 */
export const scriptResource: Resource = {
    uri: 'godot/script',
    name: 'Godot Script Content',
    mimeType: 'text/plain',
    async load() {
        const godot = getGodotConnection();
        
        try {
            // Without parameters, this can only load a predefined script
            // You would need to hardcode the script path here
            const scriptPath = 'res://default_script.gd';
            
            const result = await godot.sendCommand('get_script', {
                path: scriptPath
            });
            
            return {
                text: result.content,
                metadata: {
                    path: result.script_path,
                    language: scriptPath.endsWith('.gd') ? 'gdscript' : 
                                     scriptPath.endsWith('.cs') ? 'csharp' : 'unknown'
                }
            };
        } catch (error) {
            console.error('Error fetching script content:', error);
            throw error;
        }
    }
};

/**
 * Resource that provides a list of all scripts in the project
 */
export const scriptListResource: Resource = {
  uri: 'godot/scripts',
  name: 'Godot Script List',
  mimeType: 'application/json',
  async load() {
    const godot = getGodotConnection();
    
    try {
      // Call a command on the Godot side to list all scripts
      const result = await godot.sendCommand('list_project_files', {
        extensions: ['.gd', '.cs']
      });
      
      if (result && result.files) {
        return {
          text: JSON.stringify({
            scripts: result.files,
            count: result.files.length,
            gdscripts: result.files.filter((f: string) => f.endsWith('.gd')),
            csharp_scripts: result.files.filter((f: string) => f.endsWith('.cs'))
          })
        };
      } else {
        return {
          text: JSON.stringify({
            scripts: [],
            count: 0,
            gdscripts: [],
            csharp_scripts: []
          })
        };
      }
    } catch (error) {
      console.error('Error fetching script list:', error);
      throw error;
    }
  }
};

/**
 * Resource that provides metadata for a specific script, including classes and methods
 */
export const scriptMetadataResource: Resource = {
    uri: 'godot/script/metadata',
    name: 'Godot Script Metadata',
    mimeType: 'application/json',
    async load() {
        const godot = getGodotConnection();
        
        // Use a fixed script path
        let scriptPath = 'res://default_script.gd';
        
        try {
            // Call a command on the Godot side to get script metadata
            const result = await godot.sendCommand('get_script_metadata', {
                path: scriptPath
            });
            
            return {
                text: JSON.stringify(result)
            };
        } catch (error) {
            console.error('Error fetching script metadata:', error);
            throw error;
        }
    }
};

```

--------------------------------------------------------------------------------
/docs/command-reference.md:
--------------------------------------------------------------------------------

```markdown
# Godot MCP Command Reference

This document provides a reference for the commands available through the Godot MCP integration.

## Node Tools

### create_node
Create a new node in the Godot scene tree.

**Parameters:**
- `parent_path` - Path to the parent node (e.g., "/root", "/root/MainScene")
- `node_type` - Type of node to create (e.g., "Node2D", "Sprite2D", "Label")
- `node_name` - Name for the new node

**Example:**
```
Create a Button node named "StartButton" under the CanvasLayer.
```

### delete_node
Delete a node from the scene tree.

**Parameters:**
- `node_path` - Path to the node to delete

**Example:**
```
Delete the node at "/root/MainScene/UI/OldButton".
```

### update_node_property
Update a property of a node.

**Parameters:**
- `node_path` - Path to the node to update
- `property` - Name of the property to update
- `value` - New value for the property

**Example:**
```
Update the "text" property of the node at "/root/MainScene/UI/Label" to "Game Over".
```

### get_node_properties
Get all properties of a node.

**Parameters:**
- `node_path` - Path to the node to inspect

**Example:**
```
Show me all the properties of the node at "/root/MainScene/Player".
```

### list_nodes
List all child nodes under a parent node.

**Parameters:**
- `parent_path` - Path to the parent node

**Example:**
```
List all nodes under "/root/MainScene/UI".
```

## Script Tools

### create_script
Create a new GDScript file.

**Parameters:**
- `script_path` - Path where the script will be saved
- `content` - Content of the script
- `node_path` (optional) - Path to a node to attach the script to

**Example:**
```
Create a script at "res://scripts/player_controller.gd" with a basic movement system.
```

### edit_script
Edit an existing GDScript file.

**Parameters:**
- `script_path` - Path to the script file to edit
- `content` - New content of the script

**Example:**
```
Update the script at "res://scripts/player_controller.gd" to add a jump function.
```

### get_script
Get the content of a GDScript file.

**Parameters:**
- `script_path` (optional) - Path to the script file
- `node_path` (optional) - Path to a node with a script attached

**Example:**
```
Show me the script attached to the node at "/root/MainScene/Player".
```

### create_script_template
Generate a GDScript template with common boilerplate.

**Parameters:**
- `class_name` (optional) - Optional class name for the script
- `extends_type` - Base class that this script extends (default: "Node")
- `include_ready` - Whether to include the _ready() function (default: true)
- `include_process` - Whether to include the _process() function (default: false)
- `include_input` - Whether to include the _input() function (default: false)
- `include_physics` - Whether to include the _physics_process() function (default: false)

**Example:**
```
Create a script template for a KinematicBody2D with process and input functions.
```

## Scene Tools

### create_scene
Creates a new empty scene with an optional root node type.

**Parameters:**
- `path` (string): Path where the new scene will be saved (e.g. "res://scenes/new_scene.tscn")
- `root_node_type` (string, optional): Type of root node to create (e.g. "Node2D", "Node3D", "Control"). Defaults to "Node" if not specified

**Returns:**
- `scene_path` (string): Path where the scene was saved
- `root_node_type` (string): The type of the root node that was created

**Example:**
```typescript
// Create a new scene with a Node2D as root
const result = await mcp.execute('create_scene', {
  path: 'res://scenes/game_level.tscn',
  root_node_type: 'Node2D'
});
console.log(`Created scene at ${result.scene_path}`);
```

### save_scene
Save the current scene to disk.

**Parameters:**
- `path` (optional) - Path where the scene will be saved (uses current path if not provided)

**Example:**
```
Save the current scene to "res://scenes/level_1.tscn".
```

### open_scene
Open a scene in the editor.

**Parameters:**
- `path` - Path to the scene file to open

**Example:**
```
Open the scene at "res://scenes/main_menu.tscn".
```

### get_current_scene
Get information about the currently open scene.

**Parameters:** None

**Example:**
```
What scene am I currently editing?
```

### get_project_info
Get information about the current Godot project.

**Parameters:** None

**Example:**
```
Tell me about the current project.
```

### create_resource
Create a new resource in the project.

**Parameters:**
- `resource_type` - Type of resource to create
- `resource_path` - Path where the resource will be saved
- `properties` (optional) - Dictionary of property values to set on the resource

**Example:**
```
Create a StyleBoxFlat resource at "res://resources/button_style.tres" with a blue background color.
```

## Using Commands with Claude

When working with Claude, you don't need to specify the exact command name or format. Instead, describe what you want to do in natural language, and Claude will use the appropriate command. For example:

```
Claude, can you create a new Label node under the UI node with the text "Score: 0"?
```

Claude will understand this request and use the `create_node` command with the appropriate parameters.
```

--------------------------------------------------------------------------------
/server/src/tools/node_tools.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';
import { getGodotConnection } from '../utils/godot_connection.js';
import { MCPTool, CommandResult } from '../utils/types.js';

/**
 * Type definitions for node tool parameters
 */
interface CreateNodeParams {
  parent_path: string;
  node_type: string;
  node_name: string;
}

interface DeleteNodeParams {
  node_path: string;
}

interface UpdateNodePropertyParams {
  node_path: string;
  property: string;
  value: any;
}

interface GetNodePropertiesParams {
  node_path: string;
}

interface ListNodesParams {
  parent_path: string;
}

/**
 * Definition for node tools - operations that manipulate nodes in the scene tree
 */
export const nodeTools: MCPTool[] = [
  {
    name: 'create_node',
    description: 'Create a new node in the Godot scene tree',
    parameters: z.object({
      parent_path: z.string()
        .describe('Path to the parent node where the new node will be created (e.g. "/root", "/root/MainScene")'),
      node_type: z.string()
        .describe('Type of node to create (e.g. "Node2D", "Sprite2D", "Label")'),
      node_name: z.string()
        .describe('Name for the new node'),
    }),
    execute: async ({ parent_path, node_type, node_name }: CreateNodeParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('create_node', {
          parent_path,
          node_type,
          node_name,
        });
        
        return `Created ${node_type} node named "${node_name}" at ${result.node_path}`;
      } catch (error) {
        throw new Error(`Failed to create node: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'delete_node',
    description: 'Delete a node from the Godot scene tree',
    parameters: z.object({
      node_path: z.string()
        .describe('Path to the node to delete (e.g. "/root/MainScene/Player")'),
    }),
    execute: async ({ node_path }: DeleteNodeParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        await godot.sendCommand('delete_node', { node_path });
        return `Deleted node at ${node_path}`;
      } catch (error) {
        throw new Error(`Failed to delete node: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'update_node_property',
    description: 'Update a property of a node in the Godot scene tree',
    parameters: z.object({
      node_path: z.string()
        .describe('Path to the node to update (e.g. "/root/MainScene/Player")'),
      property: z.string()
        .describe('Name of the property to update (e.g. "position", "text", "modulate")'),
      value: z.any()
        .describe('New value for the property'),
    }),
    execute: async ({ node_path, property, value }: UpdateNodePropertyParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('update_node_property', {
          node_path,
          property,
          value,
        });
        
        return `Updated property "${property}" of node at ${node_path} to ${JSON.stringify(value)}`;
      } catch (error) {
        throw new Error(`Failed to update node property: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'get_node_properties',
    description: 'Get all properties of a node in the Godot scene tree',
    parameters: z.object({
      node_path: z.string()
        .describe('Path to the node to inspect (e.g. "/root/MainScene/Player")'),
    }),
    execute: async ({ node_path }: GetNodePropertiesParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('get_node_properties', { node_path });
        
        // Format properties for display
        const formattedProperties = Object.entries(result.properties)
          .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
          .join('\n');
        
        return `Properties of node at ${node_path}:\n\n${formattedProperties}`;
      } catch (error) {
        throw new Error(`Failed to get node properties: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'list_nodes',
    description: 'List all child nodes under a parent node in the Godot scene tree',
    parameters: z.object({
      parent_path: z.string()
        .describe('Path to the parent node (e.g. "/root", "/root/MainScene")'),
    }),
    execute: async ({ parent_path }: ListNodesParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('list_nodes', { parent_path });
        
        if (result.children.length === 0) {
          return `No child nodes found under ${parent_path}`;
        }
        
        // Format children for display
        const formattedChildren = result.children
          .map((child: any) => `${child.name} (${child.type}) - ${child.path}`)
          .join('\n');
        
        return `Children of node at ${parent_path}:\n\n${formattedChildren}`;
      } catch (error) {
        throw new Error(`Failed to list nodes: ${(error as Error).message}`);
      }
    },
  },
];
```

--------------------------------------------------------------------------------
/server/src/tools/scene_tools.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';
import { getGodotConnection } from '../utils/godot_connection.js';
import { MCPTool, CommandResult } from '../utils/types.js';

/**
 * Type definitions for scene tool parameters
 */
interface SaveSceneParams {
  path?: string;
}

interface OpenSceneParams {
  path: string;
}

interface CreateSceneParams {
  path: string;
  root_node_type?: string;
}

interface CreateResourceParams {
  resource_type: string;
  resource_path: string;
  properties?: Record<string, any>;
}

/**
 * Definition for scene tools - operations that manipulate Godot scenes
 */
export const sceneTools: MCPTool[] = [
  {
    name: 'create_scene',
    description: 'Create a new empty scene with optional root node type',
    parameters: z.object({
      path: z.string()
        .describe('Path where the new scene will be saved (e.g. "res://scenes/new_scene.tscn")'),
      root_node_type: z.string().optional()
        .describe('Type of root node to create (e.g. "Node2D", "Node3D", "Control"). Defaults to "Node" if not specified'),
    }),
    execute: async ({ path, root_node_type = "Node" }: CreateSceneParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('create_scene', { path, root_node_type });
        return `Created new scene at ${result.scene_path} with root node type ${result.root_node_type}`;
      } catch (error) {
        throw new Error(`Failed to create scene: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'save_scene',
    description: 'Save the current scene to disk',
    parameters: z.object({
      path: z.string().optional()
        .describe('Path where the scene will be saved (e.g. "res://scenes/main.tscn"). If not provided, uses current scene path.'),
    }),
    execute: async ({ path }: SaveSceneParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('save_scene', { path });
        return `Saved scene to ${result.scene_path}`;
      } catch (error) {
        throw new Error(`Failed to save scene: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'open_scene',
    description: 'Open a scene in the editor',
    parameters: z.object({
      path: z.string()
        .describe('Path to the scene file to open (e.g. "res://scenes/main.tscn")'),
    }),
    execute: async ({ path }: OpenSceneParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('open_scene', { path });
        return `Opened scene at ${result.scene_path}`;
      } catch (error) {
        throw new Error(`Failed to open scene: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'get_current_scene',
    description: 'Get information about the currently open scene',
    parameters: z.object({}),
    execute: async (): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('get_current_scene', {});
        
        return `Current scene: ${result.scene_path}\nRoot node: ${result.root_node_name} (${result.root_node_type})`;
      } catch (error) {
        throw new Error(`Failed to get current scene: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'get_project_info',
    description: 'Get information about the current Godot project',
    parameters: z.object({}),
    execute: async (): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('get_project_info', {});
        
        const godotVersion = `${result.godot_version.major}.${result.godot_version.minor}.${result.godot_version.patch}`;
        
        let output = `Project Name: ${result.project_name}\n`;
        output += `Project Version: ${result.project_version}\n`;
        output += `Project Path: ${result.project_path}\n`;
        output += `Godot Version: ${godotVersion}\n`;
        
        if (result.current_scene) {
          output += `Current Scene: ${result.current_scene}`;
        } else {
          output += "No scene is currently open";
        }
        
        return output;
      } catch (error) {
        throw new Error(`Failed to get project info: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'create_resource',
    description: 'Create a new resource in the project',
    parameters: z.object({
      resource_type: z.string()
        .describe('Type of resource to create (e.g. "ImageTexture", "AudioStreamMP3", "StyleBoxFlat")'),
      resource_path: z.string()
        .describe('Path where the resource will be saved (e.g. "res://resources/style.tres")'),
      properties: z.record(z.any()).optional()
        .describe('Dictionary of property values to set on the resource'),
    }),
    execute: async ({ resource_type, resource_path, properties = {} }: CreateResourceParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('create_resource', {
          resource_type,
          resource_path,
          properties,
        });
        
        return `Created ${resource_type} resource at ${result.resource_path}`;
      } catch (error) {
        throw new Error(`Failed to create resource: ${(error as Error).message}`);
      }
    },
  },
];
```

--------------------------------------------------------------------------------
/server/src/tools/script_tools.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';
import { getGodotConnection } from '../utils/godot_connection.js';
import { MCPTool, CommandResult } from '../utils/types.js';

/**
 * Type definitions for script tool parameters
 */
interface CreateScriptParams {
  script_path: string;
  content: string;
  node_path?: string;
}

interface EditScriptParams {
  script_path: string;
  content: string;
}

interface GetScriptParams {
  script_path?: string;
  node_path?: string;
}

interface CreateScriptTemplateParams {
  class_name?: string;
  extends_type: string;
  include_ready: boolean;
  include_process: boolean;
  include_input: boolean;
  include_physics: boolean;
}

/**
 * Definition for script tools - operations that manipulate GDScript files
 */
export const scriptTools: MCPTool[] = [
  {
    name: 'create_script',
    description: 'Create a new GDScript file in the project',
    parameters: z.object({
      script_path: z.string()
        .describe('Path where the script will be saved (e.g. "res://scripts/player.gd")'),
      content: z.string()
        .describe('Content of the script'),
      node_path: z.string().optional()
        .describe('Path to a node to attach the script to (optional)'),
    }),
    execute: async ({ script_path, content, node_path }: CreateScriptParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('create_script', {
          script_path,
          content,
          node_path,
        });
        
        const attachMessage = node_path 
          ? ` and attached to node at ${node_path}` 
          : '';
        
        return `Created script at ${result.script_path}${attachMessage}`;
      } catch (error) {
        throw new Error(`Failed to create script: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'edit_script',
    description: 'Edit an existing GDScript file',
    parameters: z.object({
      script_path: z.string()
        .describe('Path to the script file to edit (e.g. "res://scripts/player.gd")'),
      content: z.string()
        .describe('New content of the script'),
    }),
    execute: async ({ script_path, content }: EditScriptParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        await godot.sendCommand('edit_script', {
          script_path,
          content,
        });
        
        return `Updated script at ${script_path}`;
      } catch (error) {
        throw new Error(`Failed to edit script: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'get_script',
    description: 'Get the content of a GDScript file',
    parameters: z.object({
      script_path: z.string().optional()
        .describe('Path to the script file (e.g. "res://scripts/player.gd")'),
      node_path: z.string().optional()
        .describe('Path to a node with a script attached'),
    }).refine(data => data.script_path !== undefined || data.node_path !== undefined, {
      message: "Either script_path or node_path must be provided",
    }),
    execute: async ({ script_path, node_path }: GetScriptParams): Promise<string> => {
      const godot = getGodotConnection();
      
      try {
        const result = await godot.sendCommand<CommandResult>('get_script', {
          script_path,
          node_path,
        });
        
        return `Script at ${result.script_path}:\n\n\`\`\`gdscript\n${result.content}\n\`\`\``;
      } catch (error) {
        throw new Error(`Failed to get script: ${(error as Error).message}`);
      }
    },
  },

  {
    name: 'create_script_template',
    description: 'Generate a GDScript template with common boilerplate',
    parameters: z.object({
      class_name: z.string().optional()
        .describe('Optional class name for the script'),
      extends_type: z.string().default('Node')
        .describe('Base class that this script extends (e.g. "Node", "Node2D", "Control")'),
      include_ready: z.boolean().default(true)
        .describe('Whether to include the _ready() function'),
      include_process: z.boolean().default(false)
        .describe('Whether to include the _process() function'),
      include_input: z.boolean().default(false)
        .describe('Whether to include the _input() function'),
      include_physics: z.boolean().default(false)
        .describe('Whether to include the _physics_process() function'),
    }),
    execute: async ({ 
      class_name, 
      extends_type, 
      include_ready, 
      include_process, 
      include_input, 
      include_physics 
    }: CreateScriptTemplateParams): Promise<string> => {
      // Generate the template locally without needing to call Godot
      let template = '';
      
      // Add class_name if provided
      if (class_name) {
        template += `class_name ${class_name}\n`;
      }
      
      // Add extends
      template += `extends ${extends_type}\n\n`;
      
      // Add common lifecycle methods
      if (include_ready) {
        template += `func _ready():\n\tpass\n\n`;
      }
      
      if (include_process) {
        template += `func _process(delta):\n\tpass\n\n`;
      }
      
      if (include_physics) {
        template += `func _physics_process(delta):\n\tpass\n\n`;
      }
      
      if (include_input) {
        template += `func _input(event):\n\tpass\n\n`;
      }
      
      // Remove trailing newlines
      template = template.trimEnd();
      
      return `Generated GDScript template:\n\n\`\`\`gdscript\n${template}\n\`\`\``;
    },
  },
];
```

--------------------------------------------------------------------------------
/docs/mcp-server-readme.md:
--------------------------------------------------------------------------------

```markdown
# Godot MCP Server

This TypeScript server implements the Model Context Protocol (MCP) to connect Claude AI with Godot Engine. It allows Claude to interact with Godot projects through natural language commands.

## Features

- **MCP Implementation**: Full implementation of the Model Context Protocol
- **Godot Connection**: WebSocket-based connection to the Godot editor
- **Tool Definitions**: Pre-defined tools for common Godot operations
- **Error Handling**: Comprehensive error handling and logging
- **Session Management**: Support for multiple client sessions

## Installation

### Prerequisites

- Node.js 16.x or higher
- npm or yarn
- Godot Engine 4.x with the Godot MCP addon installed

### Setup

1. Clone the repository
2. Install dependencies:

```bash
npm install
```

3. Build the server:

```bash
npm run build
```

## Usage

### Starting the Server

Start the server using one of the following methods:

#### CLI

```bash
# Start with stdio transport (for Claude Desktop)
npm start

# Start with SSE transport (for web-based Claude)
npm run start:sse
```

#### Programmatic Usage

```typescript
import { server } from './src/index';

// Start with stdio transport
server.start({
  transportType: 'stdio'
});

// Start with SSE transport
server.start({
  transportType: 'sse',
  sse: {
    endpoint: '/sse',
    port: 8080
  }
});
```

### Connecting to Godot

1. Ensure the Godot MCP addon is installed and enabled in your Godot project
2. Start the WebSocket server in Godot using the MCP panel
3. The MCP server will automatically connect to Godot when needed

### Configuration

Configure the server by creating a `.env` file:

```
# Godot WebSocket connection
GODOT_WS_URL=ws://localhost:9080

# Server settings
LOG_LEVEL=info
COMMAND_TIMEOUT=10000

# SSE transport settings (if using SSE)
SSE_PORT=8080
SSE_ENDPOINT=/sse
```

## Tool Reference

The server provides the following tools to Claude:

### Node Management

- **create_node**: Create a new node in the scene tree
- **delete_node**: Remove a node from the scene tree
- **update_node**: Update node properties
- **list_nodes**: Get a list of nodes in the scene

### Script Management

- **create_script**: Create a new GDScript file
- **edit_script**: Modify an existing script
- **get_script**: Get a script's content

### Resource Management

- **create_resource**: Create a new resource
- **list_resources**: List resources in a directory

### Scene Management

- **save_scene**: Save the current scene
- **open_scene**: Open a scene file

## Implementation Details

### Architecture

The server follows a modular architecture:

```
src/
├── index.ts              # Entry point
├── godot_connection.ts   # Godot WebSocket connection manager
├── tools/                # Tool definitions
│   ├── node_tools.ts     # Node manipulation tools
│   ├── script_tools.ts   # Script manipulation tools
│   └── resource_tools.ts # Resource manipulation tools
└── utils/                # Utility functions
    ├── websocket.ts      # WebSocket utilities
    └── error_handler.ts  # Error handling utilities
```

### Key Classes

- **GodotConnection**: Manages the WebSocket connection to Godot
- **FastMCP**: Implements the Model Context Protocol
- **Tool Definitions**: Define operations available to Claude

### WebSocket Communication

The server communicates with Godot using a JSON-based protocol:

#### Command Format
```json
{
  "type": "command_type",
  "params": {
    "param1": "value1",
    "param2": "value2"
  },
  "commandId": "unique_command_id"
}
```

#### Response Format
```json
{
  "status": "success|error",
  "result": { ... },
  "message": "Error message if status is error",
  "commandId": "matching_command_id"
}
```

## Development

### Project Structure

```
godot-mcp-server/
├── src/                  # Source code
├── dist/                 # Compiled output
├── tests/                # Test files
├── docs/                 # Documentation
├── package.json          # Project configuration
└── tsconfig.json         # TypeScript configuration
```

### Adding New Tools

To add a new tool:

1. Create a new function in the appropriate tool file
2. Register the tool with FastMCP
3. Add parameter validation using Zod
4. Implement the tool logic using the Godot connection

Example:

```typescript
server.addTool({
  name: 'my_new_tool',
  description: 'Description of what the tool does',
  parameters: z.object({
    param1: z.string().describe('Description of param1'),
    param2: z.number().describe('Description of param2')
  }),
  execute: async (args) => {
    const godot = getGodotConnection();
    try {
      const result = await godot.sendCommand('my_command', args);
      return `Operation completed: ${result.someValue}`;
    } catch (error) {
      throw new Error(`Failed: ${error.message}`);
    }
  }
});
```

### Building

```bash
# Build the project
npm run build

# Build in watch mode
npm run build:watch
```

### Testing

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch
```

## Troubleshooting

### Connection Issues

- Verify the Godot WebSocket server is running
- Check that the WebSocket URL is correct
- Ensure no firewalls are blocking the connection

### Tool Execution Errors

- Check the tool parameters
- Look for detailed error messages in the logs
- Verify the Godot project is properly set up

### MCP Protocol Issues

- Check the Claude Desktop configuration
- Verify the MCP server is properly registered
- Look for errors in the Claude Desktop logs

## License

This project is licensed under the MIT License. See the LICENSE file for details.

## Acknowledgements

This project is built with:
- [FastMCP](https://github.com/punkpeye/fastmcp) - TypeScript MCP implementation
- [ws](https://github.com/websockets/ws) - WebSocket implementation
- [zod](https://github.com/colinhacks/zod) - Schema validation
```

--------------------------------------------------------------------------------
/docs/architecture.md:
--------------------------------------------------------------------------------

```markdown
# Godot MCP Architecture

This document details the architecture of the Godot Model Context Protocol (MCP) integration, explaining the design decisions, component interactions, and communication protocols.

## Overview

The Godot MCP architecture enables bidirectional communication between Claude AI and the Godot game engine using the Model Context Protocol. This allows Claude to interact with Godot projects through natural language commands, performing operations like node creation, script editing, and resource management.

## Key Design Goals

1. **Bidirectional Communication**: Enable Claude to both receive information from and send commands to Godot
2. **Robust Error Handling**: Provide clear error messages and recovery mechanisms
3. **Modularity**: Separate concerns between Godot-specific logic and MCP protocol handling
4. **Extensibility**: Make it easy to add new commands and capabilities
5. **Performance**: Minimize impact on Godot editor performance

## System Components

### 1. Godot Addon

The Godot addon runs within the Godot editor and provides:

#### WebSocket Server
- Creates a WebSocket server within Godot
- Handles client connections and message routing
- Processes incoming JSON commands
- Formats and sends JSON responses

#### Command Execution Engine
- Routes commands to appropriate handlers
- Executes Godot API calls
- Manages command execution context
- Provides error handling and response formatting

#### Editor Integration
- Provides a dock panel UI for server control
- Displays connection status and logs
- Offers configuration options
- Ensures proper lifecycle management within Godot

### 2. MCP Server

The MCP server bridges Claude and Godot:

#### FastMCP Implementation
- Uses FastMCP to implement the Model Context Protocol
- Handles communication with Claude
- Manages tool registration and execution
- Provides authentication and session management

#### Godot Connection Manager
- Maintains WebSocket connection to Godot
- Sends commands and receives responses
- Handles reconnection and timeout logic
- Provides a promise-based API for commands

#### Tool Definitions
- Defines available operations for Claude
- Validates command parameters
- Formats responses for Claude's consumption
- Provides help text and examples

## Communication Protocol

### Command Flow

1. **Claude to MCP Server**: Claude generates a command request through the MCP protocol
2. **MCP Server to Godot**: MCP server sends a WebSocket command message to Godot
3. **Godot Execution**: Godot processes the command and executes relevant engine API calls
4. **Godot to MCP Server**: Godot sends a response message to the MCP server
5. **MCP Server to Claude**: MCP server formats the response for Claude

### Message Formats

#### Command Message (MCP Server to Godot)
```json
{
  "type": "command_type",
  "params": {
    "param1": "value1",
    "param2": "value2"
  },
  "commandId": "cmd_123"
}
```

#### Response Message (Godot to MCP Server)
```json
{
  "status": "success",
  "result": {
    "key1": "value1",
    "key2": "value2"
  },
  "commandId": "cmd_123"
}
```

#### Error Response (Godot to MCP Server)
```json
{
  "status": "error",
  "message": "Detailed error message",
  "commandId": "cmd_123"
}
```

## Key Design Patterns

### Command Pattern
Commands are encapsulated as objects with a type and parameters, enabling flexible execution and routing.

### Proxy Pattern
The MCP server acts as a proxy for Godot, providing Claude with a simplified interface to Godot functionality.

### Factory Pattern
Command handlers act as factories for creating and executing Godot operations.

### Observer Pattern
The WebSocket server uses events to notify the system about connections, disconnections, and messages.

### Promise Pattern
The Godot connection manager uses promises for async command execution and response handling.

## Error Handling

The architecture implements a comprehensive error handling strategy:

1. **Validation**: Commands are validated before execution
2. **Contextual Errors**: Error messages include context about what went wrong
3. **Error Propagation**: Errors are properly propagated through the system
4. **Recovery Mechanisms**: Connection failures trigger automatic reconnection attempts
5. **Timeout Handling**: Long-running commands have timeout protection

## Scalability and Performance

### Connection Management
- WebSocket connections are reused to reduce overhead
- Connection pool allows for multiple clients if needed
- Automatic reconnection on failure

### Command Execution
- Commands are executed asynchronously
- Long-running operations report progress
- Resource cleanup ensures efficient memory usage

### Editor Performance
- WebSocket server runs in a separate thread
- UI updates are throttled to prevent editor slowdown
- Command execution is optimized to minimize impact

## Security Considerations

1. **Local-Only Communication**: By default, the WebSocket server only accepts connections from localhost
2. **Authentication Options**: Optional authentication can be implemented
3. **Command Validation**: All commands are validated before execution
4. **Error Isolation**: Errors in command execution don't crash the Godot editor

## Extensibility

The architecture is designed for extensibility:

1. **Command Registry**: New commands can be added by registering them with the command handler
2. **Tool Registration**: New tools can be added to the MCP server
3. **Modular Design**: Components can be extended or replaced independently
4. **Event System**: Events allow for hooking into system operations

## Future Considerations

1. **Multiple Sessions**: Support for multiple simultaneous Claude sessions
2. **Remote Connections**: Secure connections from remote MCP servers
3. **Command Queueing**: Queue for complex multi-step operations
4. **Advanced Authentication**: More robust authentication mechanisms
5. **Performance Optimizations**: Further reduce overhead for large projects
```

--------------------------------------------------------------------------------
/docs/getting-started.md:
--------------------------------------------------------------------------------

```markdown
# Getting Started with Godot MCP

This guide will walk you through your first steps with the Godot MCP integration, demonstrating how to use Claude to interact with Godot projects through natural language.

## Prerequisites

Before you begin, ensure you have:

1. Completed the [Installation Guide](./installation-guide.md)
2. A running Godot project with the MCP addon enabled
3. The MCP server configured and running
4. Claude Desktop set up with the MCP server

## Basic Workflow

The typical workflow when using Godot MCP with Claude follows these steps:

1. Open your Godot project
2. Start the MCP WebSocket server from the Godot MCP panel
3. Launch Claude Desktop
4. Ask Claude to perform operations on your Godot project

## Example Scenarios

Let's walk through some basic scenarios to help you get familiar with using Godot MCP.

### Creating a Simple Scene

In this scenario, we'll ask Claude to help us create a simple scene with a player character.

1. **Start a new conversation with Claude**

2. **Ask Claude to create a new scene with some basic elements:**

   ```
   I'm working on a 2D platformer in Godot. Can you help me create a simple scene with a player character sprite, a platform, and a collectible?
   ```

3. **Claude will use MCP to create the scene:**

   Claude will create a new scene structure with the requested elements. You'll see Claude accessing the Godot MCP tools, and you may be prompted to approve certain operations.

4. **Examine the results in Godot:**

   After Claude completes the operations, switch to Godot and you should see the newly created scene with the player character, platform, and collectible.

### Adding Game Logic with GDScript

Now, let's add some basic game logic to our scene.

1. **Ask Claude to add movement logic to the player character:**

   ```
   Can you add a simple movement script to the player character? I want it to move left and right with the arrow keys and jump when pressing the Space bar.
   ```

2. **Claude will create and attach a script:**

   Claude will create a GDScript file with the requested functionality and attach it to the player character node.

3. **Test the script in Godot:**

   Press F5 in Godot to run the scene and test the player character movement.

### Debugging and Fixing Issues

If there are issues with the implementation, you can ask Claude to help debug and fix them.

1. **Describe the issue to Claude:**

   ```
   The player character moves left and right, but the jump functionality isn't working correctly. Can you fix it?
   ```

2. **Claude will analyze and fix the code:**

   Claude will examine the script, identify the issue, and make the necessary corrections.

## Common Tasks

Here are some common tasks you might want to perform with Godot MCP:

### Working with Nodes

#### Creating Nodes

```
Create a CanvasLayer node named UI and add a Label node as its child with the text "Score: 0".
```

#### Modifying Nodes

```
Change the position of the player character to (100, 200) and set its scale to (2, 2).
```

#### Organizing Nodes

```
Create a new Node2D called "Enemies" and move all enemy nodes under it.
```

### Working with Scripts

#### Creating Scripts

```
Create a script for the collectible that makes it spin and disappear when the player touches it.
```

#### Modifying Scripts

```
Modify the player script to add a double jump feature when pressing the Space bar twice.
```

#### Debugging Scripts

```
The collectible's collision detection isn't working. Can you check the script and fix any issues?
```

### Working with Resources

#### Creating Resources

```
Create a new ShaderMaterial for the player that adds a glowing effect.
```

#### Modifying Resources

```
Update the player's material to change the glow color to blue.
```

## Advanced Examples

### Creating a Complete Game Feature

Let's create a more complex feature - a scoring system with UI:

```
I'd like to add a scoring system to my game. When the player collects items, the score should increase. Please create:
1. A UI with a score label
2. A script to track the score
3. Logic to update the score when collecting items
```

Claude will go through these steps:
1. Create a UI CanvasLayer with a Label
2. Create a global script to track the score
3. Update the collectible script to increase the score
4. Connect everything so the UI updates when the score changes

### Building a Menu System

```
I need a main menu for my game with "Play", "Options", and "Quit" buttons. Can you implement this?
```

Claude will:
1. Create a new menu scene with appropriate nodes
2. Add UI elements for the buttons
3. Write scripts to handle button clicks
4. Implement scene transitions for the "Play" button

## Tips for Working with Claude and Godot MCP

1. **Be specific**: Clearly describe what you want Claude to create or modify
2. **Start simple**: Begin with basic tasks before moving to complex ones
3. **Iterate**: Have Claude make small changes and test frequently
4. **Provide context**: Tell Claude about your project structure when relevant
5. **Accept or modify suggestions**: Claude might suggest alternatives; feel free to go with them or ask for changes

## Troubleshooting

### Claude can't connect to Godot

If Claude reports it can't connect to Godot:
1. Check that the WebSocket server is running in Godot
2. Verify the port number matches in both the Godot addon and MCP server configuration
3. Restart Claude Desktop and try again

### Command execution fails

If commands fail to execute:
1. Check the Godot MCP panel logs for errors
2. Make sure you're referencing valid paths in your requests
3. Verify that the node types and property names are correct

### Changes not appearing in Godot

If changes made by Claude don't appear in Godot:
1. Make sure the scene is saved after changes
2. Try refreshing the Godot editor
3. Check if there were any error messages during command execution

## Next Steps

Now that you're familiar with the basics, explore these advanced topics:
- [Command Reference](./command-reference.md) for a complete list of available commands
- [Architecture](./architecture.md) to understand how the system works
- Extend the functionality by adding custom commands to the Godot addon

Happy game development with Claude and Godot MCP!
```

--------------------------------------------------------------------------------
/server/src/utils/godot_connection.ts:
--------------------------------------------------------------------------------

```typescript
import WebSocket from 'ws';

/**
 * Response from Godot server
 */
export interface GodotResponse {
  status: 'success' | 'error';
  result?: any;
  message?: string;
  commandId?: string;
}

/**
 * Command to send to Godot
 */
export interface GodotCommand {
  type: string;
  params: Record<string, any>;
  commandId: string;
}

/**
 * Manages WebSocket connection to the Godot editor
 */
export class GodotConnection {
  private ws: WebSocket | null = null;
  private connected = false;
  private commandQueue: Map<string, { 
    resolve: (value: any) => void;
    reject: (reason: any) => void;
    timeout: NodeJS.Timeout;
  }> = new Map();
  private commandId = 0;
  
  /**
   * Creates a new Godot connection
   * @param url WebSocket URL for the Godot server
   * @param timeout Command timeout in ms
   * @param maxRetries Maximum number of connection retries
   * @param retryDelay Delay between retries in ms
   */
  constructor(
    private url: string = 'ws://localhost:9080',
    private timeout: number = 20000,
    private maxRetries: number = 3,
    private retryDelay: number = 2000
  ) {
    console.error('GodotConnection created with URL:', this.url);
  }
  
  /**
   * Connects to the Godot WebSocket server
   */
  async connect(): Promise<void> {
    if (this.connected) return;
    
    let retries = 0;
    
    const tryConnect = (): Promise<void> => {
      return new Promise<void>((resolve, reject) => {
        console.error(`Connecting to Godot WebSocket server at ${this.url}... (Attempt ${retries + 1}/${this.maxRetries + 1})`);
        
        // Use protocol option to match Godot's supported_protocols
        this.ws = new WebSocket(this.url, {
          protocol: 'json',
          handshakeTimeout: 8000,  // Increase handshake timeout
          perMessageDeflate: false // Disable compression for compatibility
        });
        
        this.ws.on('open', () => {
          this.connected = true;
          console.error('Connected to Godot WebSocket server');
          resolve();
        });
        
        this.ws.on('message', (data: Buffer) => {
          try {
            const response: GodotResponse = JSON.parse(data.toString());
            console.error('Received response:', response);
            
            // Handle command responses
            if ('commandId' in response) {
              const commandId = response.commandId as string;
              const pendingCommand = this.commandQueue.get(commandId);
              
              if (pendingCommand) {
                clearTimeout(pendingCommand.timeout);
                this.commandQueue.delete(commandId);
                
                if (response.status === 'success') {
                  pendingCommand.resolve(response.result);
                } else {
                  pendingCommand.reject(new Error(response.message || 'Unknown error'));
                }
              }
            }
          } catch (error) {
            console.error('Error parsing response:', error);
          }
        });
        
        this.ws.on('error', (error) => {
          const err = error as Error;
          console.error('WebSocket error:', err);
          // Don't terminate the connection on error - let the timeout handle it
          // Just log the error and allow retry mechanism to work
        });
        
        this.ws.on('close', () => {
          if (this.connected) {
            console.error('Disconnected from Godot WebSocket server');
            this.connected = false;
          }
        });
        
        // Set connection timeout
        const connectionTimeout = setTimeout(() => {
          if (this.ws?.readyState !== WebSocket.OPEN) {
            if (this.ws) {
              this.ws.terminate();
              this.ws = null;
            }
            reject(new Error('Connection timeout'));
          }
        }, this.timeout);
        
        this.ws.on('open', () => {
          clearTimeout(connectionTimeout);
        });
      });
    };
    
    // Try connecting with retries
    while (retries <= this.maxRetries) {
      try {
        await tryConnect();
        return;
      } catch (error) {
        retries++;
        
        if (retries <= this.maxRetries) {
          console.error(`Connection attempt failed. Retrying in ${this.retryDelay}ms...`);
          await new Promise(resolve => setTimeout(resolve, this.retryDelay));
        } else {
          throw error;
        }
      }
    }
  }
  
  /**
   * Sends a command to Godot and waits for a response
   * @param type Command type
   * @param params Command parameters
   * @returns Promise that resolves with the command result
   */
  async sendCommand<T = any>(type: string, params: Record<string, any> = {}): Promise<T> {
    if (!this.ws || !this.connected) {
      try {
        await this.connect();
      } catch (error) {
        throw new Error(`Failed to connect: ${(error as Error).message}`);
      }
    }
    
    return new Promise<T>((resolve, reject) => {
      const commandId = `cmd_${this.commandId++}`;
      
      const command: GodotCommand = {
        type,
        params,
        commandId
      };
      
      // Set timeout for command
      const timeoutId = setTimeout(() => {
        if (this.commandQueue.has(commandId)) {
          this.commandQueue.delete(commandId);
          reject(new Error(`Command timed out: ${type}`));
        }
      }, this.timeout);
      
      // Store the promise resolvers
      this.commandQueue.set(commandId, {
        resolve,
        reject,
        timeout: timeoutId
      });
      
      // Send the command
      if (this.ws?.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify(command));
      } else {
        clearTimeout(timeoutId);
        this.commandQueue.delete(commandId);
        reject(new Error('WebSocket not connected'));
      }
    });
  }
  
  /**
   * Disconnects from the Godot WebSocket server
   */
  disconnect(): void {
    if (this.ws) {
      // Clear all pending commands
      this.commandQueue.forEach((command, commandId) => {
        clearTimeout(command.timeout);
        command.reject(new Error('Connection closed'));
        this.commandQueue.delete(commandId);
      });
      
      this.ws.close();
      this.ws = null;
      this.connected = false;
    }
  }
  
  /**
   * Checks if connected to Godot
   */
  isConnected(): boolean {
    return this.connected;
  }
}

// Singleton instance
let connectionInstance: GodotConnection | null = null;

/**
 * Gets the singleton instance of GodotConnection
 */
export function getGodotConnection(): GodotConnection {
  if (!connectionInstance) {
    connectionInstance = new GodotConnection();
  }
  return connectionInstance;
}
```

--------------------------------------------------------------------------------
/docs/godot-addon-readme.md:
--------------------------------------------------------------------------------

```markdown
# Godot MCP Addon

This addon enables the Godot Editor to communicate with the Model Context Protocol (MCP), allowing AI assistants like Claude to interact with and manipulate Godot projects.

## Features

- **WebSocket Server**: Built-in WebSocket server for bidirectional communication
- **Command Execution**: Execute commands to manipulate nodes, scripts, and resources
- **Editor Integration**: Seamless integration with the Godot editor
- **Configurable**: Customizable port, logging, and security settings

## Installation

1. Copy the `godot_mcp` folder to your Godot project's `addons` directory
2. Enable the plugin in Godot via Project → Project Settings → Plugins
3. The MCP panel will appear in the editor dock

## Usage

### Starting the Server

1. Open the MCP panel in the Godot editor
2. Configure the server port (default: 9080)
3. Click "Start Server" to begin accepting connections
4. The status indicator will turn green when the server is running

### Stopping the Server

1. Click "Stop Server" in the MCP panel
2. The status indicator will turn red when the server is stopped

### Viewing Logs

The MCP panel includes a log view that shows:
- Connection events
- Command execution
- Errors and warnings

### Configuration

The following settings can be configured in the MCP panel:

| Setting | Description | Default |
|---------|-------------|---------|
| Port | WebSocket server port | 9080 |
| Allow Remote | Accept non-localhost connections | Disabled |
| Log Level | Detail level for logging | Info |
| Auto Start | Start server when Godot opens | Disabled |

## Command Reference

The addon supports the following commands:

### Node Commands

- **create_node**: Create a new node in the scene tree
  ```json
  {
    "type": "create_node",
    "params": {
      "parent_path": "/root",
      "node_type": "Sprite2D",
      "node_name": "NewSprite"
    }
  }
  ```

- **delete_node**: Remove a node from the scene tree
  ```json
  {
    "type": "delete_node",
    "params": {
      "node_path": "/root/NewSprite"
    }
  }
  ```

- **update_node**: Modify node properties
  ```json
  {
    "type": "update_node",
    "params": {
      "node_path": "/root/NewSprite",
      "properties": {
        "position": [100, 100],
        "scale": [2, 2]
      }
    }
  }
  ```

- **list_nodes**: Get a list of nodes in the scene tree
  ```json
  {
    "type": "list_nodes",
    "params": {
      "parent_path": "/root",
      "recursive": true
    }
  }
  ```

### Script Commands

- **create_script**: Create a new GDScript file
  ```json
  {
    "type": "create_script",
    "params": {
      "script_path": "res://scripts/new_script.gd",
      "content": "extends Node\n\nfunc _ready():\n\tpass",
      "node_path": "/root/NewNode"  // Optional, attach to node
    }
  }
  ```

- **edit_script**: Modify an existing script
  ```json
  {
    "type": "edit_script",
    "params": {
      "script_path": "res://scripts/new_script.gd",
      "content": "extends Node\n\nfunc _ready():\n\tprint('Hello, World!')"
    }
  }
  ```

- **get_script**: Retrieve a script's content
  ```json
  {
    "type": "get_script",
    "params": {
      "script_path": "res://scripts/new_script.gd"
    }
  }
  ```

### Resource Commands

- **create_resource**: Create a new resource
  ```json
  {
    "type": "create_resource",
    "params": {
      "resource_type": "ShaderMaterial",
      "resource_path": "res://materials/new_material.tres",
      "properties": {
        "shader_parameter/color": [1, 0, 0, 1]
      }
    }
  }
  ```

- **list_resources**: List available resources
  ```json
  {
    "type": "list_resources",
    "params": {
      "directory": "res://materials",
      "type_filter": "Material"  // Optional
    }
  }
  ```

### Scene Commands

- **save_scene**: Save the current scene
  ```json
  {
    "type": "save_scene",
    "params": {
      "path": "res://scenes/new_scene.tscn"  // Optional, uses current path if not provided
    }
  }
  ```

- **open_scene**: Open a scene
  ```json
  {
    "type": "open_scene",
    "params": {
      "path": "res://scenes/main.tscn"
    }
  }
  ```

## Response Format

All commands return responses in the following format:

### Success Response
```json
{
  "status": "success",
  "result": {
    // Command-specific result data
  },
  "commandId": "cmd_123"  // Same ID as in the command
}
```

### Error Response
```json
{
  "status": "error",
  "message": "Detailed error message",
  "commandId": "cmd_123"  // Same ID as in the command
}
```

## Implementation Details

### File Structure

```
godot_mcp/
├── plugin.cfg                 # Plugin configuration
├── godot_mcp.gd               # Main plugin file
├── websocket_server.gd        # WebSocket server implementation
├── command_handler.gd         # Command routing and execution
├── ui/                        # UI components
│   ├── mcp_panel.gd           # MCP control panel script
│   └── mcp_panel.tscn         # MCP control panel scene
└── utils/                     # Utility functions
    ├── node_utils.gd          # Node manipulation utilities
    ├── resource_utils.gd      # Resource manipulation utilities
    └── script_utils.gd        # Script manipulation utilities
```

### Key Classes

- **GodotMCP**: Main plugin class that integrates with Godot editor
- **MCPWebSocketServer**: WebSocket server implementation
- **MCPCommandHandler**: Command routing and execution
- **MCPPanel**: UI interface for controlling the server

## Development

### Prerequisites

- Godot Engine 4.x
- Basic knowledge of GDScript
- Understanding of Godot's scene system

### Adding New Commands

To add a new command:

1. Add a new method to the `MCPCommandHandler` class
2. Implement the command logic using Godot's API
3. Update the command routing in the `_handle_command` method
4. Document the new command in this README

### Debugging

The addon provides several debugging features:

- Detailed logs in the MCP panel
- Option to save logs to file
- Editor console output for critical errors

## Troubleshooting

### Server Won't Start

- Check if the port is already in use
- Verify that the plugin is properly enabled
- Ensure the Godot editor has network permissions (especially on macOS)

### Connection Issues

- Verify the client is using the correct WebSocket URL
- Check if any firewalls are blocking the connection
- Ensure the "Allow Remote" setting is enabled if connecting from another machine

### Command Execution Errors

- Check the command format and parameters
- Verify that paths exist and are correctly formatted
- Look for detailed error messages in the MCP panel logs

## License

This plugin is provided under the MIT License. See the LICENSE file for details.

## Acknowledgements

This plugin is inspired by the Blender MCP implementation and builds upon the Model Context Protocol developed by Anthropic.
```