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