@@ -123,6 +123,17 @@ class ServerSession(
123123 types .ClientNotification ,
124124 ]
125125):
126+ """Server-side MCP session.
127+
128+ Concurrency model: incoming messages are processed sequentially by a single
129+ ``_receive_loop`` task spawned in ``BaseSession.__aenter__``. All state
130+ transitions driven by messages (``_received_request``, ``_received_notification``)
131+ therefore execute without concurrent interleaving. The only other code path
132+ that mutates ``_initialization_state`` is ``__aexit__``, which may overlap
133+ briefly with the receive loop before the task group is cancelled; that path
134+ already handles transition failures gracefully.
135+ """
136+
126137 _initialization_state : InitializationState = InitializationState .NotInitialized
127138 _client_params : types .InitializeRequestParams | None = None
128139 _experimental_features : ExperimentalServerSessionFeatures | None = None
@@ -172,6 +183,12 @@ def is_initialized(self) -> bool:
172183 def _transition_state (self , new_state : InitializationState ) -> None :
173184 """Transition the session to a new state, validating the transition.
174185
186+ This method is intentionally synchronous (no ``await``), so under
187+ cooperative scheduling no task switch can occur between the validity
188+ check and the state assignment. External synchronization is therefore
189+ unnecessary as long as the single-consumer invariant documented on the
190+ class holds.
191+
175192 Args:
176193 new_state: The target state to transition to.
177194
0 commit comments