77from starlette .types import Message
88
99from mcp .server .fastmcp import Context , FastMCP
10+ from mcp .server .session import ServerSession
1011from mcp .server .streamable_http_manager import StreamableHTTPSessionManager
1112
1213
@@ -20,7 +21,7 @@ async def test_session_id_propagates_to_tool_context():
2021 mcp = FastMCP ("test-session-id-server" )
2122
2223 @mcp .tool ()
23- async def get_session_info (ctx : Context ) -> dict [str , Any ]:
24+ async def get_session_info (ctx : Context [ ServerSession , None ] ) -> dict [str , Any ]:
2425 """Tool that returns session information."""
2526 nonlocal captured_session_id
2627 captured_session_id = ctx .session_id
@@ -29,8 +30,8 @@ async def get_session_info(ctx: Context) -> dict[str, Any]:
2930 "request_id" : ctx .request_id ,
3031 }
3132
32- # Create session manager
33- manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = False )
33+ # Create session manager with JSON response mode for easier testing
34+ manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = False , json_response = True )
3435
3536 async with manager .run ():
3637 # Prepare ASGI scope and messages
@@ -122,8 +123,23 @@ async def mock_receive_tool_call():
122123
123124 await manager .handle_request (scope_with_session , mock_receive_tool_call , mock_send )
124125
126+ # Parse the response to check if tool was called successfully
127+ response_body = b""
128+ for msg in sent_messages :
129+ if msg ["type" ] == "http.response.body" :
130+ response_body += msg .get ("body" , b"" )
131+
132+ # Verify we got a response
133+ assert response_body , f"Should have received a response body, got messages: { sent_messages } "
134+
135+ # Decode and parse the response
136+ response_text = response_body .decode ()
137+ print (f"Response: { response_text } " ) # Debug output
138+
125139 # Verify session_id was captured in tool context
126- assert captured_session_id is not None , "session_id should be available in Context"
140+ assert captured_session_id is not None , (
141+ f"session_id should be available in Context. Response was: { response_text } "
142+ )
127143 assert captured_session_id == session_id_from_header , (
128144 f"session_id in Context ({ captured_session_id } ) should match "
129145 f"session ID from header ({ session_id_from_header } )"
@@ -140,14 +156,14 @@ async def test_session_id_is_none_for_stateless_mode():
140156 mcp = FastMCP ("test-stateless-server" )
141157
142158 @mcp .tool ()
143- async def check_session (ctx : Context ) -> dict [str , Any ]:
159+ async def check_session (ctx : Context [ ServerSession , None ] ) -> dict [str , Any ]:
144160 """Tool that checks session_id."""
145161 nonlocal captured_session_id
146162 captured_session_id = ctx .session_id
147163 return {"has_session_id" : ctx .session_id is not None }
148164
149- # Create session manager in stateless mode
150- manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = True )
165+ # Create session manager in stateless mode with JSON response for easier testing
166+ manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = True , json_response = True )
151167
152168 async with manager .run ():
153169 scope = {
@@ -205,13 +221,13 @@ async def test_session_id_consistent_across_requests():
205221 mcp = FastMCP ("test-consistency-server" )
206222
207223 @mcp .tool ()
208- async def track_session (ctx : Context ) -> dict [str , Any ]:
224+ async def track_session (ctx : Context [ ServerSession , None ] ) -> dict [str , Any ]:
209225 """Tool that tracks session_id."""
210226 seen_session_ids .append (ctx .session_id )
211227 return {"session_id" : ctx .session_id , "call_number" : len (seen_session_ids )}
212228
213- # Create session manager
214- manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = False )
229+ # Create session manager with JSON response mode for easier testing
230+ manager = StreamableHTTPSessionManager (app = mcp ._mcp_server , stateless = False , json_response = True )
215231
216232 async with manager .run ():
217233 # First request: initialize and get session ID
0 commit comments