gopeak 2.1.0 → 2.2.1

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/README.md CHANGED
@@ -14,108 +14,221 @@
14
14
 
15
15
  **GoPeak is an MCP server for Godot that lets AI assistants run, inspect, modify, and debug real projects end-to-end.**
16
16
 
17
- > Includes Auto Reload: when MCP edits scenes/scripts, the Godot editor refreshes automatically.
17
+ ---
18
+
19
+ ## Quick Start (3 Minutes)
20
+
21
+ ### Requirements
22
+
23
+ - Godot 4.x
24
+ - Node.js 18+
25
+ - MCP-compatible client (Claude Desktop, Cursor, Cline, OpenCode, etc.)
26
+
27
+ ### 1) Run GoPeak
28
+
29
+ ```bash
30
+ npx -y gopeak
31
+ ```
32
+
33
+ or install globally:
34
+
35
+ ```bash
36
+ npm install -g gopeak
37
+ gopeak
38
+ ```
39
+
40
+ ### 2) Add MCP client config
41
+
42
+ ```json
43
+ {
44
+ "mcpServers": {
45
+ "godot": {
46
+ "command": "npx",
47
+ "args": ["-y", "gopeak"],
48
+ "env": {
49
+ "GODOT_PATH": "/path/to/godot",
50
+ "GOPEAK_TOOL_PROFILE": "compact"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ > `GOPEAK_TOOL_PROFILE=compact` is the default. It exposes 33 core tools with 22 dynamic tool groups (78 additional tools) that activate on demand — keeping token usage low while preserving full capability.
58
+
59
+ ### 3) First prompts to try
60
+
61
+ - "List Godot projects in `/your/projects` and show project info."
62
+ - "Create `scenes/Player.tscn` with `CharacterBody2D` root and add a movement script."
63
+ - "Run project, get debug output, then fix top error."
18
64
 
19
65
  ---
20
66
 
21
- ## Why GoPeak (Short Version)
67
+ ## Why GoPeak
22
68
 
23
- - **Real project feedback loop**: run the game, read logs, fix issues in-context.
24
- - **95+ tools** across scene, script, resource, runtime, LSP, DAP, input, and assets.
25
- - **Deep Godot integration**: ClassDB introspection, runtime inspection, debugger hooks.
26
- - **Faster iteration**: less copy-paste, more direct implementation/testing.
69
+ - **Real project feedback loop**: run the game, inspect logs, and fix in-context.
70
+ - **110+ tools available** across scene/script/resource/runtime/LSP/DAP/input/assets.
71
+ - **Token-efficient by default**: compact tool surface (33 tools) + dynamic tool groups. Only activate what you need — no more 110-tool context bombs.
72
+ - **Dynamic tool groups**: search with `tool.catalog` and matching groups auto-activate. Or manually activate with `tool.groups`.
73
+ - **Deep Godot integration**: ClassDB queries, runtime inspection, debugger hooks, bridge-based scene/resource edits.
27
74
 
28
75
  ### Best For
29
76
 
30
- - Solo/indie developers building quickly with AI assistance
31
- - Teams that want AI to inspect real project state, not just generate snippets
32
- - Debug-heavy workflows where runtime introspection and breakpoints matter
77
+ - Solo/indie developers moving quickly with AI assistance
78
+ - Teams that need AI grounded in actual project/runtime state
79
+ - Debug-heavy workflows (breakpoints, stack traces, live runtime checks)
33
80
 
34
81
  ---
35
82
 
36
- ## GoPeak vs Upstream (Coding-Solo/godot-mcp)
83
+ ## Tool Surface Model (Important)
37
84
 
38
- | Capability | Upstream | GoPeak |
39
- |---|---|---|
40
- | GDScript LSP tools | Not available in README tool list | ✅ `lsp_get_diagnostics`, `lsp_get_completions`, `lsp_get_hover`, `lsp_get_symbols` |
41
- | DAP debugging tools | Not available in README tool list | ✅ breakpoints, step/continue/pause, stack trace, debug output |
42
- | Input injection tools | Not available in README tool list | ✅ `inject_action`, `inject_key`, `inject_mouse_click`, `inject_mouse_motion` |
43
- | Screenshot capture tools | Not available in README tool list | ✅ `capture_screenshot`, `capture_viewport` |
44
- | Auto Reload editor plugin | Not available | ✅ included `auto_reload` addon |
45
- | Tool coverage scale | Smaller documented scope | ✅ 95+ MCP tools |
85
+ GoPeak supports three exposure profiles:
46
86
 
47
- ---
87
+ - `compact` (default): 33 core tools + **22 dynamic tool groups** (78 additional tools activated on demand)
88
+ - `full`: exposes full legacy tool list (110+)
89
+ - `legacy`: same exposed behavior as `full`
48
90
 
49
- ## Requirements
91
+ Configure with either:
50
92
 
51
- - Godot 4.x
52
- - Node.js 18+
53
- - MCP-compatible client (Claude Desktop, Cursor, Cline, OpenCode, etc.)
93
+ - `GOPEAK_TOOL_PROFILE`
94
+ - `MCP_TOOL_PROFILE` (fallback alias)
95
+
96
+ ### Dynamic Tool Groups (compact mode)
97
+
98
+ In `compact` mode, 78 additional tools are organized into **22 groups** that activate automatically when needed:
99
+
100
+ | Group | Tools | Description |
101
+ |---|---|---|
102
+ | `scene_advanced` | 3 | Duplicate, reparent nodes, load sprites |
103
+ | `uid` | 2 | UID management for resources |
104
+ | `import_export` | 5 | Import pipeline, reimport, validate project |
105
+ | `autoload` | 4 | Autoload singletons, main scene |
106
+ | `signal` | 2 | Disconnect signals, list connections |
107
+ | `runtime` | 4 | Live scene inspection, runtime properties, metrics |
108
+ | `resource` | 4 | Create/modify materials, shaders, resources |
109
+ | `animation` | 5 | Animations, tracks, animation tree, state machine |
110
+ | `plugin` | 3 | Enable/disable/list editor plugins |
111
+ | `input` | 1 | Input action mapping |
112
+ | `tilemap` | 2 | TileSet and TileMap cell painting |
113
+ | `audio` | 4 | Audio buses, effects, volume |
114
+ | `navigation` | 2 | Navigation regions and agents |
115
+ | `theme_ui` | 3 | Theme colors, font sizes, shaders |
116
+ | `asset_store` | 3 | Search/download CC0 assets |
117
+ | `testing` | 6 | Screenshots, viewport capture, input injection |
118
+ | `dx_tools` | 4 | Error log, project health, find usages, scaffold |
119
+ | `intent_tracking` | 9 | Intent capture, decision logs, handoff briefs |
120
+ | `class_advanced` | 1 | Class inheritance inspection |
121
+ | `lsp` | 3 | GDScript completions, hover, symbols |
122
+ | `dap` | 6 | Breakpoints, stepping, stack traces |
123
+ | `version_gate` | 2 | Version validation, patch verification |
124
+
125
+ **How it works:**
126
+
127
+ 1. **Auto-activation via catalog**: Search with `tool.catalog` and matching groups activate automatically.
128
+ > "Use `tool.catalog` with query `animation` and show relevant tools."
129
+
130
+ 2. **Manual activation**: Directly activate a group with `tool.groups`.
131
+ > "Use `tool.groups` to activate the `dap` group for debugging."
132
+
133
+ 3. **Deactivation**: Remove groups when done to reduce context.
134
+ > "Use `tool.groups` to reset all active groups."
135
+
136
+ The server sends `notifications/tools/list_changed` so MCP clients (Claude Code, Claude Desktop) automatically refresh the tool list.
137
+
138
+ ### Don't worry about tokens
139
+
140
+ GoPeak uses **cursor-based pagination** for `tools/list` — even in `full` profile, tools are delivered in pages (default 33) instead of dumping all 110+ definitions at once. Your AI client fetches the next page only when it needs more.
141
+
142
+ Set page size with `GOPEAK_TOOLS_PAGE_SIZE`:
143
+
144
+ ```json
145
+ {
146
+ "env": {
147
+ "GOPEAK_TOOLS_PAGE_SIZE": "25"
148
+ }
149
+ }
150
+ ```
54
151
 
55
152
  ---
56
153
 
57
- ## Installation
154
+ ## Installation Options
58
155
 
59
- ### 1) Fastest (recommended)
156
+ ### A) Recommended: npx
60
157
 
61
158
  ```bash
62
- npx gopeak
159
+ npx -y gopeak
63
160
  ```
64
161
 
65
- or
162
+ ### B) Global install
66
163
 
67
164
  ```bash
68
165
  npm install -g gopeak
69
166
  gopeak
70
167
  ```
71
168
 
72
- ### 2) Manual (from source)
169
+ ### C) From source
73
170
 
74
171
  ```bash
75
172
  git clone https://github.com/HaD0Yun/godot-mcp.git
76
173
  cd godot-mcp
77
174
  npm install
78
175
  npm run build
176
+ node build/index.js
79
177
  ```
80
178
 
81
- Set `GODOT_PATH` if Godot is not auto-detected.
179
+ GoPeak also exposes two CLI bin names:
82
180
 
83
- ### MCP Client Config (practical examples)
181
+ - `gopeak`
182
+ - `godot-mcp`
84
183
 
85
- Use one of these depending on your client.
184
+ ---
86
185
 
87
- **A) Global install (`npm install -g gopeak`)**
186
+ ## CI
88
187
 
89
- ```json
90
- {
91
- "mcpServers": {
92
- "godot": {
93
- "command": "gopeak",
94
- "env": {
95
- "GODOT_PATH": "/path/to/godot"
96
- }
97
- }
98
- }
99
- }
188
+ GitHub Actions runs on push/PR and executes:
189
+
190
+ 1. `npm run build`
191
+ 2. `npx tsc --noEmit`
192
+ 3. `npm run test:ci`
193
+
194
+ Run the same checks locally:
195
+
196
+ ```bash
197
+ npm run ci
100
198
  ```
101
199
 
102
- **B) No global install (npx mode)**
200
+ ---
103
201
 
104
- ```json
105
- {
106
- "mcpServers": {
107
- "godot": {
108
- "command": "npx",
109
- "args": ["-y", "gopeak"],
110
- "env": {
111
- "GODOT_PATH": "/path/to/godot"
112
- }
113
- }
114
- }
115
- }
202
+ ## Versioning & Release
203
+
204
+ Use the built-in bump script to keep `package.json` and `server.json` in sync:
205
+
206
+ ```bash
207
+ node scripts/bump-version.mjs patch
208
+ node scripts/bump-version.mjs minor --dry-run
116
209
  ```
117
210
 
118
- > Tip: If your client uses `args` array style only, use `"command": "npx"` + `"args": ["-y", "gopeak"]`.
211
+ Full release checklist: [`docs/release-process.md`](docs/release-process.md).
212
+
213
+ ---
214
+
215
+ ## Addons (Recommended)
216
+
217
+ ### Auto Reload + Editor Bridge + Runtime Addon installer
218
+
219
+ Install in your Godot project folder:
220
+
221
+ ```bash
222
+ curl -sL https://raw.githubusercontent.com/HaD0Yun/godot-mcp/main/install-addon.sh | bash
223
+ ```
224
+
225
+ PowerShell:
226
+
227
+ ```powershell
228
+ iwr https://raw.githubusercontent.com/HaD0Yun/godot-mcp/main/install-addon.ps1 -UseBasicParsing | iex
229
+ ```
230
+
231
+ Then enable plugins in **Project Settings → Plugins** (especially `godot_mcp_editor` for bridge-backed scene/resource tools).
119
232
 
120
233
  ---
121
234
 
@@ -131,18 +244,27 @@ Use one of these depending on your client.
131
244
  - **Input + screenshots**: keyboard/mouse/action injection and viewport capture
132
245
  - **Asset library**: search/fetch CC0 assets (Poly Haven, AmbientCG, Kenney)
133
246
 
134
- ### Tool Coverage at a Glance
247
+ ### Tool families (examples)
135
248
 
136
249
  | Area | Examples |
137
250
  |---|---|
138
- | Scene/Node | `create_scene`, `add_node`, `set_node_properties` |
139
- | Script | `create_script`, `modify_script`, `get_script_info` |
140
- | Runtime | `inspect_runtime_tree`, `call_runtime_method` |
141
- | LSP/DAP | `lsp_get_diagnostics`, `dap_set_breakpoint` |
251
+ | Project | `project.list`, `project.info`, `editor.run` |
252
+ | Scene/Node | `scene.create`, `scene.node.add`, `set_node_properties` |
253
+ | Script | `script.create`, `script.modify`, `script.info` |
254
+ | Runtime | `runtime.status`, `inspect_runtime_tree`, `call_runtime_method` |
255
+ | LSP/DAP | `lsp.diagnostics`, `lsp_get_hover`, `dap_set_breakpoint`, `dap.output` |
142
256
  | Input/Visual | `inject_key`, `inject_mouse_click`, `capture_screenshot` |
143
257
 
144
258
  ---
145
259
 
260
+ ## Project Visualizer
261
+
262
+ Visualize your entire project architecture with `visualizer.map` (`map_project` legacy). Scripts are grouped by folder structure into color-coded categories.
263
+
264
+ ![Project Visualizer — AI-generated architecture map](assets/visualizer-category-map.png)
265
+
266
+ ---
267
+
146
268
  ## Quick Prompt Examples
147
269
 
148
270
  ### Build
@@ -151,27 +273,50 @@ Use one of these depending on your client.
151
273
 
152
274
  ### Debug
153
275
  - "Run the project, collect errors, and fix the top 3 issues automatically."
154
- - "Set a breakpoint at `scripts/player.gd:42`, continue execution, and show the stack trace when hit."
276
+ - "Set a breakpoint at `scripts/player.gd:42`, continue execution, and show stack trace when hit."
155
277
 
156
- ### Runtime Testing
278
+ ### Runtime testing
157
279
  - "Press `ui_accept`, move mouse to (400, 300), click, then capture a screenshot."
158
- - "Inspect the live scene tree and report nodes with missing scripts or invalid references."
280
+ - "Inspect live scene tree and report nodes with missing scripts or invalid references."
159
281
 
160
- ### Refactor / Maintenance
161
- - "Find all TODO/FIXME comments and group them by file with a priority suggestion."
162
- - "Analyze project health and list quick wins to improve stability before release."
282
+ ### Discovery & dynamic groups
283
+ - "Use `tool.catalog` with query `tilemap` and list the most relevant tools."
284
+ - "Activate the `dap` tool group for breakpoint debugging with `tool.groups`."
285
+ - "Find import pipeline tools with `tool.catalog` query `import` and run the best one for texture settings."
286
+ - "Reset all active tool groups with `tool.groups` to reduce context."
163
287
 
164
288
  ---
165
289
 
166
- ## Auto Reload Addon (Recommended)
290
+ ## Technical Reference
167
291
 
168
- Install in your Godot project folder:
292
+ ### Environment variables
169
293
 
170
- ```bash
171
- curl -sL https://raw.githubusercontent.com/HaD0Yun/godot-mcp/main/install-addon.sh | bash
172
- ```
294
+ | Name | Purpose | Default |
295
+ |---|---|---|
296
+ | `GOPEAK_TOOL_PROFILE` | Tool exposure profile: `compact`, `full`, `legacy` | `compact` |
297
+ | `MCP_TOOL_PROFILE` | Fallback profile env alias | `compact` |
298
+ | `GODOT_PATH` | Explicit Godot executable path | auto-detect |
299
+ | `GODOT_BRIDGE_PORT` | Bridge/Visualizer HTTP+WS port override (aliases: `MCP_BRIDGE_PORT`, `GOPEAK_BRIDGE_PORT`) | `6505` |
300
+ | `DEBUG` | Enable server debug logs (`true`/`false`) | `false` |
301
+ | `LOG_MODE` | Recording mode: `lite` or `full` | `lite` |
302
+ | `GOPEAK_TOOLS_PAGE_SIZE` | Number of tools per `tools/list` page (pagination) | `33` |
303
+ | `GOPEAK_BRIDGE_PORT` | Port for unified bridge/visualizer server | `6505` |
304
+ | `GOPEAK_BRIDGE_HOST` | Bind host for bridge/visualizer server | `127.0.0.1` |
305
+
306
+ ### Ports
307
+
308
+ | Port | Service |
309
+ |---|---|
310
+ | `6505` (default) | Unified Godot Bridge + Visualizer server (+ `/health`, `/mcp`) on loopback by default |
311
+ | `6005` | Godot LSP |
312
+ | `6006` | Godot DAP |
313
+ | `7777` | Runtime addon command socket (only needed for runtime tools) |
314
+
315
+ ### Minimal port profiles
173
316
 
174
- Then enable plugin in **Project Settings Plugins**.
317
+ - **Core editing only**: bridge port (`GODOT_BRIDGE_PORT`, default `6505`)
318
+ - **Core + runtime actions (screenshots/input/runtime inspect)**: bridge port + `7777`
319
+ - **Full debugging + diagnostics**: bridge port + `6005` + `6006` + `7777`
175
320
 
176
321
  ---
177
322
 
@@ -180,12 +325,15 @@ Then enable plugin in **Project Settings → Plugins**.
180
325
  - **Godot not found** → set `GODOT_PATH`
181
326
  - **No MCP tools visible** → restart your MCP client
182
327
  - **Project path invalid** → confirm `project.godot` exists
183
- - **Runtime tools not working** → install/enable runtime addon
328
+ - **Runtime tools not working** → install/enable runtime addon plugin
329
+ - **Need a tool that is not visible** → run `tool.catalog` to search and auto-activate matching groups, or use `tool.groups` to activate a specific group
184
330
 
185
331
  ---
186
332
 
187
333
  ## Docs & Project Links
188
334
 
335
+ - [Architecture (MCP Platform Direction)](docs/architecture.md)
336
+ - [Platform Roadmap (P1/P2/P3)](docs/platform-roadmap.md)
189
337
  - [CHANGELOG](CHANGELOG.md)
190
338
  - [ROADMAP](ROADMAP.md)
191
339
  - [CONTRIBUTING](CONTRIBUTING.md)
@@ -200,3 +348,4 @@ MIT — see [LICENSE](LICENSE).
200
348
 
201
349
  - Original MCP server by [Coding-Solo](https://github.com/Coding-Solo/godot-mcp)
202
350
  - GoPeak enhancements by [HaD0Yun](https://github.com/HaD0Yun)
351
+ - Project visualizer inspired by [tomyud1/godot-mcp](https://github.com/tomyud1/godot-mcp)
@@ -0,0 +1,178 @@
1
+ @tool
2
+ extends Node
3
+ class_name MCPEditorClient
4
+
5
+ signal connected
6
+ signal disconnected
7
+ signal tool_requested(request_id: String, tool_name: String, args: Dictionary)
8
+
9
+ const DEFAULT_URL := "ws://127.0.0.1:6505/godot"
10
+ const RECONNECT_DELAY := 3.0
11
+ const MAX_RECONNECT_DELAY := 30.0
12
+
13
+ var socket: WebSocketPeer = WebSocketPeer.new()
14
+ var server_url: String = DEFAULT_URL
15
+ var _is_connected := false
16
+ var _reconnect_timer: Timer
17
+ var _current_reconnect_delay := RECONNECT_DELAY
18
+ var _should_reconnect := true
19
+ var _project_path: String
20
+ var _initialized := false
21
+
22
+
23
+ func _ready() -> void:
24
+ _project_path = ProjectSettings.globalize_path("res://")
25
+
26
+ _reconnect_timer = Timer.new()
27
+ _reconnect_timer.one_shot = true
28
+ _reconnect_timer.timeout.connect(_on_reconnect_timer)
29
+ add_child(_reconnect_timer)
30
+
31
+ set_process(true)
32
+ _initialized = true
33
+
34
+
35
+ func _process(_delta: float) -> void:
36
+ if not _initialized:
37
+ return
38
+
39
+ if socket.get_ready_state() == WebSocketPeer.STATE_CLOSED:
40
+ if _is_connected:
41
+ _handle_disconnect()
42
+ return
43
+
44
+ socket.poll()
45
+
46
+ match socket.get_ready_state():
47
+ WebSocketPeer.STATE_OPEN:
48
+ if not _is_connected:
49
+ _handle_connect()
50
+
51
+ while socket.get_available_packet_count() > 0:
52
+ var packet := socket.get_packet()
53
+ _handle_message(packet.get_string_from_utf8())
54
+
55
+ WebSocketPeer.STATE_CLOSING:
56
+ pass
57
+
58
+ WebSocketPeer.STATE_CLOSED:
59
+ if _is_connected:
60
+ _handle_disconnect()
61
+
62
+
63
+ func connect_to_server(url: String = "") -> void:
64
+ server_url = _resolve_server_url(url)
65
+ _should_reconnect = true
66
+ _current_reconnect_delay = RECONNECT_DELAY
67
+ _attempt_connection()
68
+
69
+
70
+ func _resolve_server_url(explicit_url: String) -> String:
71
+ if explicit_url != "":
72
+ return explicit_url
73
+
74
+ var env_keys := ["GODOT_BRIDGE_PORT", "MCP_BRIDGE_PORT", "GOPEAK_BRIDGE_PORT"]
75
+ for key in env_keys:
76
+ var raw := OS.get_environment(key)
77
+ if raw == "":
78
+ continue
79
+ if raw.is_valid_int():
80
+ var port := int(raw)
81
+ if port >= 1 and port <= 65535:
82
+ return "ws://127.0.0.1:%d/godot" % port
83
+
84
+ return DEFAULT_URL
85
+
86
+
87
+ func disconnect_from_server() -> void:
88
+ _should_reconnect = false
89
+ if _reconnect_timer:
90
+ _reconnect_timer.stop()
91
+ if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
92
+ socket.close()
93
+ _is_connected = false
94
+
95
+
96
+ func _attempt_connection() -> void:
97
+ if socket.get_ready_state() != WebSocketPeer.STATE_CLOSED:
98
+ socket.close()
99
+
100
+ var err := socket.connect_to_url(server_url)
101
+ if err != OK:
102
+ push_error("[MCP Editor] Failed to connect: %s" % err)
103
+ _schedule_reconnect()
104
+
105
+
106
+ func _handle_connect() -> void:
107
+ _is_connected = true
108
+ _current_reconnect_delay = RECONNECT_DELAY
109
+
110
+ _send_message({
111
+ "type": "godot_ready",
112
+ "project_path": _project_path
113
+ })
114
+
115
+ connected.emit()
116
+
117
+
118
+ func _handle_disconnect() -> void:
119
+ _is_connected = false
120
+ disconnected.emit()
121
+
122
+ if _should_reconnect:
123
+ _schedule_reconnect()
124
+
125
+
126
+ func _schedule_reconnect() -> void:
127
+ if _reconnect_timer == null:
128
+ return
129
+ _reconnect_timer.start(_current_reconnect_delay)
130
+ _current_reconnect_delay = min(_current_reconnect_delay * 2.0, MAX_RECONNECT_DELAY)
131
+
132
+
133
+ func _on_reconnect_timer() -> void:
134
+ _attempt_connection()
135
+
136
+
137
+ func _handle_message(json_string: String) -> void:
138
+ var message = JSON.parse_string(json_string)
139
+ if message == null:
140
+ push_error("[MCP Editor] Failed to parse message: %s" % json_string)
141
+ return
142
+
143
+ match message.get("type", ""):
144
+ "ping":
145
+ _send_message({"type": "pong"})
146
+
147
+ "tool_invoke":
148
+ var request_id: String = message.get("id", "")
149
+ var tool_name: String = message.get("tool", "")
150
+ var args: Dictionary = message.get("args", {})
151
+ tool_requested.emit(request_id, tool_name, args)
152
+
153
+ _:
154
+ pass
155
+
156
+
157
+ func send_tool_result(request_id: String, success: bool, result = null, error: String = "") -> void:
158
+ var response := {
159
+ "type": "tool_result",
160
+ "id": request_id,
161
+ "success": success
162
+ }
163
+
164
+ if success:
165
+ response["result"] = result
166
+ else:
167
+ response["error"] = error
168
+
169
+ _send_message(response)
170
+
171
+
172
+ func _send_message(message: Dictionary) -> void:
173
+ if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
174
+ socket.send_text(JSON.stringify(message))
175
+
176
+
177
+ func is_connected_to_server() -> bool:
178
+ return _is_connected
@@ -0,0 +1,6 @@
1
+ [plugin]
2
+ name="Godot MCP Editor"
3
+ description="MCP Editor Plugin - Scene manipulation via Godot API"
4
+ author="HaD0Yun"
5
+ version="1.0.0"
6
+ script="plugin.gd"
@@ -0,0 +1,84 @@
1
+ @tool
2
+ extends EditorPlugin
3
+
4
+ const MCPEditorClientScript = preload("mcp_client.gd")
5
+ const MCPToolExecutorScript = preload("tool_executor.gd")
6
+
7
+ var _mcp_client: Node
8
+ var _tool_executor: Node
9
+ var _status_label: Label
10
+
11
+
12
+ func _enter_tree() -> void:
13
+ _mcp_client = MCPEditorClientScript.new()
14
+ _mcp_client.name = "MCPEditorClient"
15
+ add_child(_mcp_client)
16
+
17
+ _tool_executor = MCPToolExecutorScript.new()
18
+ _tool_executor.name = "MCPToolExecutor"
19
+ add_child(_tool_executor)
20
+ _tool_executor.set_editor_plugin(self)
21
+
22
+ _mcp_client.connected.connect(_on_connected)
23
+ _mcp_client.disconnected.connect(_on_disconnected)
24
+ _mcp_client.tool_requested.connect(_on_tool_requested)
25
+
26
+ _setup_status_indicator()
27
+ _mcp_client.connect_to_server()
28
+
29
+
30
+ func _exit_tree() -> void:
31
+ if _mcp_client:
32
+ if _mcp_client.connected.is_connected(_on_connected):
33
+ _mcp_client.connected.disconnect(_on_connected)
34
+ if _mcp_client.disconnected.is_connected(_on_disconnected):
35
+ _mcp_client.disconnected.disconnect(_on_disconnected)
36
+ if _mcp_client.tool_requested.is_connected(_on_tool_requested):
37
+ _mcp_client.tool_requested.disconnect(_on_tool_requested)
38
+ _mcp_client.disconnect_from_server()
39
+ _mcp_client.queue_free()
40
+ _mcp_client = null
41
+
42
+ if _tool_executor:
43
+ _tool_executor.queue_free()
44
+ _tool_executor = null
45
+
46
+ if _status_label:
47
+ remove_control_from_container(CONTAINER_TOOLBAR, _status_label)
48
+ _status_label.queue_free()
49
+ _status_label = null
50
+
51
+
52
+ func _setup_status_indicator() -> void:
53
+ _status_label = Label.new()
54
+ _status_label.text = "MCP: Connecting..."
55
+ _status_label.add_theme_color_override("font_color", Color.YELLOW)
56
+ _status_label.add_theme_font_size_override("font_size", 12)
57
+ add_control_to_container(CONTAINER_TOOLBAR, _status_label)
58
+
59
+
60
+ func _on_connected() -> void:
61
+ if _status_label:
62
+ _status_label.text = "MCP: Connected"
63
+ _status_label.add_theme_color_override("font_color", Color.GREEN)
64
+
65
+
66
+ func _on_disconnected() -> void:
67
+ if _status_label:
68
+ _status_label.text = "MCP: Disconnected"
69
+ _status_label.add_theme_color_override("font_color", Color.RED)
70
+
71
+
72
+ func _on_tool_requested(request_id: String, tool_name: String, args: Dictionary) -> void:
73
+ if _tool_executor == null or _mcp_client == null:
74
+ return
75
+
76
+ var result: Dictionary = _tool_executor.execute_tool(tool_name, args)
77
+ var success: bool = result.get("ok", false)
78
+
79
+ if success:
80
+ var payload := result.duplicate(true)
81
+ payload.erase("ok")
82
+ _mcp_client.send_tool_result(request_id, true, payload, "")
83
+ else:
84
+ _mcp_client.send_tool_result(request_id, false, null, str(result.get("error", "Unknown error")))