WazziCode Godot
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@WazziCode Godot Add a double jump ability to the player character"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Godot Vibe OS
Give an AI agent the same concrete context you have in the Godot editor: the edited scene, selected nodes, resource graph, ClassDB, import state, and actual 2D/3D viewport.
Godot Vibe OS combines an authenticated localhost editor addon, a focused MCP server, a source-backed Godot project map, the gvibe CLI, and the Foundry desktop app. It is a separate Godot-native product—not a renamed Unity bridge.
Set up a project
Requirements: Godot 4.7.1, Node 20+, and pnpm 10. Godot 4.7.1 is the version this addon is source-audited and integration-tested against.
node /absolute/path/to/wazzicode-godot/bootstrap.mjs /absolute/path/to/MyGodotGameThe bootstrap builds the workspace, installs and enables addons/godot_vibe_os, creates .godot-vibe/, builds the project map, and writes the project's .mcp.json. Existing AGENTS.md, CLAUDE.md, and MCP entries are preserved.
Then open the project in Godot and restart your MCP client from the project directory. The addon writes authenticated discovery state under .godot/godot-vibe-os/; the bridge only binds to 127.0.0.1.
node /absolute/path/to/wazzicode-godot/apps/cli/bin/gvibe doctor \
--project=/absolute/path/to/MyGodotGameRelated MCP server: Gear
What the agent can do
The 34 godot_* tools are deliberately smaller and more Godot-specific than the source product's tool catalog:
Orient once with live project, scenes, selection, import, play, git, and relevant project-map state.
Inspect bounded Node trees and exact NodePaths; create, delete, reparent, instantiate, set properties, open, and save through editor APIs and UndoRedo.
Query ResourceLoader dependencies before moving or changing a resource.
Query the editor's real ClassDB before writing unfamiliar Godot APIs.
Read, hash, search, create, and atomically edit GDScript and other Godot text resources with SHA preconditions.
Capture the real 2D or 3D editor viewport as multimodal image content.
Run or stop the current, main, or a custom scene.
Verify with a real headless import plus
--check-onlyfor every GDScript. The result explicitly says tests are not configured; import is never mislabeled as a test suite.Query a maintained map of project settings, autoloads, input actions, addons, scenes, resources, shaders, GDScript classes, signals, exports, functions, preloads, and relationships.
Start a task with:
Call godot_orient with my request as `task`. Inspect first. Use godot_reflect before unfamiliar APIs. Make the change through dedicated scene or file tools, then run godot_verify and report its exact verdict.CLI
gvibe setup
gvibe init
gvibe install-addon [--source=<addon-directory>]
gvibe brain [--ensure]
gvibe doctor [--json]
gvibe mcp-config [--write] [--target=codex]
gvibe lock | unlock
gvibe restore [snapshot-id]
gvibe serveProject state lives under .godot-vibe/; Godot's per-machine discovery remains under ignored .godot/ state.
Repository
godot/addons/godot_vibe_os/ Godot 4 editor addon and authenticated bridge
packages/core/ protocol, schemas, errors, envelopes
packages/bridge-client/ discovery-aware authenticated HTTP client
packages/mcp-server/ 34 tools, prompts, resources, mock bridge
packages/project-brain/ Godot scanner, parser, entity graph, queries
packages/safety/ per-target gates, snapshots, action log
apps/cli/ gvibe setup and diagnostics
apps/desktop/ Foundry for Godot desktop app
tests/godot/ real enabled-addon Godot integration fixtureVerification
pnpm install --frozen-lockfile
pnpm typecheck
pnpm test
pnpm build
pnpm test:godot
pnpm --filter @gvibe/desktop test
cd apps/desktop/src-tauri && cargo testThe installed standard Godot build verifies the GDScript addon. C# project compilation requires a Godot .NET editor and is reported as unverified when that editor is unavailable. Headless mode cannot render editor viewports; the addon returns CAPTURE_UNAVAILABLE instead of fabricating an image.
Available Tools
45 toolsanimation_createA
Create 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).
Inputs: name (required), length (required), player_path (required), loop_mode, +2 more. Returns: object
animation_manageA
AnimationPlayer 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.
Inputs: op (required), params, session_id. Returns: object
api_manageA
Inspect 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.
Inputs: op (required), params, session_id. Returns: object
audio_manageA
Sound 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.
Inputs: op (required), params, session_id. Returns: object
autoload_manageA
Autoload (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.
Inputs: op (required), params, session_id. Returns: object
batch_executeA
Execute 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.
Inputs: commands (required), undo, session_id. Returns: object
camera_manageA
Camera2D / 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.
Inputs: op (required), params, session_id. Returns: object
client_manageA
Configure AI clients to use this WazziCode Godot 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.
Inputs: op (required), params, session_id. Returns: object
editor_manageA
Editor 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, or the game is parked in a debugger break (stop and relaunch); EVAL_HUNG for a 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). 'await' only progresses while the game window is focused.
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.
Inputs: op (required), params, session_id. Returns: object
editor_reload_pluginA
Reload 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 callsession_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, raisesPLUGIN_DISCONNECTEDwithdata.reason == "reload_timeout"and recovery diagnostics.
Inputs: session_id. Returns: object
editor_screenshotA
Capture 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: trueand anotein the metadata — focus the game window and retry for a current frame.GAME_HELPER_TIMEOUTmeans 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.
Inputs: fov, source, azimuth, coverage, +5 more.
editor_stateA
Get 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.
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").
Inputs: session_id. Returns: object
filesystem_manageA
Project 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.
Inputs: op (required), params, session_id. Returns: object
game_manageA
Runtime 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.
Inputs: op (required), params, session_id. Returns: object
godot_orientA
Orient before Godot work with one bounded, read-only live snapshot.
Returns the pinned session and project, authoritative editor readiness and play/liveness state, a depth-limited current-scene hierarchy, current selection, newest bounded editor/game error and warning windows, and a bounded Git working-tree summary when the project path is available. Partial component failures are labeled instead of being mistaken for clean state.
Inputs: task, session_id. Returns: object
godot_verifyA
Verify live Godot health with an explicit, evidence-based verdict.
Always performs a fresh editor/readiness probe, reports stale cached state, and reads the newest bounded editor and current-game diagnostic windows. Set run_tests=True to also invoke the existing in-editor res://tests/test_*.gd runner with optional filters. This orchestration does not author, save, or write project content; project-owned test scripts remain arbitrary code and are responsible for their own side effects.
Verdicts are passed, passed_with_warnings, failed, or
blocked. The response states whether tests ran, which evidence was
bounded or unavailable, and gives an action for every failure.
Inputs: suite, run_tests, test_name, session_id, +1 more. Returns: object
input_map_manageA
InputMap 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.
Inputs: op (required), params, session_id. Returns: object
logs_readA
Read 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_helperautoload (Godot 4.5+). Buffer 2000, with lines retained across runs and tagged by run_id. Default reads return current-run lines only; passsince_run_idfrom 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 addseditor_errors_countandeditor_errors_hintpointing 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.
Inputs: count, offset, source, session_id, +3 more. Returns: object
material_manageA
Material 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_" | "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.
Inputs: op (required), params, session_id. Returns: object
node_createA
Create (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.
Inputs: name, type, scene_file, scene_path, +2 more. Returns: object
node_findA
Find nodes in the scene tree by name, type, or group.
At least one filter must be provided. Filters AND together. Paginated.
Inputs: name, type, group, limit, +2 more. Returns: object
node_get_propertiesA
Get 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.
Inputs: path (required), fields, session_id. Returns: object
node_manageA
Node 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.
Inputs: op (required), params, session_id. Returns: object
node_set_propertyA
Set 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. For a fresh built-in resource, pass
{"__class__": "BoxMesh", ...}. Seeresource_manage(op="create")for more control.StringName: plain string. Array/Dictionary: JSON list/object.
Inputs: path (required), value (required), property (required), scene_file, +1 more. Returns: object
particle_manageA
Particle 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.
Inputs: op (required), params, session_id. Returns: object
project_manageA
Project 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.
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.
Inputs: op (required), params, session_id. Returns: object
project_runA
Run (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 WazziCode Godot 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.
Inputs: mode, scene, autosave, session_id. Returns: object
resource_manageA
Resource (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.
Inputs: op (required), params, session_id. Returns: object
scene_get_hierarchyA
Get 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.
Inputs: depth, limit, offset, session_id. Returns: object
scene_manageA
Scene 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 a new .tscn with the given root and open it. root_name defaults to filename basename when empty. • 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.
Inputs: op (required), params, session_id. Returns: object
scene_openA
Open 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.
Inputs: path (required), session_id, force_reload. Returns: object
scene_saveB
Save the currently edited scene to disk.
Inputs: session_id. Returns: object
script_attachA
Attach a script to a node in the scene tree.
Replaces any existing script on the node. Undoable.
Inputs: path (required), script_path (required), session_id. Returns: object
script_createA
Create 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.
Inputs: path (required), content, session_id. Returns: object
script_manageA
Script (.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.
Inputs: op (required), params, session_id. Returns: object
script_patchA
Anchor-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.
Not undoable via Ctrl+Z.
Inputs: path (required), new_text (required), old_text (required), session_id, +1 more. Returns: object
session_activateA
Set 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.
Inputs: session_id (required). Returns: object
session_manageA
Session 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.
Inputs: op (required), params, session_id. Returns: object
signal_manageA
Signals (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.
Inputs: op (required), params, session_id. Returns: object
test_manageA
Test 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.
Inputs: op (required), params, session_id. Returns: object
test_runA
Run 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.
Inputs: suite, verbose, test_name, session_id, +1 more. Returns: object
theme_manageA
Theme 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.
Inputs: op (required), params, session_id. Returns: object
tilemap_manageA
TileMap / 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.
Inputs: op (required), params, session_id. Returns: object
tileset_manageA
TileSet 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.
Inputs: op (required), params, session_id. Returns: object
ui_manageA
UI / 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.
Inputs: op (required), params, session_id. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 45 tools
Several tools have overlapping or duplicate functionality: editor_state and editor_manage(op="state") are the same operation, godot_verify and godot_orient both probe health/state, and resource_manage search overlaps with filesystem_manage search. While descriptions are highly detailed, the tool boundaries are not always crisp.
The pervasive <domain>_manage convention (scene_manage, resource_manage, project_manage, etc.) provides a strong pattern, but it is mixed with standalone action verbs (scene_open, node_create, script_patch, project_run, editor_screenshot, logs_read, godot_verify, batch_execute). This is a mostly consistent system with a few notable exceptions.
45 tools is excessive for a single server, exceeding the 25+ threshold. Many tools are umbrella managers bundling multiple ops, and some duplicate functionality (editor_state vs editor_manage, scene_manage vs scene_open/scene_save), making the surface feel bloated and harder to navigate.
The tool set covers an impressively broad range of Godot editor functionality: scene, node, script, resource, material, animation, particle, camera, audio, UI, tilemap, tests, runtime input, and project settings. Minor gaps like scene file deletion or export management exist but are not critical for core workflows.
Maintenance
Related MCP Connectors
Make games with AI: one MCP server that connects your agent to Unity, Unreal and Godot editors.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
MCP server that lets your AI assistant build and deploy apps, hosting each one at a live URL.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that gives AI assistants direct control over Godot 4 game development projects. It enables launching the editor, running projects, creating and editing scenes, writing GDScript, and inspecting assets through natural language commands.4412 npm4MIT
- AlicenseAqualityDmaintenanceAn MCP server that enables AI assistants to directly run, inspect, modify, and debug Godot game development projects through 110+ tools covering scenes, scripts, resources, runtime debugging, and asset management.3321 npm3MIT
- AlicenseBqualityDmaintenanceAn enhanced MCP server for interacting with the Godot game engine, enabling AI assistants to launch the editor, run projects, manage scenes and nodes, and handle scripts.16MIT
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables AI assistants to manage Godot projects, scenes, and editor operations through natural language commands.16185 npm90MIT