breakpoint-mcp 1.27.0 → 1.27.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.
|
@@ -7,7 +7,7 @@ extends RefCounted
|
|
|
7
7
|
## wrapped in the EditorUndoRedoManager so a human can Ctrl-Z anything the assistant did.
|
|
8
8
|
|
|
9
9
|
const Codec := preload("res://addons/breakpoint_mcp/variant_json.gd")
|
|
10
|
-
const ADDON_VERSION := "1.9.
|
|
10
|
+
const ADDON_VERSION := "1.9.2"
|
|
11
11
|
|
|
12
12
|
var _plugin: EditorPlugin
|
|
13
13
|
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
name="Breakpoint MCP"
|
|
4
4
|
description="Exposes the live Godot editor and the running game to an MCP host so an AI assistant can drive them: scene/node/resource CRUD with full undo/redo, project settings, ClassDB, editor + in-game screenshots, and an in-game runtime bridge (live SceneTree, property get/set, method calls, signals, input injection, Performance monitors). Pairs with the breakpoint-mcp MCP host."
|
|
5
5
|
author="James Livingston"
|
|
6
|
-
version="1.9.
|
|
6
|
+
version="1.9.2"
|
|
7
7
|
script="plugin.gd"
|
|
@@ -80,6 +80,7 @@ var _copy_feedback: Label = null
|
|
|
80
80
|
var _timer: Timer = null
|
|
81
81
|
var _pause_toggle: CheckButton = null
|
|
82
82
|
var _pause_state: Label = null
|
|
83
|
+
var _body: VBoxContainer = null # every Control child lives in here (see _build_ui)
|
|
83
84
|
|
|
84
85
|
|
|
85
86
|
## plugin.gd injects the live bridge server so the editor-bridge plane is read
|
|
@@ -111,32 +112,52 @@ func _exit_tree() -> void:
|
|
|
111
112
|
|
|
112
113
|
func _build_ui() -> void:
|
|
113
114
|
name = "Breakpoint"
|
|
114
|
-
|
|
115
|
+
|
|
116
|
+
# #124: a dock slot cannot scroll and cannot be shrunk past its content, so a
|
|
117
|
+
# tall dock is not clipped — it raises the MINIMUM size of the whole editor
|
|
118
|
+
# layout, which the editor can only satisfy by pushing the bottom panel and
|
|
119
|
+
# the lower docks out of the window. A Label with autowrap reports a minimum
|
|
120
|
+
# height measured at its NARROWEST width, a VBoxContainer sums those, and this
|
|
121
|
+
# dock demanded 311x4015 px against ~208x125 for every built-in dock. Putting
|
|
122
|
+
# every Control inside a ScrollContainer decouples the dock's minimum height
|
|
123
|
+
# from its content height, which is what EditorInspector does for the same
|
|
124
|
+
# reason. Verify with get_combined_minimum_size(), not by eye.
|
|
125
|
+
var scroll := ScrollContainer.new()
|
|
126
|
+
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
|
127
|
+
scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO
|
|
128
|
+
scroll.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
129
|
+
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
|
130
|
+
add_child(scroll)
|
|
131
|
+
|
|
132
|
+
_body = VBoxContainer.new()
|
|
133
|
+
_body.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
134
|
+
_body.add_theme_constant_override("separation", 6)
|
|
135
|
+
scroll.add_child(_body)
|
|
115
136
|
|
|
116
137
|
var header := Label.new()
|
|
117
138
|
header.text = "Breakpoint MCP"
|
|
118
139
|
header.add_theme_font_size_override("font_size", 15)
|
|
119
|
-
add_child(header)
|
|
140
|
+
_body.add_child(header)
|
|
120
141
|
|
|
121
142
|
var sub := Label.new()
|
|
122
143
|
sub.text = "bridge status · ports · client setup"
|
|
123
144
|
sub.modulate = Color(1, 1, 1, 0.6)
|
|
124
|
-
add_child(sub)
|
|
145
|
+
_body.add_child(sub)
|
|
125
146
|
|
|
126
|
-
add_child(HSeparator.new())
|
|
147
|
+
_body.add_child(HSeparator.new())
|
|
127
148
|
|
|
128
149
|
var bridges_hdr := Label.new()
|
|
129
150
|
bridges_hdr.text = "Bridges"
|
|
130
151
|
bridges_hdr.modulate = Color(1, 1, 1, 0.75)
|
|
131
|
-
add_child(bridges_hdr)
|
|
152
|
+
_body.add_child(bridges_hdr)
|
|
132
153
|
|
|
133
154
|
for p in PLANES:
|
|
134
155
|
var row := Label.new()
|
|
135
156
|
row.add_theme_font_size_override("font_size", 13)
|
|
136
157
|
_rows[p["key"]] = row
|
|
137
|
-
add_child(row)
|
|
158
|
+
_body.add_child(row)
|
|
138
159
|
_set_plane(p["key"], "pending", "…")
|
|
139
|
-
add_child(HSeparator.new())
|
|
160
|
+
_body.add_child(HSeparator.new())
|
|
140
161
|
|
|
141
162
|
# Control: a one-click "Pause Agent" latch honored by the editor + runtime
|
|
142
163
|
# bridges (pause_latch.gd). Engaged, those two planes hold new agent commands
|
|
@@ -144,55 +165,66 @@ func _build_ui() -> void:
|
|
|
144
165
|
var ctrl_hdr := Label.new()
|
|
145
166
|
ctrl_hdr.text = "Control"
|
|
146
167
|
ctrl_hdr.modulate = Color(1, 1, 1, 0.75)
|
|
147
|
-
add_child(ctrl_hdr)
|
|
168
|
+
_body.add_child(ctrl_hdr)
|
|
148
169
|
|
|
149
170
|
_pause_toggle = CheckButton.new()
|
|
150
171
|
_pause_toggle.text = "Pause Agent"
|
|
151
172
|
_pause_toggle.tooltip_text = "Hold new agent commands on the editor + runtime bridges. In-flight ops finish and a bare ping still answers; resume to continue."
|
|
152
173
|
_pause_toggle.toggled.connect(_on_pause_toggled)
|
|
153
|
-
add_child(_pause_toggle)
|
|
174
|
+
_body.add_child(_pause_toggle)
|
|
154
175
|
|
|
155
176
|
_pause_state = Label.new()
|
|
156
177
|
_pause_state.add_theme_font_size_override("font_size", 12)
|
|
157
178
|
_pause_state.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
158
|
-
add_child(_pause_state)
|
|
179
|
+
_body.add_child(_pause_state)
|
|
159
180
|
|
|
160
|
-
add_child(HSeparator.new())
|
|
181
|
+
_body.add_child(HSeparator.new())
|
|
161
182
|
|
|
162
183
|
var cfg_hdr := Label.new()
|
|
163
184
|
cfg_hdr.text = "Config"
|
|
164
185
|
cfg_hdr.modulate = Color(1, 1, 1, 0.75)
|
|
165
|
-
add_child(cfg_hdr)
|
|
186
|
+
_body.add_child(cfg_hdr)
|
|
166
187
|
|
|
167
188
|
_config_label = Label.new()
|
|
168
189
|
_config_label.add_theme_font_size_override("font_size", 12)
|
|
169
190
|
_config_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
170
|
-
add_child(_config_label)
|
|
191
|
+
_body.add_child(_config_label)
|
|
171
192
|
|
|
172
|
-
add_child(HSeparator.new())
|
|
193
|
+
_body.add_child(HSeparator.new())
|
|
173
194
|
|
|
174
195
|
var copy_btn := Button.new()
|
|
175
196
|
copy_btn.text = "Copy MCP-client config"
|
|
176
197
|
copy_btn.tooltip_text = "Copy the mcpServers snippet for this project to the clipboard."
|
|
177
198
|
copy_btn.pressed.connect(_on_copy_pressed)
|
|
178
|
-
add_child(copy_btn)
|
|
199
|
+
_body.add_child(copy_btn)
|
|
179
200
|
|
|
180
201
|
var refresh_btn := Button.new()
|
|
181
202
|
refresh_btn.text = "Refresh"
|
|
182
203
|
refresh_btn.pressed.connect(_refresh)
|
|
183
|
-
add_child(refresh_btn)
|
|
204
|
+
_body.add_child(refresh_btn)
|
|
184
205
|
|
|
185
206
|
_copy_feedback = Label.new()
|
|
186
207
|
_copy_feedback.add_theme_font_size_override("font_size", 12)
|
|
187
208
|
_copy_feedback.modulate = Color(1, 1, 1, 0.7)
|
|
188
209
|
_copy_feedback.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
189
|
-
add_child(_copy_feedback)
|
|
210
|
+
_body.add_child(_copy_feedback)
|
|
190
211
|
|
|
191
212
|
var foot := Label.new()
|
|
192
213
|
foot.text = "Status/config only — the assistant runs in your MCP client, not here."
|
|
193
214
|
foot.modulate = Color(1, 1, 1, 0.5)
|
|
194
215
|
foot.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
195
|
-
add_child(foot)
|
|
216
|
+
_body.add_child(foot)
|
|
217
|
+
|
|
218
|
+
# The height half of #124 is the ScrollContainer above; this is the width half.
|
|
219
|
+
# A non-wrapping Label reports its FULL text width as a minimum, so one long
|
|
220
|
+
# status line (311 px) forced the dock wider than a default dock slot (280 px).
|
|
221
|
+
# Trimming with an ellipsis lets the dock shrink; _set_plane keeps the whole
|
|
222
|
+
# line reachable as a tooltip. Applies to every such Label, including any
|
|
223
|
+
# added later.
|
|
224
|
+
for child in _body.get_children():
|
|
225
|
+
var lbl := child as Label
|
|
226
|
+
if lbl != null and lbl.autowrap_mode == TextServer.AUTOWRAP_OFF:
|
|
227
|
+
lbl.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
|
196
228
|
|
|
197
229
|
|
|
198
230
|
func _display_name(key: String) -> String:
|
|
@@ -207,6 +239,7 @@ func _set_plane(key: String, status: String, detail: String) -> void:
|
|
|
207
239
|
if row == null:
|
|
208
240
|
return
|
|
209
241
|
row.text = plane_line(_display_name(key), status, detail)
|
|
242
|
+
row.tooltip_text = row.text # the row trims with an ellipsis (see _build_ui)
|
|
210
243
|
var col := COLOR_PENDING
|
|
211
244
|
if status == "ok":
|
|
212
245
|
col = COLOR_OK
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ async function main() {
|
|
|
41
41
|
// so long jobs (export/import/headless script) support poll/await/cancel.
|
|
42
42
|
// D3: also advertise resources.subscribe so clients can subscribe to
|
|
43
43
|
// godot://… resources and receive notifications/resources/updated.
|
|
44
|
-
const server = new McpServer({ name: "breakpoint-mcp", version: "1.27.
|
|
44
|
+
const server = new McpServer({ name: "breakpoint-mcp", version: "1.27.1" }, { capabilities: { ...TASK_CAPABILITIES, ...RESOURCE_CAPABILITIES }, taskStore });
|
|
45
45
|
// B1: enforce frozen output schemas on every structured tool. Must run before
|
|
46
46
|
// any register*Tools call — it wraps server.registerTool.
|
|
47
47
|
applyOutputSchemas(server);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "breakpoint-mcp",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.1",
|
|
4
4
|
"description": "MCP server exposing Godot to AI coding assistants over the Model Context Protocol — developed and tested with Claude — across four planes (CLI, live editor, LSP+DAP, runtime) with elicitation-gated destructive tools, long jobs on the formal MCP task model, captured console output, and MCP resources.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|