Defold AI: the MCP that connects Claude Code straight into your live Defold editor
Full Stack Developer - dWEB R&D
35+ tools across 11 domains, 10 versioned releases. Author 3D scenes, materials, render pipelines and orbital cameras without touching a single Defold menu.
The problem
Defold is one of the fastest, leanest game engines out there. The editor is minimal, the runtime is brutal, and the games boot in milliseconds. But authoring a project is still the same dance: open panels, drag components, hand-write .material and .render_script files, wire inputs in a UI, import textures...
Meanwhile Godot already has godot-ai — an MCP server that lets Claude Code (or Codex, or Antigravity, or any MCP client) talk straight to a live Godot editor and build scenes, nodes, scripts, materials and animations from a natural-language prompt.
Defold deserved one too.
Meet defold-ai
defold-ai ports that idea to Defold by leveraging something Godot doesn't have: the HTTP server that Defold runs inside the editor itself since version 1.10. No WebSocket bridge, no native C++ plugin, nothing exotic. Just a Lua .editor_script and a thin Python proxy on top of FastMCP.
MCP Client (Claude Code / Codex / Antigravity)
↓ stdio JSON-RPC
Python FastMCP server (server/)
↓ HTTP POST /mcp/<tool>
Defold editor's built-in HTTP server (plugin/mcp/mcp.editor_script)
↓ editor.transact + editor.tx.*
Project tree (.collection / .go / .script files)
Every MCP call is forwarded as a JSON POST to the editor. The editor script routes each /mcp/<tool> to its Lua handler, which mutates the project via editor.transact({ editor.tx.add/set/remove }) — atomic, undoable, persistable with editor.save().
What you can do today (v0.11.0)
35+ tools across 11 domains. Some highlights:
A whole render pipeline in one call
POST /mcp/render_manage
{ "op": "create",
"params": {
"path": "/main/game",
"preset": "default_3d_with_sky",
"activate": true
} }
This generates game.render + game.render_script with a sky pass (depth-write off, cull front, perfect for an inverted cube/sphere) + model + tile + particle + GUI in the right order. And rewrites your game.project's bootstrap.render so the new pipeline takes over on the next build.
Built-in presets: default_3d, default_3d_with_sky, default_2d. Or pass your own passes array for fine-grained control.
Materials with curated presets
POST /mcp/material_manage
{ "op": "apply_preset",
"params": {
"path": "/assets/materials/sky.material",
"preset": "sky_gradient"
} }
Generates the .material AND auto-writes the sky.vp / sky.fp shaders if they don't exist yet. Presets available: model_lit_tint, model_unlit_tint, sky_gradient, gui_basic, sprite_basic, tilemap_basic. Per-instance tint overrides via model.set_constant from Lua, or edit a material constant directly with material_manage(set_constant).
Third-person orbital camera in one call
POST /mcp/camera_manage
{ "op": "apply_preset",
"params": { "path": "/main/camera.go", "preset": "follow_3d" } }
Generates camera.go with a perspective camera component plus camera.script that handles mouse yaw/pitch, spring-arm offset, and exposes spring_len / height_offset / pitch_min / pitch_max as go.property for editor-time tweaks. There's follow_2d for top-down.
Particles via the same preset library
POST /mcp/particlefx_manage
{ "op": "apply_preset",
"params": { "path": "/world/rain.particlefx", "preset": "rain" } }
rain, snow, smoke, sparkle, explosion. Each preset writes a full .particlefx, with a shared white tilesource auto-created.
Structured game objects — no hand-written protobuf-text
POST /mcp/gameobject_manage
{ "op": "create_file",
"params": {
"path": "/player/player.go",
"components": [
{ "id": "script", "component": "/player/player.script" },
{ "id": "model", "type": "model",
"data": {
"mesh": "/builtins/assets/meshes/cube.dae",
"material": "/assets/materials/block.material",
"textures": "/assets/images/white.png"
}
},
{ "id": "collision", "type": "collisionobject",
"data": {
"type": "COLLISION_OBJECT_TYPE_KINEMATIC", "mass": 0,
"group": "player", "mask": "world",
"embedded_collision_shape": {
"shapes": [{ "shape_type": "TYPE_SPHERE", "index": 0, "count": 1,
"position": {"x":0,"y":0.85,"z":0},
"rotation": {"x":0,"y":0,"z":0,"w":1} }],
"data": [0.45]
}
}
}
]
} }
The internal serializer handles escaping the embedded data field to protobuf-text. No more hand-quoting data: "key: \"val\"\n" ....
Build + Run + Logs + Screenshot
POST /mcp/project_run
→ { "ok": true, "stage": "launched", "engine": "/.../dmengine" }
POST /mcp/logs_read { "source": "game", "count": 20 }
POST /mcp/editor_screenshot { "target": "game" }
→ { "ok": true, "path": "/tmp/defold_ai_screenshot.png", "size": 42117 }
project_run does the headless bob.jar build (with structured errors when it fails) and then spawns dmengine detached with stdout/stderr piped to ./dmengine.log. logs_read(source="game") tails that log via MCP. editor_screenshot captures the game window via screencapture (macOS needs Screen Recording permission).
Quick start
# 1. Install the plugin in your Defold project
git clone https://github.com/estebanrfp/defold-ai.git
cp -R defold-ai/plugin/mcp YOUR_DEFOLD_PROJECT/
# 2. Install the Python server
cd defold-ai/server
uv sync
# 3. Register it with Claude Code (or your favourite MCP client)
claude mcp add --scope user --transport stdio defold-ai \
-- uv --directory $(pwd) run defold-ai
Open Defold on your project, open Claude Code, and say:
"Create a main collection, add a player with sprite + collisionobject, wire it to a WASD movement script, set up the inputs, and build and run."
What I learned porting godot-ai to Defold
godot-ai uses a WebSocket bridge because Godot's GDScript plugins don't have a built-in HTTP server. Defold does — since 1.10 every editor runs a mini HTTP server, and .editor_script files can register routes with http.server.route(...). That cuts a whole infrastructure layer.
But there are real editor-script-API gaps in Defold that Godot doesn't have:
No editor screenshot API. defold-ai falls back to
screencapture(macOS) with a clear permission error message when blocked.editor.bob()returns opaque errors. defold-ai shells out tobob.jardirectly and parsesERROR file:line msglines.No selection API. Skippable.
editor.reload_pluginis unreliable. Defold seems to cache bytecode pastpackage.loaded— handler edits often need a full editor restart (documented clearly).The sandbox blocks
os.execute;io.popenis callable but usually returns nil. The real API iseditor.execute(...).
Each of those discoveries is in the CHANGELOG.md, with the version that closed it and the workaround. It's honest about what works and what still doesn't.
Why this matters
Defold has a small but very technical community and a brutal portfolio of shipped games (King ran on Defold for years; dozens of titles on the App Store and Steam). What's slowed new adoption isn't the engine — it's the editor learning curve and the protobuf-text asset format.
With a live MCP, that curve flattens: you can ask the assistant "give me an orbital camera", "put a sky gradient on it", "create a tinted material and apply it to this model", and get files that work on the first try. The assistant learns the gotchas (which keys each protobuf accepts, which builtins exist, which game.project settings to touch) and applies them for you without making you read the docs.
What's next
Current roadmap (CHANGELOG [Unreleased]):
Engine-side capture endpoint via
game_helper.luainjection (no OS permission required).gameobject_manage(duplicate / rename / reparent).Linux + Windows paths for
find_defold_toolchainandeditor_screenshot.Tests + CI inspired by godot-ai's 1132-test suite.
examples/applegameas a runnable demo.
Links
CHANGELOG: CHANGELOG.md
Tool reference: docs/TOOLS.md
Architecture: docs/ARCHITECTURE.md
Inspired by: hi-godot/godot-ai
If you build something with defold-ai, let me know. And if you hit a gap or a bug, open an issue — every release in this session came out of finding one and fixing it.
Esteban Fuster Pozzi (@estebanrfp) — Full Stack JavaScript Developer


