Install godot-ai from PyPI
Install exact version 3.2.5. The executable name has not been verified, so it is intentionally not guessed.
python -m pip install 'godot-ai==3.2.5'Connects MCP clients directly to a live Godot editor, enabling AI assistants to build scenes, edit nodes, and control the editor through over 120 operations
Detailed security scan evidence is not public for this MCP yet. Public identity, registry metadata, and independently observed protocol inventory remain available.
Installation and connection instructions are shown only when supported by retained package, repository, or endpoint evidence.
Install exact version 3.2.5. The executable name has not been verified, so it is intentionally not guessed.
python -m pip install 'godot-ai==3.2.5'| Canonical slug | godot-ai-f0a2dc01 | Deployment | Local Only |
|---|---|---|---|
| Canonical package | pypi:godot-ai | Repository | hi-godot/godot-ai |
| First published | Aug 11, 2026 | Latest release | Sep 3, 2026 |
| Last security verification | — | Classification confidence | 90% |
| Publication | Draft | Official distribution | Not verified |
| Channel | Identifier | Current version | Versions | Source |
|---|---|---|---|---|
| pypi | godot-ai | 3.2.5 | 6 | Repository |
| Package | Version | Published / observed | Inventory | Security scan |
|---|---|---|---|---|
| pypigodot-ai | 3.2.5Current | Sep 3, 2026 | 46 toolsSucceeded · 13 resources · 0 prompts | Evidence restricted |
Independently scan the exact version your agents use, receive alerts when its risk changes, and investigate every finding with retained version evidence.
No public current-version evidence is available yet.
| Tool | Category | Annotations | Risk |
|---|---|---|---|
animation_createCreate a new Animation clip inside an AnimationPlayer's default library.
After creating the clip, add tracks via ``animation_manage`` ops
``add_property_track`` / ``add_method_track`` / ``create_simple``.
Track node paths are stored relative to the AnimationPlayer's
``root_node`` (default: its parent), not to the scene root — see
``animation_manage`` preset ops for a forgiving target_path that
accepts either form.
If ``player_path`` doesn't resolve, an AnimationPlayer is auto-created
at that path (parent must exist).Input schema{
"additionalProperties": false,
"properties": {
"player_path": {
"type": "string",
"description": "Scene path to the AnimationPlayer node."
},
"name": {
"type": "string",
"description": "Animation clip name (e.g. \"idle\", \"pulse\")."
},
"length": {
"type": "number",
"description": "Duration in seconds."
},
"loop_mode": {
"default": "none",
"type": "string",
"description": "\"none\" (default) | \"linear\" | \"pingpong\"."
},
"overwrite": {
"default": false,
"type": "boolean",
"description": "Replace an existing animation with the same name."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"player_path",
"name",
"length"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
animation_manageAnimationPlayer authoring (player, tracks, autoplay, presets, playback).
Ops:
• player_create(parent_path, name="AnimationPlayer")
Create an AnimationPlayer with empty default library.
• delete(player_path, animation_name)
Delete an animation clip from the default library. Undoable.
• validate(player_path, animation_name)
Check all track paths resolve. Returns broken_count + per-track issues.
• add_property_track(player_path, animation_name, track_path, keyframes,
interpolation="linear")
Add a property track. track_path: "NodeName:property". keyframes:
[{time, value, transition?}, ...]. interpolation: linear|nearest|cubic.
• add_method_track(player_path, animation_name, target_node_path, keyframes)
Add a method track. keyframes: [{time, method, args?}, ...].
• set_autoplay(player_path, animation_name="")
Set autoplay. Empty animation_name clears.
• play(player_path, animation_name="")
Editor preview. Not saved with scene.
• stop(player_path)
Stop editor preview. Not saved with scene.
• list(player_path)
List animations with length, loop_mode, track_count.
• get(player_path, animation_name)
Inspect a clip's tracks and keyframes in detail.
• create_simple(player_path, name, tweens, length=None, loop_mode="none",
overwrite=False)
High-level: build a multi-track clip from tween specs in one call.
tweens: [{target, property, from, to, duration, delay?, transition?}].
• preset_fade(player_path, target_path, mode="in", duration=0.5,
animation_name="", overwrite=False)
One-call fade-in/out (modulate.a).
• preset_slide(player_path, target_path, direction="left", mode="in",
distance=None, duration=0.4, animation_name="", overwrite=False)
One-call slide-in/out (position).
• preset_shake(player_path, target_path, intensity=None, duration=0.3,
frequency=30.0, seed=0, animation_name="", overwrite=False)
One-call shake (jittered position).
• preset_pulse(player_path, target_path, from_scale=1.0, to_scale=1.1,
duration=0.4, animation_name="", overwrite=False)
One-call pulse / hover-bounce (3-keyframe scale ping-pong).
Preset target_path: accepts either a scene-absolute path (e.g. "/Main/World/Cube",
matching every other scene tool) or a path relative to the AnimationPlayer's
root_node (e.g. "World/Cube", matching how Animation tracks store node paths).
Scene-absolute targets outside the player's root_node subtree are converted to
a `..`-prefixed track path via root_node.get_path_to(target), the same shape
the relative form already accepts.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"add_method_track",
"add_property_track",
"create_simple",
"delete",
"get",
"list",
"play",
"player_create",
"preset_fade",
"preset_pulse",
"preset_shake",
"preset_slide",
"set_autoplay",
"stop",
"validate"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
api_manageInspect Godot API documentation-shaped metadata from the connected editor's
ClassDB: "what properties does X have", method signatures, signals, enums,
constants, defaults, and property hint strings.
Resource form (prefer for active-session reads):
godot://class/{class_name}
Ops:
- get_class(class_name, sections=None, include_inherited=False,
include_inheritors=False, offset=0, limit=100)
Return selected class-reference sections without creating a scene
instance. sections may be a comma-separated string or list containing
properties, methods, signals, enums, constants, inheritors.
Defaults to ["properties"] only — a bare get_class answers "what
properties does X have" without the multi-thousand-token full dump.
Pass the sections you want by name, or "all" for the full set
(properties, methods, signals, enums, constants). "all" does NOT
include the heavier "inheritors" section — request that by name.
For pagination, request one section at a time so offset/limit apply
only to the list you are paging.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"const": "get_class",
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
audio_manageSound effects, music, ambience (AudioStreamPlayer / 2D / 3D).
Ops:
• player_create(parent_path, name="AudioStreamPlayer", type="1d")
Create an AudioStreamPlayer / 2D / 3D node. type: "1d" | "2d" | "3d".
• player_set_stream(player_path, stream_path)
Assign an AudioStream resource (.ogg/.wav/.mp3 or .tres). Returns
duration_seconds.
• player_set_playback(player_path, volume_db?, pitch_scale?, autoplay?, bus?)
Update common playback properties atomically. Pass only fields to
change; at least one of volume_db/pitch_scale/autoplay/bus required.
• play(player_path, from_position=0.0)
Start real editor preview playback. Not undoable.
• stop(player_path)
Stop editor preview playback. Not undoable.
• list(root="res://", include_duration=True)
Scan project for AudioStream resources (every subclass + .tres/.res).
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"list",
"play",
"player_create",
"player_set_playback",
"player_set_stream",
"stop"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
autoload_manageAutoload (global singleton) management. Autoloads are scripts or scenes
loaded automatically at project start, accessible globally by name when
``singleton=True``. Persisted to ``project.godot``.
Ops:
• list()
List autoloads with name, path, and singleton flag.
• add(name, path, singleton=True)
Register an autoload (script or PackedScene) by ``res://`` path.
• remove(name)
Unregister an autoload by name. The underlying file is not deleted.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"add",
"list",
"remove"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
batch_executeExecute a list of editor sub-commands in order, stopping on first error.
Each item must be `{"command": "<plugin_command>", "params": {...}}`.
Use the underlying plugin command names (e.g. `create_node`, `set_property`,
`delete_node`, `attach_script`), not the MCP tool names. Commands run
sequentially; execution stops at the first error. When `undo` is True
(default), any successful sub-commands are rolled back via the scene's
undo history if a later sub-command fails, producing atomic-on-failure
semantics.
Use this to compose multi-step edits (create node + set property +
attach script) into a single tool call. Rollback works for sub-commands
that modify the currently edited scene. `batch_execute` itself is not
allowed as a sub-command.
Scene paths are relative to the edited scene root (e.g. "/Main/Enemy"),
NOT runtime "/root/..." paths. The example below assumes the scene
root is named "Main" — substitute the actual root name.Input schema{
"additionalProperties": false,
"properties": {
"commands": {
"items": {
"additionalProperties": true,
"type": "object"
},
"type": "array",
"description": "List of `{\"command\": str, \"params\": dict}` items."
},
"undo": {
"default": true,
"type": "boolean",
"description": "Roll back succeeded sub-commands on failure. Default True."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"commands"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
camera_manageCamera2D / Camera3D authoring (zoom, FOV, projection, smoothing, follow).
Ops:
• create(parent_path, name="Camera", type="2d", make_current=False)
Create a Camera2D ("2d") or Camera3D ("3d"). When make_current=True,
unmarks previously current cameras of the same class in one undo.
• configure(camera_path, properties)
Batch-set camera-specific properties (zoom, fov, projection, smoothing,
drag, limits …). Class-aware. Enum-by-name (projection, keep_aspect,
anchor_mode, doppler_tracking, process_callback). Vector2 dict
coercion for zoom/offset. Transforms (position, rotation, scale,
transform, global_*) live on the Node — set those via
node_set_property, not here.
• set_limits_2d(camera_path, left?, right?, top?, bottom?, smoothed?)
Set Camera2D bounds. Pass only the edges to change.
• set_damping_2d(camera_path, position_speed?, rotation_speed?,
drag_margins?, drag_horizontal_enabled?,
drag_vertical_enabled?)
Smooth Camera2D motion (position/rotation smoothing speeds + drag
deadzone). drag_margins: {left,top,right,bottom} fractions [0,1].
• follow_2d(camera_path, target_path, smoothing_speed=5.0, zero_transform=True)
Reparent camera under target with smoothing — Godot-native follow.
• get(camera_path="")
Inspect a camera (class, current flag, all properties). Empty path
resolves to the currently-active camera, falling back to the first.
• list()
List every Camera2D/Camera3D in the scene.
• apply_preset(parent_path, name, preset, type=None, make_current=True,
overrides=None)
Spawn with opinionated defaults. Presets: topdown_2d, platformer_2d,
cinematic_3d, action_3d. overrides merge over preset values.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"apply_preset",
"configure",
"create",
"follow_2d",
"get",
"list",
"set_damping_2d",
"set_limits_2d"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
client_manageConfigure AI clients to use this Godot AI MCP server. Writes / removes
client config files (Claude Code, Codex, Antigravity, Cursor, Devin Desktop (Windsurf),
Zed, etc.).
Ops:
• status()
List every supported client with id, display_name, status
(configured | not_configured | configured_mismatch | error),
and installed flag.
• configure(client)
Write the MCP server entry into the named client's config file.
``client`` is one of the ids returned by status().
• remove(client)
Remove this server's entry from the named client's config.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"configure",
"remove",
"status"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
csg_manageCSG authoring (create boolean shapes, set their operation).
Create CSG shapes (box, sphere, cylinder, torus, polygon) under a Node3D
parent in the currently edited scene and set their boolean operation
(union / intersection / subtraction) so geometry like holes, caves and
tunnels can be carved directly in the editor. All write ops are undoable
via EditorUndoRedoManager. Sibling CSG shapes under the same parent combine
automatically; use a CSGCombiner3D parent for explicit grouping. Size,
position and material live on the created node — set them with
node_set_property / material_manage after creation.
Ops:
• csg_create(parent_path, name="", shape="box", operation="union")
Create a CSG shape under a Node3D parent (empty parent_path = scene
root). shape: box | sphere | cylinder | torus | polygon.
operation: union | intersection | subtraction.
Returns: {path, name, shape, operation}
• csg_set_operation(path, operation)
Set the boolean operation of a CSG shape.
operation: union | intersection | subtraction.
Returns: {operation}
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"csg_create",
"csg_set_operation"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
custom_manageList or invoke custom tools registered by third-party addons.
Active session only. Use op="list" to discover registered tools.
op="invoke" requires params: tool_name (string); optional: params (dict,
forwarded to the addon handler unvalidated — shape per the tool's
params_schema from op="list"). Inside batch_execute, address a custom tool
as "custom_tool:<name>" (deferred tools cannot run in batches).
Some custom tools are also registered first-class as "custom_<name>" with
their own schema — prefer those when present.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"invoke",
"list"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
editor_manageEditor selection, performance monitors, quit, log clearing, game eval.
Resource forms (prefer for active-session reads):
godot://editor/state, godot://selection/current, godot://performance
Ops:
• state()
Editor version, project name, current scene, readiness, play state.
• selection_get()
Currently selected node paths in the editor.
• selection_set(paths)
Replace the selection with the given list of scene paths.
• monitors_get(monitors=None)
Performance singleton values (FPS, memory, draw calls, etc.). Pass
a list of monitor names to filter; None returns everything.
• quit()
Gracefully quit the Godot editor on next frame.
• logs_clear(clear_debugger_errors=False)
Clear the MCP log buffer. Returns cleared_count. Pass
clear_debugger_errors=True to also clear the Debugger dock's
visible Errors-tab rows (user-facing UI, so opt-in only); the
response then includes debugger_errors_cleared.
• game_eval(code)
Execute GDScript in the running game with return values. Uses
'await' so user code can await internally. Errors return fast and
actionable: EVAL_COMPILE_ERROR for a syntax/parse error,
EVAL_RUNTIME_ERROR (with the real message + line) for a runtime
error; EVAL_GAME_NOT_READY if the game can't service evals — still
launching (retry once it's up), the _mcp_game_helper autoload is
missing/disabled, its main loop is not advancing (focus the game),
or its debugger session closed; EVAL_HUNG for a live game's genuine
infinite loop / never-firing await; EVAL_RESULT_TOO_LARGE if the
returned value serializes past the debugger channel's capacity
(return a smaller slice).
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"game_eval",
"logs_clear",
"monitors_get",
"quit",
"selection_get",
"selection_set",
"state"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
editor_reload_pluginReload the Godot editor plugin.
Disables and re-enables the plugin on the next frame. The response
shape depends on whether this MCP server was spawned by the plugin
or launched externally:
- **Plugin-managed (default install)**: returns a pre-flight ack
``{status: "reload_initiated", transport_will_drop: true,
old_session_id, guidance}`` immediately. The reload kills this
server, so the WebSocket transport drops; reconnect and call
``session_manage(op="list")`` to find the new session_id.
- **Externally launched** (e.g. ``python -m godot_ai --transport
streamable-http --port 8000 --reload``): waits for the new
session to register and returns
``{status: "reloaded", old_session_id, new_session_id}``.
If the old bridge disappears and no replacement registers
within 15 seconds, raises ``PLUGIN_DISCONNECTED`` with
``data.reason == "reload_timeout"`` and recovery diagnostics.Input schema{
"additionalProperties": false,
"properties": {
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
editor_screenshotCapture a screenshot of the Godot editor viewport or running game.
Picking a source: the default ``"viewport"`` captures the editor's 3D
viewport, which is empty if the edited scene has no Node3D anywhere in
the tree (or no scene is open). Those cases return ``EDITOR_NOT_READY``
with ``error.data = {editor_state: "viewport_not_3d", scene_root_type}``
and an actionable ``error.message`` — switch to ``"cinematic"`` if the
scene has a Camera3D, or open a scene with 3D content.
Sources:
- "viewport" (default): editor 3D viewport. Requires Node3D content in
the edited scene (root or any descendant); see above for the
no-3D-content / no-scene error shape.
- "viewport_2d": editor 2D viewport. Use for 2D scenes.
Not compatible with view_target/coverage/elevation/azimuth/fov.
- "cinematic": render edited scene through its active Camera3D (no
editor gizmos). Prefers a Camera3D marked ``current``; falls back to
the first Camera3D found in a depth-first walk. NODE_NOT_FOUND only
when the scene contains no Camera3D at all.
- "game": running game's framebuffer (only when project is running).
A backgrounded/minimized game window freezes its main loop; the
capture then returns the last rendered frame with
``stale_frame: true`` and a ``note`` in the metadata — focus the
game window and retry for a current frame. ``GAME_HELPER_TIMEOUT``
means the game process never replied at all (nothing rendered yet,
main thread blocked, or helper dead) — focus the window and retry,
or use game_command to confirm liveness.
``include_image=True`` (default) returns an MCP ImageContent block.
``view_target`` (comma-separated Node3D paths) reframes editor camera;
AABB metadata always returned. ``coverage=True`` with view_target
captures perspective + orthographic top-down references.Input schema{
"additionalProperties": false,
"properties": {
"source": {
"default": "viewport",
"type": "string",
"description": "\"viewport\" | \"viewport_2d\" | \"cinematic\" | \"game\". Default \"viewport\"."
},
"max_resolution": {
"default": 640,
"type": "integer",
"description": "Longest-edge resolution. Default 640. 0 = full res."
},
"include_image": {
"default": true,
"type": "boolean",
"description": "Return image data. Default True."
},
"view_target": {
"default": "",
"type": "string",
"description": "Node3D scene path(s) to frame, comma-separated."
},
"coverage": {
"default": false,
"type": "boolean",
"description": "With view_target, capture two reference shots + AABB."
},
"elevation": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Camera elevation in degrees (0=level, 90=overhead)."
},
"azimuth": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Camera azimuth in degrees (0=front, 90=right)."
},
"fov": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"description": "Camera FOV in degrees. Tight 20-30 = zoom; 60-75 = context."
},
"user_prompt": {
"default": "",
"type": "string",
"description": "Optional context from the agent that requested the\ncapture. With Vision Routing enabled it is sent alongside the\nimage so the vision model can describe what the agent is\nlooking for."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
} | — | — | |
editor_stateGet current Godot editor state: version, readiness, open scene, play state.
Resource form: ``godot://editor/state`` — prefer for active-session reads.
Also reachable as ``editor_manage(op="state")`` (same handler) for clients
that prefer a single rolled-up tool.
Code-mode MCP adapters keep the server and tool names separate:
``call('godot-ai', 'editor_state', {})``. Never pass a server-prefixed
tool name such as ``godot-ai/get_editor_state``; that is neither the
adapter's call signature nor a registered tool. For dedicated current-
scene data, use ``readResource('godot-ai', 'godot://scene/current')``.
Side effect: refreshes the server's session readiness cache from the
live editor reply. Useful as a recovery step after a write call is
rejected as ``EDITOR_NOT_READY (state=playing)`` when you already know
the game has stopped — calling ``editor_state`` once syncs the cache
and the next write proceeds. Issue #262.
Response includes ``game_status`` for authoritative game liveness,
plus ``helper_live`` (status == "live") and ``session_active``
(status not in {"not_live", "stopped"}) mirrored from the same fields
inside ``game_status``. ``is_playing`` remains raw editor play-state;
use ``game_status.status`` for liveness decisions.
``game_status.status="break"`` means the game process is parked in a
remote-debugger break (boot-time parse errors do this before the game
helper registers); it will not resume on its own — call
``project_manage(op="stop")``.Input schema{
"additionalProperties": false,
"properties": {
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
filesystem_manageProject filesystem access via the Godot editor's EditorFileSystem.
Ops:
• read_text(path)
Read a text file at a ``res://`` path. Returns content, size,
line_count.
• write_text(path, content="")
Create or overwrite a text file. Updates the editor filesystem
entry for that one file (single-file update, not a full scan).
Newly-created files include ``data.cleanup.rm`` for transient
smoke tests; overwrite omits the field.
• reimport(paths)
Force-reimport the listed files via ``EditorFileSystem.update_file``.
``paths`` is a list of res:// paths.
Intended for imported assets such as textures, models, and audio.
Paths that are not imported resources (``.gd`` scripts, ``.tscn``,
hand-written ``.tres``, or an asset the editor has not imported yet)
report under ``skipped_non_imported`` rather than ``reimported``: their
filesystem entry is refreshed, but no import runs, so a success there is
not evidence that a script parsed or that diagnostics were produced. Use
``script_patch``/``script_create`` to save a script and receive fresh
diagnostics, or ``scan`` for an asset awaiting its first import.
Returns ``reimported``, ``skipped_non_imported``, ``not_found`` and their
counts.
• scan()
Force a full ``EditorFileSystem.scan()`` and wait for it to settle.
This is the headless equivalent of the editor regaining window focus:
``write_text``/``script_create`` register single files but do NOT
rebuild the global ``class_name`` table, so a freshly-created
``class_name MyThing extends Resource`` is invisible to
``resource_manage``/type references until a scan runs. Call this once
after adding ``class_name`` scripts when the editor isn't focused.
Single-flight (awaits any in-progress scan rather than stacking another).
Returns ``scan_completed`` and ``global_classes_registered_delta``.
• search(name="", type="", path="", offset=0, limit=100)
Find files by name, resource type, or path substring. At least one
filter must be set. Paginated.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"read_text",
"reimport",
"scan",
"search",
"write_text"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
game_manageRuntime game inspection and input simulation.
These ops target the running game process through Godot's EngineDebugger
bridge. Start the project first with project_run and poll editor_state until
game_capture_ready=true.
Ops:
- get_scene_tree(depth=10, root_path="")
Inspect the running scene tree. root_path accepts an absolute runtime
path or a scene-relative path rooted at the current scene.
- get_node_info(path, include_properties=True)
Inspect one running node's metadata and optional property snapshot.
- get_ui_elements(root_path="", include_hidden=False,
include_disabled=True, max_depth=10)
Inspect visible runtime Control nodes for UI testing. Includes path,
type, text where present, disabled state, and rect metadata.
- input_key(key, pressed=True, echo=False)
Send a key press/release to the running game.
- input_mouse(event, position=None, button="left", pressed=True)
Send a mouse motion or button event. event: "motion" | "button".
position is a {x, y} object or [x, y] array; omit it to use the
game's current cursor position. A present but malformed position is
rejected rather than silently falling back to the cursor.
- input_gamepad(device=0, control="button", index=0, pressed=True, value=0.0)
Send a joypad button or axis event. control: "button" | "axis".
- input_action(action, pressed=True, strength=1.0)
Set a project action's pressed state directly in the running game.
- input_sequence(steps, settle_frames=0)
Apply a frame-timed action timeline in one call — the frame-accurate,
multi-step form of input_action. Each step is
{at_frame, action, pressed=True, strength=1.0}; the game applies each
step's action on its scheduled frame, awaits settle_frames more, then
replies once. Use this instead of separate input_action calls whenever
timing matters (jump arcs, combos, walk-into-trigger): per-call network
latency makes hitting a target frame impossible otherwise. Steps must
be ordered by non-decreasing at_frame; frames (not ms) are the timing
basis. Action-based input is focus-independent, so it works on a
backgrounded game window. Cannot run inside batch_execute.
- input_state(actions=None)
Read current action pressed states. Empty actions = all project actions.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"get_node_info",
"get_scene_tree",
"get_ui_elements",
"input_action",
"input_gamepad",
"input_key",
"input_mouse",
"input_sequence",
"input_state"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
gridmap_manageGridMap authoring (set items, fill 3D regions, clear, read cells + library items).
All operations target GridMap nodes in the currently edited scene by
scene-relative path (e.g. "/Main/Terrain"). All write ops are undoable via
EditorUndoRedoManager.
item is the item id from the GridMap's MeshLibrary. Use
gridmap_list_library_items to discover valid ids and names before placing
cells (the 3D analogue of tileset atlas inspection). orientation is the
GridMap baked rotation index (0..24).
Ops:
• gridmap_set_item(path, item, map_x, map_y, map_z, orientation=0)
Set a single cell item at (map_x, map_y, map_z). item=-1 erases.
Returns: {map_x, map_y, map_z, item, orientation}
• gridmap_fill(path, item, rect_x, rect_y, rect_z, rect_w, rect_h, rect_d,
orientation=0)
Fill a rect_w × rect_h × rect_d region starting at (rect_x, rect_y,
rect_z) with one item in a single undo action.
Returns: {cells_filled, rect: {x, y, z, w, h, d}}
• gridmap_clear(path)
Remove all cells from the GridMap.
Returns: {cleared: true}
• gridmap_get_used_cells(path)
Return all used cell coordinates.
Returns: {cells: [{x, y, z}, ...], count: int}
• gridmap_list_library_items(path)
List the MeshLibrary items available to the GridMap.
Returns: {library, items: [{item, name, mesh}...], count: int}
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"gridmap_clear",
"gridmap_fill",
"gridmap_get_used_cells",
"gridmap_list_library_items",
"gridmap_set_item"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
input_map_manageInputMap actions and bindings (keyboard, mouse, gamepad). Persisted to
``project.godot``.
Resource form: ``godot://input_map`` — prefer for active-session reads.
Ops:
• list(include_builtin=False)
List input actions and their bound events. By default only
user-authored actions (those persisted in ``project.godot`` under
``input/<name>``) are returned; pass ``include_builtin=True`` to
also surface Godot's ``ui_*`` and editor-runtime actions
(``spatial_editor/*``, etc.). The ``is_builtin`` field on each
entry is true for any action not authored by the user.
• add_action(action, deadzone=0.5)
Create a new empty input action. ``deadzone`` must be in
``[0.0, 1.0]`` — Godot uses it as the analog-stick dead-zone
threshold; values outside this range are rejected with
``VALUE_OUT_OF_RANGE``. Typical values are 0.2-0.5; leave the
default 0.5 unless you have a reason. Not a key-repeat delay.
• ensure_action(action, deadzone=0.5)
Idempotently create or persist an input action. If the action exists
in live InputMap or in project.godot, the existing state is preserved.
• remove_action(action)
Remove an action and all its event bindings. Also removes actions
persisted in project.godot but not loaded in the live InputMap
(``loaded_in_input_map: false`` in ``list``), e.g. actions created
by a previous editor session.
• bind_event(action, event_type, keycode="", ctrl=False, alt=False,
shift=False, meta=False, button=None, axis=None,
axis_value=1.0)
Bind a key/mouse/gamepad event to an action. The action must
already exist (call ``add_action`` first). ``event_type`` is
``"key"`` | ``"mouse_button"`` | ``"joy_button"`` |
``"joy_axis"``.
- ``key``: ``keycode`` is a Godot keycode *name string* like
``"A"``, ``"Space"``, ``"Enter"``, ``"Escape"``, ``"F1"``,
``"Left"`` — not an integer and not ``KEY_*``. Modifier
booleans ``ctrl`` / ``alt`` / ``shift`` / ``meta`` optional.
- ``mouse_button``: ``button`` is an int — 1=left, 2=right,
3=middle, 4=wheel up, 5=wheel down.
- ``joy_button``: ``button`` is the ``JoyButton`` index
(e.g. 0=A/Cross, 1=B/Circle).
- ``joy_axis``: ``axis`` is the ``JoyAxis`` index and
``axis_value`` is the direction/value, usually -1.0 or 1.0.
• ensure_binding(action, event_type, ...)
Idempotently ensure the action exists and has the requested binding.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"add_action",
"bind_event",
"ensure_action",
"ensure_binding",
"list",
"remove_action"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
logs_readRead recent log lines from the Godot editor, plugin, or running game.
Resource form: ``godot://logs/recent`` — prefer for active-session reads.
Sources:
- "plugin" (default): MCP plugin recv/send/event traffic. Buffer 500.
- "game": stdout/stderr/push_error/push_warning from playing game
via ``_mcp_game_helper`` autoload (Godot 4.5+). Buffer 2000, with
lines retained across runs and tagged by run_id. Default reads return
current-run lines only; pass ``since_run_id`` from an earlier response
to read that prior run. Entries: {source, level, text, run_id};
response carries run_id, current_run_id, game_status, helper_live,
session_active, dropped_count, stale_run_id. helper_live and
session_active mirror the same fields inside game_status; is_running
is retained as a compatibility alias of session_active.
Boot-time parse/load errors fire before the game helper's logger
attaches, so they are NEVER in this buffer; when editor-side errors
were recorded during the current run the response adds
``editor_errors_count`` and ``editor_errors_hint`` pointing at
source="editor" — treat a clean game log carrying that hint as a
run that lost scripts, not a clean launch.
- "editor": editor-process script errors and the Debugger dock's
visible Errors-tab rows — parse errors, GDScript reload warnings,
@tool/EditorPlugin runtime errors, push_error/push_warning.
Logger-backed entries require Godot 4.5+; Errors-tab rows are read
from the editor UI when available. Use when the editor Output or
Debugger Errors panel shows red/yellow rows but other sources turned
up nothing. Buffer 500 for logger-backed entries; Debugger rows are
live UI state. Entries: {source, level, text, path, line, function}.
Filtered to .gd/.cs in the user project for Logger-backed entries;
addons/godot_ai/ dropped. Logger entries fired before plugin enable
are not captured.
- "all": plugin → editor → game lines (with source per entry).
Tail pattern: for game logs, poll the current run with offset=N and
keep the returned run_id. ``current_run_id`` identifies the active run;
``run_id`` identifies the run being read. Passing
``since_run_id=old_run_id`` reads retained lines for that prior run, and
``stale_run_id: true`` means the requested run is not the current run.
For editor logs, read once to capture
``next_cursor`` and pass it back as ``since_cursor`` on later calls.
``since_cursor`` reads Logger-backed editor entries only; live Debugger
Errors-tab rows are included in regular source="editor" reads but do
not have stable cursors. When ``since_cursor`` is set, it supersedes
``offset``. ``truncated: true`` means older entries fell out of the
ring before the poll; continue from the returned ``next_cursor`` and
treat ``oldest_cursor`` as the earliest retained sequence.
Set ``include_details=True`` for Errors-tab style metadata on game/editor
entries: original code/rationale, error type, resolved source, and
stack frames. Default false preserves compact responses.Input schema{
"additionalProperties": false,
"properties": {
"count": {
"default": 50,
"type": "integer",
"description": "Max lines to return. Default 50."
},
"offset": {
"default": 0,
"type": "integer",
"description": "Lines to skip. Default 0."
},
"source": {
"default": "plugin",
"type": "string",
"description": "\"plugin\" | \"game\" | \"editor\" | \"all\". Default \"plugin\"."
},
"since_run_id": {
"default": "",
"type": "string",
"description": "Game-log run id from a previous response; reads that\nretained run instead of the current run."
},
"since_cursor": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Editor-log cursor from a previous source=\"editor\" response."
},
"include_details": {
"default": false,
"type": "boolean",
"description": "Include rich error metadata for game/editor entries."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
material_manageMaterial authoring (StandardMaterial3D, ORMMaterial3D, ShaderMaterial,
CanvasItemMaterial). Albedo, metallic/roughness, emission, transparency,
shader uniforms.
Resource form: ``godot://materials`` — prefer for active-session reads.
Ops:
• create(path, type="standard", shader_path="", overwrite=False)
Create + save a material .tres at a res:// path. type:
"standard" | "orm" | "canvas_item" | "shader". For "shader",
shader_path points to the .gdshader.
• set_param(path, param, value)
Set a built-in property on a .tres material. Enum-valued params
accept names ("alpha" -> TRANSPARENCY_ALPHA). Color/Vector dicts.
Texture properties accept res:// paths.
• set_shader_param(path, param, value)
Set a shader uniform on a ShaderMaterial.
• get(path)
Inspect a material (type, params, uniforms, current values).
• list(root="res://", type="")
List materials under root, optional type filter.
• assign(node_path, resource_path="", slot="override", create_if_missing=False,
type="standard")
Assign a material to a node slot. Slots: "override" |
"surface_<N>" | "canvas" | "process". When create_if_missing=True
and no resource_path, makes an inline material of `type`.
• apply_to_node(node_path, type="standard", params=None, slot="override",
save_to="", overwrite=False)
High-level: build + set params + assign in one undo.
save_to optionally persists to disk; errors if the file already
exists unless overwrite=True.
• apply_preset(preset, path="", node_path="", overrides=None)
Curated looks: metal, glass, emissive, unlit, matte, ceramic.
path saves to disk; node_path assigns to a node; overrides merge.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"apply_preset",
"apply_to_node",
"assign",
"create",
"get",
"list",
"set_param",
"set_shader_param"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
node_createCreate (spawn) a new node in the scene tree.
Creates a node of the given type and adds it to the parent, or
instantiates a PackedScene from ``scene_path``. type and scene_path
are mutually exclusive — when scene_path is given, type is ignored.Input schema{
"additionalProperties": false,
"properties": {
"type": {
"default": "",
"type": "string",
"description": "Godot node class (e.g. \"Node3D\", \"MeshInstance3D\")."
},
"name": {
"default": "",
"type": "string",
"description": "Optional name; Godot auto-names if empty."
},
"parent_path": {
"default": "",
"type": "string",
"description": "Parent path relative to the edited scene root (e.g.\n\"/Main\"), NOT runtime \"/root/...\". Empty = scene root."
},
"scene_path": {
"default": "",
"type": "string",
"description": "Optional res:// path of a PackedScene to instantiate."
},
"scene_file": {
"default": "",
"type": "string",
"description": "Optional editor-scene guard (EDITED_SCENE_MISMATCH)."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
node_findFind nodes in the scene tree by name, type, or group.
At least one filter must be provided. Filters AND together. Paginated.Input schema{
"additionalProperties": false,
"properties": {
"name": {
"default": "",
"type": "string",
"description": "Substring match on node name (case-insensitive)."
},
"type": {
"default": "",
"type": "string",
"description": "Exact Godot class name (e.g. \"MeshInstance3D\")."
},
"group": {
"default": "",
"type": "string",
"description": "Group name the node must belong to."
},
"offset": {
"default": 0,
"type": "integer",
"description": "Number of results to skip. Default 0."
},
"limit": {
"default": 100,
"type": "integer",
"description": "Max number of results. Default 100."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
node_get_propertiesGet properties of a node.
Resource form: ``godot://node/{path}/properties`` — prefer for
active-session reads (returns the full property set).
The default returns every editor-visible property, which can be
50-150 entries. Pass ``fields`` to return only the properties you
need — a large response-size cut on this hot read. The response
always carries ``total_count`` (all editor-visible properties)
alongside ``count`` (returned): an unfiltered call returns the full
set, so ``count == total_count``; only the ``fields`` filter can
make ``count`` smaller. Requested names that match no
editor-visible property are listed in ``unknown_fields``, so a
nonexistent name is distinguishable from a property that exists
with a null value.
Null-valued properties are included: an unset object/resource slot
(``script`` on an unscripted node, an empty ``mesh`` or
``material``, …) returns ``"value": null`` with its declared type.
An attached script serializes to its ``res://`` path; built-in
scripts (no resource path) fall back to their string
representation.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "Scene path relative to the edited scene root (e.g.\n\"/Main/Camera3D\"), NOT runtime \"/root/...\" paths. Derive\nfrom prior tool responses or scene_get_hierarchy."
},
"fields": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "null"
}
],
"default": null,
"description": "When non-empty, return only these property names."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
node_manageNode tree manipulation (delete, duplicate, rename, reorder, reparent,
groups, hierarchy reads).
Resource forms (prefer for active-session reads):
godot://node/{path}/properties, godot://node/{path}/children,
godot://node/{path}/groups
Ops:
• get_children(path)
Direct children of a node (name, type, path each).
• get_groups(path)
Group names the node belongs to.
• delete(path, scene_file="")
Remove the node. Cannot delete scene root. Undoable.
• duplicate(path, name="", scene_file="")
Deep-copy a node + children as a sibling. Cannot duplicate scene root.
• rename(path, new_name, scene_file="")
Rename a node. Sibling-name collision and "/" / ":" / "@" rules apply.
• move(path, index, scene_file="")
Reorder among siblings. Index 0 = first.
• reparent(path, new_parent, scene_file="")
Move under a new parent. Children preserved. Cannot move into descendants.
• add_to_group(path, group, scene_file="")
Add the node to a group.
• remove_from_group(path, group, scene_file="")
Remove the node from a group.
All write ops accept the optional ``scene_file`` guard — if non-empty, the
mutation fails with EDITED_SCENE_MISMATCH when the editor's current scene
doesn't match.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"add_to_group",
"delete",
"duplicate",
"get_children",
"get_groups",
"move",
"remove_from_group",
"rename",
"reparent"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
node_set_propertySet a property on a node.
Verify the property name first — call ``node_get_properties`` (or read
``godot://node/{path}/properties``) to confirm the exact name and type
before writing. Guessing common Godot names often fails with
PROPERTY_NOT_ON_CLASS because Godot's actual properties differ from
intuition (e.g. ``Camera3D`` uses ``fov``/``current``, not ``field_of_view``;
``Sprite2D`` uses ``texture``, not ``image``; ``Node3D`` uses
``position``/``rotation``/``scale``, not ``transform.origin``).
Coerces ``value`` to the property's type:
- Vector2/Vector3: dict with x/y/z keys.
- Color: dict {r,g,b,a} or hex string ("#ff0000").
- NodePath: string ("../Other/Node").
- Resource: res:// path string (loads + assigns); null/"" clears.
``{"__class__": "BoxMesh", ...}`` creates a built-in resource owned
by this property. After scene_save it is serialized in-place as a
``[sub_resource]`` inside the .tscn; it is not a reusable .tres.
For sharing, first call ``resource_manage(op="create",
params={"type": "BoxMesh", "properties": {...},
"resource_path": "res://meshes/box.tres"})``, then pass that res://
path here (or use resource_manage(op="assign")).
- StringName: plain string. Array/Dictionary: JSON list/object.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "Scene path relative to the edited scene root (e.g.\n\"/Main/Camera3D\"), NOT runtime \"/root/...\" paths."
},
"property": {
"type": "string",
"description": "Property name (e.g. \"fov\", \"position\", \"mesh\"). Must match\nGodot's exact identifier — introspect with ``node_get_properties``\nif unsure rather than guessing."
},
"value": {
"anyOf": [
{
"type": "string"
},
{
"type": "integer"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"additionalProperties": true,
"type": "object"
},
{
"items": {},
"type": "array"
},
{
"type": "null"
}
],
"description": "New value. Pass null (or \"\" for resources) to clear."
},
"scene_file": {
"default": "",
"type": "string",
"description": "Optional editor-scene guard."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path",
"property",
"value"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
particle_manageParticle systems (GPUParticles2D/3D, CPUParticles2D/3D). All write ops
create the node + sub-resources (ProcessMaterial, default QuadMesh draw
pass) in a single undo action.
Ops:
• create(parent_path, name="Particles", type="gpu_3d")
Create an emitter. type: "gpu_3d" | "gpu_2d" | "cpu_3d" | "cpu_2d".
For GPU emitters, auto-creates ProcessMaterial; for gpu_3d, also
a default QuadMesh draw pass.
• set_main(node_path, properties)
Node-level props: amount, lifetime, one_shot, explosiveness,
preprocess, speed_scale, randomness, fixed_fps, emitting,
local_coords, interp_to_end.
• set_process(node_path, properties)
Behavior props (auto-creates ProcessMaterial for GPU). Emission shape,
velocity, gravity, color_ramp, scale_curve, turbulence. See full
property list in the Godot reference. GPU gravity is a Vector3 —
pass {x, y, z} or [x, y, z], including for gpu_2d (the shared
ProcessMaterial is 3D; z is ignored in 2D).
• set_draw_pass(node_path, pass_=1, mesh="", texture="", material="")
What gets drawn per particle. GPU 3D: mesh in draw_pass_N + optional
material override. GPU 2D / CPU 2D: texture. CPU 3D: mesh.
• restart(node_path)
Restart emission. Runtime-only, not undoable.
• get(node_path)
Inspect main props, process material, draw passes.
• apply_preset(parent_path, name, preset, type="gpu_3d", overrides=None)
Curated effects: fire, smoke, spark_burst, magic_swirl, rain,
explosion, lightning. One-shot presets re-trigger via restart.
overrides = {"main": {...}, "process": {...}, "draw": {...}}; bare
keys are auto-routed to main (amount, lifetime, one_shot, ...) or
process — draw keys must be nested under "draw". draw configures
the gpu_3d draw-pass StandardMaterial3D (blend_mode, albedo_color,
emission, ...); on gpu_2d only draw.texture (res:// path) applies;
cpu_* types reject draw overrides. Unknown or malformed override
keys return INVALID_PARAMS (never silently dropped); response
reports applied_main / applied_process / applied_draw. GPU gravity
requires {x, y, z} (or [x, y, z]) even for gpu_2d.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"apply_preset",
"create",
"get",
"restart",
"set_draw_pass",
"set_main",
"set_process"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
project_manageProject run/stop and project.godot settings.
Resource form: ``godot://project/info`` and ``godot://project/settings``
— prefer for active-session reads.
Ops:
• stop()
Stop the running project (game). Takes no params — call as
``project_manage(op="stop")`` or with ``params={}``. Idempotent:
succeeds with ``was_running=false`` if the project isn't running.
Do NOT pass extra fields like ``force`` or ``reason`` inside
``params`` — only the registered keys are accepted (here, none).
For multi-editor setups, pass ``session_id`` as a sibling of
``op``/``params``, not inside ``params``.
• settings_get(key)
Read a ProjectSettings key (e.g. "application/config/name").
• settings_set(key, value)
Write a ProjectSettings key and persist to project.godot.
Refuses the startup-execution keys (``autoload/*``,
``editor_plugins/*``, ``application/run/main_scene``,
``editor/run/main_run_args``, ``editor/script/templates_search_path``);
use ``set_main_scene`` / ``autoload_manage(op="add")`` for the two
that have a validated route.
• set_main_scene(path)
Set the project's main scene — the scene ``project_run(mode="main")``
boots and the engine loads at startup. Writes
``application/run/main_scene`` and persists to project.godot. ``path``
must be a ``res://`` scene inside the project that already exists and
loads as a PackedScene, so a scaffolded project can be made runnable
without opening the generic startup-execution surface.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"set_main_scene",
"settings_get",
"settings_set",
"stop"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
project_runRun (play) the Godot project from the editor.
Modes:
- "main": Run the project's main scene (default).
- "current": Run the currently open scene.
- "custom": Run a specific scene (requires ``scene``).
Idempotent: if the project is already running, returns success with
``data.was_already_running=true`` (no scene switch). To switch scenes,
call ``project_manage(op="stop")`` first, then ``project_run`` again.
After starting playback, waits briefly for the Godot AI game helper to
check in. The response includes ``game_status``, ``helper_live``
(status == "live"), ``session_active`` (status not in {"not_live",
"stopped"}), and any ``recent_errors`` observed during the run window.
The top-level booleans mirror the same fields inside ``game_status``.
``game_status.status="not_live"`` means playback launched but the game
did not become live before the helper-ready window elapsed;
``"no_helper"`` means the project has no _mcp_game_helper autoload, as
with some headless/custom-main-loop setups (helper_live=false,
session_active=true); ``"stopped"`` means playback stopped or never
became active before liveness could be confirmed (helper_live=false,
session_active=false); ``"break"`` means the game process is parked in
a remote-debugger break — during boot this is a GDScript parse/load
error that froze the game before the helper could register, and the
response names the failing script when captured
(``game_status.break`` = ``{reason, can_debug, pre_live}``). A game at
a break cannot continue on its own: call ``project_manage(op="stop")``,
fix the error, and relaunch. Poll ``editor_state`` to see late
transitions.Input schema{
"additionalProperties": false,
"properties": {
"mode": {
"default": "main",
"type": "string",
"description": "\"main\" | \"current\" | \"custom\". Default \"main\"."
},
"scene": {
"default": "",
"type": "string",
"description": "Scene path (e.g. \"res://levels/level1.tscn\"). Required for \"custom\"."
},
"autosave": {
"default": true,
"type": "boolean",
"description": "When True (default), Godot persists in-memory MCP scene\nmutations to disk before running. Pass False for smoke tests\nwhere MCP edits should stay in memory."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
resource_manageResource (asset) search, inspection, assignment, and creation. Covers
generic Resource subclasses plus specialized authoring (Curve, Environment,
physics shapes, gradient/noise textures).
Ops:
• search(type="", path="", offset=0, limit=100)
Search for resources by type or path. Type matching includes
subclasses. At least one filter required. Paginated.
• load(path)
Inspect a .tres / .res — returns type and editor-visible properties.
• assign(path, property, resource_path)
Load and assign a resource to a node property. Undoable.
• get_info(type)
Introspect a Resource class — properties, parent, abstract flag,
concrete_subclasses (for abstract bases). Read-only.
• create(type, properties=None, path="", property="", resource_path="",
overwrite=False)
Instantiate a Resource subclass. Either path+property (assign to a
node, undoable) or resource_path (save to .tres). For specific
families (Curve, Environment, etc.) prefer the dedicated ops.
• curve_set_points(points, path="", property="", resource_path="")
Replace all points on a Curve / Curve2D / Curve3D. Auto-creates
the curve resource if the slot is empty (curve_created flag).
• environment_create(path="", preset="default", properties=None,
sky=None, resource_path="", overwrite=False)
Build Environment + Sky chain. Presets: default | clear | sunset
| night | fog. sky may be bool or a procedural sky dict such as
{"sky_material": "procedural", "sky_top_color": "#0f172a"}.
Either assign to a WorldEnvironment node or save .tres.
• physics_shape_autofit(path, source_path="", shape_type="")
Size a CollisionShape2D/3D to a nearby visual's bounds. Searches
direct siblings then parent-siblings (handles nested
Body→Collision layouts). Ambiguous matches return candidate paths
in error.data.candidates. Auto-creates the concrete Shape subclass
if needed. shape_type accepts either the short form ("box",
"sphere", "capsule", "cylinder" for 3D; "rectangle", "circle",
"capsule" for 2D) or the matching Godot class name ("BoxShape3D",
"RectangleShape2D", etc.).
• gradient_texture_create(stops, width=256, height=1, fill="linear",
path="", property="", resource_path="",
overwrite=False)
Build GradientTexture2D from color stops. fill: linear | radial | square.
• noise_texture_create(noise_type="simplex_smooth", width=512, height=512,
frequency=0.01, seed=0, fractal_octaves=0,
path="", property="", resource_path="",
overwrite=False)
Build NoiseTexture2D wrapping FastNoiseLite. Noise types: simplex |
simplex_smooth | perlin | cellular | value | value_cubic.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"assign",
"create",
"curve_set_points",
"environment_create",
"get_info",
"gradient_texture_create",
"load",
"noise_texture_create",
"physics_shape_autofit",
"search"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
scene_get_hierarchyGet the scene tree hierarchy from the open scene.
Returns a paginated flat list of nodes with name, type, path, and
child count. Walks up to the specified depth.
Resource form: ``godot://scene/hierarchy`` — prefer for active-session
reads.Input schema{
"additionalProperties": false,
"properties": {
"depth": {
"default": 10,
"type": "integer",
"description": "Maximum walk depth. Default 10."
},
"offset": {
"default": 0,
"type": "integer",
"description": "Number of nodes to skip. Default 0."
},
"limit": {
"default": 100,
"type": "integer",
"description": "Max number of nodes to return. Default 100."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
scene_manageScene authoring (create, save_as, list open roots).
Resource form: ``godot://scene/current`` and ``godot://scene/hierarchy``
— prefer for active-session reads.
Ops:
• create(path, root_type="Node3D", root_name="")
Create the initial .tscn with the given root and open it. root_name
defaults to filename basename when empty. This initial root is written
immediately, but later node_create/node_set_property mutations remain
in editor memory until scene_save or save_as is called.
• save_as(path)
Save the currently edited scene to a new file path.
• get_roots()
List scenes currently open in the editor; flag the edited one.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"create",
"get_roots",
"save_as"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
scene_openOpen an existing scene file (.tscn) in the editor.
If ``path`` is already the currently edited scene this is a no-op
— the in-memory state (including any unsaved MCP mutations) is
preserved. Pass ``force_reload=True`` when the file on disk is the
authority and the editor should discard the open in-memory copy and
re-read the scene from disk.
The reply is sent only after the editor has actually switched to the
requested scene (``switched: true``), so follow-up writes are safe
immediately. ``switched: false`` with ``settle: "timeout"`` means the
switch had not landed within the wait window. In synchronous contexts
(e.g. inside ``batch_execute``) the reply returns immediately with
``switched: false`` and ``settle: "not_waited"``. In both of those
cases, re-check ``editor_state`` before issuing follow-up writes.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "File path of the scene to open (e.g. \"res://main.tscn\")."
},
"force_reload": {
"default": false,
"type": "boolean",
"description": "Re-read the scene from disk even when it is already\nopen. This discards unsaved in-memory edits to that scene."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
scene_saveSave the currently edited scene to disk.
Node and property mutation tools change the editor's in-memory scene;
call this explicitly to persist those mutations to the existing path.Input schema{
"additionalProperties": false,
"properties": {
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
script_attachAttach a script to a node in the scene tree.
Replaces any existing script on the node. Undoable.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "Scene path of the node (e.g. \"/Main/Player\")."
},
"script_path": {
"type": "string",
"description": "res:// path of the .gd (e.g. \"res://scripts/player.gd\")."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path",
"script_path"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
script_createCreate a new GDScript source file (.gd) on disk.
Writes content to a .gd file in the project. Overwrites if it exists.
Triggers a filesystem scan. New files include ``data.cleanup.rm``
listing the .gd + .gd.uid sidecar; overwrite omits it.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "res:// path (e.g. \"res://scripts/player.gd\")."
},
"content": {
"default": "",
"type": "string",
"description": "GDScript source. Empty creates a blank file."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
script_manageScript (.gd) reading, detachment, and outline.
Resource form: ``godot://script/{path}`` — prefer for active-session reads.
Ops:
• read(path)
Read full source, line count, file size.
• detach(path)
Remove the currently attached script from a node. Undoable.
• find_symbols(path)
Outline a .gd — class_name, extends, functions, signals, @export vars.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"detach",
"find_symbols",
"read"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
script_patchAnchor-based string-replace edit on a .gd file.
Finds an exact ``old_text`` and replaces with ``new_text``. Fails
on multiple matches unless ``replace_all=True``; fails on zero matches.
Exact byte match (whitespace significant). Triggers filesystem scan and
refreshes an already-loaded GDScript in place so the next call runs the
new code (response reloaded=true; otherwise reload_reason says why).
Not undoable via Ctrl+Z.Input schema{
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "res:// path ending in .gd."
},
"old_text": {
"type": "string",
"description": "Exact substring to find. Must be unique unless replace_all."
},
"new_text": {
"type": "string",
"description": "Replacement (empty deletes)."
},
"replace_all": {
"default": false,
"type": "boolean",
"description": "Replace every occurrence. Default False."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"required": [
"path",
"old_text",
"new_text"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
session_activateSet the active Godot editor session for subsequent tool calls.
Accepts either an exact session_id or a substring hint matched
against the session's short name (project folder basename),
project_path, or session_id. An exact id match always wins; a
substring must resolve to exactly one session or the tool returns
an error listing the candidates.Input schema{
"additionalProperties": false,
"properties": {
"session_id": {
"type": "string",
"description": "An exact session id (``<project-slug>@<4hex>``, e.g.\n``my_game@a3f2``, from ``session_manage`` with op=\"list\")\nOR a substring hint like a project folder name\n(\"test_project\", \"my_game\")."
}
},
"required": [
"session_id"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
session_manageSession listing.
Resource form: ``godot://sessions`` — prefer for resource-aware clients.
Ops:
• list()
List every connected Godot editor with metadata: session_id, short
name, godot_version, project_path, plugin_version, server_version,
editor_pid, server_launch_mode, current_scene, play_state, readiness,
connected_at, last_seen, is_active. The response also carries the
server-global ``exclude_domains`` (tool domains not registered on
this server via --exclude-domains).
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"const": "list",
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
signal_manageSignals (Godot's event/observer mechanism) — list, connect, disconnect.
Ops:
• list(path, include_editor=False)
List all signals on the node and their current connections (built-in
and custom). By default editor-internal connections (the
SceneTreeEditor dock and friends) are filtered out — pass
``include_editor=True`` to surface them. The response carries
``editor_connection_count`` so an agent can tell how many were hidden.
• connect(path, signal, target, method)
Connect a signal from ``path`` to a method on the target node.
Undoable.
• disconnect(path, signal, target, method)
Remove an existing connection. Undoable.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"connect",
"disconnect",
"list"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
test_manageTest result inspection (re-fetches the most recent ``test_run`` payload).
Resource form: ``godot://test/results`` — prefer for active-session reads.
Ops:
• results_get(verbose=False)
Same shape as test_run — full results from the last run, no
re-execution. verbose=True includes every individual test result.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"const": "results_get",
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
test_runRun GDScript test suites inside the connected Godot editor.
Discovers test_*.gd in res://tests/, instantiates them, and runs
all test_* methods. Returns a compact summary by default (counts,
suite names, duration) plus failures only. verbose=True includes
every individual test result (each with per-test ``duration_ms``).
The whole run has a 300s budget; the plugin aborts between tests
shortly before it expires and returns TEST_RUN_TIMEOUT with the
partial summary (full partials via test_manage(op="results_get")).
Long suites are safe — the editor services the MCP transport
between tests — but one single test blocking the main thread for
20s+ can still drop the session. Not allowed inside batch_execute.
The response includes ``edited_scene`` (the scene currently open in
the editor). Many suites assume the project's main scene is open; if
it is not and there are failures, the response also carries a
``scene_warning`` — open the main scene (``scene_open``) and re-run
before treating those failures as real.Input schema{
"additionalProperties": false,
"properties": {
"suite": {
"default": "",
"type": "string",
"description": "Run only the named suite (e.g. \"scene\", \"node\", \"editor\").\nEmpty runs all suites."
},
"test_name": {
"default": "",
"type": "string",
"description": "Run only tests whose name contains this substring."
},
"exclude_test_name": {
"default": "",
"type": "string",
"description": "Skip tests whose name contains this substring."
},
"verbose": {
"default": false,
"type": "boolean",
"description": "Include every individual test result. Default False."
},
"session_id": {
"default": "",
"type": "string",
"description": "Optional Godot session to target. Empty = active session."
}
},
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
theme_manageTheme authoring (Godot's stylesheet-like resource for Controls). Cascades
down a Control subtree when assigned via theme_apply.
Ops (pass via op="..." plus a params dict):
• create(path, overwrite=False)
Create a new empty Theme .tres at a res:// path.
• set_color(theme_path, class_name, name, value)
Set a color slot. value: "#rrggbb"/"#rrggbbaa", named, or
{"r","g","b","a"}.
• set_constant(theme_path, class_name, name, value)
Set an integer constant (separation, margin, padding).
• set_font_size(theme_path, class_name, name, value)
Set a font_size slot in pixels.
• set_stylebox_flat(theme_path, class_name, name, bg_color?, border_color?,
border?, corners?, margins?, shadow?, anti_aliasing?)
Compose a StyleBoxFlat (panels, button states, line edits).
border/corners/margins/shadow each accept "all" + per-side keys.
• apply(node_path, theme_path="")
Assign the theme to a Control (cascades to descendants). Empty
theme_path clears.
All ops accept `session_id` on the wrapper to target a specific editor.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"apply",
"create",
"set_color",
"set_constant",
"set_font_size",
"set_stylebox_flat"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
tilemap_manageTileMap / TileMapLayer authoring (set tiles, fill rects, clear, read cells).
All operations target TileMapLayer nodes in the currently edited scene by
scene-relative path (e.g. "/LavaLake20x20/Ground"). All write ops are
undoable via EditorUndoRedoManager.
source_id is the TileSet source index. atlas_col/atlas_row are the
atlas coordinates of the tile within that source. For full-tile animated
sources (lava, water, sewage) use atlas_col=0, atlas_row=0.
IMPORTANT — Source-ID remapping in specialized .tres files:
When a layer uses a specialized .tres (e.g. volcano_animated.tres),
Source-IDs are re-numbered from 0. Example: volcano lava is Source 8 in
the main volcano.tres but Source 0 in volcano_animated.tres.
Always use the remapped ID when the TileMapLayer references a specialized
.tres, not the original ID from the main .tres.
Ops:
• tilemap_set_cell(path, source_id, atlas_col, atlas_row, map_x, map_y)
Set a single tile at (map_x, map_y).
Returns: {map_x, map_y, source_id, atlas_col, atlas_row}
• tilemap_set_cells_rect(path, source_id, atlas_col, atlas_row,
rect_x, rect_y, rect_w, rect_h)
Fill a rect_w × rect_h region starting at (rect_x, rect_y) with
one tile type in a single undo action.
Returns: {cells_filled, rect: {x, y, w, h}}
• tilemap_clear(path)
Remove all tiles from the layer.
Returns: {cleared: true}
• tilemap_get_cells(path)
Return all used cell coordinates.
Returns: {cells: [{x, y}, ...], count: int}
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"tilemap_clear",
"tilemap_get_cells",
"tilemap_set_cell",
"tilemap_set_cells_rect"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
tileset_manageTileSet management — atlas inspection tools.
Ops:
• tileset_get_atlas_tiles(tileset_path, source_id)
Return all occupied atlas tile positions for one source in a TileSet.
Read-only — does not modify any resource or project file.
tileset_path: res:// path to the .tres TileSet resource (required)
source_id: raw TileSet source id of the TileSetAtlasSource to query (required, ≥ 0)
Returns:
{"tiles": [{"col": int, "row": int}, ...], "count": int}
Error codes (passed through from GDScript handler):
MISSING_REQUIRED_PARAM — tileset_path empty or source_id absent
RESOURCE_NOT_FOUND — tileset_path does not exist on disk
WRONG_TYPE — not a TileSet, or source is not a TileSetAtlasSource
VALUE_OUT_OF_RANGE — source_id does not exist in this TileSet
• tileset_get_atlas_image(tileset_path, source_id, max_size=0)
Return the atlas sprite-sheet texture of a TileSetAtlasSource as a
Base64-encoded PNG image. Read-only — reads the texture directly
from the resource without any UI interaction.
tileset_path: res:// path to the .tres TileSet resource (required)
source_id: raw TileSet source id of the TileSetAtlasSource to query (required, ≥ 0)
max_size: optional int; if > 0, scale the image so its longest
edge is at most max_size pixels (default 0 = full res)
Returns:
{"image_base64": str, "width": int, "height": int,
"original_width": int, "original_height": int, "format": "png"}
Error codes (passed through from GDScript handler):
MISSING_REQUIRED_PARAM — tileset_path empty or source_id absent
RESOURCE_NOT_FOUND — tileset_path does not exist on disk
WRONG_TYPE — not a TileSet, source not a TileSetAtlasSource,
or source has no texture assigned
VALUE_OUT_OF_RANGE — source_id does not exist in this TileSet
• Atlas image workflow:
To visually inspect what tiles look like, use tileset_get_atlas_image
instead of editor screenshots. It reads the texture directly from the
resource — no UI interaction or editor state required.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"tileset_get_atlas_image",
"tileset_get_atlas_tiles"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — | |
ui_manageUI / Control authoring (HUD, menus, layouts, vector decoration).
Ops:
• set_anchor_preset(path, preset, resize_mode="minsize", margin=0)
Apply a Control layout preset. preset: top_left | top_right |
bottom_left | bottom_right | center_left | center_top | center_right |
center_bottom | center | left_wide | top_wide | right_wide |
bottom_wide | vcenter_wide | hcenter_wide | full_rect.
resize_mode: minsize | keep_width | keep_height | keep_size.
Target must be a Control. CanvasLayer is the canonical HUD parent
but is not a Control — put a Control child under the CanvasLayer and
apply the preset to that overlay.
• set_text(path, text)
Set text on a Label/Button/LineEdit/TextEdit/RichTextLabel.
• build_layout(tree, parent_path="")
Atomically build a UI subtree from a nested spec
({type, name?, properties?, anchor_preset?, anchor_margin?, theme?,
children?}). Validates everything before mutating.
`properties` is direct node properties only. Theme constants like
container spacing live under `theme_override_constants/<name>` —
e.g. `{"theme_override_constants/separation": 8}` on a
VBoxContainer, not `{"separation": 8}` (which errors).
`theme` and `anchor_preset` require a Control / Window — for a HUD,
nest a Control under a CanvasLayer and apply them to the Control
child, not the layer itself.
• draw_recipe(path, ops, clear_existing=True)
Attach a declarative list of vector _draw() ops to a Control —
radar sweeps, gauges, corner brackets, crosshairs, waveforms.
Op kinds: line | rect | arc | circle | polyline | polygon | string.
Canonical call shape: ``{"op": "<verb>", "params": {...}}``. Flat op parameters are accepted as a compatibility alias when the client transmits them; ``op`` and ``session_id`` remain top-level.Input schema{
"additionalProperties": false,
"properties": {
"op": {
"enum": [
"build_layout",
"draw_recipe",
"set_anchor_preset",
"set_text"
],
"type": "string"
},
"params": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"session_id": {
"default": "",
"type": "string"
}
},
"required": [
"op"
],
"type": "object"
}Output schema{
"additionalProperties": true,
"type": "object"
} | — | — |
godot://scene/currentCurrent scene path and root node info from the active Godot editor.
godot://selection/currentCurrently selected nodes in the Godot editor.
godot://custom-toolsgodot://editor/stateEditor version, project name, current scene, readiness, play state.
godot://input_mapAll input map actions and their bound events. Excludes built-in ui_*.
godot://materialsAll Material resources under res:// (every Material subclass + .tres).
godot://performancePerformance singleton snapshot (FPS, memory, draw calls, frame time).
godot://project/infoProject name, Godot version, paths, and play state.
godot://project/settingsCommon project settings subset (display, physics, rendering).
godot://logs/recentLast 100 log lines from the Godot editor console.
godot://scene/hierarchyScene tree hierarchy from the active Godot editor (first 100 nodes). A resource URI takes no arguments, so this read is capped; a truncated result sets `resource_truncated` with a hint. Use the `scene_get_hierarchy` tool for offset/limit pagination or a scoped depth.
godot://sessionsAll connected Godot editor sessions and their metadata.
godot://test/resultsMost recent ``test_run`` results without re-executing tests.
godot://class/{class_name}ClassDB metadata for a class in the active Godot editor. Returns the full documentation set (properties, methods, signals, enums, constants). The `get_class` tool defaults to properties-only, but a resource URI cannot carry a `sections` argument, so the resource pins `sections="all"` to preserve its advertised full-reference contract.
godot://node/{path*}/childrenDirect children of the node at scene path ``path`` (name, type, path each).
godot://node/{path*}/groupsGroup names the node at scene path ``path`` belongs to.
godot://node/{path*}/propertiesAll properties of the node at scene path ``path`` (e.g. Main/Camera3D).
godot://script/{path*}Read a GDScript file at the given res:// path. ``path`` is the res:// path with the ``res://`` prefix dropped — e.g. ``godot://script/scripts/player.gd`` reads ``res://scripts/player.gd``.
| Endpoint | Transport | Authentication | Health | Observed |
|---|---|---|---|---|
| No verified remote endpoint is linked. | ||||
Install the selected package version with: python -m pip install 'godot-ai==3.2.5'
Godot AI MCP Server exposed 46 tools during independent protocol observation, including animation_create, animation_manage, api_manage, audio_manage, autoload_manage, batch_execute, camera_manage, client_manage, and others.
The selected current version does not yet have completed public verification. Unknown does not mean clean or vulnerable.
Curated product and capability guides containing this catalog record.