Skip to content

Commit 401272a

Browse files
committed
fix(dispatcher): preserve non-canonical numeric strings in coerce_request_id
Ensure coerce_request_id only folds canonical integer strings (str(int(s)) == s) so wire-distinct JSON-RPC ids like '007', '+7', '1_000', and ' 7 ' do not collide on a shared correlation key. Fixes #3432.
1 parent 7bb486a commit 401272a

2 files changed

Lines changed: 10 additions & 1 deletion

File tree

src/mcp/shared/dispatcher.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ def coerce_request_id(request_id: RequestId) -> RequestId:
6161
"""
6262
if isinstance(request_id, str):
6363
try:
64-
return int(request_id)
64+
parsed = int(request_id)
65+
if str(parsed) == request_id:
66+
return parsed
6567
except ValueError:
6668
pass
6769
return request_id

tests/shared/test_jsonrpc_dispatcher.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,13 @@ def test_coerce_request_id_passes_through_non_numeric_string_and_int():
20112011
assert coerce_request_id(42) == 42
20122012

20132013

2014+
def test_coerce_request_id_does_not_fold_non_canonical_numeric_strings():
2015+
for non_canonical in ("007", "+7", "1_000", " 7 ", "٧"):
2016+
assert coerce_request_id(non_canonical) == non_canonical
2017+
assert coerce_request_id("-3") == -3
2018+
assert coerce_request_id("0") == 0
2019+
2020+
20142021
@pytest.mark.anyio
20152022
async def test_jsonrpc_error_response_with_null_id_is_dropped():
20162023
"""Parse-error responses (id=null) have no waiter; they're dropped and the read loop stays healthy."""

0 commit comments

Comments
 (0)