Skip to content

Commit faf3a9d

Browse files
authored
Merge pull request #205 from modelcontextprotocol/issue-192-request-id-test
Add test to verify request ID preservation
2 parents 92ba4f4 + 41af509 commit faf3a9d

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

tests/issues/test_192_request_id.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import anyio
2+
import pytest
3+
4+
from mcp.server.lowlevel import NotificationOptions, Server
5+
from mcp.server.models import InitializationOptions
6+
from mcp.types import (
7+
LATEST_PROTOCOL_VERSION,
8+
ClientCapabilities,
9+
Implementation,
10+
InitializeRequestParams,
11+
JSONRPCMessage,
12+
JSONRPCNotification,
13+
JSONRPCRequest,
14+
NotificationParams,
15+
)
16+
17+
18+
@pytest.mark.anyio
19+
async def test_request_id_match() -> None:
20+
"""Test that the server preserves request IDs in responses."""
21+
server = Server("test")
22+
custom_request_id = "test-123"
23+
24+
# Create memory streams for communication
25+
client_writer, client_reader = anyio.create_memory_object_stream(1)
26+
server_writer, server_reader = anyio.create_memory_object_stream(1)
27+
28+
# Server task to process the request
29+
async def run_server():
30+
async with client_reader, server_writer:
31+
await server.run(
32+
client_reader,
33+
server_writer,
34+
InitializationOptions(
35+
server_name="test",
36+
server_version="1.0.0",
37+
capabilities=server.get_capabilities(
38+
notification_options=NotificationOptions(),
39+
experimental_capabilities={},
40+
),
41+
),
42+
raise_exceptions=True,
43+
)
44+
45+
# Start server task
46+
async with anyio.create_task_group() as tg:
47+
tg.start_soon(run_server)
48+
49+
# Send initialize request
50+
init_req = JSONRPCRequest(
51+
id="init-1",
52+
method="initialize",
53+
params=InitializeRequestParams(
54+
protocolVersion=LATEST_PROTOCOL_VERSION,
55+
capabilities=ClientCapabilities(),
56+
clientInfo=Implementation(name="test-client", version="1.0.0"),
57+
).model_dump(by_alias=True, exclude_none=True),
58+
jsonrpc="2.0",
59+
)
60+
61+
await client_writer.send(JSONRPCMessage(root=init_req))
62+
await server_reader.receive() # Get init response but don't need to check it
63+
64+
# Send initialized notification
65+
initialized_notification = JSONRPCNotification(
66+
method="notifications/initialized",
67+
params=NotificationParams().model_dump(by_alias=True, exclude_none=True),
68+
jsonrpc="2.0",
69+
)
70+
await client_writer.send(JSONRPCMessage(root=initialized_notification))
71+
72+
# Send ping request with custom ID
73+
ping_request = JSONRPCRequest(
74+
id=custom_request_id, method="ping", params={}, jsonrpc="2.0"
75+
)
76+
77+
await client_writer.send(JSONRPCMessage(root=ping_request))
78+
79+
# Read response
80+
response = await server_reader.receive()
81+
82+
# Verify response ID matches request ID
83+
assert (
84+
response.root.id == custom_request_id
85+
), "Response ID should match request ID"
86+
87+
# Cancel server task
88+
tg.cancel_scope.cancel()

0 commit comments

Comments
 (0)