Beckett: zero-sidecar MCP server for Godot 4.2+ (the AI sees, and optionally playtests, your game)

Hi all. I built Beckett, an MCP server that lives inside the Godot 4 editor as a single GDScript
EditorPlugin. Full disclosure up front: I made this, the free Lite edition is MIT, and there is a paid Full edition ($15 one-time). I am posting it here because I think the architecture is worth a
look even if you never buy anything.

What it is. An AI assistant (Claude Code, Cursor, VS Code with Cline or Copilot, Windsurf, Claude
Desktop, or any Streamable-HTTP MCP client) connects to your editor over local HTTP and works on your project. There is no Node.js, no Python, no second process, and no cloud. The editor plugin is the
server: a TCPServer polled on the main thread. It is for your own project workflow, not for engine
contributions.

Who it is for. Solo devs and small teams who want an assistant that can actually inspect, author,
run, and observe a Godot project instead of guessing at it blind.

What Lite does, free (MIT). The complete inspect, author, run, and see loop. The AI can run your
game and then see it: screenshot the running game, read its live remote scene tree and live node
state, read performance monitors, and tail game logs. It also does validate-before-write (it refuses to write GDScript that does not compile), a C# dev loop (a compile-check with structured diagnostics, plus reflection over your C# [GlobalClass] types), undo and batch rollback, and one-step install.

What Full adds ($15, one-time, lifetime updates, no subscription). The AI drives the game
(simulate input, click 2D and 3D UI, scroll, drag, record and replay) and verifies it (assert node
state, assert on-screen text, scene-structure asserts, screenshot diff), plus deterministic playtest
control (freeze the game, step exact physics frames, or run until a live-state condition is true),
an in-editor test runner, animation authoring, mass placement, background export jobs, Asset Library install tools, project-wide analysis, and 37 skill knowledge packs. 81 tools total.

Install (about a minute). Copy addons/beckett/ into a Godot 4.2+ project and enable the plugin,
or install Lite from inside the editor: open the AssetLib tab and search “Beckett”. Enabling the
plugin auto-starts the server and writes .mcp.json, so claude (or Cursor) connects with no hand editing.

On safety and staying in control. This matters to me, so it is built in. The AI proposes; gates
verify. It is localhost-only with an Origin check, an optional bearer token, and read-only / allowlist / confirm-destructive modes. Every scene edit is undoable, and the last 200 tool calls are
in an audit log you can read. Nothing here touches engine core or contribution workflows; it edits
your project, and you can see and undo everything it does.

Links: itch Beckett — MCP for Godot by beckettlabs | GitHub
GitHub - beckettlab/beckett-godot-mcp: Zero-sidecar MCP server inside the Godot editor. AI agents (Claude Code, Cursor) inspect, author, run and SEE your game. GDScript + C#, validate-before-write, no Node.js. Godot 4.2+. Free Lite; Full adds autonomous playtesting. · GitHub | Asset Library
Beckett (AI MCP for Godot) - Godot Asset Library | Discord BeckettLabs | Demo

I will keep this thread updated with each release. Feedback and bug reports very welcome.

v1.7.0 is out. The Full edition’s simulate_input now injects gamepad input (joy_button and joy_axis, analog values included, so Input.get_vector movement works) and touchscreen input (touch and touch_drag, multitouch via the index field), and record_input / replay_input round-trip them, so a recorded controller session replays exactly. Captured-mouse look is verified as well, for games reading event.relative in _input. One honest limit, stated in the tool description: injected events drive the action system and _input callbacks, not raw polling APIs like Input.get_joy_axis. Tool count intentionally stays 81; everything landed inside existing tools. On the free side, the public repo now runs a cross-platform CI matrix (Ubuntu on Godot 4.4.1 and 4.6.2, macOS and Windows on 4.6.2) that parse-checks, boots a headless editor, and probes the live MCP surface on every push, so Windows / Linux / macOS support is a tested claim. Also 3 new skill packs (input-devices, profiling, http-networking; 40 total). Same human-in-control design as always: the AI proposes, the gates verify, and every edit stays undoable and audited.

v1.8.0 is out: playtest suites. The Full edition gains a playtest tool that saves a recorded
input run plus asserts as a file in your project and replays it deterministically, frame-exact,
into the running game, then checks node state / a GDScript expression / on-screen text / a
screenshot and reports pass/fail. record_input now stamps each event’s physics frame and replay
injects at that frame while the game runs unpaused, so both _input callbacks and polled Input
(get_vector, is_action_pressed) reproduce the run identically - a real regression test. A headless
runner plays every saved suite in your own CI and exits non-zero on failure, so the playtests keep
verifying. Honest limits, stated in the tool: record with key/mouse/gamepad/touch events (not
synthetic actions), rerun from a fresh play session, and replayed input drives the action system
and _input, not raw hardware polling. This is the first tool added since 1.5 (82 total); a durable
rerunnable suite is a new capability class. The free Lite edition is unchanged at 50 tools. Same
human-in-control design: the AI proposes, the asserts verify, and every edit stays undoable and
audited.

Beckett v1.9 (rolling up 1.9.0 + 1.9.1): the AI measures your game.

Deterministic playtests now MEASURE their replay window with real Performance counters (frame_ms p95/avg, fps, memory + orphan deltas, draw calls) and can fail on a perf regression via a new perf assert; save_baseline turns any suite into an optimize loop with per-metric diffs. Lite gets window sampling on get_performance_monitors plus a new doctor self-diagnosis tool. Hardening: per-session token auth on both the MCP endpoint and the runtime game channel, port auto-negotiation, a class_name validation fix, and a duplicate-autoload guard - all verified against a real RPG (measured p95 21.8 ms @ 66 fps) with CI green on Windows/Linux/macOS. 83 tools / 44 skills, Godot 4.2+. Human-in-control as always.

v1.10.0 is out — the UI-playtest pillar.

The headline: the agent can now read a whole UI screen in one structured call
(ui_snapshot — every visible control with its real state and a flag for what’s
covering it), and its clicks are honest: a disabled or covered button is refused
with the blocker’s path instead of silently “succeeding”. type_text sends real
per-character key events so text_changed/max_length behave, ui_do runs an entire
click/type/wait/assert flow in one call, and ui_audit measures layout bugs
(overlaps, trimmed text, sub-44px touch targets, gamepad-unreachable buttons)
instead of eyeballing screenshots.

ui_snapshot ships in the free Lite edition.

Measured before → after (same build, old tools vs new; method in the repo,
dev/UI-PILLAR-P0.md):

task before after
read one screen (structure + state) screenshot + 9 probe calls (~170 ms) 1 call (~31 ms)
same read, real 119-control game 1.7-2.7 s (full-PNG screenshot) 103 ms (ui_snapshot)
re-check an unchanged screen ~1,000 tokens 44 tokens (since_hash)
fill a field + click + verify 6 calls 3 calls (whole flows: 1 ui_do call)
screenshot when eyes are needed 2.7 s / ~4,900 vision tokens 0.12 s / ~1,240 (jpeg, scale 0.5)
click on a covered/disabled button reports success, never landed refused, blocker named
layout QA (overlaps, trimmed text, small targets) eyeballing screenshots 32 measured findings in 53 ms

Devlog: Beckett v1.10.0 — the AI playtests your UI - Beckett — MCP for Godot by beckettlabs

v1.11.0 is out - three correctness features, no new tools.

Error echo (4.5+): engine errors raised while a tool call runs are now attached to that
call’s response, and inside a batch they pin to the causing step. The motivating case:
Godot pushes many failures to the console and returns normally, so a tool could report
success while the engine had rejected the work. It is advisory - the call did complete -
but it can no longer go unnoticed. BECKETT_ERROR_ECHO=0 disables it; doctor reports state.

Focus-graph audit: ui_audit builds the navigation graph the engine itself uses
(find_next/prev_valid_focus plus the four directional neighbors) over visible interactive
controls and walks it from the focus owner (or the first focusable). It reports
focus_unreachable, focus_dead_end, and no_initial_focus, with a {focusable, entry,
reachable} summary. This complements the existing mouse_only check: that one flags
focus_mode NONE, this one finds controls your layout stranded.

Per-frame typing: type_text per_frame=true streams one character per frame instead of a
single frame for the whole string, so LineEdit’s deferred text_changed fires per keystroke
rather than coalescing into one emission. Measured on the bench harness: 5 characters gave
1 emission before, 5 now.

Counts unchanged at 87 Full / 52 Lite / 44 skills. Verified on 4.6.2 and 4.7 (unit 163,
smoke 101, Lite 34).

Devlog: https://beckettlabs.itch.io/beckett-godot-mcp/devlog/1596926/beckett-v1110-the-honest-release

v1.12.0 is out, and it came out of a postmortem rather than a roadmap.

An agent built a 3D scene in 99 minutes and lost 37 of them to a single reversed index
buffer. The terrain was entirely back-face culled, so nothing drew, and every signal
available read healthy: visible was true, the AABB was correct, the node was in the remote
tree, the log was clean, it ran at 120 fps. The screenshot showed sky below the horizon,
which reads convincingly as ground, so the next half hour went into fog, exposure and
palette adjustments on geometry that had never rendered a single frame.

The gap was not observation. It was that there was no way to ask which stage of the
render broke the image, so the only move left was guess and check against pixels.

render_probe answers that as data: visibility chain, world AABB, frustum test, distance
against the far plane and visibility range, layers against the camera cull mask,
per-surface material and cull mode, and the triangle winding the camera actually sees. It
returns either a warnings list naming the stage that broke, or a verdict saying the
geometry does reach the camera. Zero sampled triangles facing the camera while back-face
culling is on identifies a reversed index buffer directly. Worth restating because it
catches people: Godot treats CLOCKWISE winding as the front face, which is the opposite of
the OpenGL convention most mesh-generation code is written against, and getting it
backwards produces no error, no warning, and a perfectly healthy-looking node.

set_debug_draw switches the running viewport between unshaded, wireframe, lighting,
overdraw and normal_buffer so a single screenshot eliminates whole classes of cause.
Wireframe enables RenderingServer.set_debug_generate_wireframes first, without which the
screen simply goes black. Both tools are in the free Lite edition.

The second half is write honesty. The runtime set path used Object.set(), which is silent
on a property name it does not recognise and blind to sub-resource paths, so the server
answered ok for writes that never landed. It now resolves ‘:’ paths to the object that
owns the leaf, rejects an unknown name with a did-you-mean, reads every write back and
returns before/after, reports a write that moved nothing as an error, and refuses a value
it cannot coerce rather than storing the type’s default over your data.

One old bug also surfaced while testing that: overwriting a .tscn the editor had open
called EditorFileSystem.update_file() from inside the synchronous handler and never
returned, wedging the whole server until the editor was killed. Open scenes now skip it.

Devlog: Beckett v1.12.0 - Which stage broke it - Beckett — MCP for Godot by beckettlabs