mirror of
https://github.com/aljazceru/mcp-python-sdk.git
synced 2025-12-19 14:54:24 +01:00
fix: 204 is an acceptable response to DELETEing the session (#697)
This commit is contained in:
@@ -410,7 +410,7 @@ class StreamableHTTPTransport:
|
|||||||
|
|
||||||
if response.status_code == 405:
|
if response.status_code == 405:
|
||||||
logger.debug("Server does not allow session termination")
|
logger.debug("Server does not allow session termination")
|
||||||
elif response.status_code != 200:
|
elif response.status_code not in (200, 204):
|
||||||
logger.warning(f"Session termination failed: {response.status_code}")
|
logger.warning(f"Session termination failed: {response.status_code}")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.warning(f"Session termination failed: {exc}")
|
logger.warning(f"Session termination failed: {exc}")
|
||||||
|
|||||||
@@ -960,6 +960,72 @@ async def test_streamablehttp_client_session_termination(
|
|||||||
await session.list_tools()
|
await session.list_tools()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
async def test_streamablehttp_client_session_termination_204(
|
||||||
|
basic_server, basic_server_url, monkeypatch
|
||||||
|
):
|
||||||
|
"""Test client session termination functionality with a 204 response.
|
||||||
|
|
||||||
|
This test patches the httpx client to return a 204 response for DELETEs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Save the original delete method to restore later
|
||||||
|
original_delete = httpx.AsyncClient.delete
|
||||||
|
|
||||||
|
# Mock the client's delete method to return a 204
|
||||||
|
async def mock_delete(self, *args, **kwargs):
|
||||||
|
# Call the original method to get the real response
|
||||||
|
response = await original_delete(self, *args, **kwargs)
|
||||||
|
|
||||||
|
# Create a new response with 204 status code but same headers
|
||||||
|
mocked_response = httpx.Response(
|
||||||
|
204,
|
||||||
|
headers=response.headers,
|
||||||
|
content=response.content,
|
||||||
|
request=response.request,
|
||||||
|
)
|
||||||
|
return mocked_response
|
||||||
|
|
||||||
|
# Apply the patch to the httpx client
|
||||||
|
monkeypatch.setattr(httpx.AsyncClient, "delete", mock_delete)
|
||||||
|
|
||||||
|
captured_session_id = None
|
||||||
|
|
||||||
|
# Create the streamablehttp_client with a custom httpx client to capture headers
|
||||||
|
async with streamablehttp_client(f"{basic_server_url}/mcp") as (
|
||||||
|
read_stream,
|
||||||
|
write_stream,
|
||||||
|
get_session_id,
|
||||||
|
):
|
||||||
|
async with ClientSession(read_stream, write_stream) as session:
|
||||||
|
# Initialize the session
|
||||||
|
result = await session.initialize()
|
||||||
|
assert isinstance(result, InitializeResult)
|
||||||
|
captured_session_id = get_session_id()
|
||||||
|
assert captured_session_id is not None
|
||||||
|
|
||||||
|
# Make a request to confirm session is working
|
||||||
|
tools = await session.list_tools()
|
||||||
|
assert len(tools.tools) == 4
|
||||||
|
|
||||||
|
headers = {}
|
||||||
|
if captured_session_id:
|
||||||
|
headers[MCP_SESSION_ID_HEADER] = captured_session_id
|
||||||
|
|
||||||
|
async with streamablehttp_client(f"{basic_server_url}/mcp", headers=headers) as (
|
||||||
|
read_stream,
|
||||||
|
write_stream,
|
||||||
|
_,
|
||||||
|
):
|
||||||
|
async with ClientSession(read_stream, write_stream) as session:
|
||||||
|
# Attempt to make a request after termination
|
||||||
|
with pytest.raises(
|
||||||
|
McpError,
|
||||||
|
match="Session terminated",
|
||||||
|
):
|
||||||
|
await session.list_tools()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_streamablehttp_client_resumption(event_server):
|
async def test_streamablehttp_client_resumption(event_server):
|
||||||
"""Test client session to resume a long running tool."""
|
"""Test client session to resume a long running tool."""
|
||||||
|
|||||||
Reference in New Issue
Block a user