mirror of
https://github.com/aljazceru/mcp-python-sdk.git
synced 2025-12-19 14:54:24 +01:00
run server in separate process
This commit is contained in:
@@ -64,8 +64,7 @@ class TestServer(Server):
|
|||||||
|
|
||||||
|
|
||||||
# Test fixtures
|
# Test fixtures
|
||||||
@pytest.fixture
|
def make_server_app()-> Starlette:
|
||||||
async def server_app()-> Starlette:
|
|
||||||
"""Create test Starlette app with SSE transport"""
|
"""Create test Starlette app with SSE transport"""
|
||||||
sse = SseServerTransport("/messages/")
|
sse = SseServerTransport("/messages/")
|
||||||
server = TestServer()
|
server = TestServer()
|
||||||
@@ -93,43 +92,46 @@ def space_around_test():
|
|||||||
yield
|
yield
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
@pytest.fixture()
|
def run_server(server_port: int):
|
||||||
def server(server_app: Starlette, server_port: int):
|
app = make_server_app()
|
||||||
proc = multiprocessing.Process(target=uvicorn.run, daemon=True, kwargs={
|
server = uvicorn.Server(config=uvicorn.Config(app=app, host="127.0.0.1", port=server_port, log_level="error"))
|
||||||
"app": server_app,
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": server_port,
|
|
||||||
"log_level": "error"
|
|
||||||
})
|
|
||||||
print(f'starting server on {server_port}')
|
print(f'starting server on {server_port}')
|
||||||
proc.start()
|
server.run()
|
||||||
|
|
||||||
# Give server time to start
|
# Give server time to start
|
||||||
while not server.started:
|
while not server.started:
|
||||||
print('waiting for server to start')
|
print('waiting for server to start')
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
try:
|
@pytest.fixture()
|
||||||
yield
|
def server(server_port: int):
|
||||||
finally:
|
proc = multiprocessing.Process(target=run_server, kwargs={"server_port": server_port}, daemon=True)
|
||||||
print('killing server')
|
print('starting process')
|
||||||
# Signal the server to stop
|
proc.start()
|
||||||
server.should_exit = True
|
|
||||||
|
|
||||||
# Force close the server's main socket
|
# Wait for server to be running
|
||||||
if hasattr(server.servers, "servers"):
|
max_attempts = 20
|
||||||
for s in server.servers:
|
attempt = 0
|
||||||
print(f'closing {s}')
|
print('waiting for server to start')
|
||||||
s.close()
|
while attempt < max_attempts:
|
||||||
|
try:
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect(('127.0.0.1', server_port))
|
||||||
|
break
|
||||||
|
except ConnectionRefusedError:
|
||||||
|
time.sleep(0.1)
|
||||||
|
attempt += 1
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Server failed to start after {} attempts".format(max_attempts))
|
||||||
|
|
||||||
# Wait for thread to finish
|
yield
|
||||||
proc.terminate()
|
|
||||||
proc.join(timeout=2)
|
print('killing server')
|
||||||
if proc.is_alive():
|
# Signal the server to stop
|
||||||
print("Warning: Server thread did not exit cleanly")
|
proc.kill()
|
||||||
# Optionally, you could add more aggressive cleanup here
|
proc.join(timeout=2)
|
||||||
import _thread
|
if proc.is_alive():
|
||||||
_thread.interrupt_main()
|
print("server process failed to terminate")
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
async def http_client(server, server_url) -> AsyncGenerator[httpx.AsyncClient, None]:
|
async def http_client(server, server_url) -> AsyncGenerator[httpx.AsyncClient, None]:
|
||||||
|
|||||||
Reference in New Issue
Block a user