| name | godot-mcp |
| description | Use when working on this Godot 4.7 C# project's scenes, GridMaps, mesh libraries, or `.tres`/`.tscn` resources — including hand-authoring or validating resources, fixing UID/import issues, and editor or headless game smoke checks. Covers this machine's Godot and dotnet binary paths, the build->import->validate workflow, and a headless GDScript validation harness. Not needed for pure C# logic changes where `dotnet build` alone verifies the work.
|
Godot (MCP + headless) for Rogue Gauntlet
Purpose
Validate real Godot behavior — scene/resource loading, UID resolution, mesh-library
alignment, editor-authored data, runtime smoke checks — and author/edit .tres/.tscn
correctly. Keep ordinary C# verification on dotnet build; reach for Godot only when the
task depends on scenes, resources, or runtime behavior.
Project setup
- Project root: the repo root. In a git worktree the root is the worktree directory.
- Gameplay scene:
res://scenes/main/main.tscn — run this for level-generation/gameplay checks.
- Project main scene:
res://scenes/menu/main_menu.tscn.
- Godot binary:
/Applications/Godot_mono.app/Contents/MacOS/Godot (the mono/C# build; not Godot.app). Use scripts/godot.sh to resolve it automatically.
dotnet binary: /usr/local/share/dotnet/dotnet — it is not on the agent shell's PATH.
Gotchas
Concrete corrections — each is a mistake that happens without being told otherwise:
dotnet is not on PATH. A bare dotnet build fails with "command not found". Use
/usr/local/share/dotnet/dotnet build "Rogue Gauntlet.sln".
- Import before headless-loading any resource. A fresh or worktree checkout has no
.godot/imported/ cache, so loading a .tres/scene fails with
Unable to open file: res://.godot/imported/...ctex|.scn plus cascading parse errors that
look real but are not. Run the import step (below) once first.
- Wrong Godot binary. The MCP server may default to
/Applications/Godot.app/... and
report spawn ... ENOENT. Fall back to the local binary via scripts/godot.sh.
- Worktree path discipline. When in a worktree, the project root is the worktree dir, not
the main checkout. Pass
--path "<worktree>" to Godot and use absolute worktree paths when
editing, or builds/edits silently hit the wrong tree.
- One
[GlobalClass] Resource per .cs file. A .tres references a script by file, so
multiple resource classes in one file make sub-resource typing ambiguous and break loads. A
plain enum may share a file. (Detail: references/tres-authoring.md.)
- New C# scripts need a
.cs.uid sidecar that .tres files reference; the import step
generates it. (Detail: references/tres-authoring.md.)
- GDScript can validate C# without a test project. A loaded resource exposes public C#
properties via
obj.get("PropName") — even computed, non-[Export] ones — and public
methods via obj.call("Method", args), but only when the signature is Godot-marshalable.
Methods taking object or generic IEnumerable<T> are not exposed (has_method returns
false); give logic you want to probe simple/Godot-typed signatures.
- Shutdown noise. Headless leak/ObjectDB "resources still in use / leaked at exit" messages
on forced quit are noise unless preceded by real load/script/resource errors during the run.
- Headless navmesh bake error is expected. A headless
main.tscn run prints an error +
C# backtrace from NavigationRegion3D.BakeNavigationMesh (MapGenerator.BakeNavigationMesh);
generation continues and logs Map generated. It is a NavigationServer-in-headless
limitation, not a real failure. Confirm Map generated. and that the player spawns; bake
navmesh visually in the editor when it actually matters.
- Bulk-generating files via Bash bypasses the Read-before-Write safety check. Writing many
new files at once (e.g. a script/heredoc loop creating a batch of wrapper
.tscns) is easy to
reach for over N individual Write calls, but it skips the "must Read before overwrite"
protection Write gets — a filename collision with an existing (even orphaned/dead) file
silently clobbers it with no diff shown. Check git status/existence for every target
filename first, or use Write per-file when the count is manageable.
- A model that renders fine in the item catalog can still be broken when equipped. See the
assets skill's in-hand verification section — floating-and-auto-framed vs. bone-attached
are different enough contexts that one passing does not imply the other passes.
_ready() on freshly-added nodes is deferred, not synchronous. In a --script main-loop
script, some_node.add_child(x) does NOT run x's (or an autoload's) _ready() before the
next call returns — it fires on a later frame. Calling logic that depends on a node's own
_ready()-wired references (e.g. MapGenerator.GenerateMap(), which needs its GridMap child
refs) immediately after add_child runs against not-yet-initialized state and silently
produces empty/wrong results, no error printed. Wait at least one _process() tick after
adding the node before calling into it (see render_level_topdown.gd's state machine).
Core workflow
- Compile:
/usr/local/share/dotnet/dotnet build "Rogue Gauntlet.sln" (the default check
for any C# change; do this before touching Godot).
- Import (only after adding/changing scripts or resources, or on a fresh/worktree checkout):
scripts/godot.sh --headless --path "$PWD" --import. This builds the import cache and
generates .cs.uid sidecars.
- Validate / smoke-test the specific thing that changed — a resource load, a scene boot,
or a logic probe (below). Prefer a targeted scene + seed over the whole game.
Commands
/usr/local/share/dotnet/dotnet build "Rogue Gauntlet.sln"
.agents/skills/godot-mcp/scripts/godot.sh --headless --path "$PWD" --import
.agents/skills/godot-mcp/scripts/godot.sh --headless --path "$PWD" res://scenes/main/main.tscn --quit-after 150
.agents/skills/godot-mcp/scripts/godot.sh --editor --path "$PWD"
Headless validation harness
Run a GDScript file as the main loop to exercise the project without the editor:
scripts/godot.sh --headless --path "$PWD" --script <file.gd> -- <args...>. The script
extends SceneTree, does its work in _init(), reads args after -- via
OS.get_cmdline_user_args(), and calls quit().
Visual verification: top-down level/room screenshots
Reasoning about tile coordinates or trusting an editor-only gizmo (e.g. DoorwayMarker's arrow,
which only draws inside the actual Godot editor process) can't confirm what a generated level or
room actually looks like. scripts/render_level_topdown.gd renders a real top-down screenshot of
a generated level instead, with an overlay drawn straight from MapGenerator.GetConnectorDebugInfo()
(Godot-native return types, since MapData itself can't marshal to GDScript) showing every
connector's position and per-direction open (green) / sealed (red) status, plus doorway (yellow)
vs inferred (cyan) markers. This must run windowed, not headless — the headless renderer
produces blank images:
.agents/skills/godot-mcp/scripts/godot.sh --path "$PWD" --script \
.agents/skills/godot-mcp/scripts/render_level_topdown.gd -- <outfile.png> [seed] [image_size]
Then Read the resulting PNG to inspect it. Use this whenever a change to room layout, doorway
placement, wall generation, or rotation needs a visual sanity check instead of (or in addition to)
numeric probes/tests — e.g. confirming a doorway's connector tile is flush with its wall gap, or
that a rotated room's markers still point the right way.
MCP tools
When the MCP server is correctly configured, prefer it for editor/runtime interaction:
godot_get_project_info (open check), godot_launch_editor, godot_run_project +
godot_get_debug_output + godot_stop_project (run and inspect), godot_get_uid /
godot_update_project_uids (UID issues), godot_export_mesh_library (intentional library
changes). If MCP reports ENOENT on Godot.app, use scripts/godot.sh via Bash instead.
Bundled scripts
scripts/godot.sh — resolves the working Godot binary and runs it with the given args.
scripts/inspect_resource.gd — loads one or more res:// resources and prints their script
properties; reports OK/FAIL/MISSING per path. The reusable resource validator.
scripts/render_level_topdown.gd — renders a windowed top-down screenshot of a generated
level with a connector/doorway overlay. See "Visual verification" above.
Authoring .tres / .tscn by text
Before creating or editing a .tres/.tscn in a text editor (rather than the Godot editor),
read references/tres-authoring.md — it covers load_steps counting, enum-as-int and
array serialization, sub-resource layout, the one-[GlobalClass]-per-file rule, UID sidecars,
the missing-res://-prefix trap, and the wrapper-.tscn pattern for correcting a raw model's
grip orientation or scale. Always validate the result with inspect_resource.gd.
Rules
- Do not replace
dotnet build with Godot's C# solution build on this machine; the Godot CLI
solution build times out with engine shutdown errors. Use dotnet.
- Do not commit temporary probe scenes/scripts. Put one-offs in the scratchpad; if a
res://tmp_* file is unavoidable, delete it before finishing.
- Do not edit
.tscn/.tres blindly when a visual result matters; launch the editor or build
a focused test scene.
- Prefer deterministic checks: run a specific scene and seed when debugging generation.
- Keep this skill focused on Godot-specific validation; do not use it for general file search
or ordinary C# refactors.