Sole engineer, OffByThree LLC · 2026 · shipped
Godot Pilot
A commercial MCP bridge that gives an AI coding agent hands-on control of the Godot 4 editor.
- Python 3.10+
- MCP
- websockets
- cryptography
- customtkinter
- GDScript
- PyInstaller
- Inno Setup
- pytest
The problem
An AI coding agent can write GDScript perfectly well and then have no idea whether it worked. It cannot open the editor, cannot see the viewport, cannot inspect the scene tree, and cannot tell a script that silently did nothing from a script that did what was asked. Every iteration ends at the file write, and a human has to alt-tab over and report back what happened.
What I built
An MCP bridge that hands Claude Code real control of a running Godot 4.x editor: execute GDScript inside the editor, screenshot the viewport, manipulate the scene tree, get and set any property on any node, manage resources and scenes, and run shell commands. The agent writes, runs, looks at the result, and corrects — the loop closes without a human relaying observations.
It is a commercial product sold under license key, shipped as a Windows installer: a Python MCP server plus a GDScript editor plugin, packaged with PyInstaller and Inno Setup, with a customtkinter desktop interface. Tests are pytest with asyncio and a separate integration marker, so the suite that needs a live editor stays out of the default run.
Decisions
Three tiers with a WebSocket in the middle, instead of two. The shape is Claude Code ↔ stdio MCP ↔ Python server ↔ WebSocket on port 9878 ↔ GDScript plugin. The extra hop exists for a concrete reason: a Godot editor plugin can host a server, but it cannot speak stdio MCP — the transport the agent requires is not one the editor can offer. So the Python process owns the protocol the agent understands, and the plugin owns the process that has the editor's memory in it, and they meet over a socket.
Given up: a lot. Two processes must both be running, port 9878 must be free, and every failure now has two places to be. A dead socket and a dead editor look alike from the agent's side, so telling them apart — and reporting which one broke — becomes its own problem to solve.
License checks that degrade instead of blocking. Verification goes
through Gumroad, bound to a machine-ID fingerprint — WMI UUID on Windows,
ioreg on macOS — with a seven-day offline grace cache behind it and
explicit degraded states rather than a binary allow/deny. The product does
not brick when someone's network drops, which for a tool that lives inside a
local editor session is not a nicety: the offline case is a normal Tuesday.
What this concedes is straightforward and I accepted it deliberately — a
seven-day window is seven days of usable software after a refund or a revoked
key, and a machine fingerprint is a heuristic, not an identity. I would
rather leak a week of access than have a paying customer's editor stop
working on a flight.
The installer writes the agent's config. PowerShell scripts configure Claude Code's MCP config during install rather than handing the buyer a JSON snippet and a file path. Hand-editing an agent config is where this class of tool loses most of its users — it happens before any value has been delivered, and a typo produces a silent no-op rather than an error. Given up: the installer now reaches into a config file owned by another application, which means version drift in that file's schema is my support burden, and the scripts are Windows-shaped in a way the rest of the codebase is not.
Hard part
Godot caches resources aggressively, and that cache is invisible from the outside.
The failure mode was brutal to diagnose because it looked like success. The agent writes a script, runs it, and gets output — but the output belongs to the previous version of that script. The engine had already compiled a resource at that path and handed back the cached instance rather than reading the new file. Every symptom pointed the wrong way: the agent concluded its edit had no effect, tried a different edit, ran again, and got the same stale result. It looks exactly like a logic bug in the generated code, and an AI agent will happily spend a dozen iterations rewriting correct code to fix a problem that is not in the code at all.
Once the cause was clear, the fix had to defeat the cache rather than
cooperate with it. Scripts are written to unique paths derived from timestamp
plus random suffix, so no execution ever reuses a resource path the engine
has seen, and loading uses CACHE_MODE_IGNORE so a hit cannot be served even
if a path somehow collided. Both, not either: the unique path avoids the
lookup and the cache mode makes the lookup unable to succeed. The result is
that every execution runs the bytes just written, which is the single
property the whole tool depends on.
Outcome
Shipping as a licensed commercial product under OffByThree LLC, distributed as an installer that leaves a working agent-plus-editor setup behind it with no manual configuration step.