- name
- godot-devtool-mcp-server
- description
- MCP server for AI-assisted Godot 4 project inspection, editing, validation, and runtime automation via WebSocket bridge
- triggers
- ["inspect my Godot project structure","edit Godot scene nodes through MCP","install the godot-devtool plugin","run Godot project and capture runtime info","check Godot project settings and input actions","automate Godot scene validation","connect to Godot editor via WebSocket","simulate input in running Godot game"]
# Godot Devtool MCP Server
> Skill by [ara.so](https://ara.so) — Devtools Skills collection.
`godot-devtool` is an MCP (Model Context Protocol) server that enables AI-assisted inspection, editing, validation, and runtime automation for Godot 4 projects. It provides 234 tools across project management, scene/node manipulation, script handling, editor integration, and live runtime control.
## Architecture Overview
```
MCP Client (Claude Code, Cursor, Cline, etc.)
↓ stdio
Node.js MCP Server (build/index.js)
↓
├─ Native routes (file inspection/editing)
├─ Headless Godot routes (scene/resource ops)
├─ WebSocket bridge (ws://127.0.0.1:8766)
│ ├─ Editor plugin (live scene editing, Inspector, UndoRedo)
│ └─ Runtime autoload (running game inspection, input simulation)
└─ Browser visualizer (local HTTP dashboard)
```
- **stdio MCP server**: Always runs over stdin/stdout, no exclusive port binding
- **Native routes**: Inspect/edit project files without opening Godot editor
- **Headless routes**: Call Godot CLI for scene/resource/script operations
- **Editor routes**: Live editing via bundled WebSocket plugin
- **Runtime routes**: Running-game scene tree, properties, input simulation, screenshots
- **Shared bridge**: Multiple MCP clients can use the same WebSocket port
## Installation
### 1. Install the MCP Server
Extract the release build or build from source:
```bash
git clone https://github.com/wangdiandao/godot-devtool.git
cd godot-devtool
npm install
npm run build
```
### 2. Configure Your MCP Client
**Claude Desktop / VS Code (JSON)**:
```json
{
"mcpServers": {
"godot-devtool": {
"command": "node",
"args": ["E:/godot-devtool/build/index.js"],
"env": {
"GODOT_PATH": "D:/Program Files/Godot/Godot_v4.x.exe",
"GODOT_DEVTOOL_WS_PORT": "8766"
}
}
}
}
```
**Codex Desktop (TOML)**:
```toml
[mcp_servers.godot-devtool]
command = "node"
args = ["E:/godot-devtool/build/index.js"]
env = { GODOT_PATH = "D:/Program Files/Godot/Godot_v4.x.exe", GODOT_DEVTOOL_WS_PORT = "8766" }
```
Environment variables:
- `GODOT_PATH`: Path to Godot executable (optional if `godot` is in PATH)
- `GODOT_DEVTOOL_WS_PORT`: WebSocket bridge port (default: 8766)
### 3. Install the Godot Plugin
The plugin enables live editor and runtime routes. Install via MCP tools:
```typescript
// Call from MCP client
plugin_install({
projectPath: "E:/my-godot-project",
overwrite: true,
websocketPort: 8766
})
```
Then in Godot:
1. Open your project
2. Go to **Project → Project Settings → Plugins**
3. Enable **godot-devtool**
For runtime routes, the plugin also registers:
```
autoload/DevtoolRuntime = *res://addons/godot_devtool/runtime_bridge.gd
```
## Core Concepts
### Sessions and Context
Tools use `projectPath`, `context`, `sessionId`, and `runId` to identify targets:
- **projectPath**: Absolute path to Godot project directory
- **context**: `editor` or `runtime`
- **sessionId**: Disambiguate multiple editor/runtime connections
- **runId**: Track specific game instances from `run_project`
### Tool Discovery
Use `get_capabilities` to discover tools and filter by workflow:
```typescript
// Lightweight catalog (no schemas)
get_capabilities()
// Focused workflow with schemas
get_capabilities({
toolNames: ["plugin_install", "plugin_status", "scene_tree_inspect"],
includeSchemas: true
})
// Filter by route group
get_capabilities({
routeGroup: "scene",
includeSchemas: true
})
// Filter by transport
get_capabilities({
transport: "editor_ws",
includeSchemas: true
})
```
Workflow filters: `project_setup`, `live_editor`, `runtime_test`, `multi_instance`, `release_verify`
### Bridge Lifecycle
- Bridge port opens **on demand** when editor/runtime tools are called
- Port stays open while:
- `run_project` is active
- Editor or runtime client is connected
- Port releases after tool cleanup if no active sessions
- Use `plugin_status` and `plugin_cleanup_port` to inspect/manage the bridge
## Key Tool Categories
### Project Management
```typescript
// Get project metadata
get_project_info({
projectPath: "E:/my-godot-project"
})
// Read project settings
project_get_settings({
projectPath: "E:/my-godot-project",
sections: ["application/config", "display/window"]
})
// Update project settings (dry run first)
project_update_settings({
projectPath: "E:/my-godot-project",
settings: {
"application/config/name": "My Game",
"display/window/size/viewport_width": 1920
},
dryRun: true
})
// Configure input actions
project_input_action({
projectPath: "E:/my-godot-project",
action: "jump",
events: [
{ type: "InputEventKey", keycode: "KEY_SPACE" },
{ type: "InputEventJoypadButton", button_index: 0 }
]
})
// Run project
run_project({
projectPath: "E:/my-godot-project",
scene: "res://levels/level_01.tscn",
debugCollisions: true,
position: [100, 100],
size: [1280, 720]
})
// List running instances
list_run_instances({
projectPath: "E:/my-godot-project"
})
// Stop specific instance
stop_run_instance({
projectPath: "E:/my-godot-project",
runId: "run_12345"
})
```
### Scene and Node Operations
```typescript
// Inspect scene tree (native)
scene_tree_inspect({
projectPath: "E:/my-godot-project",
scenePath: "res://player.tscn",
maxDepth: 3
})
// Inspect live editor scene (WebSocket)
editor_ws_scene_tree_inspect({
projectPath: "E:/my-godot-project",
maxDepth: 5
})
// Add node to live scene
editor_ws_node_add({
projectPath: "E:/my-godot-project",
parentPath: "Player/Body",
nodeType: "Sprite2D",
nodeName: "WeaponSprite",
position: 1
})
// Update node property
editor_ws_node_set_property({
projectPath: "E:/my-godot-project",
nodePath: "Player/WeaponSprite",
property: "texture",
value: { type: "Resource", path: "res://sprites/sword.png" }
})
// Delete node with undo
editor_ws_node_delete({
projectPath: "E:/my-godot-project",
nodePath: "Player/OldSprite",
undoable: true
})
// Save scene
editor_ws_scene_save({
projectPath: "E:/my-godot-project"
})
```
### Script Management
```typescript
// List GDScript files
script_index({
projectPath: "E:/my-godot-project",
includeTests: true
})
// Read script
script_read({
projectPath: "E:/my-godot-project",
scriptPath: "res://player.gd"
})
// Write script
script_write({
projectPath: "E:/my-godot-project",
scriptPath: "res://enemy.gd",
content: `extends CharacterBody2D
var speed = 200.0
func _physics_process(delta):
var direction = Vector2.ZERO
if Input.is_action_pressed("move_right"):
direction.x += 1
velocity = direction * speed
move_and_slide()
`
})
// Check syntax
script_check_syntax({
projectPath: "E:/my-godot-project",
scriptPath: "res://player.gd"
})
// Create and attach script
script_create({
projectPath: "E:/my-godot-project",
scriptPath: "res://powerup.gd",
template: "Node2D",
attachTo: "res://scenes/powerup.tscn"
})
```
### Runtime Inspection & Automation
```typescript
// Inspect running game scene tree
runtime_ws_scene_tree_inspect({
projectPath: "E:/my-godot-project",
rootPath: "/root/Game",
maxDepth: 4
})
// Get runtime node property
runtime_ws_node_get_property({
projectPath: "E:/my-godot-project",
nodePath: "/root/Game/Player",
property: "position"
})
// Set runtime property
runtime_ws_node_set_property({
projectPath: "E:/my-godot-project",
nodePath: "/root/Game/Player",
property: "health",
value: { type: "int", value: 100 }
})
// Simulate input action
runtime_ws_input_action({
projectPath: "E:/my-godot-project",
action: "jump",
pressed: true,
strength: 1.0
})
// Capture screenshot
runtime_ws_screenshot({
projectPath: "E:/my-godot-project",
outputPath: "E:/screenshots/test_jump.png"
})
// Wait for node to appear
runtime_ws_wait_for_node({
projectPath: "E:/my-godot-project",
nodePath: "/root/Game/VictoryScreen",
timeout: 5000
})
// Run QA assertion
runtime_ws_qa_assert({
projectPath: "E:/my-godot-project",
nodePath: "/root/Game/Player",
property: "health",
expected: { type: "int", value: 100 },
operator: "greater_than",
message: "Player should have full health at start"
})
```
### File & Resource Operations
```typescript
// List project files
file_list({
projectPath: "E:/my-godot-project",
directory: "res://sprites",
pattern: "*.png",
recursive: true
})
// Search in files
file_search({
projectPath: "E:/my-godot-project",
query: "extends CharacterBody2D",
paths: ["res://scripts"],
filePattern: "*.gd"
})
// Load resource metadata
resource_load({
projectPath: "E:/my-godot-project",
resourcePath: "res://player.tscn",
shallow: true
})
// Build dependency graph
resource_dependency_graph({
projectPath: "E:/my-godot-project",
resourcePath: "res://levels/level_01.tscn",
direction: "forward",
maxDepth: 3
})
```
## Common Workflows
### 1. Project Setup & Inspection
```typescript
// Verify Godot installation
get_godot_version()
// Discover available tools
get_capabilities({
routeGroup: "project",
includeSchemas: true
})
// Get project info
get_project_info({ projectPath: "E:/my-game" })
// Check project settings
project_get_settings({
projectPath: "E:/my-game",
sections: ["application", "display", "input"]
})
// Install plugin for live editing
plugin_install({
projectPath: "E:/my-game",
overwrite: true,
websocketPort: 8766
})
// Verify plugin installation
plugin_status({ projectPath: "E:/my-game" })
```
### 2. Live Scene Editing
```typescript
// 1. Ensure editor is open with plugin enabled
// 2. Get current editor selection
editor_ws_selection_get({ projectPath: "E:/my-game" })
// 3. Inspect current scene
editor_ws_scene_tree_inspect({
projectPath: "E:/my-game",
maxDepth: 5
})
// 4. Add a new node
editor_ws_node_add({
projectPath: "E:/my-game",
parentPath: "Player",
nodeType: "Area2D",
عرض على GitHub