Analysis Date: 2026-01-11 Repository: https://github.com/Coding-Solo/godot-mcp Purpose: Deep analysis for CLI enhancement to maximize game developer productivity
- Executive Summary
- Current Implementation Analysis
- Architecture Overview
- Feature Assessment
- Gap Analysis
- Competitive Analysis
- Improvement Recommendations
- Development Roadmap
- Technical Implementation Details
The godot-mcp project is a TypeScript-based MCP server that enables AI assistants to interact with the Godot game engine. It provides 14 tools for basic project management, scene manipulation, and debug operations.
| Category | Score | Notes |
|---|---|---|
| Core Functionality | 6/10 | Basic operations covered, many gaps |
| Scene Management | 5/10 | Create/modify scenes, limited node operations |
| Asset Pipeline | 2/10 | Minimal support |
| Build/Export | 1/10 | Not implemented |
| GDScript Interaction | 3/10 | Limited to operations script |
| Error Handling | 7/10 | Good error messages with solutions |
| Documentation | 7/10 | Clear README, good examples |
The current implementation covers ~15-20% of what Godot's CLI and API capabilities offer. There's massive potential for expansion that would dramatically improve game developer productivity.
godot-mcp/
├── src/
│ ├── index.ts # Main MCP server (2207 lines)
│ └── scripts/
│ └── godot_operations.gd # GDScript operations handler (1193 lines)
├── scripts/
│ └── build.js # Build script
├── package.json
├── tsconfig.json
└── README.md
- Runtime: Node.js
- Language: TypeScript
- MCP SDK: @modelcontextprotocol/sdk v0.6.0
- Dependencies: axios, fs-extra
| Tool | Description | Maturity |
|---|---|---|
launch_editor |
Open Godot editor for project | Stable |
run_project |
Execute project in debug mode | Stable |
get_debug_output |
Retrieve console output/errors | Stable |
stop_project |
Stop running project | Stable |
get_godot_version |
Get installed Godot version | Stable |
list_projects |
Find Godot projects in directory | Stable |
get_project_info |
Retrieve project metadata | Stable |
create_scene |
Create new scene file | Stable |
add_node |
Add node to existing scene | Stable |
load_sprite |
Load texture into Sprite2D | Stable |
export_mesh_library |
Export scene as MeshLibrary | Stable |
save_scene |
Save scene changes | Stable |
get_uid |
Get UID for file (Godot 4.4+) | Stable |
update_project_uids |
Update UID references | Stable |
┌─────────────────┐ MCP Protocol ┌─────────────────┐
│ AI Assistant │◄──────────────────►│ MCP Server │
│ (Claude, etc.) │ (JSON-RPC) │ (Node.js) │
└─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐
│ Godot Engine │
│ (--headless) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ godot_operations│
│ .gd │
└─────────────────┘
- AI Assistant sends tool request via MCP protocol
- MCP Server validates parameters and normalizes naming (snake_case ↔ camelCase)
- Server spawns Godot process with
--headless --scriptflags - GDScript executes operation and outputs result
- Server parses output and returns to AI
- No temporary files - Operations script is bundled
- Clean parameter handling - Bidirectional case normalization
- Good error messages - Includes possible solutions
- Path validation - Prevents traversal attacks
- Multi-platform - Windows, macOS, Linux support
- Synchronous execution - One operation at a time
- No persistent connection - New Godot process per operation
- Limited state management - Cannot track ongoing changes
- No streaming - Large outputs not handled efficiently
- Recursive project scanning
- Project info extraction from
project.godot - Godot version detection with auto-path discovery
- Scene creation with configurable root node types
- Node addition with property setting
- Scene saving with variant support
- MeshLibrary export for GridMap workflows
- Collision shape preservation
- UID management for new resource system
- Resource resaving for UID generation
- No script creation - Cannot generate .gd files
- No script modification - Cannot edit existing scripts
- No class registration - Cannot add to global class list
- No signal connection - Cannot wire up signals
- No import configuration - Cannot set import settings
- No texture operations - Beyond simple sprite loading
- No audio handling - No sound/music operations
- No font management - No TTF/OTF handling
- No 3D model import - No GLTF/FBX operations
- No export presets - Cannot configure platforms
- No CI/CD support - Cannot automate builds
- No template management - Cannot handle export templates
- Limited node types - Only basic instantiation
- No node deletion - Cannot remove nodes
- No node reparenting - Cannot restructure scenes
- No node duplication - Cannot clone nodes
- No property bulk update - One property at a time
- No ProjectSettings manipulation - Cannot change settings
- No input map configuration - Cannot set up controls
- No autoload management - Cannot configure singletons
- No layer configuration - Cannot set up physics/render layers
- No animation creation - Cannot make animations
- No AnimationPlayer support - Cannot add tracks
- No AnimationTree support - Cannot configure state machines
- No tileset creation - Cannot generate tilesets
- No tilemap operations - Cannot paint tiles
Based on Godot's command-line documentation, these features are available but not exposed:
| Capability | CLI Flag | Status |
|---|---|---|
| Export project | --export-release, --export-debug |
NOT IMPLEMENTED |
| Export pack | --export-pack |
NOT IMPLEMENTED |
| Import resources | --import |
NOT IMPLEMENTED |
| Validate project | --validate-project-settings |
NOT IMPLEMENTED |
| Dump extension API | --dump-gdextension-interface |
NOT IMPLEMENTED |
| Generate documentation | --doctool |
NOT IMPLEMENTED |
| Convert project | --convert-3to4 |
NOT IMPLEMENTED |
| Render quality | --rendering-method, --rendering-driver |
NOT IMPLEMENTED |
| Verbose mode | -v, --verbose |
PARTIAL |
| Breakpoints | --breakpoint |
NOT IMPLEMENTED |
| GPU selection | --gpu-index |
NOT IMPLEMENTED |
| Audio driver | --audio-driver |
NOT IMPLEMENTED |
| Display server | --display-driver |
NOT IMPLEMENTED |
| API Area | Available Methods | Status |
|---|---|---|
| EditorInterface | 50+ methods | NOT EXPOSED |
| EditorPlugin | 80+ methods | NOT EXPOSED |
| ResourceSaver | 10+ flags | PARTIAL |
| ResourceLoader | 15+ methods | PARTIAL |
| ProjectSettings | Full API | NOT EXPOSED |
| EditorSettings | Full API | NOT EXPOSED |
| FileAccess | Full API | PARTIAL |
| DirAccess | Full API | PARTIAL |
| ClassDB | Full reflection | NOT EXPOSED |
- 48 tools vs current 14
- Runtime debugging focus
- C# / .NET implementation
- HTTP server inside Godot (port 7777)
- Scene tree queries, signal monitoring, property modification
Key Differentiators:
- Real-time connection to running game
- Signal event listening
- Ring buffer for logs (1000 entries)
- Thread-safe request queue
- WebSocket-based communication
- EditorPlugin addon approach
- Node, script, and resource tools
- Live editor integration
Key Differentiators:
- Bidirectional communication
- Editor state access
- Real-time updates
| Engine | MCP Status | Capabilities |
|---|---|---|
| Godot | Multiple projects | Basic-Intermediate |
| Unity | Several implementations | Advanced (Editor API access) |
| Unreal | Limited | Python/Blueprint automation |
Unity MCP implementations typically offer:
- Asset database queries
- Prefab manipulation
- Component management
- Build pipeline integration
- Play mode control
- Console log access
- Scene hierarchy navigation
// New tools needed:
- create_script(projectPath, scriptPath, className, extends, content)
- modify_script(projectPath, scriptPath, modifications)
- add_function(projectPath, scriptPath, functionName, params, body)
- add_signal(projectPath, scriptPath, signalName, params)
- add_export_var(projectPath, scriptPath, varName, type, default)
- get_script_info(projectPath, scriptPath) // Returns structure// New tools needed:
- export_project(projectPath, preset, outputPath, debug?)
- list_export_presets(projectPath)
- create_export_preset(projectPath, presetConfig)
- validate_project(projectPath)// New tools needed:
- delete_node(projectPath, scenePath, nodePath)
- duplicate_node(projectPath, scenePath, nodePath, newName)
- reparent_node(projectPath, scenePath, nodePath, newParent)
- get_node_info(projectPath, scenePath, nodePath)
- list_scene_nodes(projectPath, scenePath) // Returns tree structure
- set_node_properties(projectPath, scenePath, nodePath, properties) // Bulk update// New tools needed:
- get_project_setting(projectPath, setting)
- set_project_setting(projectPath, setting, value)
- add_input_action(projectPath, actionName, events)
- add_autoload(projectPath, name, path)
- set_main_scene(projectPath, scenePath)
- configure_physics_layers(projectPath, layers)// New tools needed:
- reimport_resource(projectPath, resourcePath)
- set_import_options(projectPath, resourcePath, options)
- get_import_options(projectPath, resourcePath)
- list_importable_files(projectPath)// New tools needed:
- connect_signal(projectPath, scenePath, sourceNode, signal, targetNode, method)
- disconnect_signal(projectPath, scenePath, sourceNode, signal, targetNode, method)
- list_node_signals(projectPath, scenePath, nodePath)
- list_connections(projectPath, scenePath)// New tools needed:
- create_animation(projectPath, scenePath, animationName)
- add_animation_track(projectPath, scenePath, animationName, trackConfig)
- set_animation_keyframe(projectPath, scenePath, animationName, trackIdx, time, value)
- create_animation_player(projectPath, scenePath, nodePath)// New tools needed:
- create_resource(projectPath, resourcePath, resourceType, properties)
- create_shader(projectPath, shaderPath, shaderType, code)
- create_material(projectPath, materialPath, materialType, properties)
- create_theme(projectPath, themePath, themeConfig)// New tools needed:
- create_tileset(projectPath, tilesetPath, textureSource, tileSize)
- configure_tileset_tile(projectPath, tilesetPath, tileId, config)
- create_tilemap_layer(projectPath, scenePath, parentNode, tilesetPath)
- set_tilemap_cells(projectPath, scenePath, nodePath, cells)Implement WebSocket/HTTP server inside Godot for real-time communication:
- Scene tree inspection during runtime
- Property modification while playing
- Signal monitoring
- Performance metrics
// New tools needed:
- list_plugins(projectPath)
- enable_plugin(projectPath, pluginName)
- disable_plugin(projectPath, pluginName)
- install_asset_lib_plugin(projectPath, assetId)// New tools needed:
- get_modified_resources(projectPath)
- compare_scenes(projectPath, scenePath1, scenePath2)
- get_resource_dependencies(projectPath, resourcePath)Goal: Establish robust GDScript operations and core missing features
| Week | Tasks | Deliverables |
|---|---|---|
| 1 | GDScript file operations | create_script, modify_script, get_script_info |
| 1 | Enhanced node operations | delete_node, duplicate_node, list_scene_nodes |
| 2 | Project settings API | get/set_project_setting, add_input_action |
| 2 | Export foundations | list_export_presets, export_project |
| 3 | Testing & documentation | Test suite, API docs |
Goal: Add features that significantly speed up game development
| Week | Tasks | Deliverables |
|---|---|---|
| 4 | Signal management | connect_signal, list_connections |
| 4 | Import system | set_import_options, reimport_resource |
| 5 | Animation basics | create_animation, add_animation_track |
| 5 | Resource creation | create_material, create_shader |
| 6 | 2D tools | Tileset/Tilemap operations |
| 7 | Testing & refinement | Integration tests |
Goal: Implement live connection and advanced features
| Week | Tasks | Deliverables |
|---|---|---|
| 8-9 | WebSocket server addon | Live connection protocol |
| 10-11 | Runtime tools | Scene inspection, property modification |
| 12-13 | Performance & polish | Optimization, error handling |
| Metric | Current | Phase 1 | Phase 2 | Phase 3 |
|---|---|---|---|---|
| Total Tools | 14 | 28 | 45 | 60+ |
| API Coverage | ~15% | ~35% | ~55% | ~75% |
| Test Coverage | 0% | 60% | 80% | 90% |
src/
├── index.ts # Main server entry
├── server/
│ ├── GodotServer.ts # Core server class
│ ├── GodotConnection.ts # Godot process management
│ └── ParameterNormalizer.ts # Case conversion
├── tools/
│ ├── project/
│ │ ├── projectTools.ts # Project management
│ │ └── settingsTools.ts # ProjectSettings
│ ├── scene/
│ │ ├── sceneTools.ts # Scene operations
│ │ ├── nodeTools.ts # Node operations
│ │ └── signalTools.ts # Signal management
│ ├── script/
│ │ ├── scriptTools.ts # GDScript operations
│ │ └── classTools.ts # Class management
│ ├── asset/
│ │ ├── importTools.ts # Import configuration
│ │ └── resourceTools.ts # Resource creation
│ ├── build/
│ │ ├── exportTools.ts # Export operations
│ │ └── presetTools.ts # Export presets
│ └── animation/
│ └── animationTools.ts # Animation tools
├── operations/
│ ├── godot_operations.gd # Main operations script
│ ├── script_operations.gd # GDScript-specific ops
│ └── animation_operations.gd # Animation ops
└── utils/
├── validation.ts # Input validation
└── errors.ts # Error handling
The current godot_operations.gd should be extended with:
# New operations to add:
func create_script(params):
var script_path = params.script_path
var class_name = params.get("class_name", "")
var extends_type = params.get("extends", "Node")
var content = params.get("content", "")
var script_content = ""
if class_name:
script_content += "class_name " + class_name + "\n"
script_content += "extends " + extends_type + "\n\n"
script_content += content
var file = FileAccess.open(script_path, FileAccess.WRITE)
if file:
file.store_string(script_content)
file.close()
print("Script created: " + script_path)
else:
printerr("Failed to create script: " + str(FileAccess.get_open_error()))
func modify_script(params):
var script_path = params.script_path
var modifications = params.modifications # Array of {type, target, content}
var file = FileAccess.open(script_path, FileAccess.READ)
if not file:
printerr("Cannot open script: " + script_path)
return
var content = file.get_as_text()
file.close()
for mod in modifications:
match mod.type:
"add_function":
content = _add_function_to_script(content, mod)
"add_variable":
content = _add_variable_to_script(content, mod)
"replace_function":
content = _replace_function_in_script(content, mod)
file = FileAccess.open(script_path, FileAccess.WRITE)
file.store_string(content)
file.close()
func export_project(params):
var preset_name = params.preset
var output_path = params.output_path
var debug = params.get("debug", false)
# Export is handled via command line, not script
# Return export command for the server to execute
var result = {
"command": "export",
"args": [
"--export-" + ("debug" if debug else "release"),
preset_name,
output_path
]
}
print(JSON.stringify(result))Example implementation for create_script tool:
// In scriptTools.ts
{
name: 'create_script',
description: 'Create a new GDScript file with optional class name and content',
inputSchema: {
type: 'object',
properties: {
projectPath: {
type: 'string',
description: 'Path to the Godot project directory',
},
scriptPath: {
type: 'string',
description: 'Path for the new script file (relative to project)',
},
className: {
type: 'string',
description: 'Optional: Class name for global registration',
},
extends: {
type: 'string',
description: 'Base class to extend (default: Node)',
},
content: {
type: 'string',
description: 'Optional: Initial script content (functions, variables)',
},
},
required: ['projectPath', 'scriptPath'],
},
}private async handleExportProject(args: any) {
args = this.normalizeParameters(args);
if (!args.projectPath || !args.preset || !args.outputPath) {
return this.createErrorResponse(
'Missing required parameters',
['Provide projectPath, preset, and outputPath']
);
}
// Validate project
const projectFile = join(args.projectPath, 'project.godot');
if (!existsSync(projectFile)) {
return this.createErrorResponse(
`Not a valid Godot project: ${args.projectPath}`,
['Ensure the path points to a directory containing a project.godot file']
);
}
// Build export command
const exportFlag = args.debug ? '--export-debug' : '--export-release';
const cmd = [
`"${this.godotPath}"`,
'--headless',
'--path',
`"${args.projectPath}"`,
exportFlag,
`"${args.preset}"`,
`"${args.outputPath}"`,
].join(' ');
try {
const { stdout, stderr } = await execAsync(cmd, { timeout: 300000 }); // 5 min timeout
if (stderr && stderr.includes('ERROR')) {
return this.createErrorResponse(
`Export failed: ${stderr}`,
[
'Verify export preset exists',
'Check export templates are installed',
'Ensure output path is writable',
]
);
}
return {
content: [{
type: 'text',
text: `Project exported successfully to: ${args.outputPath}\n\nOutput: ${stdout}`,
}],
};
} catch (error: any) {
return this.createErrorResponse(
`Export failed: ${error?.message || 'Unknown error'}`,
[
'Verify export templates are installed for target platform',
'Check GODOT_PATH environment variable',
'Ensure output directory exists',
]
);
}
}The godot-mcp project has a solid foundation but currently exposes only a fraction of Godot's capabilities. By implementing the recommended improvements, we can transform it into a comprehensive tool that dramatically increases game developer productivity.
- GDScript operations are the biggest gap - Adding script creation/modification would have the highest impact
- Export/build automation is essential - CI/CD support is expected in modern development
- Node operations need expansion - Current tools cover creation but not modification/deletion
- Live connection mode would be transformative - Real-time interaction with running games opens new possibilities
- Immediate: Implement
create_script,delete_node,list_scene_nodes - Short-term: Add
export_project,set_project_setting - Medium-term: Implement signal management and animation tools
- Long-term: Build WebSocket-based live connection system
This analysis was generated to guide the enhancement of godot-mcp for maximum game developer productivity through CLI automation.