godot-mcp-runtime 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +154 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/godot_operations.gd +757 -0
- package/dist/scripts/mcp_bridge.gd +463 -0
- package/dist/tools/node-tools.d.ts +15 -0
- package/dist/tools/node-tools.d.ts.map +1 -0
- package/dist/tools/node-tools.js +178 -0
- package/dist/tools/node-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +130 -0
- package/dist/tools/project-tools.d.ts.map +1 -0
- package/dist/tools/project-tools.js +638 -0
- package/dist/tools/project-tools.js.map +1 -0
- package/dist/tools/scene-tools.d.ts +27 -0
- package/dist/tools/scene-tools.d.ts.map +1 -0
- package/dist/tools/scene-tools.js +270 -0
- package/dist/tools/scene-tools.js.map +1 -0
- package/dist/utils/godot-runner.d.ts +71 -0
- package/dist/utils/godot-runner.d.ts.map +1 -0
- package/dist/utils/godot-runner.js +601 -0
- package/dist/utils/godot-runner.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Owen Sterling
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Godot Runtime MCP Server
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io/) server that gives AI assistants direct access to a running Godot 4.x game. Not just file editing, not just scene manipulation, but actual runtime control: input simulation, screenshots, UI discovery, and live GDScript execution while the game is running.
|
|
4
|
+
|
|
5
|
+
Most Godot MCP servers operate headlessly. They can create scenes, add nodes, attach scripts, and that covers a lot of ground. But they stop at the editor boundary. This one doesn't. When you run a project through this server, it injects a lightweight UDP bridge as an autoload, and suddenly the AI can interact with your game the same way a player would. It presses keys, clicks buttons, reads what's on screen, and runs arbitrary code against the live scene tree.
|
|
6
|
+
|
|
7
|
+
The distinction matters: the AI doesn't just write your game, it can test it.
|
|
8
|
+
|
|
9
|
+
## What It Does
|
|
10
|
+
|
|
11
|
+
**Headless editing**: Create scenes, add nodes, set properties, attach scripts, manage UIDs. All the standard operations you'd expect, no editor window required.
|
|
12
|
+
|
|
13
|
+
**Runtime bridge**: When `run_project` is called, the server injects `McpBridge` as an autoload. This opens a UDP channel on port 9900 and enables:
|
|
14
|
+
|
|
15
|
+
- **Screenshots**: Capture the viewport at any point during gameplay
|
|
16
|
+
- **Input simulation**: Batched sequences of key presses, mouse clicks and movement, UI element clicks by name or path, Godot action presses, and timed waits
|
|
17
|
+
- **UI discovery**: Walk the live scene tree and collect every visible Control node with its position, type, text content, and disabled state
|
|
18
|
+
- **Live script execution**: Compile and execute arbitrary GDScript with full SceneTree access while the game is running
|
|
19
|
+
|
|
20
|
+
The bridge cleans itself up automatically when `stop_project` is called. No leftover autoloads, no modified project files.
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Prerequisites
|
|
25
|
+
|
|
26
|
+
- [Node.js](https://nodejs.org/) v18+
|
|
27
|
+
- [Godot 4.x](https://godotengine.org/)
|
|
28
|
+
|
|
29
|
+
### Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/Erodenn/godot-mcp-runtime.git
|
|
33
|
+
cd godot-mcp-runtime
|
|
34
|
+
npm install
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Configure Your MCP Client
|
|
39
|
+
|
|
40
|
+
Add the following to your MCP client config. This works with Claude Code, Claude Desktop, Cursor, or any MCP-compatible client:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"godot": {
|
|
46
|
+
"command": "node",
|
|
47
|
+
"args": ["<path-to>/godot-mcp-runtime/dist/index.js"],
|
|
48
|
+
"env": {
|
|
49
|
+
"GODOT_PATH": "<path-to-godot-executable>"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If Godot is on your `PATH`, you can omit `GODOT_PATH` entirely. The server will auto-detect it.
|
|
57
|
+
|
|
58
|
+
Set `"DEBUG": "true"` in `env` for verbose logging.
|
|
59
|
+
|
|
60
|
+
### Verify
|
|
61
|
+
|
|
62
|
+
Ask your AI assistant to call `get_project_info`. If it returns a Godot version string (e.g., `4.4.stable`), you're connected and working.
|
|
63
|
+
|
|
64
|
+
## Tools
|
|
65
|
+
|
|
66
|
+
### Project
|
|
67
|
+
|
|
68
|
+
| Tool | Description |
|
|
69
|
+
|------|-------------|
|
|
70
|
+
| `launch_editor` | Open the Godot editor for a project |
|
|
71
|
+
| `run_project` | Run a project and inject the MCP bridge |
|
|
72
|
+
| `stop_project` | Stop the running project and clean up the bridge |
|
|
73
|
+
| `get_debug_output` | Read stdout/stderr from the running project |
|
|
74
|
+
| `list_projects` | Find Godot projects in a directory |
|
|
75
|
+
| `get_project_info` | Get project metadata, or just the Godot version if no project path is given |
|
|
76
|
+
|
|
77
|
+
### Runtime (requires `run_project` first)
|
|
78
|
+
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `take_screenshot` | Capture a PNG of the running viewport |
|
|
82
|
+
| `simulate_input` | Batched input: key, mouse_button, mouse_motion, click_element, action, wait |
|
|
83
|
+
| `get_ui_elements` | Get visible Control nodes with positions, types, and text |
|
|
84
|
+
| `run_script` | Execute GDScript at runtime with full SceneTree access |
|
|
85
|
+
|
|
86
|
+
### Scene: `manage_scene`
|
|
87
|
+
|
|
88
|
+
| Operation | Description |
|
|
89
|
+
|-----------|-------------|
|
|
90
|
+
| `create` | Create a new scene file |
|
|
91
|
+
| `add_node` | Add a node to an existing scene |
|
|
92
|
+
| `load_sprite` | Set a texture on a Sprite2D, Sprite3D, or TextureRect |
|
|
93
|
+
| `save` | Save a scene, or save-as with `newPath` |
|
|
94
|
+
| `export_mesh_library` | Export scenes as a MeshLibrary for GridMap |
|
|
95
|
+
|
|
96
|
+
### UIDs: `manage_uids` (Godot 4.4+)
|
|
97
|
+
|
|
98
|
+
| Operation | Description |
|
|
99
|
+
|-----------|-------------|
|
|
100
|
+
| `get` | Get a resource's UID |
|
|
101
|
+
| `update` | Resave all resources to update UID references |
|
|
102
|
+
|
|
103
|
+
### Node: `manage_node`
|
|
104
|
+
|
|
105
|
+
| Operation | Description |
|
|
106
|
+
|-----------|-------------|
|
|
107
|
+
| `delete` | Remove a node from a scene |
|
|
108
|
+
| `update_property` | Set a property on a node |
|
|
109
|
+
| `get_properties` | Read node properties |
|
|
110
|
+
| `attach_script` | Attach a GDScript to a node |
|
|
111
|
+
| `list` | List child nodes |
|
|
112
|
+
| `get_tree` | Get the full scene tree hierarchy |
|
|
113
|
+
|
|
114
|
+
## Architecture
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
src/
|
|
118
|
+
├── index.ts # MCP server entry point, routes tool calls
|
|
119
|
+
├── tools/
|
|
120
|
+
│ ├── project-tools.ts # Project and runtime tool handlers
|
|
121
|
+
│ ├── scene-tools.ts # Scene operations
|
|
122
|
+
│ └── node-tools.ts # Node operations
|
|
123
|
+
├── scripts/
|
|
124
|
+
│ ├── godot_operations.gd # Headless GDScript operations
|
|
125
|
+
│ └── mcp_bridge.gd # UDP autoload for runtime communication
|
|
126
|
+
└── utils/
|
|
127
|
+
└── godot-runner.ts # Process spawning, output parsing
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Headless operations spawn Godot with `--headless --script godot_operations.gd`, perform the operation, and return JSON.
|
|
131
|
+
|
|
132
|
+
Runtime operations communicate over UDP with the injected `McpBridge` autoload in the running game.
|
|
133
|
+
|
|
134
|
+
## How the Bridge Works
|
|
135
|
+
|
|
136
|
+
When `run_project` is called:
|
|
137
|
+
|
|
138
|
+
1. `mcp_bridge.gd` is copied into the project directory
|
|
139
|
+
2. It's registered as an autoload in `project.godot`
|
|
140
|
+
3. The project launches with the bridge listening on UDP port 9900
|
|
141
|
+
4. Runtime tools send JSON commands to the bridge and await responses
|
|
142
|
+
5. When `stop_project` is called, the autoload entry and bridge script are removed
|
|
143
|
+
|
|
144
|
+
Files generated during runtime (screenshots, executed scripts) are stored in `.mcp/` inside the project directory. This directory is automatically added to `.gitignore` and has a `.gdignore` so Godot won't import it.
|
|
145
|
+
|
|
146
|
+
## Acknowledgments
|
|
147
|
+
|
|
148
|
+
Built on the foundation laid by [Coding-Solo/godot-mcp](https://github.com/Coding-Solo/godot-mcp) for headless Godot operations.
|
|
149
|
+
|
|
150
|
+
Developed with [Claude Code](https://claude.ai/code).
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
[MIT](LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Godot MCP Server
|
|
4
|
+
*
|
|
5
|
+
* This MCP server provides tools for interacting with the Godot game engine.
|
|
6
|
+
* It enables AI assistants to launch the Godot editor, run Godot projects,
|
|
7
|
+
* capture debug output, manipulate scenes and nodes, and more.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Godot MCP Server
|
|
4
|
+
*
|
|
5
|
+
* This MCP server provides tools for interacting with the Godot game engine.
|
|
6
|
+
* It enables AI assistants to launch the Godot editor, run Godot projects,
|
|
7
|
+
* capture debug output, manipulate scenes and nodes, and more.
|
|
8
|
+
*/
|
|
9
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
11
|
+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
import { GodotRunner } from './utils/godot-runner.js';
|
|
13
|
+
// Project tools
|
|
14
|
+
import { projectToolDefinitions, handleLaunchEditor, handleRunProject, handleGetDebugOutput, handleStopProject, handleListProjects, handleGetProjectInfo, handleTakeScreenshot, handleSimulateInput, handleGetUiElements, handleRunScript, } from './tools/project-tools.js';
|
|
15
|
+
// Scene tools
|
|
16
|
+
import { sceneToolDefinitions, handleManageScene, handleManageUids, } from './tools/scene-tools.js';
|
|
17
|
+
// Node tools
|
|
18
|
+
import { nodeToolDefinitions, handleManageNode, } from './tools/node-tools.js';
|
|
19
|
+
class GodotMcpServer {
|
|
20
|
+
server;
|
|
21
|
+
runner;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.runner = new GodotRunner(config);
|
|
24
|
+
this.server = new Server({
|
|
25
|
+
name: 'godot-mcp',
|
|
26
|
+
version: '0.3.0',
|
|
27
|
+
}, {
|
|
28
|
+
capabilities: {
|
|
29
|
+
tools: {},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
this.setupToolHandlers();
|
|
33
|
+
this.server.onerror = (error) => console.error('[MCP Error]', error);
|
|
34
|
+
process.on('SIGINT', async () => {
|
|
35
|
+
await this.cleanup();
|
|
36
|
+
process.exit(0);
|
|
37
|
+
});
|
|
38
|
+
process.on('SIGTERM', async () => {
|
|
39
|
+
await this.cleanup();
|
|
40
|
+
process.exit(0);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async cleanup() {
|
|
44
|
+
console.error('[SERVER] Cleaning up resources');
|
|
45
|
+
this.runner.stopProject();
|
|
46
|
+
await this.server.close();
|
|
47
|
+
}
|
|
48
|
+
setupToolHandlers() {
|
|
49
|
+
// Combine all tool definitions
|
|
50
|
+
const allTools = [
|
|
51
|
+
...projectToolDefinitions,
|
|
52
|
+
...sceneToolDefinitions,
|
|
53
|
+
...nodeToolDefinitions,
|
|
54
|
+
];
|
|
55
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
56
|
+
tools: allTools,
|
|
57
|
+
}));
|
|
58
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
59
|
+
const toolName = request.params.name;
|
|
60
|
+
const args = request.params.arguments || {};
|
|
61
|
+
console.error(`[SERVER] Handling tool request: ${toolName}`);
|
|
62
|
+
switch (toolName) {
|
|
63
|
+
// Project tools
|
|
64
|
+
case 'launch_editor':
|
|
65
|
+
return await handleLaunchEditor(this.runner, args);
|
|
66
|
+
case 'run_project':
|
|
67
|
+
return await handleRunProject(this.runner, args);
|
|
68
|
+
case 'get_debug_output':
|
|
69
|
+
return handleGetDebugOutput(this.runner, args);
|
|
70
|
+
case 'stop_project':
|
|
71
|
+
return handleStopProject(this.runner);
|
|
72
|
+
case 'list_projects':
|
|
73
|
+
return await handleListProjects(args);
|
|
74
|
+
case 'get_project_info':
|
|
75
|
+
return await handleGetProjectInfo(this.runner, args);
|
|
76
|
+
case 'take_screenshot':
|
|
77
|
+
return await handleTakeScreenshot(this.runner, args);
|
|
78
|
+
case 'simulate_input':
|
|
79
|
+
return await handleSimulateInput(this.runner, args);
|
|
80
|
+
case 'get_ui_elements':
|
|
81
|
+
return await handleGetUiElements(this.runner, args);
|
|
82
|
+
case 'run_script':
|
|
83
|
+
return await handleRunScript(this.runner, args);
|
|
84
|
+
// Scene tools
|
|
85
|
+
case 'manage_scene':
|
|
86
|
+
return await handleManageScene(this.runner, args);
|
|
87
|
+
case 'manage_uids':
|
|
88
|
+
return await handleManageUids(this.runner, args);
|
|
89
|
+
// Node tools
|
|
90
|
+
case 'manage_node':
|
|
91
|
+
return await handleManageNode(this.runner, args);
|
|
92
|
+
default:
|
|
93
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${toolName}`);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
async run() {
|
|
98
|
+
try {
|
|
99
|
+
await this.runner.detectGodotPath();
|
|
100
|
+
const godotPath = this.runner.getGodotPath();
|
|
101
|
+
if (!godotPath) {
|
|
102
|
+
console.error('[SERVER] Failed to find a valid Godot executable path');
|
|
103
|
+
console.error('[SERVER] Please set GODOT_PATH environment variable or provide a valid path');
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
console.error(`[SERVER] Using Godot at: ${godotPath}`);
|
|
107
|
+
const transport = new StdioServerTransport();
|
|
108
|
+
await this.server.connect(transport);
|
|
109
|
+
console.error('Godot MCP server running on stdio');
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
113
|
+
console.error('[SERVER] Failed to start:', errorMessage);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Create and run the server
|
|
119
|
+
const server = new GodotMcpServer();
|
|
120
|
+
server.run().catch((error) => {
|
|
121
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
122
|
+
console.error('Failed to run server:', errorMessage);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
});
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|