"Nothing happens. Nobody comes, nobody goes. It's awful!" β Waiting for Godot
Didi keeps the bridge native, local, and explicit about what it can actually execute.
Didi (godot-mcp-native) is a high-performance, native Model Context Protocol (MCP) server for Godot 4.5+, engineered in C++20 as a standalone executable (didi.exe on Windows, didi on POSIX) and an in-engine GDExtension library for the target platform.
The current documented release is 2.0.0.
Didi follows semantic versioning, so the major number says what changed, not how
finished the project is. 2.0.0 corrects error codes, handshake validation and
schema strictness across the surface, and a client written against 1.8.0 can
break on any of them. Didi itself is still PARTIAL_DELIVERY: three canonical
tools are registered and unimplemented, and the roadmap phase that owns
compatibility guarantees has not started. See
Stability before you pin a version, and the
Breaking list before you upgrade.
Didi builds, tests and ships on Windows, macOS and Linux. Every release
carries one archive per platform, with SHA256SUMS and a build provenance
attestation beside them.
| Platform | Release archive | On every push | Live editor coverage |
|---|---|---|---|
| Windows x64 | didi-windows-x64.zip |
MSVC build, native and Python suites | Godot 4.5.1, 4.6.2 and 4.7.2 editors, in CI |
| Linux x64 | didi-linux-x64.tar.gz, built in an Ubuntu 22.04 container and linked against a static C++ runtime, so glibc 2.34 is the whole floor: Ubuntu 22.04, Debian 12, Rocky, RHEL and AlmaLinux 9 and anything newer |
gcc build, native and Python suites, ASan and UBSan | Not in CI |
| macOS (Apple silicon), macOS 14 or newer | didi-macos-arm64.tar.gz; there is no Intel archive, and the .gdextension inside it declares only arm64, so an Intel Mac is told there is no library for it rather than handed one it cannot load |
clang build, native and Python suites | Not in CI |
macOS and Linux are the least-tested platforms, and testers are wanted. The live editor harness runs on Windows in CI, so a real editor session on either of the other two is evidence CI does not have. If you run Didi there, open an issue with the Godot version, the client, and what the Didi tab's Diagnostics page reported, whether it worked or not. Contributing says what a useful report contains.
| Document | Target Audience | Description |
|---|---|---|
| π Project Website | Everyone | What Didi is, the tool surface, setup, and the in-editor console. |
| π Documentation Index | Everyone | Every page under docs/, grouped, with the status of each design record. |
| π Quickstart Guide | Developers / Humans | 5-minute step-by-step setup for Godot, Cursor, Claude, and VS Code. |
| π€ LLM Agent Instructions | AI Assistants / LLMs | Dedicated system prompt & decision tree for Claude, Cursor, Windsurf, Antigravity. |
| β Current Capability Matrix | Everyone | Authoritative live, offline, unavailable, and unimplemented behavior. |
| β»οΈ Managed Recovery | Users / Operators | Opt-in owned editor, project copies, checkpoints, and recovery limits. |
| ποΈ Control Room | Users / Operators | The MCP Apps dashboard: bridge lights, live tool modes, safety posture, and Didi's own log, rendered inside your assistant. |
| πΊοΈ Roadmap & 113-Tool Surface | Developers / Contributors | Completed phases and technical build order. |
| π§ͺ Phase 7 API Feasibility Evidence | Developers / Governance | Reproducible Godot 4.5.1/4.7.2 feasibility results and the exact three blocked contracts. |
| π Phase 7 Approved Executable Plan | Developers / Governance | Approved atomic 83/83 plan, stopped at its feasibility gate. |
| π οΈ Tool Reference Manual | Developers / LLMs | Current behavior and limits for 116 canonical tools plus 10 legacy names. |
| ποΈ Architecture & System Topology | Engineers / Architects | Deep-dive into C++20 design, dual execution topology, threading safety, and named-pipe IPC. |
| π¦ Dynamic Resources & Prompts | Developers / LLMs | Technical specs for godot://... resources and prompt workflows. |
| π Integration Guide | Developers / Integrators | Installing the addon into an existing project and wiring each supported assistant to it. |
| π‘οΈ Administrator & Operations Guide | DevOps / Admins | Security DACL hardening, CI/CD headless execution, observability, and troubleshooting. |
| π©βπ» Developer & Extension Guide | Contributors | How to build from source, write tests, and add custom MCP tools. |
| π§ͺ Test Inventory | Contributors / Reviewers | Generated totals for every suite, derived from the suites themselves rather than written down beside them. |
| π‘ API & Wire Protocol Specification | Integrators | JSON-RPC 2.0 transport and binary frame specifications. |
| π Security Policy | Users / Operators | Supported release line, local attachment boundary, and private reporting guidance. |
| π Changelog | All | Version history and notable changes. |
| π€ Contributing | Contributors | Build, test, and review expectations for a change you want merged. |
| π Code of Conduct | Everyone | How people here are expected to treat each other, and how to report a problem. |
| π€ On the Use of AI | Everyone | Where AI was used to build Didi, what checks it, where it is no help at all, and who is responsible when it is wrong. |
| π¦ Third Party Code | Maintainers / Security | The vendored sources no package manager resolves, their versions, and what Dependabot does not cover. |
| π¨ Brand Identity | Contributors / Maintainers | The mark, wordmark, lockups, palette, and the assets they generate from. |
| Feature | Legacy Script/CLI Wrappers | Multi-Hop Network Bridges | Didi (godot-mcp-native) |
|---|---|---|---|
| Execution Topology | Offline CLI subprocesses | Node.js + WebSocket + C# Plugin | Direct C++ GDExtension + Standalone Binary |
| In-Memory Scene Access | β Blind to live editor state | β Direct Godot objects for supported live tools | |
| Undo / Redo Safety | β None (file overwrites) | β
Native EditorUndoRedoManager transactions |
|
| Visual Inspection | β None | β Live editor PNG capture, node isolation, and exact pixel diffs | |
| Transport | Process startup per call | Network or multi-process bridge | Local named pipe / Unix socket |
| External Dependencies | Node.js / Python runtime | Node.js runtime + WebSockets | Zero external runtime dependencies |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LLM Client (IDE / Agent) β
β Cursor / Claude Desktop / VS Code β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β Standard MCP Protocol (stdio / JSON-RPC 2.0)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Didi (C++ MCP Core Engine - didi / didi.exe) β
β - JSON-RPC 2.0 Dispatcher (MCP 2024-11-05 standard) β
β - Registry (116 canonical tools + 10 legacy names) β
β - Dynamic Resources (godot://project/tree, editor/state) β
β - IPC Session Manager (Named Pipes / Local IPC) β
β - Offline Fallback Engine (GDScript AST, .tscn parser) β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β Authenticated process-unique local IPC endpoint
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Godot 4.5+ Process (Didi extension library) β
β βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ β
β β EditorInterface Hook β Editor ViewportTexture β β
β β (Main-thread Dispatch)β (RGBA8 β PNG capture) β β
β βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ€ β
β β Live SceneTree & Undo β Extension IPC lifecycle β β
β β (EditorUndoRedoManagerβ (timeouts and cancellation) β β
β βββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The 116 canonical names are the stable protocol surface, with 10 additional legacy registrations (126 total). The implementation remains 113/116 canonical tools, and all 3 Phase 7 names remain registered but unimplemented. Availability is explicit rather than implied: inspect _meta.didi.executionModes, implemented, currentMode, liveAvailable, editorConnected, and optional selected sessionKind from tools/list. editorConnected is true only for an editor route, while liveAvailable also requires that the selected editor/game kind is allowed for that exact definition. Phase 6 keeps the surface stable while requiring an explicit Godot project, adding project-keyed endpoints and one-client runtime locks, and exposing dry-run/confirmation controls on mutations. The coordination tools are the exception to the one-client picture: they are how separate agent processes share decisions and divide work, since each MCP client runs its own didi and nothing is shared in memory. Every definition also carries specification annotations: readOnlyHint describes tool intent using the same classification that drives dry_run. In managed mode, an ordinary authorized read can trigger the single editor restart and execute project startup code, so read-only auto-approval must account for that effect. Successful JSON results carry structuredContent alongside the text block.
| Domain | Key Tools | Current execution |
|---|---|---|
| 1. Scene Tree & Nodes (7) | scene_get_hierarchy, scene_instantiate_node, scene_remove_node, scene_reparent_node, scene_set_property, scene_get_property, scene_duplicate_node |
Implemented live; hierarchy also has an offline .tscn fallback. Built-in nodes and scalar properties only. |
| 2. Signals & Events (4) | signal_list_connections, signal_connect, signal_disconnect, signal_emit |
Implemented live. Connect and disconnect register with the edited scene's UndoRedo history; emit requires confirmation. |
| 3. Scripting & Reflection (4) | script_check_syntax, script_reflect_class, script_get_symbols, script_patch_method |
Implemented offline/file-based; reflection covers every engine class from the pinned Godot API dump. |
| 4. Vision & Render (5) | viewport_capture_frame, viewport_diff_capture, viewport_set_camera_transform, viewport_create_test_lab, viewport_toggle_debug_draw |
Live capture returns a process-local ID; named-node isolation is reversible; exact-dimension RGBA diffs are live-only. Synthetic capture and test-lab generation remain offline. Camera transforms are editor-only UndoRedo mutations; collision/navigation debug hints affect future games run from that editor and return their prior state. |
| 5. Physics & Navigation (6) | physics_raycast_query, physics_simulate_step, nav_bake_mesh, nav_query_path, anim_list_tracks, anim_play_track |
Raycast and path queries run live against the root viewport's existing worlds in the editor or a game; animation listing reads an AnimationPlayer's library in either, and playback is a game-only transient call. Physics stepping and navigation baking remain unimplemented. |
| 6. Tilemaps & GridMaps (3) | tilemap_set_cells, tilemap_get_used_rect, gridmap_set_cells |
Editor-only live batch editing with whole-request preflight, one UndoRedo action, and read-only TileMapLayer used bounds. |
| 7. Resources & Files (9) | resource_create, resource_inspect, project_list_resources, project_get_uid_map, project_audit_assets, project_analyze_impact, project_search_text, project_search_symbols, asset_reimport |
File/resource inspection, bounded search, impact analysis, and conservative .import health diagnostics are offline; source-asset reimport is editor-only and waits for stable idle. |
| 8. Runtime & Debug (4) | runtime_launch, runtime_inject_input, runtime_get_call_stack, runtime_read_profiler |
Process launch is implemented offline; the profiler samples Performance monitors live over a bounded window; input injection dispatches explicit press and release events into a game session. Call stack remains unimplemented. |
| 9. Editor Lifecycle (4) | editor_undo, editor_redo, editor_save_scene, editor_reload_project |
Implemented live. Reload requests a resource-filesystem rescan. |
| 10. Project Wiring (18) | Script attach/detach; autoload, InputMap, and setting management; groups; scene create/open/close/pack | Implemented live with UndoRedo, ProjectSettings persistence, typed events, overwrite guards, and normalized res:// paths. |
| 11. Runtime Sessions (10) | runtime_list_sessions, attach/detach/get, logs, pause/step/stop/tree, eval_gdscript |
Four local session-management tools plus six live tools. Attachment is deterministic or explicit and always authenticated; evaluation is a strict read-only expression subset, not arbitrary GDScript. |
| 12. Deep Domains (6) | csharp_check_build, shader_check_compile, project_list_export_presets, project_export, gridmap_export_mesh_library, ui_hit_test |
Five bounded offline subprocess/file tools plus one editor-only transformed Control hit-test. Writes require project-contained normalized paths and explicit overwrite. |
| 13. Agent Coordination (10) | blackboard_write, blackboard_read, blackboard_patch, blackboard_list_keys, blackboard_clear, blackboard_task_create, blackboard_task_claim, blackboard_task_update, blackboard_task_complete, blackboard_task_list |
Offline and file-backed under .didi/blackboard/, because each MCP client is its own process and shares no memory with the next. Every operation takes an exclusive OS lock for the whole read-modify-write, so a claim is atomic and two agents racing for one task produce a single winner. A lease expires, so an agent that dies strands nothing. Board content is data, never instruction. |
| 14. Managed Recovery (4) | runtime_recovery_status, runtime_checkpoint, runtime_recover_editor, runtime_restore_checkpoint |
Managed-only host tools for saved-file checkpoints, one automatic owned-editor restart, explicit reconciliation, and confirmed restore. |
Didi publishes one private descriptor per loaded editor or game process. Windows uses <OS temp>/didi-sessions; POSIX uses $XDG_RUNTIME_DIR/didi-sessions when that value is absolute and otherwise falls back to <OS temp>/didi-sessions-<euid> (override only for controlled deployments with DIDI_SESSION_DIR; the operator owns override-directory access controls). POSIX defaults are owner-only; Windows grants the owning SID and local administrators. On first live availability, Didi auto-attaches only when the canonical project has one matching session, or one matching editor among games; same-kind ambiguity stays detached. Use runtime_list_sessions and runtime_attach_session to choose explicitly when needed. Public responses never include the 64-hex authentication token. Descriptor schema 1 / protocol 1.3 binds a 32-hex session ID to PID plus process start time so PID reuse is not treated as the same engine. Windows deletes an exactly verified retired descriptor through its open handle; POSIX deliberately retains the unpredictable non-.json tombstone after proof-safe retirement because it has no portable object-bound unlink, and discovery ignores that tombstone.
Live main-thread work has finite boundaries. At the extension's 15-second deadline, work that has not started returns outcome: "not_started" without quarantining the route; work that started but remains unresolved returns outcome: "unknown_outcome" and requests route quarantine. Public live tools and the runtime-log resource use a 17-second outer transport deadline and quarantine only the exact failed route generation, so callers must not blindly retry mutations with unknown outcomes.
runtime_read_logs polls the bounded 2,000-record Didi ring with a cursor. This structured ring records Didi lifecycle, command, control, and evaluation events; it does not intercept arbitrary print() output from Godot or another external process. Poll the separate bounded runtime_read_output stream for print(), warnings, errors, and script diagnostics from an attached editor or game. Use runtime_launch when you need bounded stdout/stderr from a Didi-owned child process captured after that process exits.
eval_gdscript accepts one expression (1β2048 UTF-8 bytes), an optional in-subtree context_node, and timeout_ms from 1β5000. It rejects statements, assignment, dynamic/indexed access, traversal, arbitrary dispatch, and mutation. Its timeout checks are cooperative, not preemptive; the grammar and receiver allowlist are deliberately small enough to bound accepted work. See the Tool Reference for the exact allowed calls and result limits.
project_search_text and project_search_symbols scan only allowlisted project text formats under strict file, byte, result, path, encoding, and preview bounds. asset_reimport accepts an all-or-nothing batch of normalized source assets and completes only after two consecutive editor-idle observations.
Every successful live viewport capture returns a 32-lowercase-hex capture_id backed by an 8-entry/64 MiB process-local raw RGBA cache; offline previews never receive IDs. node_isolation_path temporarily hides unrelated 2D/3D branches and restores every original value before success. viewport_diff_capture requires an unexpired live ID, exact dimensions, and a 0..255 threshold, returning metrics plus one transparent PNG diff without duplicating Base64 in the JSON metadata.
Process-backed Phase 5 tools launch argv directly without a command shell, enforce per-request deadlines, cap combined output at 1 MiB, and terminate the child process group on timeout. Godot-backed checks require a discoverable Godot 4.5+ executable (or GODOT_BIN); C# checks require dotnet. Export and MeshLibrary outputs must be normalized project-contained res:// paths and preserve existing files unless overwrite: true. Export-preset listing exposes only public preset identity and routing fields, never option values. ui_hit_test traverses at most 10,000 live nodes, applies visibility, clipping, transforms, canvas layer, z-order, draw order, and mouse-filter rules, returns at most 256 hits, and never injects input.
Didi now refuses startup without --project <root> or DIDI_PROJECT_ROOT, and the selected directory must contain project.godot. Runtime endpoint names include a stable 16-hex project key while retaining process/session uniqueness. A per-session OS lock permits one MCP client at a time and is released automatically when that client exits. Every implemented mutation advertises dry_run; dry-runs return a handler-free structured change plan bound to the exact project and live route. The always-confirmed and overwrite-confirmed tools require the 64-hex, 120-second, single-use confirmation_token returned by the exact preview.
Status: PARTIAL_DELIVERY
Canonical implementation: 113/116
Phase 7 registrations: 3/18 unimplemented
Feasibility: 15/18 implementation-feasible; 3/18 API-blocked
Phases 1-6 established the implementation baseline. Phase 7 is PARTIAL_DELIVERY: the 2026-08-29 gate on Godot 4.5.1 and 4.7.2 found 15/18 names implementation-feasible and 3/18 API-blocked under the approved contracts. All 15 feasible names are now delivered; the implementation is 113/116 canonical tools and only the 3 API-blocked names remain registered but unimplemented.
Governance selected partial delivery: feasible tools ship only after their own production evidence, while implemented: false keeps unavailable names honest. The three API-blocked contracts remain physics_simulate_step, nav_bake_mesh, and runtime_get_call_stack.
Phase 8 is now IN PROGRESS. Its read-only slices provide bounded project audit, reverse impact analysis including exact static node paths, and conservative .import source/output health evidence. UID-cache reconciliation, checksum/importer-version validation, guarded import configuration, and broader incremental freshness remain planned.
See the Roadmap, Phase 7 feasibility evidence, approved executable plan, and Future Phases Design.
-
Build Didi:
cmake -B build -S . cmake --build build --config Release
-
Enable Godot Plugin:
Copy
build/addons/didiinto your project asaddons/didiand check Enable in Project Settings$\rightarrow$ Plugins. A Didi tab appears beside 2D, 3D and Script. The build assembles the addon underbuild/. Theaddons/didifolder in this repository is the manifest that goes into that assembly, not a build output, so itsbin/holds whatever was last put there by hand. -
Connect AI Assistant:
Open the Didi tab, go to Connect, and copy the generated configuration β it already
carries the located binary and this project's path. Or write it by hand into
claude_desktop_config.jsonor.cursor/mcp.json:{ "mcpServers": { "didi": { "command": "D:/didi/build/Release/didi.exe", "args": ["--project", "D:/my_game"] } } }
Start with --managed-editor <absolute-Godot-executable> --recovery-workspace <new-directory> alongside --project. Didi edits a separate project copy, checkpoints saved files, and can restart its owned editor once without replaying an uncertain edit. Ordinary attachment is unchanged. Setup, coverage and recovery tools.
Enabling the plugin adds a Didi main screen to the Godot editor, carrying Didi's own mark. It answers, without anyone having to read a log, the question every bridge raises first: can my assistant actually reach this project right now?
The Dashboard is six cards, each with a red, amber or green light, the fact behind it, and the one thing to do about it:
| Card | Green | Amber | Red |
|---|---|---|---|
| Live bridge | Up, with how long for | Extension loaded, no endpoint | Closed |
| Extension | Loaded, with the library path | Present but not loaded β Load it | Library missing for this platform |
| Server binary | Verified by running it | Found but not verified β Verify it | Not found β Detect |
| Client configuration | Present in the project | Absent β Write it | β |
| This editor | Session id, pid and project | Publishing nothing | β |
| Other sessions | None competing | Others published β List them | β |
Three switches sit above them. Live bridge opens and closes the bridge for real: it loads and unloads the extension and reports the status Godot returns, including the one that means "not without a restart". Auto refresh decides whether the dashboard re-reads state on a timer, and Technical detail reveals the session id, endpoint, descriptor path and the list of other sessions.
| Tab | What it is for |
|---|---|
| Dashboard | The lights, the switches, and the exact values behind them. |
| Connect | The launch configuration your client needs, generated with the binary located and the project path filled in, for Claude Code, Cursor, Claude Desktop and VS Code. Copy it, or write it straight into the project for the clients that read one from there. |
| Log | Two sources, filterable by level and by text: the console's own timestamped record of every state change and action, and the log Godot writes for the last run of the project. Didi's server logs to its own standard error, which your MCP client captures β the page says so rather than showing an empty view. |
| Settings | Refresh rate, whether the binary may be verified by running it, and the log level, endpoint name and confirmation policy the generated configuration carries. Stored in Godot's EditorSettings under didi/, which lives with your editor rather than inside the project, so nothing Didi can write to the project can change them. |
| Diagnostics | Every check names the path or pid it looked at, and the report is copyable into an issue. Nothing here starts a process unless you ask it to. |
The console never displays, copies, or reports a session token. It reads the descriptors Didi publishes and keeps the fields it names; the shared secret in them is not one of those fields.
Copy docs/LLM_INSTRUCTIONS.md into your agent instructions and keep docs/CAPABILITIES.md available as the current execution contract.
MIT License. See LICENSE for details.