An MCP server that lets an LLM (Claude Code, Claude Desktop, etc.) drive a running Dungeondraft instance — place objects, draw walls, inspect the map — through Dungeondraft's GDScript modding API.
Dungeondraft has no built-in server to talk to, so this project is two halves that meet over a localhost socket:
Claude / MCP client
│ MCP (stdio)
▼
server/ ── Python MCP server (this repo)
│ newline-delimited JSON over TCP (127.0.0.1:8787)
▼
mod/ ── Dungeondraft mod (GDScript, runs inside DD)
│ modding API calls
▼
the open map (Objects, Walls, Levels, …)
The mod opens a TCP server inside Dungeondraft and polls it every frame from the
update(delta) hook; the Python side exposes each capability as an MCP tool and
forwards calls as JSON. See PROTOCOL.md for the wire format.
Status: working. Confirmed end-to-end against Dungeondraft on Godot 3.4.2 — raw TCP from the modding sandbox works, no fallback needed. 39 tools across query / create / modify / terrain / levels / selection / capture / camera / undo (see below).
- Inspect:
get_status,list_levels,list_elements,get_element,list_asset_categories,list_assets(with substring search). - Create:
place_object,draw_wall,draw_path,add_light,add_portal,add_roof,add_text,place_pattern(tiled floor shapes — wood planks, tile, brick — rendered below objects),build_room(a wall loop- matching floor on one shared path, like the UI's combined trace).
- Terrain:
set_terrain_slot,fill_terrain(whole level),fill_region(a rect/polygon, e.g. one room's floor),paint_terrain(a soft brush),paint_path(a smooth continuous stroke along a polyline — roads/trails). - Caves:
dig_cavecarves caverns/tunnels along a path (the Cave Brush — dig open floor out of rock, with auto rocky walls + debris;dig=falsefills back; optional ground/wall tints),clear_caveswipes the whole cave layer. - Edit:
move_element,modify_object,duplicate_object,delete_element,select_elements,clear_selection. - Levels:
add_level,set_level. - See:
screenshot(current window) andexport_map(clean full-map render) return images, so the model can look at its own work and iterate. - Camera:
get_camera,set_camera,focus_element(center on one element),fit_elements(frame a group) — point the view before ascreenshotto inspect specific spots like a door cut into a wall. - Undo: the bridge keeps its own undo/redo stacks for create / move / modify
/ terrain edits, so
undo/redolet the model reliably reverse its own changes (independent of Dungeondraft's Ctrl+Z;delete_elementis not reversible).
Every element is referenced by an integer id; create and list calls return
ids you feed back into edit calls. Coordinates are woxel (pixel) space — call
get_status for map_center. Discover assets with list_assets.
Prerequisites: Dungeondraft (tested on the
Godot 3.4.2 builds), Python 3.10+, and an MCP client (e.g. Claude Code or
Claude Desktop). On Windows, python/.venv\Scripts\ replace the python3/
.venv/bin/ paths shown below.
- In Dungeondraft's title screen, open Mods and note (or set) your mods folder.
- Copy
mod/dungeondraft-mcp-bridge/into that folder. - Enable MCP Bridge in the mod list, then open or create a map.
On load you should see in the Dungeondraft log:
[mcp-bridge] listening on 127.0.0.1:8787 (protocol v6)
Install into a dedicated venv (most distros' system Python is externally managed, so a venv keeps the entrypoint clean and stable). Run from the repo root:
python3 -m venv .venv
.venv/bin/pip install -e ./serverThis installs the dungeondraft_mcp package and creates the
.venv/bin/dungeondraft-mcp entrypoint.
With DD open and a map loaded, run the per-command validator. It builds a small throwaway scene near the map center, prints PASS/FAIL for each command, then deletes what it made:
.venv/bin/python server/test_bridge.pyIf it fails to connect and you never saw the listening line in DD's log, the
sandbox blocked TCP_Server — see the fallback note in PROTOCOL.md.
To see something get built (a small furnished room left on the map, rather
than a self-cleaning test), run .venv/bin/python server/demo_build.py.
Register the entrypoint by its absolute path. For Claude Code:
claude mcp add dungeondraft -s user -- "$PWD/.venv/bin/dungeondraft-mcp"Restart Claude Code so the server loads (/mcp shows its status and tools).
Or add to a client config (e.g. Claude Desktop claude_desktop_config.json),
using the absolute path:
{
"mcpServers": {
"dungeondraft": {
"command": "/abs/path/to/dungeondraft-mcp/.venv/bin/dungeondraft-mcp"
}
}
}Then ask the model things like "what's the status of my Dungeondraft map?" or "list some object assets and drop a chair in the middle of the map."
These env vars configure the Python server (set them where the MCP client
launches it). The defaults match the mod, so you only need them if you change
the mod's HOST / PORT consts in mcp_bridge.gd — both halves must agree.
| Env var | Default | Purpose |
|---|---|---|
DD_BRIDGE_HOST |
127.0.0.1 |
host the server connects to |
DD_BRIDGE_PORT |
8787 |
port the server connects to (match the mod's PORT) |
Adding a capability is symmetric — one handler on each side:
- Mod (
mod/.../scripts/tools/mcp_bridge.gd): add acaseto thematchin_safe_dispatch()and a_my_command(req)function returning_ok(...)/_err(...). - Server (
server/dungeondraft_mcp/server.py): add an@mcp.tool()that callsbridge.request("my_command", ...).
Good next targets: pattern shapes (floors), region-scoped terrain fill, and grouping a batch of edits into a single undo step.
Two things will bite you if you don't know them up front:
-
Editing the mod and the server are different reload paths. GDScript changes in
mcp_bridge.gdtake effect when you reload the mod inside Dungeondraft (or restart DD). New or changed@mcp.tool()definitions inserver.pyonly appear after the MCP server process restarts — in Claude Code that means/mcp→ reconnectdungeondraft(or restart the client). The install is editable (pip install -e), so you never reinstall; you just cycle the process. Adding a new tool needs both reloads (mod for the handler, server for the tool registration); changing an existing handler's behavior needs only the mod reload. -
There's no live
eval/introspect command, so probing a running node's properties needs a mod reload. When a DD API behaves unexpectedly (e.g. a setter that doesn't stick), a quick way to diagnose it is to return intermediate state in the response — stash before/after values in a debug field — so one reload shows where a value changes.
mod/dungeondraft-mcp-bridge/ the Dungeondraft mod (copy into DD's mods folder)
mcp_bridge.ddmod manifest
scripts/tools/mcp_bridge.gd TCP server + command handlers
server/ the Python MCP server
dungeondraft_mcp/server.py MCP tool definitions
dungeondraft_mcp/bridge_client.py TCP/JSON client
test_bridge.py standalone per-command smoke test
demo_build.py builds a visible sample room and leaves it
PROTOCOL.md wire protocol + implementation notes
Built against the Dungeondraft Modding API. Engine is Godot 3.4.2, so the GDScript uses Godot 3 networking class names.
MIT.