MCP server¶
The editor has an MCP server built in. An agent like Claude Code, or a plain Python script, can use it to inspect and edit maps, take screenshots and play input into the UI.
Use it to let an AI assistant build or review a level, to script repetitive edits, or to test the editor automatically. The server is off until you start it, and it only listens on your own machine.
Starting it¶
| Transport | How to start it |
|---|---|
| HTTP | Launch the editor with --mcp-http for port 7841, or --mcp-http=PORT for another port. To have it start every time, go to File > Preferences, open Advanced, tick enable on startup next to MCP server (HTTP, localhost), set the port beside it and restart |
| stdio | Launch with --mcp. The client starts the editor itself for each session and talks to it over standard input and output |
Pick HTTP when you keep the editor open and work in it yourself while an agent helps. Pick stdio when the client should own its editor, or when other people use the same computer. To connect Claude Code to either:
claude mcp add --transport http trenchdot http://127.0.0.1:7841/mcp # HTTP
claude mcp add trenchdot -- /path/to/trenchdot --mcp # stdio
The repository's .mcp.json already points Claude Code at the HTTP server. File > Preferences shows the command
for the server that runs, and Copy command puts it on the clipboard.
Started the editor on another port? Set TRENCHDOT_MCP_URL and
tools/mcp_client.py and
tools/mcp_script.py connect there instead.
The HTTP token¶
Any program on your computer can reach the HTTP server, and so can other people signed in to it. To keep them out,
tick Require a token under Advanced in File > Preferences. From the next request on, the server only answers
requests that send its token as Authorization: Bearer <token>. The command in Preferences then includes the token,
use it instead of .mcp.json. stdio needs no token, only the client that started the editor can talk to it.
The editor makes a random token the first time you ask for one and keeps it in mcp-token, a file only you can read,
next to its settings: %APPDATA%\TrenchDot\data on Windows, ~/.local/share/trenchdot on Linux and
~/Library/Application Support/TrenchDot on macOS. A --default-prefs run keeps its own in
trenchdot-default-prefs.mcp-token in the temp folder.
To pick the token yourself for one run, set TRENCHDOT_MCP_TOKEN or launch with --mcp-token=<token>, which wins
over the variable. Either one turns the token on whatever Preferences says, and Require a token shows it ticked and
greyed out. tools/mcp_client.py and tools/mcp_script.py send a token only when you give them one, with --token or
TRENCHDOT_MCP_TOKEN.
Turning MCP off¶
To keep agents and scripts out of the editor altogether, untick MCP at the top of the MCP part of
File > Preferences. The HTTP server closes at once and drops its open connections, a client on stdio gets an error
for every request, and the other MCP settings grey out. The setting is saved at once, so every editor you start
without --default-prefs keeps MCP off until you tick it again, which brings the HTTP server back on its port.

To turn MCP off for one run whatever Preferences says, set TRENCHDOT_DISABLE_MCP to anything but empty or 0.
MCP then shows unticked and greyed out. While MCP is off, --mcp and --mcp-http start no server. The editor still
opens and its status line says MCP is off, and a client on stdio gets an error saying so instead of waiting.
An agent can turn MCP off as well, with set_editor and "mcp": false. Only you can turn it back on.
Tools¶
| Area | What it is for | Tools |
|---|---|---|
| Inspect | Read the map, the editor state, the entity definitions and how to use an entity from game code, without changing anything | get_state, summarize_map, list_nodes, get_node, changes_since, validate_map, get_game_config, code_reference |
| Create | Add brushes, meshes, terrains, entities and imported models, and trim along face edges | create_brush, create_mesh, create_terrain, create_entity, import_model, trim |
| Edit | Change what exists: entity keys, selection, placement, faces, textures, terrain, layers and groups, and worldspawn | update_entity, select, transform, duplicate, set_face, mesh_edit, texture, terrain_edit, hierarchy, set_map_properties, bake_lighting |
| Paint and gameplay | Scatter models, blend materials, paste pieces from the prefab library, and turn brushes into doors, platforms and buttons | scatter, blend, prefab_library, random_fill, gameplay |
| Editor | Run menu actions, open and save files, change editor settings, move the camera, take screenshots, send input and check where a player can walk | run_action, map_file, open_project, set_editor, set_camera, screenshot, simulate_input, walkability |
| Project | Add the Gameplay entities pack, the nature models or the demo to the open Godot project | project_content |
| Scripts | Replay a saved list of tool calls, see MCP scripts | run_script |
Each tool's description lists its operations and arguments, so an agent learns them straight from the server.
tools/mcp_client.py prints them with list
and calls a tool from the shell:
python tools/mcp_client.py call screenshot '{"target":"3d","width":1280,"height":720}' --out shot.png
Screenshots¶
screenshot returns a PNG of the whole editor window, or of one view when target is 3d, top, front or side.
For a view, the other arguments decide what you get:
| Arguments | Result |
|---|---|
| None | The whole editor window |
target only |
That docked view as it is, overlays included |
width and height |
Rendered offscreen up to 4096 pixels, without grid, entity boxes, gizmos or selection |
width, height and "overlays": true |
Offscreen, with the editor overlays |
"overlays": false |
A clean shot at the docked size |
What Godot renders¶
"source": "godot" asks the Godot editor to render the map with its real lights, environment, fog and post
processing. You get that PNG back, plus any errors or warnings Godot logged while building it. Handy for judging
lighting and materials without launching the game.
python tools/mcp_client.py call screenshot '{"source":"godot","position":[0,256,512],"look_at":[0,64,0]}' --out godot.png
- Save the map inside the project that is open in TrenchDot.
- Open that project in the Godot editor, with a scene whose
FuncGodotMapbuilds the map. - Call
screenshotwith"source": "godot". Withoutpositionandlook_atit uses the 3D view's camera.
Without live mode Godot first builds the map as shown in TrenchDot, like Build in Godot.
"build": false captures the scene as Godot has it. width and height default to 1280 by 720, and fov to the 3D
view's.
Note
Godot needs a window to render, a headless Godot returns an error instead of an image. The window can be in the background or minimized.
Reading and reviewing a map¶
| Step | Tool |
|---|---|
| Get an overview | summarize_map lists the layers, entity classes, I/O links and materials, and any missing assets |
| Find nodes | list_nodes filters by layer, material, property ({"model": "*crate*"}) or a box in the map |
| Look at one | get_node returns one node. compact: true leaves out vertices and faces |
| Show what you changed | changes_since compares against the last save, a number of undo_steps back, or a map file |
| Take it back | Each call and each run_script is one undo step named MCP: .... run_action undo with steps undoes several |
See Reviewing changes for keeping maps in git.
Behavior worth knowing¶
| Topic | Behavior |
|---|---|
| Browsers | The HTTP server refuses any request with an Origin header and any POST that is not application/json, so web pages cannot reach it, not even ones served from localhost |
| Errors | A tool that could not do its job returns isError, including a failed run_action |
| File dialogs | Actions that open one are refused, use map_file with a path. run_action save needs a map that already has a file |
| Unsaved tabs | run_action close_tab refuses unsaved changes unless args.discard is true. args.close_others closes every tab but the active one instead |
| File paths | res:// and relative paths in map_file, run_script, import_model, changes_since and validate_map start at the open project, or at the editor's working directory without one. map_file open and open_tab resolve the path to an absolute one before opening, so a later save cannot land somewhere else |
| Editor settings | transform and run_action rotate and flip pivot on the selection center, snapped to the grid only while snapping is on, and keep textures locked while UV lock is on. transform takes snap and uv_lock to override that for one call, duplicate takes uv_lock. run_action sculpt and blend use the tool settings a person can change, terrain_edit uses fixed defaults |
| Selection | select refuses unknown ids and skips hidden or locked nodes, listing them in skipped |
| CSG | csg_subtract, csg_merge, csg_intersect, csg_hollow and clip_apply return replaced, old ids mapped to new ones |
| Timeouts | Calls time out after 120 s, except run_script, project_content and bake_lighting |
| Content question | The question a new project gets about ready made content closes on the first call other than get_state, screenshot and simulate_input, and does not open again in that session |
| Script variables | $name/rest (unbraced) is an error when name is a known variable, since only $name alone or ${name}/rest expand it. Write ${project}/maps |
Tool notes¶
| Tool | Note |
|---|---|
run_action copy, cut, paste |
Copy and cut return the clipboard text, paste takes it as args.text with an optional offset or origin |
run_action clip_apply |
Takes a plane (point and normal, or three points) and keep: front, back or both |
run_action create_decal |
Places a decal, use it instead of thin brushes |
create_brush |
openings carves doors and windows, {min, max, count, step, rows, row_step} repeats one as a grid |
create_mesh rotate |
[x, y, z] degrees in Godot's YXZ order, so [0, 0, 90] lays a cylinder along X |
transform |
Applies translate, rotate, flip and scale_to in that order, as one undo step. rotate turns 90 degrees about Y unless told otherwise |
create_terrain |
origin is the terrain's minimum corner, unlike other tools. center places it around a point instead |
create_brush, create_mesh |
A gable ridge runs along Z for brushes and along X for meshes. Both tools take ridge_x and ridge_z |
map_file exports |
path is the written file, kept for older callers, exported names it too and map_path is the open map |
terrain_edit |
probe [x, z] without op only reads the height. clear_layer needs layer |
validate_map |
Accepts any method or property of the target's Godot class or script as an input. coplanar_faces flags faces that will flicker. Every issue has bounds. path checks a saved map without opening it, project: true checks every map in the project |
run_action reload_materials |
Rescans the texture folder now, though new files are found on their own anyway |
set_editor live_link_port |
Talks to a Godot editor whose project sets another trenchdot/live_link_port |
scatter preset |
Adds the embedded Blockbench models a preset needs. A glTF preset in a project without the nature pack is an error that names project_content |
bake_lighting |
Bakes like Bake Lighting and waits for it. Options left out keep what the map was last baked with. bake: false only switches the view, remove: true drops the bake. out_of_date says whether the map changed since |
project_content |
install: "nature" or "demo" downloads from the release and answers once the files are in. install: "gameplay" copies the Gameplay entities pack from the project's addon, also inside scripts. Without arguments it says what the project has |