mirror of
https://github.com/aljazceru/mcp-python-sdk.git
synced 2025-12-19 06:54:18 +01:00
Servers to accept older versions of client (#722)
This commit is contained in:
@@ -52,6 +52,7 @@ from mcp.shared.session import (
|
|||||||
BaseSession,
|
BaseSession,
|
||||||
RequestResponder,
|
RequestResponder,
|
||||||
)
|
)
|
||||||
|
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS
|
||||||
|
|
||||||
|
|
||||||
class InitializationState(Enum):
|
class InitializationState(Enum):
|
||||||
@@ -150,13 +151,16 @@ class ServerSession(
|
|||||||
):
|
):
|
||||||
match responder.request.root:
|
match responder.request.root:
|
||||||
case types.InitializeRequest(params=params):
|
case types.InitializeRequest(params=params):
|
||||||
|
requested_version = params.protocolVersion
|
||||||
self._initialization_state = InitializationState.Initializing
|
self._initialization_state = InitializationState.Initializing
|
||||||
self._client_params = params
|
self._client_params = params
|
||||||
with responder:
|
with responder:
|
||||||
await responder.respond(
|
await responder.respond(
|
||||||
types.ServerResult(
|
types.ServerResult(
|
||||||
types.InitializeResult(
|
types.InitializeResult(
|
||||||
protocolVersion=types.LATEST_PROTOCOL_VERSION,
|
protocolVersion=requested_version
|
||||||
|
if requested_version in SUPPORTED_PROTOCOL_VERSIONS
|
||||||
|
else types.LATEST_PROTOCOL_VERSION,
|
||||||
capabilities=self._init_options.capabilities,
|
capabilities=self._init_options.capabilities,
|
||||||
serverInfo=types.Implementation(
|
serverInfo=types.Implementation(
|
||||||
name=self._init_options.server_name,
|
name=self._init_options.server_name,
|
||||||
|
|||||||
@@ -106,3 +106,97 @@ async def test_server_capabilities():
|
|||||||
caps = server.get_capabilities(notification_options, experimental_capabilities)
|
caps = server.get_capabilities(notification_options, experimental_capabilities)
|
||||||
assert caps.prompts == PromptsCapability(listChanged=False)
|
assert caps.prompts == PromptsCapability(listChanged=False)
|
||||||
assert caps.resources == ResourcesCapability(subscribe=False, listChanged=False)
|
assert caps.resources == ResourcesCapability(subscribe=False, listChanged=False)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
async def test_server_session_initialize_with_older_protocol_version():
|
||||||
|
"""Test that server accepts and responds with older protocol (2024-11-05)."""
|
||||||
|
server_to_client_send, server_to_client_receive = anyio.create_memory_object_stream[
|
||||||
|
SessionMessage
|
||||||
|
](1)
|
||||||
|
client_to_server_send, client_to_server_receive = anyio.create_memory_object_stream[
|
||||||
|
SessionMessage | Exception
|
||||||
|
](1)
|
||||||
|
|
||||||
|
received_initialized = False
|
||||||
|
received_protocol_version = None
|
||||||
|
|
||||||
|
async def run_server():
|
||||||
|
nonlocal received_initialized
|
||||||
|
|
||||||
|
async with ServerSession(
|
||||||
|
client_to_server_receive,
|
||||||
|
server_to_client_send,
|
||||||
|
InitializationOptions(
|
||||||
|
server_name="mcp",
|
||||||
|
server_version="0.1.0",
|
||||||
|
capabilities=ServerCapabilities(),
|
||||||
|
),
|
||||||
|
) as server_session:
|
||||||
|
async for message in server_session.incoming_messages:
|
||||||
|
if isinstance(message, Exception):
|
||||||
|
raise message
|
||||||
|
|
||||||
|
if isinstance(message, types.ClientNotification) and isinstance(
|
||||||
|
message.root, InitializedNotification
|
||||||
|
):
|
||||||
|
received_initialized = True
|
||||||
|
return
|
||||||
|
|
||||||
|
async def mock_client():
|
||||||
|
nonlocal received_protocol_version
|
||||||
|
|
||||||
|
# Send initialization request with older protocol version (2024-11-05)
|
||||||
|
await client_to_server_send.send(
|
||||||
|
SessionMessage(
|
||||||
|
types.JSONRPCMessage(
|
||||||
|
types.JSONRPCRequest(
|
||||||
|
jsonrpc="2.0",
|
||||||
|
id=1,
|
||||||
|
method="initialize",
|
||||||
|
params=types.InitializeRequestParams(
|
||||||
|
protocolVersion="2024-11-05",
|
||||||
|
capabilities=types.ClientCapabilities(),
|
||||||
|
clientInfo=types.Implementation(
|
||||||
|
name="test-client", version="1.0.0"
|
||||||
|
),
|
||||||
|
).model_dump(by_alias=True, mode="json", exclude_none=True),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Wait for the initialize response
|
||||||
|
init_response_message = await server_to_client_receive.receive()
|
||||||
|
assert isinstance(init_response_message.message.root, types.JSONRPCResponse)
|
||||||
|
result_data = init_response_message.message.root.result
|
||||||
|
init_result = types.InitializeResult.model_validate(result_data)
|
||||||
|
|
||||||
|
# Check that the server responded with the requested protocol version
|
||||||
|
received_protocol_version = init_result.protocolVersion
|
||||||
|
assert received_protocol_version == "2024-11-05"
|
||||||
|
|
||||||
|
# Send initialized notification
|
||||||
|
await client_to_server_send.send(
|
||||||
|
SessionMessage(
|
||||||
|
types.JSONRPCMessage(
|
||||||
|
types.JSONRPCNotification(
|
||||||
|
jsonrpc="2.0",
|
||||||
|
method="notifications/initialized",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
async with (
|
||||||
|
client_to_server_send,
|
||||||
|
client_to_server_receive,
|
||||||
|
server_to_client_send,
|
||||||
|
server_to_client_receive,
|
||||||
|
anyio.create_task_group() as tg,
|
||||||
|
):
|
||||||
|
tg.start_soon(run_server)
|
||||||
|
tg.start_soon(mock_client)
|
||||||
|
|
||||||
|
assert received_initialized
|
||||||
|
assert received_protocol_version == "2024-11-05"
|
||||||
|
|||||||
Reference in New Issue
Block a user