Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/mcp/client/streamable_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ async def terminate_session(self, client: httpx2.AsyncClient) -> None:

if response.status_code == 405:
logger.debug("Server does not allow session termination")
elif response.status_code not in (200, 204):
elif response.status_code not in (200, 202, 204):
logger.warning(f"Session termination failed: {response.status_code}") # pragma: no cover
except Exception as exc: # pragma: no cover
logger.warning(f"Session termination failed: {exc}")
Expand Down
21 changes: 21 additions & 0 deletions tests/client/test_streamable_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import base64
import json
import logging
from collections.abc import AsyncIterator, Callable, Mapping
from typing import Any

Expand Down Expand Up @@ -968,3 +969,23 @@ async def test_https_endpoint_redirected_to_plain_http_elsewhere_never_suggests_
The server is likely behind a TLS-terminating proxy whose forwarded headers it does not trust,
often combined with a trailing-slash difference. Try https://backend.lan:8000/mcp/ instead, or fix the proxy settings.\
""")


@pytest.mark.anyio
@pytest.mark.parametrize("status_code", [200, 202, 204])
async def test_terminate_session_accepts_successful_delete_status_codes(
status_code: int, caplog: pytest.LogCaptureFixture
) -> None:
"""HTTP 200, 202 (Accepted), and 204 (No Content) are valid DELETE success statuses (#3546)."""
transport = StreamableHTTPTransport("http://test/mcp")
transport.session_id = "test-session"

def handler(request: httpx2.Request) -> httpx2.Response:
assert request.method == "DELETE"
return httpx2.Response(status_code)

async with httpx2.AsyncClient(transport=httpx2.MockTransport(handler)) as http:
with caplog.at_level(logging.WARNING):
await transport.terminate_session(http)

assert not [rec for rec in caplog.records if "Session termination failed" in rec.message]
Loading