1- # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2- # SPDX-License-Identifier: Apache-2.0
3-
41import asyncio
52import json
63import multiprocessing
1512from mcp .server .sse import SseServerTransport
1613from starlette .applications import Starlette
1714from starlette .requests import Request
18- from starlette .responses import StreamingResponse
15+ from starlette .responses import JSONResponse , StreamingResponse
1916from starlette .routing import Mount , Route
2017
2118from tensorrt_llm .scaffolding .controller import ChatWithMCPController , NativeGenerationController
@@ -67,9 +64,13 @@ async def handle_sse(request: Request) -> StreamingResponse:
6764 # Return an empty streaming response after SSE connection closes
6865 return StreamingResponse (iter ([]), media_type = "text/event-stream" )
6966
67+ async def handle_health (_request : Request ) -> JSONResponse :
68+ return JSONResponse ({"status" : "ok" })
69+
7070 return Starlette (
7171 debug = debug ,
7272 routes = [
73+ Route ("/health" , endpoint = handle_health ),
7374 Route ("/sse" , endpoint = handle_sse ),
7475 Mount ("/messages/" , app = sse .handle_post_message ),
7576 ],
@@ -103,9 +104,13 @@ def __init__(self, host: str = "0.0.0.0", port: int = 8080, env: Optional[dict]
103104 )
104105 self .proc .start ()
105106
106- # Wait for server to be ready
107- # self._wait_for_server(url=self.sse_url,
108- # timeout=self.MAX_SERVER_START_WAIT_S)
107+ try :
108+ self ._wait_for_server (
109+ url = f"{ self .url_root } /health" , timeout = self .MAX_SERVER_START_WAIT_S
110+ )
111+ except RuntimeError :
112+ self .terminate ()
113+ raise
109114
110115 def __enter__ (self ):
111116 return self
@@ -166,9 +171,9 @@ def get_sse_url(self) -> str:
166171
167172
168173@pytest .fixture (scope = "module" )
169- def mcp_server ():
174+ def mcp_server (unused_tcp_port_factory ):
170175 # Create and start MCP server (similar to RemoteOpenAIServer usage)
171- remote_server = RemoteMCPServer (host = "0 .0.0.0 " , port = 8080 )
176+ remote_server = RemoteMCPServer (host = "127 .0.0.1 " , port = unused_tcp_port_factory () )
172177
173178 # Yield server instance for test use
174179 yield remote_server
@@ -220,7 +225,6 @@ async def dummy_handler(self, task: ChatTask):
220225# ============================================================
221226
222227
223- @pytest .mark .skip (reason = "https://nvbugs/6337229" )
224228@pytest .mark .asyncio
225229async def test_mcp_worker_add_numbers (mcp_server ):
226230 # 1. Initialize MCPWorker with mcp_server's SSE URL
@@ -254,10 +258,9 @@ async def test_mcp_worker_add_numbers(mcp_server):
254258
255259 finally :
256260 # 6. Clean up worker resources
257- worker .shutdown ()
261+ await worker .async_shutdown ()
258262
259263
260- @pytest .mark .skip (reason = "https://nvbugs/6337229" )
261264@pytest .mark .asyncio
262265async def test_mcp_worker_echo_message (mcp_server ):
263266 # Initialize MCPWorker
@@ -284,10 +287,9 @@ async def test_mcp_worker_echo_message(mcp_server):
284287 print (f"✓ Test passed: echo_message returned '{ task .result_str } '" )
285288
286289 finally :
287- worker .shutdown ()
290+ await worker .async_shutdown ()
288291
289292
290- @pytest .mark .skip (reason = "https://nvbugs/6337229" )
291293@pytest .mark .asyncio
292294async def test_mcp_worker_multiple_calls (mcp_server ):
293295 import json
@@ -337,10 +339,9 @@ async def test_mcp_worker_multiple_calls(mcp_server):
337339 print (f" - Call 3: echo_message returned '{ task3 .result_str } '" )
338340
339341 finally :
340- worker .shutdown ()
342+ await worker .async_shutdown ()
341343
342344
343- @pytest .mark .skip (reason = "https://nvbugs/6337229" )
344345@pytest .mark .asyncio
345346async def test_multiple_calls_to_same_tool (mcp_server ):
346347 sse_url = mcp_server .get_sse_url ()
@@ -368,10 +369,9 @@ async def test_multiple_calls_to_same_tool(mcp_server):
368369 print (f" - Call 1: add_numbers(10, 20) = { result1 } " )
369370 print (f" - Call 2: add_numbers(100, 200) = { result2 } " )
370371
371- worker .shutdown ()
372+ await worker .async_shutdown ()
372373
373374
374- @pytest .mark .skip (reason = "https://nvbugs/6337229" )
375375@pytest .mark .asyncio
376376async def test_scaffolding_with_chat_mcp_controller (mcp_server ):
377377 # Initialize workers
@@ -441,7 +441,7 @@ async def test_scaffolding_with_chat_mcp_controller(mcp_server):
441441
442442 finally :
443443 # Clean up
444- await mcp_worker .shutdown ()
444+ await mcp_worker .async_shutdown ()
445445 scaffolding_llm .shutdown (shutdown_workers = False ) # Don't shutdown workers again
446446
447447
0 commit comments