22import os
33import subprocess
44import time
5+ import socket
56from pathlib import Path
67from typing import List , Optional
78
@@ -69,11 +70,8 @@ def start(self) -> None:
6970 self ._log_file = log_file
7071 self ._log_file_path = log_file_path
7172
72- # Wait for server to start
73- time .sleep (3 )
74-
75- # Check if process is still running
76- if self .process .poll () is not None :
73+ # Wait for server to be ready with proper health check
74+ if not self ._wait_for_server_ready (timeout = 15 ):
7775 try :
7876 with open (self ._log_file_path , "r" ) as f :
7977 log_content = f .read ()
@@ -82,13 +80,45 @@ def start(self) -> None:
8280 print ("=" * 50 )
8381 print (log_content )
8482 print ("=" * 50 )
85- raise RuntimeError (f"Server failed to start. Check log above for details." )
83+ raise RuntimeError (f"Server failed to start or become ready . Check log above for details." )
8684 except Exception as e :
8785 stdout , stderr = self .process .communicate ()
88- raise RuntimeError (f"Server failed to start. stderr: { stderr } , log error: { e } " )
86+ raise RuntimeError (f"Server failed to start or become ready . stderr: { stderr } , log error: { e } " )
8987
9088 print (f"✅ Server started successfully on port { self .port } " )
9189
90+ def _wait_for_server_ready (self , timeout : int = 15 ) -> bool :
91+ """
92+ Wait for server to be ready by polling socket connection.
93+ """
94+ start_time = time .time ()
95+ health_check_failures = 0
96+
97+ while time .time () - start_time < timeout :
98+ # Check if process is still running
99+ if self .process .poll () is not None :
100+ print (f"Server process exited early" )
101+ return False
102+
103+ try :
104+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
105+ s .settimeout (1 )
106+ result = s .connect_ex (("localhost" , self .port ))
107+ if result == 0 :
108+ time .sleep (0.5 )
109+ return True
110+ except Exception as e :
111+ health_check_failures += 1
112+ # Print first few failures for debugging
113+ if health_check_failures <= 3 :
114+ print (f"Health check failed: { e } " )
115+
116+ # Wait before next check
117+ time .sleep (0.1 )
118+
119+ print (f"Server failed to become ready within { timeout } seconds" )
120+ return False
121+
92122 def stop (self ) -> None :
93123 """Stop the MCP server."""
94124 if self .process :
0 commit comments