Skip to content

Commit 29e17be

Browse files
nielskaspersclaude
andcommitted
Add warning log when rejecting requests with unknown session IDs
The else branch in _handle_stateful_request silently returned 404 for unknown or expired session IDs, while the other branches logged at debug/info level. This made it difficult to diagnose connection failures caused by stale session IDs (e.g. after server restarts). Closes #2204 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b33c811 commit 29e17be

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

src/mcp/server/streamable_http_manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ async def run_server(*, task_status: TaskStatus[None] = anyio.TASK_STATUS_IGNORE
272272
# Unknown or expired session ID - return 404 per MCP spec
273273
# TODO: Align error code once spec clarifies
274274
# See: https://github.com/modelcontextprotocol/python-sdk/issues/1821
275+
logger.warning(
276+
"Rejected request with unknown or expired session ID: %s",
277+
request_mcp_session_id,
278+
)
275279
error_response = JSONRPCError(
276280
jsonrpc="2.0",
277281
id=None,

tests/server/test_streamable_http_manager.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for StreamableHTTPSessionManager."""
22

33
import json
4+
import logging
45
from typing import Any
56
from unittest.mock import AsyncMock, patch
67

@@ -269,7 +270,7 @@ async def mock_receive():
269270

270271

271272
@pytest.mark.anyio
272-
async def test_unknown_session_id_returns_404():
273+
async def test_unknown_session_id_returns_404(caplog: pytest.LogCaptureFixture):
273274
"""Test that requests with unknown session IDs return HTTP 404 per MCP spec."""
274275
app = Server("test-unknown-session")
275276
manager = StreamableHTTPSessionManager(app=app)
@@ -299,7 +300,14 @@ async def mock_send(message: Message):
299300
async def mock_receive():
300301
return {"type": "http.request", "body": b"{}", "more_body": False} # pragma: no cover
301302

302-
await manager.handle_request(scope, mock_receive, mock_send)
303+
with caplog.at_level(logging.WARNING, logger="mcp.server.streamable_http_manager"):
304+
await manager.handle_request(scope, mock_receive, mock_send)
305+
306+
# Verify warning was logged for the unknown session ID
307+
assert any(
308+
"non-existent-session-id" in record.message and record.levelno == logging.WARNING
309+
for record in caplog.records
310+
), "Should log a warning for unknown session ID"
303311

304312
# Find the response start message
305313
response_start = next(

0 commit comments

Comments
 (0)