# Defold AI: the MCP that connects Claude Code straight into your live Defold editor

![Defold Game Engine](https://raw.githubusercontent.com/estebanrfp/defold-ai/main/docs/images/hero.webp align="center")

> 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](https://defold.com) 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`](https://github.com/hi-godot/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**](https://github.com/estebanrfp/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.

```text
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

```jsonc
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

```jsonc
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

```jsonc
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

```jsonc
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

```jsonc
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

```jsonc
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

```bash
# 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 to `bob.jar` directly and parses `ERROR file:line msg` lines.
    
*   **No selection API**. Skippable.
    
*   `editor.reload_plugin` **is unreliable**. Defold seems to cache bytecode past `package.loaded` — handler edits often need a full editor restart (documented clearly).
    
*   **The sandbox blocks** `os.execute`; `io.popen` is callable but usually returns nil. The real API is `editor.execute(...)`.
    

Each of those discoveries is in the [CHANGELOG.md](https://github.com/estebanrfp/defold-ai/blob/main/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]`](https://github.com/estebanrfp/defold-ai/blob/main/CHANGELOG.md)):

*   Engine-side capture endpoint via `game_helper.lua` injection (no OS permission required).
    
*   `gameobject_manage(duplicate / rename / reparent)`.
    
*   Linux + Windows paths for `find_defold_toolchain` and `editor_screenshot`.
    
*   Tests + CI inspired by godot-ai's 1132-test suite.
    
*   `examples/applegame` as a runnable demo.
    

## Links

*   **Repo**: [github.com/estebanrfp/defold-ai](https://github.com/estebanrfp/defold-ai)
    
*   **CHANGELOG**: [CHANGELOG.md](https://github.com/estebanrfp/defold-ai/blob/main/CHANGELOG.md)
    
*   **Tool reference**: [docs/TOOLS.md](https://github.com/estebanrfp/defold-ai/blob/main/docs/TOOLS.md)
    
*   **Architecture**: [docs/ARCHITECTURE.md](https://github.com/estebanrfp/defold-ai/blob/main/docs/ARCHITECTURE.md)
    
*   **Inspired by**: [hi-godot/godot-ai](https://github.com/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*](https://github.com/estebanrfp)*) — Full Stack JavaScript Developer*
