@@ -650,17 +650,31 @@ async def http_client(basic_server, basic_server_url):
650650@pytest .fixture
651651async def initialized_client_session (basic_server , basic_server_url ):
652652 """Create initialized StreamableHTTP client session."""
653- async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as streams :
654- async with ClientSession (* streams ) as session :
653+ async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as (
654+ read_stream ,
655+ write_stream ,
656+ _ ,
657+ ):
658+ async with ClientSession (
659+ read_stream ,
660+ write_stream ,
661+ ) as session :
655662 await session .initialize ()
656663 yield session
657664
658665
659666@pytest .mark .anyio
660667async def test_streamablehttp_client_basic_connection (basic_server , basic_server_url ):
661668 """Test basic client connection with initialization."""
662- async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as streams :
663- async with ClientSession (* streams ) as session :
669+ async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as (
670+ read_stream ,
671+ write_stream ,
672+ _ ,
673+ ):
674+ async with ClientSession (
675+ read_stream ,
676+ write_stream ,
677+ ) as session :
664678 # Test initialization
665679 result = await session .initialize ()
666680 assert isinstance (result , InitializeResult )
@@ -709,8 +723,15 @@ async def test_streamablehttp_client_session_persistence(
709723 basic_server , basic_server_url
710724):
711725 """Test that session ID persists across requests."""
712- async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as streams :
713- async with ClientSession (* streams ) as session :
726+ async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as (
727+ read_stream ,
728+ write_stream ,
729+ _ ,
730+ ):
731+ async with ClientSession (
732+ read_stream ,
733+ write_stream ,
734+ ) as session :
714735 # Initialize the session
715736 result = await session .initialize ()
716737 assert isinstance (result , InitializeResult )
@@ -732,8 +753,15 @@ async def test_streamablehttp_client_json_response(
732753 json_response_server , json_server_url
733754):
734755 """Test client with JSON response mode."""
735- async with streamablehttp_client (f"{ json_server_url } /mcp" ) as streams :
736- async with ClientSession (* streams ) as session :
756+ async with streamablehttp_client (f"{ json_server_url } /mcp" ) as (
757+ read_stream ,
758+ write_stream ,
759+ _ ,
760+ ):
761+ async with ClientSession (
762+ read_stream ,
763+ write_stream ,
764+ ) as session :
737765 # Initialize the session
738766 result = await session .initialize ()
739767 assert isinstance (result , InitializeResult )
@@ -767,8 +795,14 @@ async def message_handler(
767795 if isinstance (message , types .ServerNotification ):
768796 notifications_received .append (message )
769797
770- async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as streams :
771- async with ClientSession (* streams , message_handler = message_handler ) as session :
798+ async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as (
799+ read_stream ,
800+ write_stream ,
801+ _ ,
802+ ):
803+ async with ClientSession (
804+ read_stream , write_stream , message_handler = message_handler
805+ ) as session :
772806 # Initialize the session - this triggers the GET stream setup
773807 result = await session .initialize ()
774808 assert isinstance (result , InitializeResult )
@@ -789,3 +823,33 @@ async def message_handler(
789823 assert (
790824 resource_update_found
791825 ), "ResourceUpdatedNotification not received via GET stream"
826+
827+
828+ @pytest .mark .anyio
829+ async def test_streamablehttp_client_session_termination (
830+ basic_server , basic_server_url
831+ ):
832+ """Test client session termination functionality."""
833+
834+ # Create the streamablehttp_client with a custom httpx client to capture headers
835+ async with streamablehttp_client (f"{ basic_server_url } /mcp" ) as (
836+ read_stream ,
837+ write_stream ,
838+ terminate_session ,
839+ ):
840+ async with ClientSession (read_stream , write_stream ) as session :
841+ # Initialize the session
842+ result = await session .initialize ()
843+ assert isinstance (result , InitializeResult )
844+
845+ # Make a request to confirm session is working
846+ tools = await session .list_tools ()
847+ assert len (tools .tools ) == 2
848+
849+ # After exiting ClientSession context, explicitly terminate the session
850+ await terminate_session ()
851+ with pytest .raises (
852+ McpError ,
853+ match = "Session terminated" ,
854+ ):
855+ await session .list_tools ()
0 commit comments