Godot MCP
by grinry
README.md
> This project is a fork of [Coding-Solo/godot-mcp](https://github.com/Coding-Solo/godot-mcp), originally created by Solomon Elias.
# Godot MCP
[](https://modelcontextprotocol.io/introduction)
[](https://godotengine.org)
[](https://nodejs.org/en/download/)
[](https://www.typescriptlang.org/)
[](https://github.com/grinry/godot-mcp/commits/main)
[](https://github.com/grinry/godot-mcp/stargazers)
[](https://github.com/grinry/godot-mcp/network/members)
[](https://opensource.org/licenses/MIT)
```text
((((((( (((((((
((((((((((( (((((((((((
((((((((((((( (((((((((((((
(((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((
((((( ((((((((((((((((((((((((((((((((((((((((( (((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((@@@@@@@(((((((((((((((((((((((((((@@@@@@@(((((((((((
(((((((((@@@@,,,,,@@@(((((((((((((((((((((@@@,,,,,@@@@(((((((((
((((((((@@@,,,,,,,,,@@(((((((@@@@@(((((((@@,,,,,,,,,@@@((((((((
((((((((@@@,,,,,,,,,@@(((((((@@@@@(((((((@@,,,,,,,,,@@@((((((((
(((((((((@@@,,,,,,,@@((((((((@@@@@((((((((@@,,,,,,,@@@(((((((((
((((((((((((@@@@@@(((((((((((@@@@@(((((((((((@@@@@@((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
@@@@@@@@@@@@@((((((((((((@@@@@@@@@@@@@((((((((((((@@@@@@@@@@@@@
((((((((( @@@(((((((((((@@(((((((((((@@(((((((((((@@@ (((((((((
(((((((((( @@((((((((((@@@(((((((((((@@@((((((((((@@ ((((((((((
(((((((((((@@@@@@@@@@@@@@(((((((((((@@@@@@@@@@@@@@(((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((((((((((((((((
(((((((((((((((((((((((((((((((((
/$$ /$$ /$$$$$$ /$$$$$$$
| $$$ /$$$ /$$__ $$| $$__ $$
| $$$$ /$$$$| $$ \__/| $$ \ $$
| $$ $$/$$ $$| $$ | $$$$$$$/
| $$ $$$| $$| $$ | $$____/
| $$\ $ | $$| $$ $$| $$
| $$ \/ | $$| $$$$$$/| $$
|__/ |__/ \______/ |__/
```
A Model Context Protocol (MCP) server for interacting with the Godot game engine.
The npm package for this fork is [`@grinry/godot-mcp`](https://www.npmjs.com/package/@grinry/godot-mcp).
## Introduction
Godot MCP enables AI agents to launch the Godot editor, run projects, capture debug output, and control project execution. This direct feedback loop helps agents understand what works and what doesn't in real Godot projects, leading to better code generation and debugging assistance.
## Features
This README describes the code in this checkout. Features with pending changesets may not yet be available in the published npm package or its plugin launcher; use a local build to try unreleased changes.
- **Launch Godot Editor**: Open the Godot editor for a specific project
- **Run Godot Projects**: Execute Godot projects in debug mode
- **Capture Debug Output**: Retrieve console output and error messages
- **Reusable Playtests**: Run frame-based input sequences, state assertions, PNG baseline comparisons with diff images, and screenshot steps with structured results and cleanup
- **Runtime Performance**: Read timestamped engine monitors with units and renderer availability
- **Frame-Based Sampling**: Collect monitor/property series with scalar and vector summaries
- **Project Configuration**: Preview and edit settings, autoloads and InputMap bindings while preserving unrelated comments and values
- **Control Execution**: Start and stop Godot projects programmatically
- **Get Godot Version**: Retrieve the installed Godot version
- **List Godot Projects**: Find Godot projects in a specified directory
- **Project Analysis**: Inspect project configuration, source declarations, dependencies and saved scene structure
- **Validation and Export**: Check all or selected GDScript files, run scene tests or GUT tests, and export through existing presets
- **Live Feedback and Input**: Inspect runtime trees/properties, simulate input, pause and step frames, and capture fresh-scene or running-game screenshots
- **Godot Reflection**: Inspect built-in class properties, methods, signals and enums from the installed engine
- **Independent Sessions**: Track separate game/editor processes with explicit handles on modern MCP clients
- **Scene Management**:
- Create new scenes with specified root node types
- Add nodes to existing scenes with customizable properties
- Load sprites and textures into Sprite2D nodes
- Export 3D scenes as MeshLibrary resources for GridMap
- Save scenes with options for creating variants
- Instance reusable scenes and duplicate supported local subtrees with atomic saves and previews
- Attach scripts, assign node references and configure the main scene
- Preview transactional property, hierarchy, group and signal edits with content-hash guards
- **Resource Authoring**: Inspect, create, and edit `.tres`/`.res` resources using validated typed properties
- **UID Management** (for Godot 4.4+):
- Get UID for specific files
- Update UID references by resaving resources
## Requirements
- [Godot Engine 4](https://godotengine.org/download) installed on your system
- Node.js (>=22.14.0) and npm
- An AI agent that supports MCP
## Quick Start
### Codex
With the Codex CLI installed, register the server:
```bash
codex mcp add godot -- npx -y @grinry/godot-mcp
```
With environment variables, use this command instead:
```bash
codex mcp add godot --env GODOT_PATH=/path/to/godot --env DEBUG=true -- npx -y @grinry/godot-mcp
```
Alternatively, add this to `~/.codex/config.toml`:
```toml
[mcp_servers.godot]
command = "npx"
args = ["-y", "@grinry/godot-mcp"]
[mcp_servers.godot.env]
GODOT_PATH = "/path/to/godot"
DEBUG = "true"
```
Omit `GODOT_PATH` to use automatic detection. Start a new Codex session after saving the configuration. Run `codex mcp list` to check registration, or `/mcp` in the Codex CLI to view active servers. See the [official Codex MCP documentation](https://developers.openai.com/codex/mcp) for more configuration options.
### Claude Code
```bash
claude mcp add godot -- npx @grinry/godot-mcp
```
That's it. Restart Claude Code and your Godot MCP tools are available.
With environment variables:
```bash
claude mcp add godot -e GODOT_PATH=/path/to/godot -e DEBUG=true -- npx @grinry/godot-mcp
```
### Autohand Code
```bash
autohand mcp add godot npx @grinry/godot-mcp
```
For a project-scoped registration, use `autohand mcp add --scope project godot npx @grinry/godot-mcp`. On macOS/Linux, a custom executable can be passed with `autohand mcp add godot env GODOT_PATH=/path/to/godot npx @grinry/godot-mcp`. See [Autohand Code](https://github.com/autohandai/code-cli) for platform-specific environment configuration.
<details>
<summary><strong>Cline</strong></summary>
Add to your Cline MCP settings file (`~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`):
```json
{
"mcpServers": {
"godot": {
"command": "npx",
"args": ["@grinry/godot-mcp"],
"env": {
"DEBUG": "true"
},
"disabled": false,
"autoApprove": [
"launch_editor",
"run_project",
"get_debug_output",
"stop_project",
"get_godot_version",
"list_projects",
"get_project_info",
"get_performance_monitors",
"create_scene",
"add_node",
"load_sprite",
"export_mesh_library",
"save_scene",
"get_uid",
"update_project_uids"
]
}
}
}
```
</details>
<details>
<summary><strong>Cursor</strong></summary>
**Using the Cursor UI:**
1. Go to **Cursor Settings** > **Features** > **MCP**
2. Click on the **+ Add New MCP Server** button
3. Fill out the form:
- Name: `godot`
- Type: `command`
- Command: `npx @grinry/godot-mcp`
4. Click "Add"
5. You may need to press the refresh button in the top right corner of the MCP server card to populate the tool list
**Using Project-Specific Configuration:**
Create a file at `.cursor/mcp.json` in your project directory:
```json
{
"mcpServers": {
"godot": {
"command": "npx",
"args": ["@grinry/godot-mcp"],
"env": {
"DEBUG": "true"
}
}
}
}
```
</details>
<details>
<summary><strong>Other MCP Clients</strong></summary>
For any MCP-compatible client, use this configuration:
```json
{
"mcpServers": {
"godot": {
"command": "npx",
"args": ["@grinry/godot-mcp"],
"env": {
"GODOT_PATH": "/path/to/godot",
"DEBUG": "true"
}
}
}
}
```
</details>
### Environment Variables
| Variable | Description |
|----------|-------------|
| `GODOT_PATH` | Path to the Godot executable (overrides automatic detection) |
| `DEBUG` | Set to `"true"` to enable detailed server-side debug logging |
<details>
<summary><strong>Building from Source</strong></summary>
```bash
git clone https://github.com/grinry/godot-mcp.git
cd godot-mcp
npm install
npm run build
```
Then point your MCP client to `build/index.js` instead of using `npx`.
</details>
## Architecture
The Godot MCP server uses a bundled GDScript approach for complex operations:
1. **Direct Commands**: Simple operations like launching the editor or getting project info use Godot's built-in CLI commands directly.
2. **Bundled Operations Script**: Complex operations like creating scenes or adding nodes use a single, comprehensive GDScript file (`godot_operations.gd`) that handles all operations.
The bundled script accepts operation type and parameters as JSON, allowing for flexible and dynamic operation execution without generating temporary files for each operation.
## Troubleshooting
- **Godot Not Found**: Set the `GODOT_PATH` environment variable to your Godot executable path
- **Connection Issues**: Ensure the server is running and restart your AI assistant
- **Invalid Project Path**: Ensure the path points to a directory containing a `project.godot` file
- **Build Issues**: Make sure all dependencies are installed by running `npm install`
<details>
<summary><strong>Cursor-Specific Issues</strong></summary>
- Ensure the MCP server shows up and is enabled in Cursor settings (Settings > MCP)
- MCP tools can only be run using the Agent chat profile (Cursor Pro or Business subscription)
- Use "Yolo Mode" to automatically run MCP tool requests
</details>
## Releases
Releases use Changesets to manage versions and changelogs, then GitHub Actions to publish the public `@grinry/godot-mcp` npm package. See [Contributing](CONTRIBUTING.md#releases) for the contributor workflow and one-time maintainer setup.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Validation and feedback tools
Requires Node.js **22.14 or newer** and Godot 4. The MCP SDK has been upgraded and the unused Axios dependency removed.
| Tool | Behavior |
|---|---|
| `list_project_files` | Lists scenes, scripts and resources. Accepts `type`, a relative glob `pattern`, and `limit` (default 1,000, maximum 10,000). Skips hidden files and symlinks; reports `truncated` when a traversal/result limit is reached. |
| `run_scene` | Runs `scenePath` (relative or `res://`) and stops after `timeoutMs` (default 30,000, maximum 600,000). Optional `headless`. |
| `validate_project` | Checks discovered GDScript files with Godot `--check-only`, retaining every diagnostic. Default total timeout: 60 seconds. C# and gameplay are outside this check. |
| `run_scene_test` | Runs a headless scene and returns `passed`, exit code, timeout status, output and diagnostics. A test scene must call `get_tree().quit(0)` for success or a nonzero code for failure. Default timeout: 60 seconds. |
| `export_project` | Uses an existing `preset` from `export_presets.cfg`, writing `outputPath`. Requires matching Godot export templates. Optional `debug` and `timeoutMs`. |
| `capture_scene_screenshot` | Runs a fresh `scenePath`, waits `frames` (default 3), and returns an inline PNG. Requires a display renderer; output uses a private temporary directory that is removed afterward. Default timeout: 30 seconds. |
| `view_log` | Reads the latest launched editor's output and errors; `lineCount` defaults to 200. |
| `quit_godot` | Terminates the editor launched by this server and waits for exit. Save editor changes first: unsaved changes may be lost. |
`run_project` also accepts `headless` and `timeoutMs`. Game and editor launches each replace the preceding process of the same kind. `get_debug_output` retains the most recent game's final logs after exit or timeout. Logs are bounded to 1 MiB per process and 10,000 lines per stream; truncation is reported. Scene paths reject traversal and symlinks that escape the project.
`add_node` converts JSON numeric arrays to Vector2/3/4, their integer variants, Quaternion and Color properties. Colors accept three or four components; other vectors require the exact component count. Invalid properties fail before saving the scene. Integral JSON numbers are accepted for integer properties.
### Imported textures
Before `load_sprite`, open the project in Godot or run `godot --headless --editor --path /path/to/project --import`. Godot must generate import metadata for the texture; copying a PNG alone is insufficient. Use its project resource path (for example, `res://textures/player.png`).
### Verification
Run `npm test` for process lifecycle and discovery regression tests. Set `GODOT_TEST_PATH` to a Godot 4 executable to include the real-engine MCP and scene-editing integration test:
```bash
GODOT_TEST_PATH=/path/to/godot npm test
```
## Live visual feedback and input
### Godot annotations
Any compatible MCP client or agent can use the annotation tools; no client-specific
API is required.
Call `ensure_annotation_addon` with `projectPath` to install and enable the bundled
editor addon automatically. Save and reopen an already-open editor after first
installation; `get_annotation_status` distinguishes installation from activation.
In the **Annotations** bottom panel, capture a 2D/3D scene viewport, draw a rectangle
or pin, add comments and submit. Editor-launched games also get an **Annotate**
button that pauses gameplay while a frozen frame is annotated.
For a temporary game without addon installation, call `start_debug_session` with
`annotations: true` and `headless: false`. Godot 4.7.1 is verified.
Ask your MCP client to call `list_annotations`, then `get_annotation` for original
and marked PNG images plus comments/scene context. Use `resolve_annotation` with
the returned revision to resolve or reopen a comment. Submission saves locally;
it does not automatically start a chat turn. Data persists under the hidden
`.godot-mcp/annotations/` directory. `remove_annotation_addon` preserves that data
and refuses modified addon files. Setup/removal and resolution respect read-only
policy; all annotation tools respect allowed project roots.
See the [annotation contract](docs/domains/annotations.md) for tool schemas,
limits, export isolation and activation details. Use a local build until this
feature is released.
### Editor plugin configuration
`get_editor_plugins` lists installed addons and their saved enablement. Use
`enable_editor_plugin` or `disable_editor_plugin` with `projectPath` and
`pluginPath` (for example `res://addons/godot_mcp_annotations/plugin.cfg`). Both
support `dryRun` and `expectedHash`, preserve other plugins/comments and are
blocked by read-only policy. Enabling validates the config and script paths;
disabling can remove a stale entry whose files no longer exist.
These tools change saved configuration. Save and reopen an already-open Godot
editor to apply it; they do not toggle the live checkbox remotely. Annotation
`ensure` also re-enables an already-installed disabled addon. Its
`configuredEnabled` reports the saved setting, while `editorReady` and
`activation` report whether recent matching addon presence confirms activation.
### Temporary debug sessions
Call `start_debug_session` with `projectPath` and optional `scenePath` to run a game with the temporary debug bridge. If no scene is supplied, the configured main scene is used. `capture_screenshot` returns a PNG of that running game's current state; `capture_scene_screenshot` starts a separate fresh scene.
The bridge uses a private temporary directory with authenticated requests, bounded messages and unique response IDs. It installs no addon, changes no autoload settings, and opens no network port. It runs only in the game process explicitly launched by `start_debug_session`; exported games do not include it. Godot may still generate its normal `.godot` import cache.
Use `simulate_input` with one of the argument objects below (one event per call):
```json
[
{ "kind": "action", "action": "ui_accept", "pressed": true },
{ "kind": "key", "keycode": 32, "pressed": true },
{ "kind": "mouse_button", "button": 1, "x": 120, "y": 80, "pressed": true },
{ "kind": "mouse_motion", "x": 120, "y": 80 }
]
```
Send `pressed: false` to release a held input. Actions must exist in the project's InputMap. Events use [Godot's input event dispatch](https://docs.godotengine.org/en/4.4/classes/class_input.html#class-input-method-parse-input-event), so scene input callbacks can observe them. `set_debug_pause` accepts `paused: true` or `false`; screenshots preserve that state. A headless session supports input and logs but cannot render screenshots. `stop_project`, another game launch, or server shutdown stops the session and removes temporary bridge files. Request cancellation/timeouts also stop the affected live session.
## GUT tests
Install [GUT](https://github.com/bitwes/Gut) in `addons/gut`, then import the project once in Godot. `run_gut_tests` accepts `projectPath` and exactly one `testFile` or `directory` (relative or `res://`). Optional arguments: `headless` (default true), `includeSubdirs` (default true), `logLevel` (0–3), and `timeoutMs` (default 60,000; maximum 600,000). It reports exit status, diagnostics, truncation and timeout, and rejects a run with no tests. It follows the [GUT command-line runner](https://gut.readthedocs.io/en/9.3.1/Command-Line.html); integration has been verified with GUT 9.6.1.
## Desktop bundle and Codex plugin
`npm run build:mcpb` creates `dist/godot-mcp-VERSION.mcpb`. It rebuilds the source, bundles runtime dependencies, copies all Godot scripts, validates the manifest, and verifies that the bundled server exposes the same MCP tools. Import the bundle into a desktop client supporting MCPB and configure its Godot executable path. Node.js >=22.14 and Godot must be available on the client machine. CI verifies the bundle; successful npm releases attach it to the matching GitHub release. Desktop installation itself has not been automated.
The repository also includes `.codex-plugin/plugin.json` and `.codex-plugin/mcp.json` for local/repository plugin distribution using the [supported Codex compatibility layout](https://developers.openai.com/plugins/build/plugins). Its launcher uses the published `@grinry/godot-mcp` package. Changesets updates the plugin version when preparing a release. The Codex CLI configuration above remains available for direct MCP registration.
To exercise the display and GUT integrations locally:
```bash
GODOT_TEST_PATH=/path/to/godot GODOT_TEST_RENDER=true GODOT_TEST_EXPORT=true GUT_TEST_ADDON_PATH=/path/to/addons/gut npm test
```
`update_project_uids` performs a headless editor import before resaving resources, so Godot creates script/shader `.uid` files in editor mode. It verifies missing UID files rather than reporting a save as successful generation.
## Scene authoring and reflection
| Tool | Behavior |
|---|---|
| `attach_script` | Attaches `scriptPath` (`.gd` or `.cs`, relative or `res://`) to `nodePath` in `scenePath`. Checks the script's native base type and loadability before saving. |
| `set_node_reference` | Sets an exported `property` on `nodePath` to `targetNodePath` in the same scene. Supports typed Node references and NodePath properties; rejects incompatible targets. |
| `set_main_scene` | Sets `application/run/main_scene` to `scenePath`, preserving other settings and comments. |
| `get_class_info` | Reflects a built-in `className` from the installed Godot version. Optional `section`: `properties` (default), `methods`, `signals`, or `enums`; `filter`, `includeInherited` (default true), and `limit` (default 100, maximum 500). Does not provide prose documentation. |
| `get_runtime_tree` | Reads the live debug session's scene nodes, classes and script paths. `maxDepth` defaults to 10 (maximum 20), `maxNodes` to 100 (maximum 200). Reports truncation and preserves pause state. |
Scene node paths use `root`, `.`, or a path beneath the root such as `root/Player`. Scene editing runs project constructors: use trusted projects. Mutating scene tools preflight script dependencies and verify that repacking preserves existing scripts. Unavailable scripts fail before scene saving. C# operations require a Godot **.NET executable and a built, loadable assembly**; a standard executable refuses C# edits instead of dropping attachments. GDScript attachment and safe rejection/preservation with standard Godot have integration coverage; positive .NET attachment still needs verification with a .NET installation.
`update_project_uids` imports the project before resaving and returns scene/UID counters. One-shot engine operations have bounded output, a 60-second deadline (version queries use 10 seconds), request cancellation and shutdown cleanup. `launch_editor` observes the first 1.5 seconds for errors or early exit, returns its diagnostics and distinguishes process startup from project readiness. `view_log` retains later errors.
## Project inspection and transactional editing
| Tool | Behavior |
|---|---|
| `get_project_overview` | Reads main-scene settings, autoloads, input actions, enabled addons, custom GDScript declarations and text resource dependencies without starting Godot. `limit` defaults to 200 (maximum 500). Godot expressions are returned verbatim; binary resources and UID targets are marked incomplete or left unresolved. |
| `get_scene_info` | Reads saved scene nodes, ownership, stored properties, attached script paths/export metadata, persistent connections, groups and dependencies without instantiating the scene. Includes base-scene and instance paths; does not flatten inherited/instanced content or infer unsaved editor changes. `maxNodes` defaults to 100 (maximum 500); `maxProperties` to 50 (maximum 200). |
| `set_node_properties` | Sets a `properties` dictionary on an existing local `nodePath`. Supports `dryRun` and `expectedHash` just like `modify_scene`. |
| `modify_scene` | Validates and applies 1–100 ordered `operations` to one scene, then saves once using an atomic replacement. A failed operation leaves the scene file untouched by the tool. |
`modify_scene` operations are `set_properties` (`properties`), `rename_node` (`newName`), `reparent_node` (`parentNodePath`), `remove_node`, `connect_signal` / `disconnect_signal` (`signal`, `targetNodePath`, `method`), and `add_group` / `remove_group` (`group`). Every operation includes `nodePath`. Paths after a rename/reparent refer to the updated hierarchy. Reparenting preserves the transform; groups and signal connections persist after reload. Signal connections check declared argument counts/types and built-in or registered script inheritance; untyped signal arguments cannot be assigned to a typed method parameter without a compatible declaration.
`instance_scene` and `duplicate_node` are available both as dedicated tools and as `modify_scene` operations. Both take `newName`; `nodePath` identifies the local parent for instancing and the source subtree for duplication. Instancing also takes `instanceScenePath`, preserves the scene instance and its ownership, and rejects dependencies back to the edited scene. Duplication creates a sibling and preserves scripts, groups, internal NodePaths/exported Node references and persistent signals. It refuses the scene root, subtrees containing scene instances or unique-name nodes, links outside the subtree, embedded resource references and references nested in collections. External file resources may be shared by the copy. Names must be unique among siblings. Dedicated tools accept `dryRun` and `expectedHash`.
```json
{
"projectPath": "/path/to/project",
"scenePath": "res://level.tscn",
"dryRun": true,
"operations": [
{"op": "instance_scene", "nodePath": ".", "newName": "Player", "instanceScenePath": "res://player.tscn"},
{"op": "duplicate_node", "nodePath": "SpawnPoint", "newName": "SecondSpawn"}
]
}
```
Preview first, then pass its `sourceHash` as `expectedHash` when applying:
```json
{
"projectPath": "/path/to/project",
"scenePath": "res://player.tscn",
"dryRun": true,
"operations": [
{"op": "set_properties", "nodePath": ".", "properties": {"position": {"type": "Vector2", "value": [32, 64]}}},
{"op": "add_group", "nodePath": ".", "group": "players"}
]
}
```
`dryRun` validates and repacks without replacing the original file; it still executes constructors and setters. A fresh content check guards every save; `expectedHash` additionally rejects stale previews. Supported values are booleans, numbers, strings, null object references, numeric vectors/colors/quaternions, NodePaths and resource references (`{"type":"Resource","path":"res://icon.svg"}`). Vectors accept component arrays or explicit type tags; colors require four components. Use `attach_script` and `set_node_reference` for script and typed node assignments. Collections, transforms and other unsupported property types fail explicitly.
Transactional edits refuse inherited scenes, nodes inside scene instances, scene-root structural edits, and changes to ownership or script properties. Rename/reparent update resolvable relative NodePaths; removal refuses surviving node references and persistent connections into the removed subtree. Structural edits refuse unresolved/absolute paths, embedded resources and references nested in collections rather than guessing their meaning. Script string literals and dynamically computed paths cannot be rewritten: validate and play-test after changing node paths. Instantiation, resource loading, autoloads, constructors and setters can execute project code; these tools are blocked by `GODOT_READ_ONLY` and do not sandbox those side effects.
## Resource inspection and authoring
| Tool | Behavior |
| --- | --- |
| `get_resource_info` | Reads stored resource properties with typed values and `sourceHash`. `maxProperties` defaults to 50 (maximum 200). |
| `create_resource` | Creates an instantiable built-in `className` at `resourcePath` (`.tres`/`.res`), optionally with `properties`. Refuses existing files; the parent directory must exist. Supports `dryRun`. |
| `set_resource_properties` | Sets 1–100 stored `properties` on an existing resource. Supports `dryRun` and `expectedHash`, preserves its UID/script, verifies a reload and saves through atomic replacement. |
These tools support the same primitive, numeric vector/color, NodePath and external Resource values as scene property editing. They exclude scripts and PackedScenes, custom resource creation, collection/transform writes, script/path/metadata changes and embedded-resource editing. Inspection, previews and setters may execute project code; all three require execution permission and are blocked by `GODOT_READ_ONLY`. Previews leave the target file untouched, but do execute resource loading/setters. An independently created resource is never overwritten by `create_resource`.
```json
{
"projectPath": "/path/to/project",
"resourcePath": "res://shapes/player.tres",
"className": "RectangleShape2D",
"properties": {"size": {"type": "Vector2", "value": [24, 48]}},
"dryRun": true
}
```
## Runtime inspection and frame stepping
`get_node_properties` reads 1–50 explicitly named `properties` from a live `nodePath`, returning typed, bounded values and the current pause state. It executes getters and is blocked in read-only mode. Collections are limited to 100 entries and six nesting levels, with a shared traversal budget of 1000 values per response; unsupported values are labeled rather than converted to misleading strings. Requests whose encoded response exceeds 60 KiB fail with an actionable limit error.
For gameplay checks, start a debug session, send input, pause it with `set_debug_pause`, record properties, call `step_frames` with `frames` (1–120) and `kind` (`physics`, default, or `process`), and inspect again or capture a screenshot. Stepping requires a paused session, resumes through the requested frame boundaries, and leaves it paused. Process stepping may advance physics too, and physics stepping may advance process frames. Nodes that ignore pause, wall-clock timers, asynchronous work and external systems continue to follow Godot's behavior; this is not a deterministic replay engine. Use the returned session handle on modern MCP clients.
`get_performance_monitors` reads the current debug session's FPS, process/physics times (milliseconds), memory, object/node/resource counts, draw calls and active physics bodies. Each monitor includes `unit` and `available`, with null values for unavailable headless render metrics. `sampledAtMs` is monotonic engine uptime, not a calendar timestamp. Some engine monitors update only once per second; an early zero does not prove that the measured work is absent. This tool works while paused and in read-only mode. It provides snapshots; use `sample_performance` below for multi-frame series and summaries. Function-level profiling is not supported.
## Project configuration
| Tool | Behavior |
| --- | --- |
| `get_project_setting` | Reads a stored `setting` expression, `stored` and `sourceHash` directly from `project.godot`. This is serialized configuration, not an effective value with defaults/feature tags/`override.cfg` applied. |
| `set_project_setting` / `remove_project_setting` | Sets a typed `value` or removes a stored override. Use `section/key` paths, for example `display/window/size/viewport_width`. Input/autoload writes use their dedicated tools. |
| `register_autoload` / `unregister_autoload` | Adds/removes a `name` and existing `resourcePath` (`.gd`, `.cs`, `.tscn`, `.scn`). `singleton` defaults to true. Replacing a different registration requires `replace:true`. New entries append after existing autoloads. |
| `get_input_actions` | Reads configured action bindings; optional `action` filters the result. `limit` defaults to 100 (maximum 200). Engine defaults and runtime InputMap changes are excluded. |
| `set_input_action` / `remove_input_action` | Creates/replaces an `action` and its complete `events` list, or removes its configured entry. Omitted `deadzone` preserves an existing value; new actions default to 0.5. An empty event list clears configured bindings. Removing a built-in override restores the engine default on next launch rather than disabling it. |
All configuration writers accept `dryRun` and `expectedHash`. They preserve unrelated entries, multiline values, comments, line endings and existing autoload order; saves are atomic and serialized with `set_main_scene`. A preview returns the old file's `sourceHash` for the subsequent `expectedHash`. Changes affect future launches; already-running games and unsaved editor state are unchanged.
Settings accept primitives, bounded JSON arrays/dictionaries and explicit vector/color/NodePath/StringName/PackedStringArray tags. Built-in types are checked against the installed engine, including feature-tag base types; engine ranges/enums and full gameplay suitability are not comprehensively validated. Values are limited to six nested levels and 1000 items. Resource/Object setting values are unsupported. `project.godot` is limited to 1 MiB; ambiguous duplicate sections/keys, unbalanced syntax and invalid UTF-8 are refused. Malformed Variant syntax is rejected before saving.
Autoload registration checks file existence/confinement and built-in class-name conflicts. It does not compile the script, verify Node inheritance/compiled C# assemblies or resolve conflicts with project-defined global classes. Use validation and a fresh debug session to verify runtime compatibility. Isolated engine serialization/config parsing starts no project autoloads and does not install project files. Parsed config tools require execution permission; `GODOT_READ_ONLY` permits only the raw `get_project_setting` query among these tools.
```json
{
"projectPath": "/path/to/project",
"action": "move_right",
"deadzone": 0.2,
"events": [
{"kind": "key", "key": "D"},
{"kind": "joypad_motion", "axis": 0, "axisValue": 1}
],
"dryRun": true
}
```
Pass this to `set_input_action`. Bindings support `key` (choose exactly one `key`, numeric `keycode` or `physicalKeycode`), `mouse_button` (`button` 1–9), `joypad_button` (`button` 0–127) and `joypad_motion` (`axis` 0–9, `axisValue` -1 or 1). `device` defaults to -1 (all devices). Key/mouse bindings support `ctrl`, `shift`, `alt`, `meta` and `commandOrControl`; the last enables Godot's platform-specific Command/Control mapping and cannot be combined with explicit ctrl/meta. Up to 32 events are accepted. Reads mark unsupported event shapes/classes rather than silently converting them, including non-default key locations, mouse double-clicks and fractional controller-axis bindings; their original bytes survive unrelated edits. Action/autoload names use identifier syntax.
Examples for other writers:
```json
{"projectPath":"/path/to/project","setting":"display/window/size/viewport_width","value":1280,"dryRun":true}
```
```json
{"projectPath":"/path/to/project","name":"GameState","resourcePath":"res://game_state.gd","singleton":true,"dryRun":true}
```
## Frame-based sampling
Pause a debug session with `set_debug_pause`, then call `sample_performance` or `sample_node_properties`. Both capture an initial value, advance `intervalFrames` between subsequent samples, and finish paused. Defaults are 30 samples, one physics frame per interval and `timeoutMs:60000`; `kind:"process"` selects process-frame boundaries.
```json
{"samples":60,"intervalFrames":1,"monitors":["physicsTime","staticMemory","nodeCount"]}
```
```json
{"nodePath":"Player","properties":["velocity","health"],"samples":30,"intervalFrames":2}
```
Pass the first example to `sample_performance` and the second to `sample_node_properties`, adding `sessionId` on modern clients. Performance sampling accepts the monitor names returned by `get_performance_monitors`; omitting `monitors` selects all. Property sampling reads 1–10 named properties on one node and rejects incomplete/unsupported encoded values. Each sample includes monotonic `sampledAtMs`, global engine process/physics-frame counters and `values`. `advancedFrames` counts resumed callback boundaries; global engine counters also include frames spent paused.
Summaries include minimum, maximum, mean, nearest-rank p50/p95, first/last and delta for numeric series. Vectors/colors/quaternions have component summaries. Unavailable monitors have null values and an unavailable summary; nonnumeric properties report the count of transitions instead. Arithmetic overflow is labeled, with affected summary values null. Monitor units and renderer availability accompany performance series.
Limits are 2–120 samples, 1–120 frames per interval, 1200 total advanced frames, 40 KiB of raw evidence and 60 KiB including summaries. The global deadline is at most 600000 ms. Sampling advances project code and executes getters, so both tools are blocked by read-only policy. Invalid fields are rejected before stepping. Cancellation/timeouts stop the debug game and clear IPC so a pending sample cannot continue into another session. Other failures leave the session paused. These are controlled frame-based observations, not passive sampling, a deterministic simulator or a function-level profiler; slowly refreshed engine monitors may repeat values.
## Reusable gameplay scenarios
`run_playtest` starts a fresh temporary debug session in the selected session, pauses it, executes ordered `steps`, and always stops its game before returning. It replaces any preceding game in that session. Successful runs on modern clients return an idle `sessionId`; use it for retained logs or release it with `close_session`. Newly allocated handles are released automatically on failure; evidence remains in the returned report. Existing sessions in other handles are unaffected. Project files remain unchanged by the tool; game scripts retain their normal filesystem side effects.
Steps are `input` (`event`, using `simulate_input` fields), `frames` (`frames`, optional `kind`), `assert` (`nodePath`, `property`, `expected`, optional `comparison`/`tolerance`) and `screenshot`. Input events are queued while paused and flushed when the next frame step resumes, before its node callbacks. Follow input with a frame step before assertions, screenshots or the end of the sequence. Multiple queued events retain their order.
Comparisons are `eq` (default), `ne`, numeric `lt`/`lte`/`gt`/`gte`, and `approx` (recursive numeric tolerance, default 0.00001). Vectors/colors use the explicit typed shapes returned by `get_node_properties`. Truncated or unsupported values cannot pass an assertion. At least one state assertion or screenshot comparison is required. The result contains per-step evidence, overall `passed`, diagnostics and inline screenshot images; failed assertions return `isError:true`. Operational failures report `RUNTIME_ERROR`, `TIMEOUT` or `OUTPUT_LIMIT` with completed-step evidence. Cancellation stops the game before propagating the cancelled request.
```json
{
"projectPath": "/path/to/project",
"scenePath": "res://player.tscn",
"steps": [
{"op": "input", "event": {"kind": "action", "action": "jump", "pressed": true}},
{"op": "frames", "frames": 10},
{"op": "assert", "nodePath": ".", "property": "health", "comparison": "gt", "expected": 0},
{"op": "input", "event": {"kind": "action", "action": "jump", "pressed": false}},
{"op": "frames", "frames": 1}
]
}
```
Limits: 100 steps, 50 combined state/visual assertions, 120 frames per step/1200 total, three screenshots and 30 KiB of assertion evidence. `timeoutMs` defaults to 60000 (maximum 600000). `headless` defaults to true; screenshots require `headless:false` and a display. Frame boundaries improve repeatability but do not guarantee deterministic gameplay, fixed startup-frame counts or paused external systems. Input recording and stress testing are not provided yet.
### Screenshot baseline comparison
Use a `compare_screenshot` step in `run_playtest` with `headless:false`:
```json
{
"projectPath": "/path/to/project",
"scenePath": "res://menu.tscn",
"headless": false,
"steps": [
{"op": "frames", "frames": 3, "kind": "process"},
{"op": "compare_screenshot", "baselinePath": "res://tests/baselines/menu.png", "pixelTolerance": 2, "maxChangedRatio": 0.001}
]
}
```
`baselinePath` must name an existing PNG inside the project; escaping paths/symlinks are rejected. All baselines are snapshotted, hashed and decoded in an isolated headless engine before replacing the selected game. Missing, malformed or oversized references leave any existing game running. Comparison reads the snapshot, so later edits to the reference cannot change the check. The tool never writes, creates or updates baseline files. To establish a baseline, capture the intended state with a `screenshot` step and explicitly save its returned PNG to your chosen project path.
Both images convert to RGBA8 with Godot's [Image API](https://docs.godotengine.org/en/stable/classes/class_image.html). A pixel is changed if any of its four channel differences exceeds `pixelTolerance` (integer 0–255, default 0). The step passes when `changedPixels / totalPixels <= maxChangedRatio` (0–1, default 0); the example allows a channel difference of 2 and up to 0.1% changed pixels. Comparison includes alpha and RGB even in transparent pixels; it does not apply perceptual, anti-aliasing or color-profile corrections. Images are compared at their original size. Different dimensions return a failed step with `IMAGE_DIMENSION_MISMATCH` and both sizes, without a diff.
Each completed comparison reports `passed`, `baselinePath`, `baselineHash`, dimensions, `changedPixels`, `totalPixels`, `changedRatio`, `changedPercentage` and `maxChannelDelta`, plus tolerances. The tool returns both the actual screenshot and a diff PNG: magenta pixels exceed tolerance; other pixels show the actual image in dim grayscale. `imageIndex` and `diffImageIndex` index the response's image blocks, excluding its initial text block. `screenshotCount` counts captures and `diffCount` counts diff images. A failed visual assertion makes the overall tool result `isError:true`; remaining steps still execute, and the game is stopped afterward.
Each PNG is limited to 8 MiB, 4096 pixels per axis and four million total pixels; comparison shares the existing three-capture scenario limit, deadline and cancellation cleanup. References need no Godot import metadata. A display renderer is required for the actual capture. Keep resolution, renderer, fonts and scene state consistent; this is a byte-channel comparison, not a guarantee of cross-platform visual identity. Wait for the intended state using frames/state assertions before capturing.
## Targeted validation and diagnostics
`validate_project` accepts either `scripts` (1–1000 relative or `res://` GDScript paths) or a relative `pattern` glob. Omitting both checks all discovered GDScript files. An empty selection reports `nothingChecked` and fails rather than claiming success. C# validation remains outside this tool's scope.
Validation, finite test/export runs and game debug output include `diagnostics` entries with `file`, `line`, `severity` and `message`, plus error/warning `counts`. Unknown locations are null; raw bounded output remains available. Warnings are reported separately and do not fail an otherwise successful run. New inspection/edit/runtime results also include MCP `structuredContent` alongside text for compatible clients.
## Protocol compatibility and sessions
The official MCP v2 server supports `2026-07-28` over stdio, including discovery and per-request metadata, while retaining `2025-11-25` initialization compatibility. Server instructions guide the workflow and tool annotations identify read and mutation operations.
For `2026-07-28`, `run_project`, `run_scene`, `launch_editor`, and `start_debug_session` return a `sessionId` in a final text content block. Pass it to subsequent log, input, pause, screenshot, runtime-tree, property inspection, performance snapshots, sampling, stepping and stop calls. Multiple sessions are independent. Supplying an existing handle replaces the previous process of that kind in that session. `close_session` stops its game/editor and releases the handle; stale handles are rejected. A server supports at most 16 explicit sessions at once. Older clients retain the existing default-session workflow, and may opt into explicit sessions by using handles returned by newer clients.
## Optional execution policy
Set `GODOT_ALLOWED_ROOTS` to permitted project/search directories, separated by the platform path-list delimiter (`:` on macOS/Linux, `;` on Windows). Canonical paths are checked, including symlinks. With no value, project selection remains unrestricted.
Set `GODOT_READ_ONLY=true` to allow metadata/discovery/log/reflection queries and process cleanup while rejecting resource writes and project execution, including tests and screenshots that start scenes. For an existing session, runtime-tree and performance-snapshot reads are allowed. Property getters, sampling, input, pause changes and screenshots require execution permission and are blocked. Configuration/resource parsing that invokes Godot is also blocked; raw project-setting reads remain allowed. These controls restrict MCP requests; they are not an OS sandbox for project scripts. Hosts should retain their tool-approval controls.
### Windows and WSL
Use an executable file in `GODOT_PATH`, not its containing directory. The server passes JSON and paths as native argument arrays, including spaces and quotes. CI runs portable regression checks on Windows, macOS and Linux with Node 22.14 and 24; platform coverage does not imply all engine/render/.NET combinations are verified.
In WSL, use a Linux Godot binary and Linux project paths. Alternatively run both this server and Godot natively on Windows with Windows paths. Directly combining WSL project paths with a Windows `.exe` is rejected with an actionable error; binary-aware cross-environment path translation is not supported.
### Google Antigravity
Following [Google's MCP configuration guide](https://antigravity.google/docs/mcp), open **MCP Servers → Manage MCP Servers → View raw config** in the IDE, or use the CLI's `/mcp` manager. Add the server to `mcpServers` in your global `~/.gemini/config/mcp_config.json` or workspace `.agents/mcp_config.json`:
```json
{
"mcpServers": {
"godot": {
"command": "npx",
"args": ["-y", "@grinry/godot-mcp"],
"env": { "GODOT_PATH": "/absolute/path/to/godot" }
}
}
}
```
Refresh the server configuration. This is a local stdio server; it does not require an editor addon or OAuth.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues