@@ -49,6 +49,7 @@ async def handle_list_prompts(ctx: RequestContext) -> list[types.Prompt]:
4949from mcp .server .experimental .session_features import ExperimentalServerSessionFeatures
5050from mcp .server .models import InitializationOptions
5151from mcp .server .validation import validate_sampling_tools , validate_tool_use_result_messages
52+ from mcp .shared .exceptions import StatelessModeNotSupported
5253from mcp .shared .experimental .tasks .capabilities import check_tasks_capability
5354from mcp .shared .experimental .tasks .helpers import RELATED_TASK_METADATA_KEY
5455from mcp .shared .message import ServerMessageMetadata , SessionMessage
@@ -157,26 +158,6 @@ def check_client_capability(self, capability: types.ClientCapabilities) -> bool:
157158
158159 return True
159160
160- def _require_stateful_mode (self , feature_name : str ) -> None :
161- """Raise an error if trying to use a feature that requires stateful mode.
162-
163- Server-to-client requests (sampling, elicitation, list_roots) are not
164- supported in stateless HTTP mode because there is no persistent connection
165- for bidirectional communication.
166-
167- Args:
168- feature_name: Name of the feature being used (for error message)
169-
170- Raises:
171- RuntimeError: If the session is in stateless mode
172- """
173- if self ._stateless :
174- raise RuntimeError (
175- f"Cannot use { feature_name } in stateless HTTP mode. "
176- "Stateless mode does not support server-to-client requests. "
177- "Use stateful mode (stateless_http=False) to enable this feature."
178- )
179-
180161 async def _receive_loop (self ) -> None :
181162 async with self ._incoming_message_stream_writer :
182163 await super ()._receive_loop ()
@@ -332,9 +313,10 @@ async def create_message(
332313 Raises:
333314 McpError: If tools are provided but client doesn't support them.
334315 ValueError: If tool_use or tool_result message structure is invalid.
335- RuntimeError : If called in stateless HTTP mode.
316+ StatelessModeNotSupported : If called in stateless HTTP mode.
336317 """
337- self ._require_stateful_mode ("sampling" )
318+ if self ._stateless :
319+ raise StatelessModeNotSupported (method = "sampling" )
338320 client_caps = self ._client_params .capabilities if self ._client_params else None
339321 validate_sampling_tools (client_caps , tools , tool_choice )
340322 validate_tool_use_result_messages (messages )
@@ -372,7 +354,8 @@ async def create_message(
372354
373355 async def list_roots (self ) -> types .ListRootsResult :
374356 """Send a roots/list request."""
375- self ._require_stateful_mode ("list_roots" )
357+ if self ._stateless :
358+ raise StatelessModeNotSupported (method = "list_roots" )
376359 return await self .send_request (
377360 types .ServerRequest (types .ListRootsRequest ()),
378361 types .ListRootsResult ,
@@ -417,9 +400,10 @@ async def elicit_form(
417400 The client's response with form data
418401
419402 Raises:
420- RuntimeError : If called in stateless HTTP mode.
403+ StatelessModeNotSupported : If called in stateless HTTP mode.
421404 """
422- self ._require_stateful_mode ("elicitation" )
405+ if self ._stateless :
406+ raise StatelessModeNotSupported (method = "elicitation" )
423407 return await self .send_request (
424408 types .ServerRequest (
425409 types .ElicitRequest (
@@ -455,9 +439,10 @@ async def elicit_url(
455439 The client's response indicating acceptance, decline, or cancellation
456440
457441 Raises:
458- RuntimeError : If called in stateless HTTP mode.
442+ StatelessModeNotSupported : If called in stateless HTTP mode.
459443 """
460- self ._require_stateful_mode ("elicitation" )
444+ if self ._stateless :
445+ raise StatelessModeNotSupported (method = "elicitation" )
461446 return await self .send_request (
462447 types .ServerRequest (
463448 types .ElicitRequest (
0 commit comments