Beckett — MCP for Godot
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| BECKETT_PORT | No | Port for the MCP server (default 8770) | 8770 |
| BECKETT_TOKEN | No | Optional bearer token for authentication | |
| BECKETT_READONLY | No | Set to 1 to enable read-only mode | |
| BECKETT_ALLOWLIST | No | Comma-separated list of allowed paths or patterns | |
| BECKETT_CONFIRM_DESTRUCTIVE | No | Set to 1 to require confirmation for destructive actions |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| apply_templateA | Instantiate a bundled (or project) template into res:// in one call â copies its files and, if the template declares a main_scene, sets and opens it. Generic: a template can be a game starter, a UI screen, a settings menu, a test harness. Project templates under res://.beckett/templates/ override bundled ones. Call with no 'template' to list what's available. |
| attach_scriptA | Attach a script (res:// path) to a node in the open scene (undoable). |
| batch_executeA | Run several tool calls in one request, in order. steps = [{tool, args}]. Stops at the first failure (stop_on_error, default true). When a step fails, scene edits made by the batch are rolled back via the editor undo history (rollback, default true) â file/resource writes are not. Use to collapse multi-step authoring (create node â set props â attach script) into one atomic call. |
| build_csharpA | Compile-check a C#/.NET Godot project with |
| call_methodA | Invoke a method on a resolved object. args = a positional array. Returns the result as JSON. |
| connect_signalA | Connect a node's signal to a method on another node, persisted into the scene (undoable). from/to = node path/name in the open scene. |
| create_nodeA | Create a node of the given class and add it to the open scene (undoable). parent = a node path/name (default: scene root). |
| create_resourceA | Create a Resource of the given class and save it to a res:// path (.tres). Optional 'properties' dict sets initial values. |
| delete_nodeB | Remove a node from the open scene (undoable). |
| describe_classA | List a class's properties and methods (with signatures) so you know exactly what to set_property / call_method. The discovery key for full domain coverage. |
| describe_object | Dump a live object's properties as JSON. target = a res:// path, a node name/path in the open scene, or a class name (falls back to describe_class). |
| disconnect_signal | Disconnect a previously connected signal (undoable). |
| doctor | Beckett self-diagnosis â one call answers 'why can't the agent see or do X?'. Reports: edition (Lite/Full), the effort dial vs its ceiling AND where the cap comes from (a beckett/effort= line committed in project.godot silently trims every clone's tool list), advertised-vs-ceiling tool counts, dock-disabled tools, server/port/auth state, per-client config freshness (does each written config still carry the CURRENT endpoint URL?), and runtime-bridge liveness. Run this FIRST when tools seem missing, counts look wrong, or calls fail unexpectedly. |
| duplicate_node | Duplicate a node (with its children) under the same parent (undoable). Optional 'name' for the copy. |
| find_classes | Search classes by name substring â engine classes AND your project's own types (GDScript class_name + C# [GlobalClass]). Optional 'base' restricts to subclasses (e.g. base=Node2D). The discovery entry point â pair with describe_class. |
| find_methods | Search methods by name substring, optionally restricted to a class (incl. inherited). Any result is invokable via call_method. |
| find_nodes | Find LIVE nodes in the RUNNING game by type and/or name; returns their paths to feed into runtime_call/runtime_get_property/runtime_set_property. 'class' matches native classes AND custom class_name scripts (is_class alone misses custom nodes â they read as @Node@NN). name=substring on the node name. path=scope root (default scene root). recursive=true. max=cap (default 100). |
| game_logs | Read the RUNNING game's captured output off the runtime channel (real-time, no file logging): runtime SCRIPT errors WITH stack traces, push_error/push_warning, and print(). This is the play->see-error->fix signal â the blind spot logs_read (file-based) can't reliably cover. level=error (default: errors+script+shader) | warning (adds warnings) | all (adds print/stderr). limit=newest N (default 100), filter=substring, clear=true empties the buffer after reading. |
| get_godot_version | Return the running Godot engine version info. |
| get_performance_monitors | Profiling: read Performance monitors (fps, frame time, memory, object/node counts, draw calls, video mem, physics) â measured engine counters, never estimates. target=game (default when a play session is connected) reads the RUNNING game; target=editor reads the editor. duration_s>0 (game only, max 30) SAMPLES OVER TIME: polls every interval_ms (default 100, min 30) while the game keeps running, then returns per-monitor stats {min,avg,p95,max} â e.g. fps.p95 or process_time.max over a stress window; series=true also returns the raw per-sample series (token-heavy). Editor-target sampling is refused honestly: a tool call blocks the editor's own loop, so an over-time editor read would only measure a stalled editor. |
| get_play_state | Report whether a scene is playing and whether the runtime channel to the game is connected. |
| get_project_setting | Read a ProjectSettings value by its property path (e.g. application/run/main_scene). Pass it as 'setting' ('name' is also accepted). |
| get_project_statistics | Project overview: file/script/scene/resource counts, total GDScript lines, autoloads, main scene, input-action count, Godot version. Read-only static scan. |
| get_remote_tree | Dump the live scene tree of the RUNNING game (runtime counterpart of get_scene_tree). SCOPE IT to stay under token limits â a full game tree blows the budget. path=subtree root (name, relative, or absolute /root/...); depth=levels (-1=all); max_nodes (default 250); max_children per node (default 50); collapse=true groups runs of identical leaf siblings (e.g. '8x CPUParticles2D'). Returns {tree, node_count, truncated?}. |
| get_scene_tree | Return the node tree of the scene currently open in the editor (name/class/script, nested). |
| instance_scene | Instantiate a packed scene (res://*.tscn) as a child in the open scene (undoable). |
| list_dir | List entries (dirs + files) of a res:// directory. |
| list_signals | List a node's signals and their current connections (target node + method). |
| logs_read | Tail Godot's log FILE (the editor session and any played game log here). For the RUNNING game's errors/stack traces/prints in REAL TIME, prefer game_logs (runtime channel, no file needed) â this file reader is a fallback and needs file logging enabled (off by default; the result tells you how). Optional: level='error'|'warning', 'filter' substring, 'lines' (default 200), 'path' to override. |
| monitor_properties | Sample a node's property in the running game over several frames (detect movement/changes). Returns the sample series. |
| move_node | Reorder a node within its parent to a new child index (undoable). |
| open_scene | Open a scene by res:// path in the editor (makes it the edited scene). |
| play_scene | Play a scene in the editor. 'scene' (res://) plays a specific scene; current=true plays the open scene; otherwise the project's main scene. Then wait_until condition=play_started, and logs_read for errors. |
| read_file | Read a text file by res:// (or user://) path. |
| read_script | Read a script/text file from res://. |
| rename_node | Rename a node in the open scene (undoable). |
| reparent_node | Move a node under a new parent in the open scene (undoable). |
| runtime_get_property | Read a property of a node in the RUNNING game. Address by path (node path/name) OR a live selector: class (native or custom class_name) / name / text [+ nth, default 0]. The selector resolves fresh each call â no need to re-fetch volatile @Node@NN paths. Returns the value plus the 'resolved' path that matched. |
| save_scene | Save the scene currently open in the editor. Pass 'path' (res://) to save-as. |
| screenshot | Capture an image the agent can see. target=game (default) screenshots the RUNNING game via the runtime channel; target=editor captures the 2D editor viewport (PNG only). Token-cost dials (game target, 1.10+): scale=0.5 quarters the pixels; format=jpeg|webp with quality (default 0.8) compresses far below PNG for game frames; region=[x,y,w,h] crops (clamped). annotate=ui draws numbered Set-of-Mark boxes over every visible interactive control and ALSO returns the legend as structured {marks:[{i, path, rect, text?}]} â one glance answers both 'does it look right' and 'what can I click where'; follow up with click_control path=. For pure functional state, ui_snapshot is cheaper than any image. |
| script_patch | Surgically edit an existing res:// file without rewriting it whole. edits = an ordered array; each item is {find, replace[, all]} (find must match EXACTLY once unless all:true), {append: text}, or {prepend: text}. Atomic + safe: nothing is written if any anchor is missing/ambiguous or (for .gd) the result fails to compile. Prefer this over write_script for small changes. |
| search_files | Search file contents under res:// for a substring (or regex with regex=true). Returns file:line matches. |
| set_project_setting | Set a ProjectSettings value and persist project.godot. The property path goes in 'setting' ('name' is also accepted); e.g. set application/run/main_scene to res://main.tscn. |
| set_property | Set a property on a resolved object (undoable). value is coerced to the property's type (vectors accept "x y z" or [x,y,z]). |
| set_resource | Assign a resource to a node's property (undoable). Use 'resource' (res:// path to load) OR 'class' (mint a new inline sub-resource of that class). e.g. set Sprite2D.texture from a path, or a fresh RectangleShape2D on CollisionShape2D.shape. |
| stop_scene | Stop the running play session. |
| ui_snapshot | One-call UI snapshot of the RUNNING game: every visible Control as structured data â path, class (+custom class_name), text, rect [x,y,w,h] (gui space, ints), and the semantic state pixels can't tell you: disabled, focused, checked (toggles), value + range (sliders/spin/progress), selected (+selected_text / tabs / item_count), editable / placeholder / secret (text fields), tooltip, mouse_ignore. Interactive controls also get honesty flags: clipped (scrolled out of view) and occluded_by (another control would swallow the click â popup/modal/overlay). Top level: focus owner, open popup/dialog windows (exclusive = modal), viewport size, and a stable content 'hash' â pass it back as since_hash and an unchanged UI returns {unchanged:true} for ~free. For functional UI checks this replaces the screenshot + find_ui_elements + get_control_rect + runtime_get_property round-trips (keep screenshot for VISUAL/render bugs). Walks the whole SceneTree root (autoload HUD layers and popups included); scope with path=, slim with interactive_only=true, cap with max_nodes (default 400). |
| validate_script | Parse/compile GDScript WITHOUT writing it. Pass 'content' (source) or 'path' (res://). Returns whether it compiles â use before write_script to catch hallucinated APIs. Scripts whose class_name is already registered validate correctly (v1.9; the old false 'hides a global class' error is fixed); when validating 'content' destined for an existing file, ALSO pass its 'path' so a real cross-file class_name duplicate is still reported as the error it is. |
| wait_for_node | Block until a node appears in the RUNNING game (by path/name) or timeout. Use after play_scene to sync before driving. |
| wait_until | Wait for a condition. Blocks the editor at most ~1.5 s per call â longer would stall the editor's own game-launch pipeline and background jobs (they need main-thread frames). If not met yet it answers 'not yet': just call it again. condition = play_started | play_stopped | game_connected | seconds:N | file_exists:res://path. |
| write_file | Write a text file under res:// (or user://), path-traversal guarded. Refreshes the editor filesystem. |
| write_script | Write a GDScript (or other text, e.g. .cs) file under res://. GDScript is validated first by default â refuses code that doesn't compile; non-.gd files (C#, configâ¦) are written as-is (use build_csharp to compile-check C#). Set validate=false to force. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/beckettlab/beckett-godot-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server