Skip to content

Commit be3fe9d

Browse files
docs: Update cline_docs for resave_resources fix
1 parent be1f0c2 commit be3fe9d

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed

cline_docs/codebaseSummary.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Codebase Summary: Godot MCP Server
2+
3+
## Key Components and Their Interactions
4+
5+
### 1. MCP Server (`src/index.ts`)
6+
- **Purpose:** Acts as the bridge between the MCP client (e.g., AI assistant) and the Godot engine.
7+
- **Functionality:**
8+
- Initializes an MCP server using `@modelcontextprotocol/sdk`.
9+
- Defines available tools (`create_scene`, `add_node`, etc.) with their input/output schemas using `setRequestHandler`.
10+
- Handles incoming `CallToolRequest` messages.
11+
- Normalizes incoming parameters (camelCase to snake_case).
12+
- Detects the Godot executable path.
13+
- Constructs command-line arguments, including the operation name and a JSON string of parameters.
14+
- Invokes the `godot_operations.gd` script using `child_process.spawn` (configured with `shell: false`).
15+
- Captures stdout/stderr from the Godot process.
16+
- Formats and returns the result or error to the MCP client.
17+
- **Key Methods:** `constructor`, `setupToolHandlers`, `executeOperation`, individual tool handlers (`handleCreateScene`, etc.).
18+
19+
### 2. Godot Operations Script (`src/scripts/godot_operations.gd`)
20+
- **Purpose:** Executes specific Godot engine actions based on commands received from the MCP server.
21+
- **Functionality:**
22+
- Runs as a headless Godot script (`extends SceneTree`).
23+
- Parses command-line arguments to get the operation name and JSON parameter string.
24+
- Uses `JSON.parse()` to convert the JSON string into a Godot Dictionary (`params`).
25+
- Uses a `match` statement to call the appropriate function based on the operation name.
26+
- Contains functions for each tool operation (e.g., `create_scene`, `add_node`).
27+
- Interacts with Godot APIs (`ResourceSaver`, `PackedScene`, `Node`, `ClassDB`, `DirAccess`, `FileAccess`, etc.) to perform actions.
28+
- Includes specific cleanup logic (e.g., freeing instantiated nodes (`scene_root.free()`), adding delays) in functions like `add_node`, `create_scene`, `load_sprite`, `export_mesh_library`, and `save_scene` to prevent resource leaks or issues in headless mode.
29+
- Prints success messages to stdout or error messages to stderr.
30+
- Exits using `quit()`.
31+
- **Key Methods:** `_init`, `create_scene`, `add_node`, `load_sprite`, `export_mesh_library`, `save_scene`, etc., `log_*`, `instantiate_class`.
32+
33+
### Interaction Flow (`create_scene` example)
34+
1. MCP client sends `CallToolRequest` for `create_scene` with arguments (projectPath, scenePath, rootNodeType).
35+
2. `src/index.ts` receives the request via `setRequestHandler(CallToolRequestSchema, ...)`.
36+
3. `handleCreateScene` is called.
37+
4. Parameters are normalized (camelCase to snake_case).
38+
5. `executeOperation` is called with operation "create_scene" and snake_case params.
39+
6. `executeOperation` converts params to a JSON string.
40+
7. `executeOperation` calls `spawn` with the Godot executable path, `--headless`, `--path`, `--script`, the operation name ("create_scene"), and the JSON string as arguments (`shell: false`).
41+
8. `godot_operations.gd` starts execution.
42+
9. `_init` parses command-line args, extracts "create_scene" and the JSON string.
43+
10. `_init` calls `JSON.parse()` on the JSON string.
44+
11. `_init` calls the `create_scene(params)` function with the parsed Dictionary.
45+
12. `create_scene` function uses Godot APIs to create the root node, pack the scene, ensure the directory exists, and save the `.tscn` file using `ResourceSaver.save()`.
46+
13. `create_scene` prints success/error messages.
47+
14. Godot script exits (`quit()`).
48+
15. `executeOperation` in `src/index.ts` resolves its promise with stdout/stderr.
49+
16. `handleCreateScene` processes stdout/stderr and returns a result object to the MCP client.
50+
51+
## Data Flow
52+
- **Input:** MCP `CallToolRequest` with JSON arguments (camelCase or snake_case).
53+
- **Internal:**
54+
- Node.js normalizes arguments to snake_case.
55+
- Node.js serializes snake_case arguments to a JSON string.
56+
- JSON string passed as a command-line argument to GDScript.
57+
- GDScript parses the JSON string back into a Dictionary.
58+
- **Output:** MCP response object containing success/error message and relevant data (e.g., created scene path). Stdout/stderr from Godot script captured by Node.js.
59+
60+
## External Dependencies
61+
- **@modelcontextprotocol/sdk:** Core dependency for MCP communication. Managed via `package.json` and `npm`.
62+
- **Godot Engine:** External executable. Path is auto-detected or configured via environment variable/server config. The server relies on Godot's command-line interface and headless execution capabilities.
63+
64+
## Recent Significant Changes
65+
- **Argument Passing:** Switched from `spawn` with `shell: true` and manual escaping to `spawn` with `shell: false` and passing the raw JSON string. This resolved issues with argument parsing on Windows.
66+
- **MCP SDK Usage:** Refactored tool registration from `server.registerTool` to using `server.setRequestHandler` for `ListToolsRequestSchema` and `CallToolRequestSchema`, aligning with current SDK practices.
67+
- **GDScript Error Fix:** Removed incorrect `scene_root.owner = scene_root` assignment in `create_scene` function, resolving a Godot engine assertion error during `PackedScene.pack()`.
68+
- **Logging:** Added detailed debug logging in both `index.ts` and `godot_operations.gd` to trace argument passing and execution flow.
69+
- **`add_node` Fixes:** Debugged and resolved multiple issues in the `add_node` GDScript function:
70+
- Addressed initial "RID allocation leak" errors by adding `scene_root.free()`.
71+
- Resolved subsequent node duplication issues (likely caused by freeing `scene_root` too early) by adding a small delay (`OS.delay_msec(100)`) after `ResourceSaver.save()` but before `scene_root.free()` in `add_node`.
72+
- Corrected a "Can't free a RefCounted object" error introduced by incorrectly trying to free the `PackedScene` resource.
73+
- **RID Leak Fix:** Added missing `scene_root.free()` calls to the end of `create_scene`, `load_sprite`, `export_mesh_library`, and `save_scene` functions in `godot_operations.gd` to resolve RID allocation leaks observed during testing.
74+
- **`resave_resources` Fix:** Addressed issues with the `resave_resources` tool:
75+
- Modified `godot_operations.gd` (`_init`) to make the JSON parameter optional and default to an empty dictionary if not provided.
76+
- Added explicit parameter validation checks within specific GDScript functions that require them.
77+
- Added a small delay (`OS.delay_msec(100)`) before `quit()` in `godot_operations.gd` to potentially aid output buffer flushing.
78+
- Updated the `handleUpdateProjectUids` function in `index.ts` to infer success based on the Godot script's exit code (0) and the absence of "ERROR" in stderr, improving reliability over parsing stdout.
79+
80+
## User Feedback Integration
81+
- N/A (No user feedback integrated yet for this specific task).

cline_docs/currentTask.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Current Task: Update Fork with RID Leak Fix
2+
3+
## Objective
4+
- Update the user's fork (`alienfrenZyNo1/godot-mcp`) with the commit containing the fix for the RID allocation leaks, ensuring documentation files are *not* included in this update.
5+
6+
## Context
7+
- The previous task involved fixing the `add_node` tool and preparing a PR.
8+
- Further testing revealed similar RID allocation leaks in other scene modification tools (`load_sprite`, `create_scene`, `export_mesh_library`, `save_scene`).
9+
- These leaks were traced back to missing `scene_root.free()` calls in the corresponding functions within `src/scripts/godot_operations.gd`.
10+
- The fix involved adding the necessary `scene_root.free()` calls to all affected functions.
11+
12+
## Completed Steps
13+
1. Identified missing `scene_root.free()` calls in `create_scene`, `load_sprite`, `export_mesh_library`, and `save_scene` functions in `src/scripts/godot_operations.gd`.
14+
2. Applied the fix by adding the `scene_root.free()` calls to these functions using `replace_in_file`.
15+
3. Rebuilt the project (`npm run build`).
16+
4. Successfully tested the `load_sprite` tool, confirming the RID leak was resolved.
17+
5. Successfully used the `save_scene` tool to persist the changes.
18+
6. Updated `cline_docs` (`currentTask.md`, `projectRoadmap.md`, `codebaseSummary.md`) to reflect the completion of the RID leak fix across multiple tools.
19+
20+
## Next Steps
21+
- Stage the documentation changes (`git add cline_docs/`).
22+
- Debugged and fixed the `resave_resources` tool:
23+
- Modified `godot_operations.gd` to handle optional parameters correctly.
24+
- Added debugging logs to trace parameter parsing in GDScript.
25+
- Modified `index.ts` (`handleUpdateProjectUids`) to check for the correct stdout message ("Resave operation complete").
26+
- Added a delay (`OS.delay_msec(100)`) before `quit()` in `godot_operations.gd` to attempt to fix output flushing issues.
27+
- Modified `index.ts` (`handleUpdateProjectUids`) again to infer success based on exit code 0 and lack of "ERROR" in stderr, as stdout parsing remained unreliable.
28+
- Rebuilt the server (`npm run build`) multiple times.
29+
- Confirmed `resave_resources` works correctly after server restart.
30+
31+
## Next Steps
32+
- Stage the code changes (`src/index.ts`, `src/scripts/godot_operations.gd`).
33+
- Commit the code changes with an appropriate message.
34+
- Push the commit to the user's fork (`fork main`).
35+
- Update local documentation (`cline_docs/`) and commit separately (locally only).

cline_docs/projectRoadmap.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Project Roadmap: Godot MCP Server
2+
3+
## Goals
4+
- Provide robust tools for interacting with the Godot engine via MCP.
5+
- Ensure reliable communication between Node.js server and Godot scripts.
6+
7+
## Features
8+
- [x] `create_scene`: Create new Godot scene files. (Fixed RID leak)
9+
- [x] `add_node`: Add nodes to existing scenes. (Fixed RID leak)
10+
- [x] `load_sprite`: Load textures onto sprite nodes. (Fixed RID leak)
11+
- [x] `export_mesh_library`: Export meshes to a MeshLibrary. (Fixed RID leak)
12+
- [x] `save_scene`: Save scene changes. (Fixed RID leak)
13+
- [ ] `get_uid`: Retrieve resource UIDs.
14+
- [x] `resave_resources`: Update project UIDs. (Fixed argument/output handling)
15+
- [ ] `launch_editor`: Launch the Godot editor.
16+
- [ ] `run_project`: Run a Godot project.
17+
- [ ] `get_debug_output`: Capture debug output.
18+
- [ ] `stop_project`: Stop a running project.
19+
- [ ] `get_godot_version`: Get Godot version.
20+
- [ ] `list_projects`: List projects in a directory.
21+
- [ ] `get_project_info`: Get project scene/script info.
22+
23+
## Completion Criteria
24+
- All defined tools function correctly across platforms (especially Windows).
25+
- Argument passing between Node.js and Godot is reliable.
26+
- Error handling is robust.
27+
28+
## Progress Tracker
29+
- Initial setup and basic tool implementation.
30+
- Debugging and fixing argument passing for `create_scene`.
31+
32+
## Completed Tasks
33+
- [x] Debug and fix JSON argument passing for `create_scene` tool.
34+
- [x] Correct node ownership issue in `create_scene` GDScript function.
35+
- [x] Debug and fix resource leaks and node duplication issues for `add_node` tool.
36+
- [x] Debug and fix RID allocation leaks in `create_scene`, `load_sprite`, `export_mesh_library`, and `save_scene` by ensuring `scene_root.free()` is called.
37+
- [x] Debug and fix argument handling and success reporting for `resave_resources` tool.

cline_docs/techStack.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Tech Stack: Godot MCP Server
2+
3+
## Core Technologies
4+
- **Node.js:** Runtime environment for the MCP server.
5+
- **TypeScript:** Primary language for the server codebase, providing static typing.
6+
- **Godot Engine:** Target game engine for interactions.
7+
- **GDScript:** Language used for the Godot-side operations script (`godot_operations.gd`).
8+
9+
## Key Libraries/Modules
10+
- **@modelcontextprotocol/sdk:** Used for MCP server implementation (`Server`, `StdioServerTransport`, schemas).
11+
- **Node.js `child_process`:**
12+
- `spawn`: Used for executing the Godot command-line tool reliably, especially for passing complex arguments like JSON strings. Configured with `shell: false` for better cross-platform argument handling.
13+
- `exec` / `execAsync`: Potentially used for simpler commands like `--version` or launching the editor.
14+
- **Node.js `fs`:** Used for file system checks (`existsSync`, `readdirSync`).
15+
- **Node.js `path`:** Used for path manipulation and normalization (`join`, `dirname`, `basename`, `normalize`).
16+
17+
## Architecture Decisions
18+
- **MCP Server (`src/index.ts`):** Handles incoming MCP tool requests, validates parameters, prepares arguments, and invokes the Godot operations script.
19+
- **Godot Operations Script (`src/scripts/godot_operations.gd`):** A headless Godot script that receives commands and JSON parameters via command-line arguments. It performs the actual Godot engine operations (e.g., creating scenes, adding nodes).
20+
- **Argument Passing:** JSON strings are passed as command-line arguments from Node.js to the GDScript. Using `spawn` with `shell: false` is crucial for correct parsing on Windows, avoiding shell interpretation issues.
21+
- **Parameter Normalization:** The Node.js server normalizes incoming MCP arguments (potentially camelCase) to snake_case before sending them to the GDScript, which expects snake_case.

0 commit comments

Comments
 (0)