Skip to content

Commit 86059bd

Browse files
dsarnoclaude
andcommitted
Fix plugin server start: use existing server instead of killing it
Plugin now checks if port 8000 is already in use and skips starting its own server. This fixes CI where an external server is pre-started, and avoids killing unrelated servers (like godot-mcp-studio). The plugin still manages its own server lifecycle via _server_pid — _stop_server kills only the process the plugin started, not foreign ones. Verified locally: macOS headless Godot + external server = 35/35 tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 952e9e0 commit 86059bd

1 file changed

Lines changed: 14 additions & 16 deletions

File tree

plugin/addons/godot_ai/plugin.gd

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ func _exit_tree() -> void:
6565

6666

6767
func _start_server() -> void:
68-
## Kill any stale listener on our HTTP port (leftover from crash,
69-
## old install, or a different server like godot-mcp-studio).
70-
_kill_listener_on_port(McpClientConfigurator.SERVER_HTTP_PORT)
68+
## If a server is already listening on our HTTP port, use it.
69+
## This covers: CI (external server), another Godot instance, or manual start.
70+
if _is_port_in_use(McpClientConfigurator.SERVER_HTTP_PORT):
71+
print("MCP | server already running on port %d, using existing" % McpClientConfigurator.SERVER_HTTP_PORT)
72+
return
7173

7274
var server_cmd := McpClientConfigurator.get_server_command()
7375
if server_cmd.is_empty():
@@ -86,20 +88,16 @@ func _start_server() -> void:
8688
push_warning("MCP | failed to start server")
8789

8890

89-
func _kill_listener_on_port(port: int) -> void:
91+
func _is_port_in_use(port: int) -> bool:
9092
var output: Array = []
91-
## -sTCP:LISTEN finds only the server process, not clients connected to it
92-
var exit_code := OS.execute("lsof", ["-ti:%d" % port, "-sTCP:LISTEN"], output, true)
93-
if exit_code != 0 or output.is_empty():
94-
return
95-
var pids_str: String = output[0].strip_edges()
96-
if pids_str.is_empty():
97-
return
98-
for pid_str in pids_str.split("\n"):
99-
var pid := pid_str.strip_edges().to_int()
100-
if pid > 0:
101-
OS.kill(pid)
102-
print("MCP | killed stale process on port %d (PID %d)" % [port, pid])
93+
if OS.get_name() == "Windows":
94+
var exit_code := OS.execute("netstat", ["-ano"], output, true)
95+
if exit_code == 0 and output.size() > 0:
96+
return output[0].find(":%d " % port) >= 0 and output[0].find("LISTENING") >= 0
97+
else:
98+
var exit_code := OS.execute("lsof", ["-ti:%d" % port, "-sTCP:LISTEN"], output, true)
99+
return exit_code == 0 and output.size() > 0 and not output[0].strip_edges().is_empty()
100+
return false
103101

104102

105103
func _stop_server() -> void:

0 commit comments

Comments
 (0)