{
  "markdown": "# GodotLens: Godot's own view of your GDScript project\n\n[![GitHub Release](https://img.shields.io/github/v/release/pzalutski-pixel/godotlens-mcp)](https://github.com/pzalutski-pixel/godotlens-mcp/releases)\n[![npm](https://img.shields.io/npm/v/godotlens-mcp)](https://www.npmjs.com/package/godotlens-mcp)\n[![PyPI](https://img.shields.io/pypi/v/godotlens-mcp)](https://pypi.org/project/godotlens-mcp/)\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)\n\nAn MCP server that lets an AI agent ask **Godot itself** about your project — where a symbol\nis used, what a method's real signature is, whether an edit compiles, how a scene is wired,\nand what the game actually printed when it ran.\n\n## Why\n\nAn agent editing GDScript from text alone is guessing. It cannot tell a call from a comment,\ncannot know which methods exist on a `CharacterBody2D` in *your* Godot version, cannot see that\na signal handler is wired by name inside a `.tscn`, and cannot see what happened at runtime.\n\nGodotLens never answers those questions itself. It asks the engine and returns the engine's\nanswer. Measured on Godot 4.7.1, in a project where `take_damage` is defined in `player.gd`,\ncalled twice from `enemy.gd`, once from `player.gd`, and named in a comment:\n\n| Approach | Result |\n|----------|--------|\n| `grep take_damage` | 5 matches, including the comment |\n| `gdscript_references` | exactly 4 real call sites; the comment is not among them |\n\nThat principle — *delegate every judgement to Godot* — is what makes the answers trustworthy,\nand it is why the tool names tell you where an answer came from. `gdscript_*` is the language\nserver. `scene_*` and `project_config` run the engine. `debug_*` is the debugger.\n\n## Requirements\n\n| | Needed for |\n|---|---|\n| **Godot 4.6+** with your project open | everything — the language server and debug adapter live inside the editor |\n| **Python 3.10+**, or **Node.js 16+** for `npx` | running this server |\n| A Godot **binary** via `GODOT_BIN`, a `./godot/` directory, or `PATH` | `scene_*` and `project_config`, which invoke the engine |\n\nGodot 4.6 is the floor because the language server changed materially at 4.5 (URI encoding)\nand 4.6 (document ownership). Older versions are refused with a clear message rather than\nsilently misread.\n\nThe editor does not need a visible window — this is what CI uses:\n\n```bash\ngodot --path <project> --editor --headless --lsp-port 6005 --dap-port 6006\n```\n\n## Install\n\n**npx** (recommended). The package bundles the server; there are no runtime dependencies.\n\n```json\n{\n  \"mcpServers\": {\n    \"godotlens\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"godotlens-mcp\"]\n    }\n  }\n}\n```\n\n**pip**\n\n```bash\npip install godotlens-mcp\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"godotlens\": { \"command\": \"godotlens-mcp\" }\n  }\n}\n```\n\n## The loop\n\nThe tools are designed around one cycle. Read it once and the rest of this document is a\nreference.\n\n```mermaid\nflowchart LR\n    U[\"<b>Understand</b><br/>gdscript_find<br/>gdscript_references<br/>gdscript_hover\"]\n    W[\"<b>Write</b><br/>gdscript_engine_api<br/>gdscript_complete<br/>gdscript_validate\"]\n    S[\"<b>Sync</b><br/>gdscript_sync_file\"]\n    V[\"<b>Verify</b><br/>gdscript_diagnostics<br/>scene_validate\"]\n    R[\"<b>Run</b><br/>debug_run<br/>debug_output\"]\n\n    U --> W --> S --> V --> R\n    R -- \"something is wrong\" --> U\n\n    classDef step fill:#f5f7fa,stroke:#4a6785,stroke-width:1px,color:#1b2733;\n    class U,W,S,V,R step;\n```\n\n1. **Understand.** `gdscript_find` locates a symbol by name; `gdscript_references` and\n   `gdscript_hover` explain how it is used and what type it is.\n2. **Write.** `gdscript_engine_api` gives real signatures instead of recalled ones,\n   `gdscript_complete` offers scene-aware candidates, and `gdscript_validate` checks proposed\n   content *before* it reaches disk.\n3. **Sync.** Godot's language server does not watch the filesystem. After editing a `.gd`\n   file, call `gdscript_sync_file` or it keeps answering from the old text.\n4. **Verify.** `gdscript_diagnostics` for compile errors, `scene_validate` for the wiring the\n   compiler cannot see.\n5. **Run.** `debug_run` starts the game and returns what it printed.\n\nTwo conventions apply throughout:\n\n- **All line and character parameters are 0-indexed**, matching the LSP. Editor line 1 is\n  line 0. `gdscript_find` exists partly so you rarely have to compute one by hand.\n- **Results carry a `verified` flag** where it matters. `verified: false` with an empty\n  diagnostics list means Godot never reported back — that is *not* a clean bill of health.\n\n## Tools\n\n### Understanding code\n\n| Tool | Description |\n|------|-------------|\n| `gdscript_find` | Locate a declaration **by name**. Returns a position the tools below accept directly. |\n| `gdscript_definition` | Where a symbol is defined. |\n| `gdscript_references` | Every reference project-wide. On 4.6+ this reparses every `.gd` file, so it is not cheap. |\n| `gdscript_references_in_file` | Occurrences within one file. Much cheaper. Godot 4.7+. |\n| `gdscript_hover` | Type information and documentation for a symbol. |\n| `gdscript_symbols` | The symbol tree of a file. |\n| `gdscript_signature_help` | Parameter info at a call site. |\n| `gdscript_symbols_batch`, `gdscript_definitions_batch`, `gdscript_references_batch` | The same, across many files or positions in one call. |\n\n### Writing code\n\n| Tool | Description |\n|------|-------------|\n| `gdscript_engine_api` | Signatures and docs for an engine class or member, from the exact build in use. Use instead of recalling Godot's API. |\n| `gdscript_complete` | Completions at a position. The only **scene-aware** query: includes real `$NodePath` entries and the signals actually on the owning node. |\n| `gdscript_validate` | Check proposed content for errors **without writing it to disk**. |\n| `gdscript_rename` | Rename a symbol. Refuses when Godot will not rename it, and warns when the name also appears in scene files it cannot update. |\n\n### Keeping Godot in step\n\n| Tool | Description |\n|------|-------------|\n| `gdscript_sync_file` | Sync one modified file and return its diagnostics. |\n| `gdscript_sync_files` | Sync several at once. |\n| `gdscript_release_file` | Release a file so the language server reads from disk again. |\n| `gdscript_diagnostics` | Errors and warnings for one or more files. |\n| `gdscript_status` | Connection check. Start here if anything behaves oddly. |\n\n### Project and scenes\n\nThese invoke the Godot binary so scenes resolve exactly as the engine builds them, inherited\nscenes included. They do not parse `.tscn` as text.\n\n| Tool | Description |\n|------|-------------|\n| `project_config` | Autoload singletons, input action names, `class_name` globals, and the main scene, via `ProjectSettings`. |\n| `scene_state` | Node tree, types, script attachments, `unique_name_in_owner` flags, exported values, and signal connections. |\n| `scene_validate` | Checks every connection points at a method that exists. |\n\n### Runtime\n\nGodot serves a Debug Adapter Protocol server from the editor, no addon required. The language\nserver tells you whether code compiles; only the debugger tells you what it **did**.\n\n| Tool | Description |\n|------|-------------|\n| `debug_run` | Run the project and return what it printed. |\n| `debug_output` | Console output from a running game — `print`, stdout, stderr, and runtime errors with their source location. Drained on each call. |\n| `debug_set_breakpoints` | Set breakpoints in a file. |\n| `debug_stack_trace` | The call stack where execution is paused. Empty means not paused. |\n| `debug_inspect` | Variables in a stack frame, by scope. |\n| `debug_evaluate` | Evaluate an expression at a breakpoint, instead of adding `print` and re-running. |\n| `debug_continue`, `debug_pause`, `debug_step_over` | Execution control. |\n| `debug_terminate` | Stop the running game. |\n| `debug_status` | Adapter connection and whether the game is running or paused. |\n\n## What Godot cannot tell you\n\nWorth knowing before you trust a result:\n\n- **The language server reads `.gd` files only.** A signal handler wired in a `.tscn`\n  `[connection]` block is invisible to it, so renaming that handler leaves the scene pointing\n  at a method that no longer exists — and that fails at runtime with no compile error. This is\n  why `scene_validate` exists and why `gdscript_rename` warns.\n- **Autoload and input action names are bare strings.** `GameState.add_score(1)` and\n  `Input.is_action_pressed(\"jump\")` are validated by nothing at all. Check them against\n  `project_config` before writing them.\n- **`gdscript_references` is expensive on 4.6+**, reparsing every script in the project.\n  Prefer `gdscript_references_in_file` when one file is enough.\n\n## Architecture\n\nThree mechanisms, one process. Each tool group maps to exactly one of them, which is how you\nknow where an answer came from.\n\n```mermaid\nflowchart TD\n    Agent[\"AI Agent\"]\n    GL[\"<b>GodotLens</b><br/>MCP server · JSON-RPC 2.0<br/>Python 3.10+ · no dependencies\"]\n\n    Agent <-- \"stdio\" --> GL\n\n    GL -- \"TCP 6005<br/>language server\" --> Editor\n    GL -- \"TCP 6006<br/>debug adapter\" --> Editor\n    GL -- \"subprocess<br/>--headless --script\" --> Binary\n\n    Editor[\"<b>Godot Editor</b><br/>must be open<br/><i>gdscript_* · debug_*</i>\"]\n    Binary[\"<b>Godot binary</b><br/>invoked on demand<br/><i>scene_* · project_config</i>\"]\n\n    classDef svc fill:#eef4fb,stroke:#4a6785,stroke-width:1px,color:#1b2733;\n    classDef godot fill:#f3f0fb,stroke:#6b5b95,stroke-width:1px,color:#1b2733;\n    class Agent,GL svc;\n    class Editor,Binary godot;\n```\n\nThe MCP and LSP/DAP protocols are implemented directly against the standard library, so the\npackage has **zero runtime dependencies** and the npm bundle is a handful of `.py` files.\n\n## Configuration\n\n| Variable | Default | Description |\n|---|---|---|\n| `GODOT_LSP_HOST` | `127.0.0.1` | Language server host |\n| `GODOT_LSP_PORT` | `6005` | Language server port. The official VS Code extension uses `6008` |\n| `GODOT_DAP_HOST` | `127.0.0.1` | Debug adapter host |\n| `GODOT_DAP_PORT` | `6006` | Debug adapter port, used by `debug_*` |\n| `GODOT_BIN` | auto | Godot executable, required by `scene_*` and `project_config` |\n| `GODOT_PROJECT_ROOT` | auto | Project root; auto-detected by walking up for `project.godot` |\n| `GODOT_LSP_TIMEOUT` | `15` | Seconds to wait for a single language server response |\n| `GODOT_DIAGNOSTICS_TIMEOUT` | `8` | Seconds to wait for diagnostics after a sync |\n| `GODOT_VERSION` | auto | Override capability detection |\n| `GODOT_FIND_FILE_LIMIT` | `60` | Max files `gdscript_find` inspects when searching the whole project |\n\n## Contributing\n\n```bash\npip install -e \".[dev]\"\npytest -m \"not integration\"   # no Godot needed\nruff check .\n```\n\nIntegration tests launch a real headless Godot and skip cleanly without one:\n\n```bash\nGODOT_BIN=/path/to/godot pytest -m integration\n```\n\nCI runs the suite on Linux, Windows and macOS across Python 3.10–3.13, runs the integration\ntests against a real Godot on all three, and installs the built npm tarball and executes it.\n\n## License\n\nApache License 2.0 — see [LICENSE](LICENSE) and [NOTICE](NOTICE).\n\n<!-- mcp-name: io.github.pzalutski-pixel/godotlens -->\n",
  "bytes": 11233,
  "sha": "ad7072764cb30b07c65a615575815a1549894331f299834fd36046ace5a65190",
  "repo_slug": "pzalutski-pixel/godotlens-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_pzalutski_pixel_godotlens_4fb77c3e/readme"
}