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
4 changes: 3 additions & 1 deletion src/mcp/shared/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def coerce_request_id(request_id: RequestId) -> RequestId:
"""
if isinstance(request_id, str):
try:
return int(request_id)
parsed = int(request_id)
if str(parsed) == request_id:
return parsed
except ValueError:
pass
return request_id
Expand Down
7 changes: 7 additions & 0 deletions tests/shared/test_jsonrpc_dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -2011,6 +2011,13 @@ def test_coerce_request_id_passes_through_non_numeric_string_and_int():
assert coerce_request_id(42) == 42


def test_coerce_request_id_does_not_fold_non_canonical_numeric_strings():
for non_canonical in ("007", "+7", "1_000", " 7 ", "٧"):
assert coerce_request_id(non_canonical) == non_canonical
assert coerce_request_id("-3") == -3
assert coerce_request_id("0") == 0


@pytest.mark.anyio
async def test_jsonrpc_error_response_with_null_id_is_dropped():
"""Parse-error responses (id=null) have no waiter; they're dropped and the read loop stays healthy."""
Expand Down
Loading