fix: raise clear error for server-to-client requests in stateless mode (#1827)
This commit is contained in:
parent
d52937b39c
commit
bb6cb029f0
1 changed files with 295 additions and 0 deletions
|
|
@ -93,6 +93,7 @@ class ServerSession(
|
|||
stateless: bool = False,
|
||||
) -> None:
|
||||
super().__init__(read_stream, write_stream, types.ClientRequest, types.ClientNotification)
|
||||
self._stateless = stateless
|
||||
self._initialization_state = (
|
||||
InitializationState.Initialized if stateless else InitializationState.NotInitialized
|
||||
)
|
||||
|
|
@ -156,6 +157,26 @@ class ServerSession(
|
|||
|
||||
return True
|
||||
|
||||
def _require_stateful_mode(self, feature_name: str) -> None:
|
||||
"""Raise an error if trying to use a feature that requires stateful mode.
|
||||
|
||||
Server-to-client requests (sampling, elicitation, list_roots) are not
|
||||
supported in stateless HTTP mode because there is no persistent connection
|
||||
for bidirectional communication.
|
||||
|
||||
Args:
|
||||
feature_name: Name of the feature being used (for error message)
|
||||
|
||||
Raises:
|
||||
RuntimeError: If the session is in stateless mode
|
||||
"""
|
||||
if self._stateless:
|
||||
raise RuntimeError(
|
||||
f"Cannot use {feature_name} in stateless HTTP mode. "
|
||||
"Stateless mode does not support server-to-client requests. "
|
||||
"Use stateful mode (stateless_http=False) to enable this feature."
|
||||
)
|
||||
|
||||
async def _receive_loop(self) -> None:
|
||||
async with self._incoming_message_stream_writer:
|
||||
await super()._receive_loop()
|
||||
|
|
@ -311,7 +332,9 @@ class ServerSession(
|
|||
Raises:
|
||||
McpError: If tools are provided but client doesn't support them.
|
||||
ValueError: If tool_use or tool_result message structure is invalid.
|
||||
RuntimeError: If called in stateless HTTP mode.
|
||||
"""
|
||||
self._require_stateful_mode("sampling")
|
||||
client_caps = self._client_params.capabilities if self._client_params else None
|
||||
validate_sampling_tools(client_caps, tools, tool_choice)
|
||||
validate_tool_use_result_messages(messages)
|
||||
|
|
@ -349,6 +372,7 @@ class ServerSession(
|
|||
|
||||
async def list_roots(self) -> types.ListRootsResult:
|
||||
"""Send a roots/list request."""
|
||||
self._require_stateful_mode("list_roots")
|
||||
return await self.send_request(
|
||||
types.ServerRequest(types.ListRootsRequest()),
|
||||
types.ListRootsResult,
|
||||
|
|
@ -391,7 +415,11 @@ class ServerSession(
|
|||
|
||||
Returns:
|
||||
The client's response with form data
|
||||
|
||||
Raises:
|
||||
RuntimeError: If called in stateless HTTP mode.
|
||||
"""
|
||||
self._require_stateful_mode("elicitation")
|
||||
return await self.send_request(
|
||||
types.ServerRequest(
|
||||
types.ElicitRequest(
|
||||
|
|
@ -425,7 +453,11 @@ class ServerSession(
|
|||
|
||||
Returns:
|
||||
The client's response indicating acceptance, decline, or cancellation
|
||||
|
||||
Raises:
|
||||
RuntimeError: If called in stateless HTTP mode.
|
||||
"""
|
||||
self._require_stateful_mode("elicitation")
|
||||
return await self.send_request(
|
||||
types.ServerRequest(
|
||||
types.ElicitRequest(
|
||||
|
|
|
|||
Loading…
Reference in a new issue