Skip to content

Commit c3d7cc9

Browse files
committed
Only change the RequestId
1 parent 69fe3e2 commit c3d7cc9

File tree

3 files changed

+18
-20
lines changed

3 files changed

+18
-20
lines changed

src/mcp/client/sse.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,24 +98,6 @@ async def sse_reader(
9898
message = types.JSONRPCMessage.model_validate_json( # noqa: E501
9999
sse.data
100100
)
101-
102-
# Normalize ID to int
103-
# if it's a numeric string.
104-
if isinstance( # noqa: E501
105-
message.root,
106-
types.JSONRPCResponse
107-
):
108-
msg_id = message.root.id
109-
if (isinstance(msg_id, str) and
110-
msg_id.isdigit()):
111-
message.root.id = int(msg_id)
112-
elif not isinstance(msg_id, int):
113-
logger.warning(
114-
"Ignored message with "
115-
f"invalid ID: {msg_id!r}"
116-
)
117-
continue
118-
119101
logger.debug(
120102
f"Received server message: {message}"
121103
)

src/mcp/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
ProgressToken = str | int
3535
Cursor = str
3636
Role = Literal["user", "assistant"]
37-
RequestId = str | int
37+
RequestId = Annotated[int | str, Field(union_mode="left_to_right")]
3838
AnyFunction: TypeAlias = Callable[..., Any]
3939

4040

@@ -353,7 +353,7 @@ class ProgressNotificationParams(NotificationParams):
353353
"""Total number of items to process (or total progress required), if known."""
354354
message: str | None = None
355355
"""
356-
Message related to progress. This should provide relevant human readable
356+
Message related to progress. This should provide relevant human readable
357357
progress information.
358358
"""
359359
model_config = ConfigDict(extra="allow")

tests/shared/test_sse.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
import httpx
99
import pytest
1010
import uvicorn
11+
from inline_snapshot import snapshot
1112
from pydantic import AnyUrl
1213
from starlette.applications import Starlette
1314
from starlette.requests import Request
1415
from starlette.responses import Response
1516
from starlette.routing import Mount, Route
1617

18+
import mcp.types as types
1719
from mcp.client.session import ClientSession
1820
from mcp.client.sse import sse_client
1921
from mcp.server import Server
@@ -503,3 +505,17 @@ async def test_request_context_isolation(context_server: None, server_url: str)
503505
assert ctx["request_id"] == f"request-{i}"
504506
assert ctx["headers"].get("x-request-id") == f"request-{i}"
505507
assert ctx["headers"].get("x-custom-value") == f"value-{i}"
508+
509+
510+
def test_sse_message_id_coercion():
511+
"""Test that string message IDs that look like integers are parsed as integers.
512+
513+
See <https://github.com/modelcontextprotocol/python-sdk/pull/851> for more details.
514+
"""
515+
json_message = '{"jsonrpc": "2.0", "id": "123", "method": "ping", "params": null}'
516+
msg = types.JSONRPCMessage.model_validate_json(json_message)
517+
assert msg == snapshot(
518+
types.JSONRPCMessage(
519+
root=types.JSONRPCRequest(method="ping", jsonrpc="2.0", id=123)
520+
)
521+
)

0 commit comments

Comments
 (0)