Godot MCP RTS
Extended MCP (Model Context Protocol) server for the Godot game engine, with RTS agentic testing, scene/script introspection & mutation, and live game screenshot capture.
Forked from Coding-Solo/godot-mcp.
   
What this fork adds
On top of the original 14 godot-mcp tools, this fork ships 15 additional tools in three groups:
- Test harness — agentic game testing (
test_get_info,
test_get_game_state, test_validate_scenario, test_check_entity, test_validate_paths, test_run_scenario, test_check_mlx)
- Scene & script introspection / mutation —
get_scene_tree,
remove_node, set_node_property, create_script, attach_script, list_scripts
- Visual capture —
take_screenshot(script-mode, standalone scenes)
and test_take_screenshot (live game via TestController IPC, real scenes with autoloads)
Plus infrastructure improvements:
- Upgraded to MCP SDK 1.x (from 0.6.0)
preflightProject()helper retrofit on the scene-op handlers (−150 LoC of
validation boilerplate)
- Dropped the unused
axiosdependency (npm auditclean) - End-to-end test suite (
npm test) covering protocol handshake, all
mutation tools, and live screenshot capture
Tool reference
All 29 tools at a glance:
Original Godot MCP tools (14)
| Tool | Purpose | |---|---| | launch_editor | Open the Godot editor for a project | | run_project | Run a project in debug mode and capture output | | get_debug_output | Read stdout/stderr from the running project | | stop_project | Stop the running project | | get_godot_version | Print the installed Godot version | | list_projects | Find Godot projects in a directory | | get_project_info | Project metadata + counts of scenes/scripts/assets | | create_scene | Create a new .tscn with a chosen root node type | | add_node | Add a node to a scene | | load_sprite | Load a texture into a Sprite2D/Sprite3D/TextureRect | | export_mesh_library | Export a scene as a .res MeshLibrary | | save_scene | Save a scene (optionally to a new path) | | get_uid | Get the UID of a file (Godot 4.4+) | | update_project_uids | Resave resources to refresh UID references |
Test harness tools (7)
| Tool | Purpose | |---|---| | test_get_info | Test harness capabilities + project info | | test_get_game_state | Snapshot of autoloads, constants, config | | test_validate_scenario | Validate a scenario config before running it | | test_check_entity | Verify a unit/building/resource scene exists | | test_validate_paths | Validate all expected paths for a race | | test_run_scenario | Launch the game with --test-harness | | test_check_mlx | MLX local LLM health + Apple Silicon platform info |
Scene & script tools (6, new in v0.3.0)
| Tool | Purpose | |---|---| | get_scene_tree | Hierarchical JSON dump of a scene's nodes | | remove_node | Delete a node from a scene and save | | set_node_property | Bulk-set properties on an existing node | | create_script | Create a .gd file (custom content or extends template) | | attach_script | Attach an existing script to a node in a scene | | list_scripts | Recursively list .gd files in a project or subdir |
Visual capture tools (2, new in v0.3.0)
| Tool | Purpose | |---|---| | take_screenshot | Render a scene via --script and save PNG. Standalone scenes only — does not load autoloads. | | test_take_screenshot | Capture the currently running game via file-based IPC with TestController. Real game scenes with autoloads loaded. |
Installation
git clone https://github.com/mikeumus/godot-mcp-rts.git
cd godot-mcp-rts
npm install # also runs npm run build via the prepare hook
Configuration
Claude Code
Add to your MCP settings (.claude/settings.json or global settings):
{
"mcpServers": {
"godot": {
"command": "node",
"args": ["/absolute/path/to/godot-mcp-rts/build/index.js"],
"env": {
"GODOT_PATH": "/Applications/Godot.app/Contents/MacOS/Godot"
}
}
}
}
Cline / Cursor / other MCP clients
Same configuration format. The server speaks MCP over stdio.
Environment variables
GODOT_PATH— Path to the Godot executable. If unset, the server
auto-detects common install locations on macOS / Windows / Linux.
DEBUG— Set totruefor verbose stderr logging.
Usage examples
Inspect a scene
get_scene_tree(
projectPath: "/path/to/game",
scenePath: "maps/test_map.tscn",
includeProperties: true
)
Returns nested JSON with name, type, path, script, children, and optionally properties.position / properties.visible for each node.
Create a script and attach it
create_script(
projectPath: "/path/to/game",
scriptPath: "scripts/my_unit.gd",
extendsClass: "CharacterBody3D"
)
attach_script(
projectPath: "/path/to/game",
scenePath: "units/my_unit.tscn",
nodePath: "MyUnit",
scriptPath: "scripts/my_unit.gd"
)
Set node properties
set_node_property(
projectPath: "/path/to/game",
scenePath: "units/my_unit.tscn",
nodePath: "MyUnit",
properties: { visible: false, modulate.r: 0.5 }
)
Note: Property names are converted to snake_case before reaching Godot. Built-in Godot properties (
position,rotation_degrees, etc.) are already snake_case so this is a no-op for them. Vector/Color values can't currently round-trip through JSON; pass scalar properties only.
Run a test scenario
test_run_scenario(
projectPath: "/path/to/game",
timeout: 30000
)
Launches the game with the --test-harness flag, capturing stdout for later inspection via get_debug_output.
Capture a live game screenshot
# 1. Start the game (must be running for IPC to work)
run_project(projectPath: "/path/to/game")
# 2. Wait a few seconds for it to render the first frame, then
test_take_screenshot(projectPath: "/path/to/game")
# → Screenshot saved to: /path/to/game/.mcp_screenshots/capture_<id>.png
# 3. Stop when done
stop_project()
TestController integration
For the test harness tools and test_take_screenshot to work, your Godot project needs to include the TestController autoload from tests/harness/test_controller.gd (or its parent-repo equivalent).
Setup
- Copy
tests/harness/test_controller.gdinto your project - Register it as an autoload (Project Settings → AutoLoad)
- The controller activates when the game runs with
--test-harness,
--test-mode, or when the GODOT_MCP_TEST env var is set
- The screenshot polling code is independent of activation — it runs in
any debug build so test_take_screenshot works even from a plain run_project invocation
Screenshot IPC architecture
test_take_screenshot uses a file-based IPC handshake instead of trying to capture from a headless --script subprocess (which can't load autoloads or the main scene):
MCP server Running game
───────────── ────────────
1. Write request.json ──→ .mcp_screenshots/ ─→ TestController._process()
{ request_id, output_path? } polls every 6 frames
2. Detect request
3. get_viewport()
.get_texture()
.get_image()
.save_png(...)
4. Poll for response.json ←── .mcp_screenshots/ ←─ Write response.json
{ request_id, status, absolute_path } Print TestController log
The polling is gated on OS.is_debug_build() so exported builds are unaffected. The polling interval is 6 frames (~10 Hz at 60 fps), which is fast enough to feel synchronous from the MCP side and slow enough to be free.
The IPC workspace lives at <projectPath>/.mcp_screenshots/. Add it to your .gitignore:
.mcp_screenshots/
Testing
This project has an end-to-end test suite that exercises a real Godot binary. There are no unit tests — the value of testing this server lives almost entirely in verifying that real godot --headless --script invocations round-trip correctly, so e2e is the right shape.
npm run build # always build first
npm test # smoke + mutations (~35s, no game window)
npm run test:smoke # ~3s protocol handshake + tool registration
npm run test:mutations # ~30s every scene/script tool against a sandbox project
npm run test:screenshot # ~15s INTRUSIVE: opens a game window, opt-in
The screenshot test is opt-in and gated behind the MCP_TEST_PROJECT_PATH env var:
MCP_TEST_PROJECT_PATH=/path/to/your/game npm run test:screenshot
It validates the full test_take_screenshot pipeline against a live game, including the TestController IPC handshake. See tests/e2e/README.md for the full breakdown.
Architecture
Claude Code / Cursor / etc.
│
│ MCP over stdio (SDK 1.x)
▼
godot-mcp-rts (Node/TypeScript)
│
├──→ child_process → godot --headless --script godot_operations.gd <op> <json>
│ (most tools: scene mutation, script create, etc.)
│
├──→ child_process → godot --headless --script test_operations.gd <op> <json>
│ (test harness tools: state snapshots, validation)
│
├──→ child_process → godot <project> [--debug | --test-harness]
│ (run_project, test_run_scenario; long-running)
│
└──→ file-based IPC at <project>/.mcp_screenshots/request.json
(test_take_screenshot, polled by TestController)
Development
npm run build # compile TypeScript, copy .gd scripts to build/
npm run watch # tsc --watch
npm run inspector # launch the MCP inspector UI against the built server
npm test # run the e2e suite (see Testing above)
When adding a new tool, see CONTRIBUTING.md for the full checklist.
Project layout
godot-mcp-rts/
├── src/
│ ├── index.ts # MCP server, tool definitions, handlers
│ └── scripts/
│ ├── godot_operations.gd # Headless GDScript dispatcher (file ops)
│ └── test_operations.gd # Headless GDScript dispatcher (test harness)
├── tests/
│ └── e2e/
│ ├── _client.mjs # JSON-RPC stdio client + tiny test runner
│ ├── smoke.mjs # Protocol + tool registration check
│ ├── mutations.mjs # All scene/script tools, 20 assertions
│ ├── screenshot.mjs # Live game capture via TestController IPC
│ └── README.md # How to run / extend the suite
├── scripts/
│ └── build.js # Post-tsc copy of .gd files into build/
├── build/ # Compiled JS + copied scripts (gitignored)
├── README.md
├── CONTRIBUTING.md
├── LICENSE # MIT
├── package.json
└── tsconfig.json
License
MIT — see LICENSE.
Credits
- Original godot-mcp by Coding-Solo
- RTS testing extension and v0.3.0 tool additions by the As Above, So Below team











