@baixfeng/godot-mcp-cli 1.0.11

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.
Files changed (115) hide show
  1. package/README.md +187 -0
  2. package/addons/godot_mcp/command_handler.gd +161 -0
  3. package/addons/godot_mcp/command_handler.gd.uid +1 -0
  4. package/addons/godot_mcp/commands/base_command_processor.gd +221 -0
  5. package/addons/godot_mcp/commands/base_command_processor.gd.uid +1 -0
  6. package/addons/godot_mcp/commands/debugger_commands.gd +221 -0
  7. package/addons/godot_mcp/commands/debugger_commands.gd.uid +1 -0
  8. package/addons/godot_mcp/commands/editor_commands.gd +237 -0
  9. package/addons/godot_mcp/commands/editor_commands.gd.uid +1 -0
  10. package/addons/godot_mcp/commands/editor_script_commands.gd +365 -0
  11. package/addons/godot_mcp/commands/editor_script_commands.gd.uid +1 -0
  12. package/addons/godot_mcp/commands/input_commands.gd +337 -0
  13. package/addons/godot_mcp/commands/input_commands.gd.uid +1 -0
  14. package/addons/godot_mcp/commands/node_commands.gd +222 -0
  15. package/addons/godot_mcp/commands/node_commands.gd.uid +1 -0
  16. package/addons/godot_mcp/commands/project_commands.gd +298 -0
  17. package/addons/godot_mcp/commands/project_commands.gd.uid +1 -0
  18. package/addons/godot_mcp/commands/scene_commands.gd +337 -0
  19. package/addons/godot_mcp/commands/scene_commands.gd.uid +1 -0
  20. package/addons/godot_mcp/commands/script_commands.gd +349 -0
  21. package/addons/godot_mcp/commands/script_commands.gd.uid +1 -0
  22. package/addons/godot_mcp/mcp_asset_commands.gd +153 -0
  23. package/addons/godot_mcp/mcp_asset_commands.gd.uid +1 -0
  24. package/addons/godot_mcp/mcp_debug_output_publisher.gd +1669 -0
  25. package/addons/godot_mcp/mcp_debug_output_publisher.gd.uid +1 -0
  26. package/addons/godot_mcp/mcp_debugger_bridge.gd +1455 -0
  27. package/addons/godot_mcp/mcp_debugger_bridge.gd.uid +1 -0
  28. package/addons/godot_mcp/mcp_enhanced_commands.gd +1083 -0
  29. package/addons/godot_mcp/mcp_enhanced_commands.gd.uid +1 -0
  30. package/addons/godot_mcp/mcp_input_handler.gd +545 -0
  31. package/addons/godot_mcp/mcp_input_handler.gd.uid +1 -0
  32. package/addons/godot_mcp/mcp_runtime_debugger_bridge.gd +464 -0
  33. package/addons/godot_mcp/mcp_runtime_debugger_bridge.gd.uid +1 -0
  34. package/addons/godot_mcp/mcp_script_resource_commands.gd +165 -0
  35. package/addons/godot_mcp/mcp_script_resource_commands.gd.uid +1 -0
  36. package/addons/godot_mcp/mcp_server.gd +260 -0
  37. package/addons/godot_mcp/mcp_server.gd.uid +1 -0
  38. package/addons/godot_mcp/plugin.cfg +7 -0
  39. package/addons/godot_mcp/runtime_debugger.gd +81 -0
  40. package/addons/godot_mcp/runtime_debugger.gd.uid +1 -0
  41. package/addons/godot_mcp/ui/mcp_panel.gd +94 -0
  42. package/addons/godot_mcp/ui/mcp_panel.gd.uid +1 -0
  43. package/addons/godot_mcp/ui/mcp_panel.tscn +96 -0
  44. package/addons/godot_mcp/utils/node_utils.gd +82 -0
  45. package/addons/godot_mcp/utils/node_utils.gd.uid +1 -0
  46. package/addons/godot_mcp/utils/resource_utils.gd +81 -0
  47. package/addons/godot_mcp/utils/resource_utils.gd.uid +1 -0
  48. package/addons/godot_mcp/utils/script_utils.gd +114 -0
  49. package/addons/godot_mcp/utils/script_utils.gd.uid +1 -0
  50. package/addons/godot_mcp/websocket_server.gd +197 -0
  51. package/addons/godot_mcp/websocket_server.gd.uid +1 -0
  52. package/dist/cli.d.ts +2 -0
  53. package/dist/cli.js +561 -0
  54. package/dist/cli.js.map +1 -0
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +156 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/resources/asset_resources.d.ts +29 -0
  59. package/dist/resources/asset_resources.js +145 -0
  60. package/dist/resources/asset_resources.js.map +1 -0
  61. package/dist/resources/debug_resources.d.ts +11 -0
  62. package/dist/resources/debug_resources.js +106 -0
  63. package/dist/resources/debug_resources.js.map +1 -0
  64. package/dist/resources/debugger_resources.d.ts +62 -0
  65. package/dist/resources/debugger_resources.js +201 -0
  66. package/dist/resources/debugger_resources.js.map +1 -0
  67. package/dist/resources/editor_resources.d.ts +47 -0
  68. package/dist/resources/editor_resources.js +155 -0
  69. package/dist/resources/editor_resources.js.map +1 -0
  70. package/dist/resources/project_resources.d.ts +33 -0
  71. package/dist/resources/project_resources.js +137 -0
  72. package/dist/resources/project_resources.js.map +1 -0
  73. package/dist/resources/scene_resources.d.ts +33 -0
  74. package/dist/resources/scene_resources.js +160 -0
  75. package/dist/resources/scene_resources.js.map +1 -0
  76. package/dist/resources/script_resources.d.ts +51 -0
  77. package/dist/resources/script_resources.js +203 -0
  78. package/dist/resources/script_resources.js.map +1 -0
  79. package/dist/tools/asset_tools.d.ts +5 -0
  80. package/dist/tools/asset_tools.js +125 -0
  81. package/dist/tools/asset_tools.js.map +1 -0
  82. package/dist/tools/debugger_tools.d.ts +2 -0
  83. package/dist/tools/debugger_tools.js +342 -0
  84. package/dist/tools/debugger_tools.js.map +1 -0
  85. package/dist/tools/editor_tools.d.ts +2 -0
  86. package/dist/tools/editor_tools.js +165 -0
  87. package/dist/tools/editor_tools.js.map +1 -0
  88. package/dist/tools/enhanced_tools.d.ts +5 -0
  89. package/dist/tools/enhanced_tools.js +706 -0
  90. package/dist/tools/enhanced_tools.js.map +1 -0
  91. package/dist/tools/input_tools.d.ts +2 -0
  92. package/dist/tools/input_tools.js +408 -0
  93. package/dist/tools/input_tools.js.map +1 -0
  94. package/dist/tools/node_tools.d.ts +5 -0
  95. package/dist/tools/node_tools.js +217 -0
  96. package/dist/tools/node_tools.js.map +1 -0
  97. package/dist/tools/project_tools.d.ts +5 -0
  98. package/dist/tools/project_tools.js +162 -0
  99. package/dist/tools/project_tools.js.map +1 -0
  100. package/dist/tools/scene_tools.d.ts +5 -0
  101. package/dist/tools/scene_tools.js +260 -0
  102. package/dist/tools/scene_tools.js.map +1 -0
  103. package/dist/tools/script_resource_tools.d.ts +5 -0
  104. package/dist/tools/script_resource_tools.js +5 -0
  105. package/dist/tools/script_resource_tools.js.map +1 -0
  106. package/dist/tools/script_tools.d.ts +5 -0
  107. package/dist/tools/script_tools.js +154 -0
  108. package/dist/tools/script_tools.js.map +1 -0
  109. package/dist/utils/godot_connection.d.ts +30 -0
  110. package/dist/utils/godot_connection.js +285 -0
  111. package/dist/utils/godot_connection.js.map +1 -0
  112. package/dist/utils/types.d.ts +16 -0
  113. package/dist/utils/types.js +2 -0
  114. package/dist/utils/types.js.map +1 -0
  115. package/package.json +58 -0
@@ -0,0 +1,221 @@
1
+ @tool
2
+ class_name MCPDebuggerCommands
3
+ extends MCPBaseCommandProcessor
4
+
5
+ # Reference to the debugger bridge provided by the plugin
6
+ var _debugger_bridge = null
7
+
8
+ func _ready():
9
+ _debugger_bridge = _get_debugger_bridge()
10
+
11
+ if _debugger_bridge:
12
+ # Connect signals so the bridge can forward debugger events to MCP
13
+ _debugger_bridge.breakpoint_hit.connect(_on_breakpoint_hit)
14
+ _debugger_bridge.execution_paused.connect(_on_execution_paused)
15
+ _debugger_bridge.execution_resumed.connect(_on_execution_resumed)
16
+ _debugger_bridge.stack_frame_changed.connect(_on_stack_frame_changed)
17
+ _debugger_bridge.breakpoint_set.connect(_on_breakpoint_set)
18
+ _debugger_bridge.breakpoint_removed.connect(_on_breakpoint_removed)
19
+ else:
20
+ print('[MCPDebuggerCommands] Warning: Could not get debugger bridge reference')
21
+
22
+ func _get_debugger_bridge():
23
+ if Engine.has_meta('MCPDebuggerBridge'):
24
+ return Engine.get_meta('MCPDebuggerBridge')
25
+
26
+ var plugin = Engine.get_meta('GodotMCPPlugin')
27
+ if plugin and plugin.has_method('get_debugger_bridge'):
28
+ return plugin.get_debugger_bridge()
29
+
30
+ return null
31
+
32
+ func _ensure_bridge(client_id: int, command_id: String) -> bool:
33
+ if _debugger_bridge:
34
+ return true
35
+
36
+ _send_error(client_id, 'Debugger bridge not available', command_id)
37
+ return false
38
+
39
+ func _normalize_script_path(script_path: String) -> String:
40
+ if script_path.is_empty():
41
+ return script_path
42
+
43
+ if script_path.begins_with('res://'):
44
+ return script_path
45
+
46
+ if script_path.begins_with('/'):
47
+ return 'res://' + script_path.substr(1)
48
+
49
+ return 'res://' + script_path
50
+
51
+ func _forward_bridge_result(client_id: int, command_id: String, result: Variant, failure_message: String) -> void:
52
+ if result is Dictionary and not result.get('success', true):
53
+ _send_error(client_id, result.get('message', failure_message), command_id)
54
+ return
55
+
56
+ _send_success(client_id, result, command_id)
57
+
58
+ func _call_breakpoint_operation(client_id: int, params: Dictionary, command_id: String, method_name: String, failure_message: String) -> void:
59
+ if not _ensure_bridge(client_id, command_id):
60
+ return
61
+
62
+ var script_path: String = params.get('script_path', '')
63
+ var line: int = params.get('line', -1)
64
+
65
+ if script_path.is_empty():
66
+ _send_error(client_id, 'script_path parameter is required', command_id)
67
+ return
68
+
69
+ if line < 0:
70
+ _send_error(client_id, 'line parameter must be >= 0', command_id)
71
+ return
72
+
73
+ script_path = _normalize_script_path(script_path)
74
+
75
+ var result = _debugger_bridge.call(method_name, script_path, line)
76
+ _forward_bridge_result(client_id, command_id, result, failure_message)
77
+
78
+ func _call_bridge_no_args(client_id: int, command_id: String, method_name: String, failure_message: String) -> void:
79
+ if not _ensure_bridge(client_id, command_id):
80
+ return
81
+
82
+ var result = _debugger_bridge.call(method_name)
83
+ _forward_bridge_result(client_id, command_id, result, failure_message)
84
+
85
+ func process_command(client_id: int, command_type: String, params: Dictionary, command_id: String) -> bool:
86
+ match command_type:
87
+ 'debugger_set_breakpoint':
88
+ _call_breakpoint_operation(client_id, params, command_id, 'set_breakpoint', 'Failed to set breakpoint')
89
+ return true
90
+ 'debugger_remove_breakpoint':
91
+ _call_breakpoint_operation(client_id, params, command_id, 'remove_breakpoint', 'Failed to remove breakpoint')
92
+ return true
93
+ 'debugger_get_breakpoints':
94
+ _get_breakpoints(client_id, params, command_id)
95
+ return true
96
+ 'debugger_clear_all_breakpoints':
97
+ _call_bridge_no_args(client_id, command_id, 'clear_all_breakpoints', 'Failed to clear all breakpoints')
98
+ return true
99
+ 'debugger_pause_execution':
100
+ _call_bridge_no_args(client_id, command_id, 'pause_execution', 'Failed to pause execution')
101
+ return true
102
+ 'debugger_resume_execution':
103
+ _call_bridge_no_args(client_id, command_id, 'resume_execution', 'Failed to resume execution')
104
+ return true
105
+ 'debugger_step_over':
106
+ _call_bridge_no_args(client_id, command_id, 'step_over', 'Failed to step over')
107
+ return true
108
+ 'debugger_step_into':
109
+ _call_bridge_no_args(client_id, command_id, 'step_into', 'Failed to step into')
110
+ return true
111
+ 'debugger_get_call_stack':
112
+ await _get_call_stack(client_id, params, command_id)
113
+ return true
114
+ 'debugger_get_current_state':
115
+ _get_current_state(client_id, params, command_id)
116
+ return true
117
+ 'debugger_enable_events':
118
+ _enable_debugger_events(client_id, params, command_id)
119
+ return true
120
+ 'debugger_disable_events':
121
+ _disable_debugger_events(client_id, params, command_id)
122
+ return true
123
+ return false
124
+
125
+ func _get_breakpoints(client_id: int, params: Dictionary, command_id: String) -> void:
126
+ if not _ensure_bridge(client_id, command_id):
127
+ return
128
+
129
+ var result = _debugger_bridge.get_breakpoints()
130
+ _send_success(client_id, result, command_id)
131
+
132
+ func _parse_session_identifier(raw_value) -> Variant:
133
+ var session_id = raw_value
134
+ var value_type := typeof(raw_value)
135
+ match value_type:
136
+ TYPE_INT:
137
+ return raw_value
138
+ TYPE_FLOAT:
139
+ return int(raw_value)
140
+ TYPE_STRING:
141
+ var session_str: String = raw_value
142
+ if session_str.is_valid_int():
143
+ return int(session_str)
144
+ return session_str.strip_edges()
145
+ _:
146
+ return raw_value
147
+ return session_id
148
+
149
+ func _get_call_stack(client_id: int, params: Dictionary, command_id: String):
150
+ if not _ensure_bridge(client_id, command_id):
151
+ return
152
+
153
+ var session_id = null
154
+ if params.has('session_id'):
155
+ session_id = _parse_session_identifier(params['session_id'])
156
+
157
+ var result = await _debugger_bridge.get_call_stack(session_id)
158
+ if typeof(result) == TYPE_DICTIONARY and result.has("error"):
159
+ var message := String(result.get("message", result.get("error", "unknown_call_stack_error")))
160
+ _send_error(client_id, "Failed to capture call stack: %s" % message, command_id)
161
+ return
162
+
163
+ _send_success(client_id, result, command_id)
164
+
165
+ func _get_current_state(client_id: int, params: Dictionary, command_id: String) -> void:
166
+ if not _ensure_bridge(client_id, command_id):
167
+ return
168
+
169
+ var result = _debugger_bridge.get_current_state()
170
+ _send_success(client_id, result, command_id)
171
+
172
+ func _enable_debugger_events(client_id: int, params: Dictionary, command_id: String) -> void:
173
+ if not _ensure_bridge(client_id, command_id):
174
+ return
175
+
176
+ _debugger_bridge.set_client_id(client_id)
177
+
178
+ if not _debugger_bridge._websocket_server:
179
+ _debugger_bridge.set_websocket_server(_websocket_server)
180
+
181
+ _send_success(client_id, {
182
+ 'message': 'Debugger events enabled for this client',
183
+ 'client_id': client_id,
184
+ }, command_id)
185
+
186
+ func _disable_debugger_events(client_id: int, params: Dictionary, command_id: String) -> void:
187
+ if not _ensure_bridge(client_id, command_id):
188
+ return
189
+
190
+ if _debugger_bridge._current_client_id == client_id:
191
+ _debugger_bridge.set_client_id(-1)
192
+
193
+ _send_success(client_id, {
194
+ 'message': 'Debugger events disabled for this client',
195
+ 'client_id': client_id,
196
+ }, command_id)
197
+
198
+ # Signal handlers to provide editor-side visibility into debugger activity
199
+ func _on_breakpoint_hit(session_id: int, script_path: String, line: int, stack_info: Dictionary) -> void:
200
+ print('Breakpoint hit in session %s at %s:%d' % [session_id, script_path, line])
201
+
202
+ func _on_execution_paused(session_id: int, reason: String) -> void:
203
+ print('Execution paused in session %s: %s' % [session_id, reason])
204
+
205
+ func _on_execution_resumed(session_id: int) -> void:
206
+ print('Execution resumed in session %s' % session_id)
207
+
208
+ func _on_stack_frame_changed(session_id: int, frame_info: Dictionary) -> void:
209
+ print('Stack frame changed in session %s' % session_id)
210
+
211
+ func _on_breakpoint_set(session_id: int, script_path: String, line: int, success: bool) -> void:
212
+ if success:
213
+ print('Breakpoint set successfully at %s:%d' % [script_path, line])
214
+ else:
215
+ print('Failed to set breakpoint at %s:%d' % [script_path, line])
216
+
217
+ func _on_breakpoint_removed(session_id: int, script_path: String, line: int, success: bool) -> void:
218
+ if success:
219
+ print('Breakpoint removed successfully at %s:%d' % [script_path, line])
220
+ else:
221
+ print('Failed to remove breakpoint at %s:%d' % [script_path, line])
@@ -0,0 +1 @@
1
+ uid://b3j3sw8hamog6
@@ -0,0 +1,237 @@
1
+ @tool
2
+ class_name MCPEditorCommands
3
+ extends MCPBaseCommandProcessor
4
+
5
+ func process_command(client_id: int, command_type: String, params: Dictionary, command_id: String) -> bool:
6
+ match command_type:
7
+ "get_editor_state":
8
+ _get_editor_state(client_id, params, command_id)
9
+ return true
10
+ "get_selected_node":
11
+ _get_selected_node(client_id, params, command_id)
12
+ return true
13
+ "create_resource":
14
+ _create_resource(client_id, params, command_id)
15
+ return true
16
+ "reload_project":
17
+ _reload_project(client_id, params, command_id)
18
+ return true
19
+ "reload_scene":
20
+ _reload_scene(client_id, params, command_id)
21
+ return true
22
+ "rescan_filesystem":
23
+ _rescan_filesystem(client_id, params, command_id)
24
+ return true
25
+ return false # Command not handled
26
+
27
+ func _get_editor_state(client_id: int, params: Dictionary, command_id: String) -> void:
28
+ # Get editor plugin and interfaces
29
+ var plugin = Engine.get_meta("GodotMCPPlugin")
30
+ if not plugin:
31
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
32
+
33
+ var editor_interface = plugin.get_editor_interface()
34
+
35
+ var state = {
36
+ "current_scene": "",
37
+ "current_script": "",
38
+ "selected_nodes": [],
39
+ "is_playing": editor_interface.is_playing_scene()
40
+ }
41
+
42
+ # Get current scene
43
+ var edited_scene_root = editor_interface.get_edited_scene_root()
44
+ if edited_scene_root:
45
+ state["current_scene"] = edited_scene_root.scene_file_path
46
+
47
+ # Get current script if any is being edited
48
+ var script_editor = editor_interface.get_script_editor()
49
+ var current_script = script_editor.get_current_script()
50
+ if current_script:
51
+ state["current_script"] = current_script.resource_path
52
+
53
+ # Get selected nodes
54
+ var selection = editor_interface.get_selection()
55
+ var selected_nodes = selection.get_selected_nodes()
56
+
57
+ for node in selected_nodes:
58
+ state["selected_nodes"].append({
59
+ "name": node.name,
60
+ "path": str(node.get_path())
61
+ })
62
+
63
+ _send_success(client_id, state, command_id)
64
+
65
+ func _get_selected_node(client_id: int, params: Dictionary, command_id: String) -> void:
66
+ # Get editor plugin and interfaces
67
+ var plugin = Engine.get_meta("GodotMCPPlugin")
68
+ if not plugin:
69
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
70
+
71
+ var editor_interface = plugin.get_editor_interface()
72
+ var selection = editor_interface.get_selection()
73
+ var selected_nodes = selection.get_selected_nodes()
74
+
75
+ if selected_nodes.size() == 0:
76
+ return _send_success(client_id, {
77
+ "selected": false,
78
+ "message": "No node is currently selected"
79
+ }, command_id)
80
+
81
+ var node = selected_nodes[0] # Get the first selected node
82
+
83
+ # Get node info
84
+ var node_data = {
85
+ "selected": true,
86
+ "name": node.name,
87
+ "type": node.get_class(),
88
+ "path": str(node.get_path())
89
+ }
90
+
91
+ # Get script info if available
92
+ var script = node.get_script()
93
+ if script:
94
+ node_data["script_path"] = script.resource_path
95
+
96
+ # Get important properties
97
+ var properties = {}
98
+ var property_list = node.get_property_list()
99
+
100
+ for prop in property_list:
101
+ var name = prop["name"]
102
+ if not name.begins_with("_"): # Skip internal properties
103
+ # Only include some common properties to avoid overwhelming data
104
+ if name in ["position", "rotation", "scale", "visible", "modulate", "z_index"]:
105
+ properties[name] = node.get(name)
106
+
107
+ node_data["properties"] = properties
108
+
109
+ _send_success(client_id, node_data, command_id)
110
+
111
+ func _create_resource(client_id: int, params: Dictionary, command_id: String) -> void:
112
+ var resource_type = params.get("resource_type", "")
113
+ var resource_path = params.get("resource_path", "")
114
+ var properties = params.get("properties", {})
115
+
116
+ # Validation
117
+ if resource_type.is_empty():
118
+ return _send_error(client_id, "Resource type cannot be empty", command_id)
119
+
120
+ if resource_path.is_empty():
121
+ return _send_error(client_id, "Resource path cannot be empty", command_id)
122
+
123
+ # Make sure we have an absolute path
124
+ if not resource_path.begins_with("res://"):
125
+ resource_path = "res://" + resource_path
126
+
127
+ # Get editor interface
128
+ var plugin = Engine.get_meta("GodotMCPPlugin")
129
+ if not plugin:
130
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
131
+
132
+ var editor_interface = plugin.get_editor_interface()
133
+
134
+ # Create the resource
135
+ var resource
136
+
137
+ if ClassDB.class_exists(resource_type):
138
+ if ClassDB.is_parent_class(resource_type, "Resource"):
139
+ resource = ClassDB.instantiate(resource_type)
140
+ if not resource:
141
+ return _send_error(client_id, "Failed to instantiate resource: %s" % resource_type, command_id)
142
+ else:
143
+ return _send_error(client_id, "Type is not a Resource: %s" % resource_type, command_id)
144
+ else:
145
+ return _send_error(client_id, "Invalid resource type: %s" % resource_type, command_id)
146
+
147
+ # Set properties
148
+ for key in properties:
149
+ resource.set(key, properties[key])
150
+
151
+ # Create directory if needed
152
+ var dir = resource_path.get_base_dir()
153
+ if not DirAccess.dir_exists_absolute(dir):
154
+ var err = DirAccess.make_dir_recursive_absolute(dir)
155
+ if err != OK:
156
+ return _send_error(client_id, "Failed to create directory: %s (Error code: %d)" % [dir, err], command_id)
157
+
158
+ # Save the resource
159
+ var result = ResourceSaver.save(resource, resource_path)
160
+ if result != OK:
161
+ return _send_error(client_id, "Failed to save resource: %d" % result, command_id)
162
+
163
+ # Refresh the filesystem
164
+ editor_interface.get_resource_filesystem().scan()
165
+
166
+ _send_success(client_id, {
167
+ "resource_path": resource_path,
168
+ "resource_type": resource_type
169
+ }, command_id)
170
+
171
+ func _reload_project(client_id: int, params: Dictionary, command_id: String) -> void:
172
+ var plugin = Engine.get_meta("GodotMCPPlugin")
173
+ if not plugin:
174
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
175
+
176
+ var editor_interface = plugin.get_editor_interface()
177
+ var save_before_restart: bool = params.get("save", true)
178
+
179
+ # Send success response before restarting (since restart will disconnect)
180
+ _send_success(client_id, {
181
+ "status": "restarting",
182
+ "save": save_before_restart,
183
+ "message": "Godot editor is restarting..."
184
+ }, command_id)
185
+
186
+ # Use call_deferred to allow the response to be sent before restart
187
+ editor_interface.call_deferred("restart_editor", save_before_restart)
188
+
189
+ func _reload_scene(client_id: int, params: Dictionary, command_id: String) -> void:
190
+ var plugin = Engine.get_meta("GodotMCPPlugin")
191
+ if not plugin:
192
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
193
+
194
+ var editor_interface = plugin.get_editor_interface()
195
+ var scene_path: String = params.get("scene_path", "")
196
+
197
+ # If no scene path provided, reload the current scene
198
+ if scene_path.is_empty():
199
+ var edited_scene_root = editor_interface.get_edited_scene_root()
200
+ if not edited_scene_root:
201
+ return _send_error(client_id, "No scene is currently open in the editor", command_id)
202
+
203
+ scene_path = edited_scene_root.scene_file_path
204
+ if scene_path.is_empty():
205
+ return _send_error(client_id, "Current scene has not been saved yet", command_id)
206
+
207
+ # Validate scene path
208
+ if not scene_path.begins_with("res://"):
209
+ scene_path = "res://" + scene_path
210
+
211
+ if not ResourceLoader.exists(scene_path):
212
+ return _send_error(client_id, "Scene does not exist: %s" % scene_path, command_id)
213
+
214
+ # Reload the scene from disk
215
+ editor_interface.reload_scene_from_path(scene_path)
216
+
217
+ _send_success(client_id, {
218
+ "status": "reloaded",
219
+ "scene_path": scene_path,
220
+ "message": "Scene reloaded from disk"
221
+ }, command_id)
222
+
223
+ func _rescan_filesystem(client_id: int, params: Dictionary, command_id: String) -> void:
224
+ var plugin = Engine.get_meta("GodotMCPPlugin")
225
+ if not plugin:
226
+ return _send_error(client_id, "GodotMCPPlugin not found in Engine metadata", command_id)
227
+
228
+ var editor_interface = plugin.get_editor_interface()
229
+ var filesystem = editor_interface.get_resource_filesystem()
230
+
231
+ # Trigger filesystem scan
232
+ filesystem.scan()
233
+
234
+ _send_success(client_id, {
235
+ "status": "scanning",
236
+ "message": "Filesystem rescan initiated"
237
+ }, command_id)
@@ -0,0 +1 @@
1
+ uid://dudosnjgw5kp1