by aigengame
Provides a CLI, skill definition, and MCP server for automating Godot Engine tasks with structured JSON output, supporting both headless project manipulation and live runtime control.
Enables AI coding agents, scripts, and CI pipelines to create, edit, export, and control Godot projects via a single command surface that always returns a single JSON object. The tool works in two modes: headless (one‑shot, no editor required) and live (real‑time interaction with a running game).
pipx install gda).GDA_GODOT or the --godot flag.GDA_PROJECT or --project.gda scene create ... --json for headless operations or start the daemon with gda daemon start and then use gda game tree --json for live interaction.gda skill) or expose the MCP server (gda-mcp).--json) and provides a JSON‑Schema (--schema).gda skill), and MCP server (gda-mcp).Q: Do I need to install a Godot editor plugin? A: No. All operations run headlessly via the Godot binary or through the daemon for live control.
Q: Which Godot versions are supported? A: Headless commands require Godot 4.4 or newer; live commands require Godot 4.6+ (macOS/Linux).
Q: How does the tool avoid parsing engine logs?
A: The GDScript payload wraps the result in unique sentinels, and gda extracts only the JSON between them, while all diagnostics go to stderr.
Q: Can I use this with non‑Python agents?
A: Yes. The MCP server (gda-mcp) exposes the same operations over the Model Context Protocol, making it usable from any language that supports MCP.
Q: What happens if the daemon crashes?
A: gda reports a non‑zero exit code in the live category and returns a structured error envelope, allowing callers to restart the daemon.
gda): Godot AI Agent CLI, Skill, and MCP Server
Read this in: 简体中文 · Español · 日本語
gdagives your AI coding agent — or your shell scripts and CI — structured, machine-readable control of the Godot Engine. Create scenes, edit nodes & scripts, and export builds headlessly, then drive a running game live: runtime tree, input, screenshots, performance — one command surface, three ways in.
AI agents are great at writing GDScript and terrible at seeing what happened. gda
closes that loop: your agent issues one operation and gets back a single clean JSON
result it can act on — never engine logs it has to scrape. It runs in two modes:
gdais pre-1.0: every command works end-to-end today, but the CLI surface may still change before 1.0.
gda?gda?--json); engine banners, warnings and print() go to stderr. Your
agent parses one result, not a wall of logs.--schema (a JSON-Schema contract), so an agent can
discover and validate the whole surface programmatically instead of guessing.gda CLI, hand your agent a bundled Skill (gda skill) that teaches it how and when
to use the CLI, or expose the same operations as MCP tools (gda-mcp, generated from the
CLI's own schemas). One command surface, three ways in — pick whatever your agent supports.gda scene create,
gda node add, gda game set) with a tiny, consistent verb vocabulary — zero learning
curve if you already know Godot.{"error": {…}}
envelope — so a shell or agent can branch on the failure category without parsing prose.| What you need | Reach for |
|---|---|
| Build project files from an agent or script | scene / node / script / resource / shader / theme — create & edit headlessly |
| Parse results instead of scraping engine logs | --json (one clean object) and --schema (a JSON-Schema contract) |
| Hand an agent Godot tools | the bundled Skill (gda skill) or the gda-mcp server |
| Automate CI, exports, and project analysis | headless commands — no editor, no plugin, just a Godot binary |
| Debug a running game's runtime behavior | gda daemon start, then game / diag / logger / perf / input / screen |
Requirements: Python 3.13+, and a Godot binary — 4.4+ for headless commands, 4.6+ on macOS/Linux for live (daemon) commands.
Install the CLI from PyPI onto your PATH:
uv tool install gda # or: pipx install gda
gda --help
Into an existing environment:
pip install gda
From source (for development or unreleased changes):
git clone https://github.com/aigengame/godot-agent.git
cd godot-agent
uv sync # create the environment + install dependencies
uv run gda --help
Point gda at your Godot binary, then ask the engine its version — no project needed:
export GDA_GODOT="/path/to/Godot" # or pass --godot to any command
gda info --json
# {"major":4,"minor":6,"patch":3,"status":"stable","string":"4.6.3-stable (official)",…}
stdout is always clean JSON you can pipe; all engine and script diagnostics go to stderr:
gda info --json | jq .major # → 4
Build a scene headlessly. Point gda at a Godot project (a directory with project.godot)
once; relative paths then resolve inside it, and nodes are addressed by their path relative to
the scene root:
export GDA_PROJECT="/path/to/your/godot-project" # or pass --project to any command
gda scene create scenes/main.tscn --root-type Node2D --json
gda node add scenes/main.tscn --type Sprite2D --name Hero --json
gda node set scenes/main.tscn --node Hero --property position --value 10,20 --json
gda scene get scenes/main.tscn --json
# {"path":"scenes/main.tscn","root":{"name":"main","type":"Node2D","children":[{"name":"Hero",…}]}}
No project?
gdastill runs projectless on plain filesystem paths (relative to your current directory) — onlyres://resolution needs a project. See Configuration.
Drive a running game live. Live ops run the project's main scene, so point it at the
one you just built via Godot's application/run/main_scene project setting (the editor's
Application → Run → Main Scene), then start the daemon (macOS/Linux, Godot 4.6+):
gda project set application/run/main_scene --value res://scenes/main.tscn --json # a Godot project setting key
gda daemon start # start the daemon for $GDA_PROJECT (installs the in-game harness)
gda game tree --json # the runtime scene tree, after _ready
gda perf monitors --json # live engine counters: fps, memory, node count
gda daemon stop
(gda screen capture works live too, but needs a windowed session — start the daemon
with gda daemon start --windowed.)
gda exposes the same command surface three ways — pick whichever your agent (or you) supports:
| Entry point | Best for | How |
|---|---|---|
CLI (gda) |
humans, shell scripts, CI, and agents that can run commands | gda <group> <command> --json |
Skill (gda skill) |
coding agents that support Agent Skills and prefer a token-light CLI workflow | print/install SKILL.md (below) |
MCP (gda-mcp) |
agents that call tools over the Model Context Protocol | run the stdio server (below) |
gda ships an agent Skill — a SKILL.md that teaches an AI agent how and when to drive
Godot from the CLI. It's the lightest way in (no server to register), bundled in the package and
version-locked to your install. Print it, or install it into your agent's skills directory:
gda skill # print SKILL.md (redirect it anywhere)
gda skill --install --provider claude --scope user # resolve a known agent's skills dir
gda skill --install --dir ~/.claude/skills/gda # …or give the directory yourself
--install --provider <claude|codex> --scope <project|user> resolves a known agent's skills
directory (--scope defaults to user); --dir is the neutral fallback for any other agent —
there's no built-in default. The skill recipes list each agent's directory
(Claude Code's ~/.claude/skills/, Codex's ~/.agents/skills/, …). Or fetch the same file straight
from the repo, if you'd rather not go through gda skill — you still install gda, since the Skill
drives it:
curl --create-dirs -o ~/.claude/skills/gda/SKILL.md \
https://raw.githubusercontent.com/aigengame/godot-agent/main/src/gda/skill/SKILL.md
gda ships a stdio MCP server behind a [mcp] extra,
so any MCP agent (Claude Code, Codex, Cursor, …) can drive Godot. Try it with no install:
uvx --from "gda[mcp]" gda-mcp
The server resolves two pieces of context — which Godot project to drive and which Godot binary to run (MCP can't pass per-call flags):
GDA_PROJECT when your client can't advertise workspace roots; otherwise
gda-mcp auto-detects the project from the roots the client sends (the folder you have open). A
set-but-invalid GDA_PROJECT is a reported error, not a silent fallback. See
Configuration for the full CLI-vs-MCP resolution order.GDA_GODOT to your Godot binary, e.g. "GDA_GODOT": "/path/to/Godot".Project scope, .mcp.json at the repo root (auto-detects the project via roots):
{
"mcpServers": {
"gda-mcp": {
"command": "uvx",
"args": ["--from", "gda[mcp]", "gda-mcp"]
}
}
}
User scope (every project) — the CLI, which writes ~/.claude.json:
claude mcp add --scope user gda-mcp -- uvx --from "gda[mcp]" gda-mcp
Project scope, .codex/config.toml at the repo root (the project must be trusted):
[mcp_servers.gda-mcp]
command = "uvx"
args = ["--from", "gda[mcp]", "gda-mcp"]
[mcp_servers.gda-mcp.env]
GDA_PROJECT = "/absolute/path/to/your/godot/project"
User scope (available everywhere, but pinned to one project) — the same table in
~/.codex/config.toml, or add it with the CLI. Codex has no workspace variable, so
GDA_PROJECT is an absolute path; use project scope if you work across several projects:
codex mcp add gda-mcp --env GDA_PROJECT=/absolute/path/to/your/godot/project -- \
uvx --from "gda[mcp]" gda-mcp
Project scope, .cursor/mcp.json at the repo root (${workspaceFolder}
tracks the open project):
{
"mcpServers": {
"gda-mcp": {
"type": "stdio",
"command": "/path/to/uvx",
"args": ["--from", "gda[mcp]", "gda-mcp"],
"env": {
"GDA_PROJECT": "${workspaceFolder}"
}
}
}
}
User scope (available everywhere, but pinned to one project) — the same config in
~/.cursor/mcp.json with GDA_PROJECT set to an absolute path (${workspaceFolder} only
works in project scope; use project scope for several projects). Cursor has no mcp add
command — register via the JSON above or the Settings → MCP UI.
Cursor is GUI-launched with a minimal
PATH, so a bareuvxmay not resolve — hence the absolutecommandabove; fill it with the output ofwhich uvx. Full recipes — PATH injection, Claude Desktop, user vs project scope, per-agent project pinning — are in the registration recipes.
gda is three components serving operations in two modes:
| Component | Role |
|---|---|
gda |
The agent-facing CLI — exposes Godot with structured --json output. |
gda-mcp |
An MCP server exposing the same operations as tools, from --schema. |
gda-daemon |
A per-project process supervising a running game for live operations. |
gda-daemon launches it, injects an inert
in-game harness, and brokers requests over a Unix domain socket (runtime tree, input,
screenshots, performance, diagnostics).The in-game harness gda-daemon injects is dev-only: gda export run strips it from the
artifact entirely, and built any other way (editor GUI, raw godot --export) it still
self-disables in the exported game — so a shipped game never runs anything daemon-related
(and via gda export run, doesn't even carry it).
Platform & version support:
| Mode | Godot | Platforms |
|---|---|---|
| Headless | 4.4+ | macOS · Linux · Windows¹ |
Live (via gda-daemon) |
4.6+ | macOS · Linux² |
¹ Headless is cross-platform by design (one-shot processes, no platform-specific dependency) — Windows keeps the full headless surface, though CI does not exercise it yet. ² Live operations use Unix domain sockets, so Windows is not supported yet.
gda commands are grouped by Godot domain object and use a small, consistent verb
vocabulary, so the same verb means the same thing in every group:
| Verb | Meaning |
|---|---|
create / delete |
Make / remove a standalone entity (scene, script, resource). |
add / remove |
Add / remove a sub-entity within a container (node → scene). |
get / list |
Read one entity / enumerate many. |
set |
Mutate a property. |
| domain verbs | play, run, export, import, … kept with their natural meaning. |
Every command supports --json and --schema — except gda schema itself, which emits
the aggregate manifest as JSON directly. Commands that read or mutate a res:// path
resolve a project context. Run gda <group> <command> --help for full
flags — gda --help is the authoritative list of what is installed.
New here? A good first path: gda info → gda scene create → gda node add →
gda script validate → gda export run; then go live with gda daemon start → gda game tree.
Meta — about gda / the engine itself
| Command | What it does |
|---|---|
gda info |
Report the Godot engine version info. |
gda schema |
Emit the whole command surface as one machine-readable JSON manifest. |
gda skill |
Emit or install the bundled Agent Skill (SKILL.md) that teaches an agent how to drive gda. |
scene — scene files (.tscn)
| Command | What it does |
|---|---|
scene create |
Create a new .tscn with the given root node type. |
scene get |
Read a scene and report its structured node tree. |
scene list |
Enumerate the .tscn scenes in the resolved project. |
scene get-exports |
List the @export properties a scene's nodes' scripts declare. |
scene delete |
Delete a scene file and report what was removed. |
node — nodes within a scene file
| Command | What it does |
|---|---|
node add |
Add a node under a parent (built-in type or class_name script). |
node get |
Read a node's properties (by node path) as typed JSON. |
node list |
List a scene's node tree with each node's path relative to the root. |
node set |
Set a node property, coercing the value to its declared Godot type. |
node remove |
Remove a node (and its subtree) by node path. |
node duplicate |
Duplicate a node (and its subtree) under its parent. |
node move |
Reparent a node (and its subtree) under a new parent. |
node connect-signal |
Wire a source node's signal to a target node's method. |
node disconnect-signal |
Unwire an existing signal→method connection. |
script — GDScript files (.gd)
| Command | What it does |
|---|---|
script create |
Create a new .gd script from a template or verbatim --content. |
script get |
Read a script's source plus its class_name / extends metadata. |
script list |
Enumerate the .gd scripts in the resolved project. |
script set |
Edit a script via search-replace, line-range, or full overwrite. |
script delete |
Delete a script file and report what was removed. |
script attach |
Attach a .gd script to a node (by node path) in a scene. |
script validate |
Syntax/compile-check a .gd script. |
project — the project as a whole (settings, autoloads, static analysis)
| Command | What it does |
|---|---|
project info |
Report project metadata (name, main scene, viewport, engine version). |
project get |
Read a single project setting by section/key as typed JSON. |
project list |
List the project's settings keys (customized by default; --all adds engine defaults, --section filters by prefix). |
project set |
Set a project setting, coercing the value to its declared type. |
project add-autoload |
Register an autoload singleton (name → script/scene). |
project remove-autoload |
Unregister an autoload singleton by name. |
project find-references |
Find every project file that references a given resource. |
project dependencies |
Map each scene/resource to the resources it depends on. |
project find-unused-resources |
Find resource files that nothing references. |
project statistics |
Report the project's file/line counts, autoloads, and more. |
resource — resource files (.tres)
| Command | What it does |
|---|---|
resource create |
Create a new .tres resource of the given type. |
resource get |
Read a .tres resource's properties as typed JSON. |
resource set |
Set a .tres property, coercing the value to its declared type. |
resource delete |
Delete a .tres resource file and report what was removed. |
resource uid |
Resolve a resource UID ↔ its res:// path in both directions. |
export — export presets and artifacts
| Command | What it does |
|---|---|
export list |
Enumerate the project's export presets (name, platform, …). |
export get |
Report one preset's details plus export-template install status. |
export run |
Export a named preset (release / debug / pack) to a destination. |
shader — shader files (.gdshader)
| Command | What it does |
|---|---|
shader create |
Create a new .gdshader from a template or verbatim --content. |
shader get |
Read a shader's source plus its shader_type. |
shader set |
Edit a .gdshader via search-replace, line-range, or full overwrite. |
theme — theme resources (.tres)
| Command | What it does |
|---|---|
theme create |
Create a new, loadable .tres Theme resource (no-clobber). |
gda-daemon; Godot 4.6+, macOS/Linuxdaemon — the live runtime lifecycle
| Command | What it does |
|---|---|
daemon start |
Start the per-project daemon and install the in-game harness; the engine session launches on the first live op (--windowed for screen capture). |
daemon stop |
Stop the project's daemon and any running engine session. |
daemon status |
Report the daemon's state (running, windowed mode, session). |
daemon uninstall |
Remove the in-game gda harness (autoload entry + files) from the project — an explicit dev-tooling teardown; gda export run already strips it from exported artifacts automatically. |
game — the running game's runtime scene graph
| Command | What it does |
|---|---|
game tree |
Read the running game's runtime scene tree (after _ready). |
game get |
Read a runtime node's live properties by node path. |
game set |
Set a runtime node property on the running game. |
diag — runtime diagnostics
| Command | What it does |
|---|---|
diag errors |
Tail the running game's runtime errors (categorized). |
logger — structured runtime log
| Command | What it does |
|---|---|
logger tail |
Tail the running game's whole runtime log as structured records (--level, --limit, --raw). |
perf — performance monitoring
| Command | What it does |
|---|---|
perf monitors |
Snapshot the engine's performance counters (fps, memory, nodes, …). |
perf monitor |
Sample a node property or signal over a frame window (timeline). |
input — input simulation
| Command | What it does |
|---|---|
input key |
Inject a key event (with modifiers). |
input mouse-click |
Inject a mouse click at (x, y). |
input mouse-move |
Inject mouse motion to (x, y). |
input action |
Press/release a mapped input action. |
input sequence |
Inject a multi-frame event timeline. |
screen — viewport capture
| Command | What it does |
|---|---|
screen capture |
Capture one viewport frame to a PNG. |
screen frames |
Capture an N-frame PNG sequence. |
| Flag | Description |
|---|---|
--json |
Emit the result as a single JSON object on stdout. Without it, commands print a concise human-readable rendering. |
--schema |
Emit the command's input/output JSON Schema contract (no Godot spawned). |
--godot |
Path to the Godot binary (overrides $GDA_GODOT and the default). |
--project |
Godot project directory for res:// resolution (overrides $GDA_PROJECT; defaults to the current directory if it is a project). Domain commands only. Resolving a project runs that project's code — see Project code execution. |
--help |
Show usage for gda or any command. |
gda finds the Godot binary from the --godot <path> flag, otherwise the
GDA_GODOT environment variable — set one of these so gda can locate your engine.
Domain commands resolve a Godot project (so res:// paths and a scene's inter-resource
references resolve deterministically) in this order:
--project <dir> flag.GDA_PROJECT environment variable.project.godot).A named directory must be a project, or gda reports it as an error. When none resolves,
gda runs projectless — only filesystem paths (absolute or cwd-relative) resolve, not
res://. The MCP server has no flags, so it resolves a project a little differently:
| Context | Project resolution order |
|---|---|
| CLI | --project → GDA_PROJECT (both strict — invalid is reported) → cwd if it holds project.godot, else projectless |
MCP (gda-mcp) |
GDA_PROJECT (strict — set-but-invalid is reported, not skipped) → a valid client workspace root → a valid server cwd, else projectless |
Resolving a project so res:// paths work runs Godot against that project, and Godot runs
some of the project's own code as part of that. Concretely:
--project operation. When a project is resolved, the engine
constructs the project's autoload singletons at startup — before the command's own work
runs — so their _init (and _ready) execute on every operation, including read-only
ones like scene get and node list. Without a resolved project, no autoloads are
registered, so they do not run.node add, node set,
node remove, …), and node get (which reports runtime property defaults the stored data
does not carry) — loads and instantiates the scene, which constructs each node and runs the
_init of any script attached to a node in it. Commands that only read the stored scene
data (scene get, scene list, node list) walk it without instantiating, so they do not
run those scripts.gda treats the target project as trusted, so this is by design — see
ADR-0009 for the trust model.
Headless Godot interleaves its banner, warnings, and print() output into stdout. gda
solves this with a sentinel contract
(ADR-0002):
The GDScript payload emits exactly one result, wrapped in unique sentinels on stdout:
<<<GDA:RESULT>>>{ …json… }<<<GDA:END>>>
It routes all of its own diagnostics to stderr; stdout carries nothing but the contract.
gda extracts and parses only the bytes between the sentinels, ignoring the surrounding
engine noise, and surfaces stderr for inspection.
This is what makes gda's output safe to consume programmatically, and it generalizes to
the per-message protocol the daemon uses for live operations.
Exit codes (the CLI ABI). A failed gda run exits with a small, stable code so a shell
or agent can branch on the failure category without parsing the JSON error:
| Exit code | Category | When |
|---|---|---|
0 |
— | Success. |
127 |
environment |
The Godot binary could not be launched (shell convention: not found). |
124 |
environment |
Godot launched but did not return before the runner timeout (shell convention: timed out). |
3 |
version |
The detected Godot version is below the supported minimum. |
4 |
operation |
The engine ran but the operation failed — a registered operation error, an engine crash, or an unstructured non-zero exit. |
5 |
parse |
The process claimed success but violated the structured-output contract. |
6 |
live |
A live operation failed — e.g. no running daemon/session, or a live timeout. |
These values are the public ABI; their authoritative source is
src/gda/exit_codes.py. The {"error": {category, code, …}}
envelope carries a finer code within each category (e.g. path_not_found,
already_exists, node_not_found all sit under operation / exit 4). The full
registry lives in
ADR-0002's GdaError.code table.
uv sync # set up the environment
uv run pytest # run the full suite (includes e2e tests against a real Godot)
uv run pytest -m "not e2e" # unit tests only (no Godot binary required)
uv run pytest -m e2e # only the end-to-end tests (needs Godot 4.4+ on this machine)
uv run ruff check . # lint
uv run ruff format . # auto-format (append --check to verify without writing)
uv run pyright # type-check (src/ + tests/, basic mode)
The e2e tier runs by default with uv run pytest, and fails loudly — naming the
resolved path and how to fix it — if no Godot binary is found there, rather than skipping.
Deselect the whole tier with -m "not e2e" (CI's per-PR job uses exactly this).
Linting and formatting are enforced by ruff — one tool in
place of flake8 + black + isort, configured under [tool.ruff] in pyproject.toml and
pinned via uv.lock so local and CI agree. CI's lint job runs ruff check . and
ruff format --check . on every PR; run uv run ruff format . before committing to stay
green.
Types are checked by pyright in basic mode, covering
src/ and tests/ and configured under [tool.pyright] in pyproject.toml (also pinned via
uv.lock). CI's type-check job runs uv run --frozen pyright on every PR.
src/gda/
cli.py # CLI entrypoint (Typer): all command groups, --json / --schema
surface.py # walks the live Typer tree → the `gda schema` manifest
headless.py # the per-command descriptor (one HeadlessCommand per command)
binary.py # Godot binary resolution (flag > $GDA_GODOT > default)
runner.py # the one-shot headless spawn seam (Protocol + subprocess impl)
live_runner.py # the live-operation client that talks to gda-daemon
models.py # typed I/O models (Pydantic) backing --json and --schema
errors.py / error_codes.py / exit_codes.py # failure classification + the CLI ABI
render.py # human-readable (non-JSON) rendering
ops/operations.gd # the headless GDScript payload, dispatched by operation name
daemon/ # gda-daemon: server, session supervision, IPC protocol, discovery
harness/ # the inert in-game `gda` autoload injected into a live session
mcp/ # gda-mcp: the schema → MCP-tool server
tests/ # unit + e2e tests against a real engine (shared fixtures in conftest.py)
docs/adr/ # architecture decision records
CONTEXT.md # the project's shared domain language
gda has two external boundaries, each behind a seam fast tests inject through: spawning a
one-shot headless process (runner.py) and talking to a running game via the daemon
(live_runner.py). The e2e suite drives a real engine across both.
Contributions are welcome. Read CONTEXT.md to align with the project's
shared language, and review the relevant ADRs for the area you're touching.
Issues and PRDs live as GitHub issues.
Commits follow the Conventional Commits specification.
Python code is linted and formatted with ruff and type-checked
with pyright, both enforced in CI — run
uv run ruff format . and uv run pyright before committing (see Development above).
Working with an AI coding agent? This project is built to be agent-navigable —
AGENTS.mdis the entry point for coding agents, wiring in the project's rules, domain docs, and skills.
Released under the MIT License. Copyright (c) 2026 aigengame.
Please log in to share your review and rating for this MCP.
Explore related MCPs that share similar capabilities and solve comparable challenges
by modelcontextprotocol
A Model Context Protocol server for Git repository interaction and automation.
by zed-industries
A high‑performance, multiplayer code editor designed for speed and collaboration.
by modelcontextprotocol
Model Context Protocol Servers
by modelcontextprotocol
A Model Context Protocol server that provides time and timezone conversion capabilities.
by cline
An autonomous coding assistant that can create and edit files, execute terminal commands, and interact with a browser directly from your IDE, operating step‑by‑step with explicit user permission.
by upstash
Provides up-to-date, version‑specific library documentation and code examples directly inside LLM prompts, eliminating outdated information and hallucinated APIs.
by daytonaio
Provides a secure, elastic infrastructure that creates isolated sandboxes for running AI‑generated code with sub‑90 ms startup, unlimited persistence, and OCI/Docker compatibility.
by continuedev
Enables faster shipping of code by integrating continuous AI agents across IDEs, terminals, and CI pipelines, offering chat, edit, autocomplete, and customizable agent workflows.
by github
Connects AI tools directly to GitHub, enabling natural‑language interactions for repository browsing, issue and pull‑request management, CI/CD monitoring, code‑security analysis, and team collaboration.