You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Trim the ClientSession migration section to behavior-relevant changes
Collapse 12 dense bullets to 6: keep BaseSession removal, the new
concurrency model, pre-enter/post-close error contracts, the raising-
callback code change, the removed metadata kwargs, and the
ClientRequestContext rename. Drop ids-from-1, the courtesy-cancel
exemption taxonomy, the (incorrect) resumption-hints-from-callbacks
bullet, the shutdown-CONNECTION_CLOSED detail, and the stray-response
handling - these are feature/internals trivia, not migration steps.
Also correct the protocol:error:null-id divergence note in the
requirements manifest: v1.x had a non-nullable JSONRPCError.id, so a
null-id error response failed transport validation and the
ValidationError reached message_handler as an exception. The note
previously described the v2-prerelease BaseSession's MCPError path
(PR #2056) as v1 behavior.
Copy file name to clipboardExpand all lines: docs/migration.md
+2-8Lines changed: 2 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1170,14 +1170,8 @@ In practice, replace direct `ServerSession` use with `Server.run(read_stream, wr
1170
1170
1171
1171
Behavior changes:
1172
1172
1173
-
-**Request ids count from 1** (previously 0); progress tokens, which reuse the id, shift too. Ids are opaque per JSON-RPC — do not assign meaning to them.
1174
-
-**Timeouts**: the error message is now `Request 'tools/call' timed out`, and a timed-out or abandoned request is followed by `notifications/cancelled` so the server stops the handler instead of leaving it running. Exempt: `initialize`, requests sent with resumption metadata (so they stay resumable), and requests whose initial write never completed (the peer never saw the id).
1175
-
-**Resumption hints sent from inside a request callback are dropped** (stream-routing metadata takes precedence there), so those requests are cancelled like any other.
1176
-
-**Server-initiated requests run concurrently.** A slow sampling/elicitation/roots callback no longer blocks other traffic, a callback may itself send requests without deadlocking, and a server's `notifications/cancelled` now interrupts the callback (the request is then answered with an error).
1177
-
-**Session shutdown now answers in-flight server-initiated requests with `CONNECTION_CLOSED` (-32000)**; v1 left them unanswered. The write is bounded (~1s) so closing stays fast.
1178
-
-**Notification callbacks are concurrent.**`logging_callback`, `progress_callback`, and `message_handler` deliveries start in arrival order but each runs as its own task: they may interleave, and a `progress_callback` delivery may finish after the request it reports on has returned. Callbacks that need strict sequencing must coordinate themselves, and there is no built-in bound on concurrent deliveries (v1's inline loop processed one message at a time).
1179
-
-**Transport-level `Exception` items are delivered to `message_handler` the same way** — as their own task, without blocking the receive loop — and a `message_handler` that raises on one is logged, not fatal to the session.
1180
-
-**Stray responses are no longer surfaced to `message_handler`.** Responses with an unknown id are ignored (as the spec asks; v1 surfaced a `RuntimeError`), and error responses with a null `id` — a peer reporting a parse error — are dropped with a debug log (v1 surfaced the transport's `ValidationError`).
1173
+
-**Callbacks and notifications now run concurrently.** In v1 the receive loop processed one inbound message at a time, so callbacks ran inline and in order. Now each delivery starts in arrival order but runs as its own task. Server-initiated request callbacks (`sampling`, `elicitation`, `roots`) no longer block other traffic, may themselves send requests without deadlocking, and are interrupted if the server sends `notifications/cancelled` (the request is then answered with an error). Notification callbacks (`logging_callback`, `progress_callback`, `message_handler`) may interleave, and a `progress_callback` may run after the request it reports on has returned; there is no built-in bound on concurrent deliveries. Transport-level errors reach `message_handler` the same way, and a `message_handler` that raises is logged rather than fatal to the session. Callbacks that need strict sequencing must coordinate themselves.
1174
+
-**Timeouts**: a timed-out or abandoned request is now followed by `notifications/cancelled`, so the server stops the handler instead of leaving it running.
1181
1175
-**A raising request callback** is answered with `code=0` and the exception text; v1 flattened every callback exception to `INVALID_PARAMS`. For a specific error response, return `ErrorData` (unchanged) or raise `MCPError`. One carve-out: pydantic's `ValidationError` is still answered with `INVALID_PARAMS`, as in v1.
1182
1176
-**`send_request` before entering the context manager** raises `RuntimeError` immediately; v1 wrote to the transport and hung until the timeout. After the connection has closed it raises `MCPError` (`CONNECTION_CLOSED`) instead. `send_notification` before entry still works.
1183
1177
-**`send_notification` no longer takes `related_request_id`, and `send_request` no longer accepts `ServerMessageMetadata`.** No client transport ever serialized these hints; progress and response correlation via `progressToken` and the request id is unaffected.
0 commit comments