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
docs: cross-link callbacks/elicitation/deprecated to MRTR; add when-to-drive-yourself
- multi-round-trip.md: spell out that all three callbacks serve both eras
(standalone RPCs gone in 2026, same payloads ride in input_requests);
expand the manual-loop section with the distributed-client / inspection /
wall-clock-bound use cases.
- callbacks.md: note that the 2026 auto-loop dispatches to the same
elicitation/sampling/roots callbacks; clarify it's the RPCs that go,
not the callbacks.
- deprecated.md: roots replacement now points at MRTR (ListRootsRequest
embedded in InputRequiredResult); clarify payload-survives-RPC-doesn't.
- tutorial/elicitation.md: recap bullet linking to MRTR.
Copy file name to clipboardExpand all lines: docs/advanced/deprecated.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ The table below names each deprecated feature, why it is going away, and the rep
8
8
9
9
| Deprecated | Why | What you do instead |
10
10
|---|---|---|
11
-
|**Roots**: `ctx.session.list_roots()`, `client.send_roots_list_changed()`, the `list_roots_callback=` you pass to `Client(...)`|[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) retires the capability. | Take the paths that matter as ordinary tool arguments or resource URIs. |
11
+
|**Roots**: `ctx.session.list_roots()`, `client.send_roots_list_changed()`, the `list_roots_callback=` you pass to `Client(...)`|[SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) retires the capability. | Take the paths as ordinary tool arguments or resource URIs, or embed a `ListRootsRequest` in an `InputRequiredResult` (see **Multi-round-trip requests**). |
12
12
|**Server-initiated sampling**: `ctx.session.create_message()`, the `sampling_callback=` you pass to `Client(...)`| SEP-2577 retires the capability. | Return `InputRequiredResult` and let the client retry the call (see **Multi-round-trip requests**). |
13
13
|**Protocol logging**: `ctx.log()`, `ctx.debug()`, `ctx.info()`, `ctx.warning()`, `ctx.error()`, `ctx.session.send_log_message()`, `client.set_logging_level()`| SEP-2577 retires the capability. Nothing in-protocol replaces it. | Ordinary `import logging` to stderr (see **Logging**). |
14
14
|**`ping`**: `client.send_ping()`|**Removed** from the protocol, not merely deprecated. There is no `ping` method in 2026-07-28. | Nothing. It only works against a `mode="legacy"` connection. |
@@ -17,7 +17,7 @@ The table below names each deprecated feature, why it is going away, and the rep
17
17
Three things fall out of that table:
18
18
19
19
* Roots, sampling, and logging go together. One proposal, **SEP-2577**, deprecates all three capabilities at once.
20
-
* Sampling and roots share a deeper problem: they are the two places a **server** sends a **request** to the **client**. That whole direction is what 2026-07-28 replaces with **Multi-round-trip requests**.
20
+
* Sampling and roots share a deeper problem: they are places a **server** sends a **request** to the **client**. That whole direction is what 2026-07-28 replaces with **Multi-round-trip requests**. It is the standalone RPC methods (`sampling/createMessage`, `roots/list`, and push-style `elicitation/create`) that are gone; the `CreateMessageRequest` / `ListRootsRequest` / `ElicitRequest` payload types survive, embedded in `InputRequiredResult.input_requests`, and on the client they hit the same callbacks.
21
21
*`ping` is the odd one out. The protocol does not deprecate it, it removes it. The SDK method still warns (its message says *removed*, not *deprecated*) and calling it on a modern connection answers with *"Method not found"*.
22
22
23
23
## Deprecated is advisory
@@ -82,7 +82,7 @@ That is the whole API. There is no per-method switch, and you don't want one: th
82
82
## Recap
83
83
84
84
* The 2026-07-28 spec deprecates **roots**, server-initiated **sampling**, and protocol **logging** (all SEP-2577), restricts **progress** to server-to-client, and removes **`ping`**.
85
-
* The replacement column points you onward: **Multi-round-trip requests** for sampling, **Logging** for logging, **Progress** for progress. Roots needs no chapter (pass the paths as arguments) and`ping` needs nothing at all.
85
+
* The replacement column points you onward: **Multi-round-trip requests** for sampling and roots, **Logging** for logging, **Progress** for progress. `ping` needs nothing at all.
86
86
* Deprecated is advisory: no wire changes, everything keeps working against pre-2026 sessions, and you get a visible `MCPDeprecationWarning` (a `UserWarning`, so it is on by default).
87
87
* Sampling and roots additionally need a back-channel that a 2026-07-28 session does not have. On a modern connection they warn and then they raise.
88
88
*`warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` silences the whole category; `"error::mcp.MCPDeprecationWarning"` in pytest turns it into a test failure.
Copy file name to clipboardExpand all lines: docs/advanced/multi-round-trip.md
+8-2Lines changed: 8 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -41,7 +41,7 @@ Register the callbacks the server might ask for (`elicitation_callback`, `sampli
41
41
--8<--"docs_src/mrtr/tutorial003.py"
42
42
```
43
43
44
-
* That `elicitation_callback` is the same one a pre-2026 server's back-channel `elicitation/create` would have hit. One callback serves both eras.
44
+
* That `elicitation_callback` is the same one a pre-2026 server's back-channel `elicitation/create` would have hit. The same is true of `sampling_callback` for `sampling/createMessage` and `list_roots_callback` for `roots/list`: at 2026-07-28 the standalone server->client RPCs are gone, but the identical `ElicitRequest` / `CreateMessageRequest` / `ListRootsRequest` payloads ride inside `input_requests` and dispatch to the same three callbacks. One set of callbacks serves both eras.
45
45
*`call_tool` returns a plain `CallToolResult`. The intermediate rounds are invisible to the caller.
46
46
*`get_prompt` and `read_resource` drive the same loop.
47
47
@@ -54,7 +54,13 @@ The loop is bounded. `Client(..., input_required_max_rounds=10)` is the default
54
54
55
55
### Driving the loop yourself
56
56
57
-
The auto-loop holds nothing between calls. If you need to see each round (to persist `request_state` across a process restart, to show the user what was asked, to bail early) drop to the underlying session, where `allow_input_required=True` hands you the union directly:
57
+
The auto-loop is enough for a single-process client. Own the loop instead when:
58
+
59
+
* Your client is **distributed**: the process that renders the question to the user is not the process that called `call_tool`, so a different worker issues the retry. `request_state` is the persistable token you carry across that boundary, through your own storage, and `input_responses` is what the other side sends back with it.
60
+
* You want to **inspect** each round: log or audit every `input_requests` entry, refuse certain request kinds, or apply your own backoff between legs.
61
+
* You want a **wall-clock** bound rather than a round-count bound: wrap your own loop in `anyio.fail_after(...)` instead of relying on `input_required_max_rounds`.
62
+
63
+
Drop to the underlying session, where `allow_input_required=True` hands you the union directly:
Copy file name to clipboardExpand all lines: docs/client/callbacks.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,10 @@ One `tools/call` from you, one `elicitation/create` back from the server, answer
61
61
protocol does, in-memory and over a URL alike. Pin `mode="legacy"` whenever your client has
62
62
to answer one; every test behind this page does. **Protocol versions** has the whole story.
63
63
64
+
On a 2026-07-28 session the callback isn't dead, it's fed differently: when a tool returns an
65
+
`InputRequiredResult` carrying an `ElicitRequest`, `Client` dispatches that entry to the same
66
+
`elicitation_callback` and retries the call for you. That flow is **Multi-round-trip requests**.
67
+
64
68
## A callback is a capability
65
69
66
70
You never told the server that your client can answer elicitation requests. The SDK did.
@@ -109,7 +113,7 @@ Pass all three callbacks and you get `['elicitation', 'sampling', 'roots']`. Pas
109
113
110
114
`sampling_callback` answers `sampling/createMessage`: the server asking *your* model to complete something. `list_roots_callback` answers `roots/list`: the server asking which directories it may work in.
111
115
112
-
Both work. Both follow the rule above. And both serve features the **2026-07-28 spec deprecates**: a modern server doesn't call back into your model mid-request, it hands the request back to you as part of the tool result (**Multi-round-trip requests**), and roots give way to plain tool arguments and resource URIs. The whole list is in **Deprecated features**.
116
+
Both work. Both follow the rule above. And both serve RPCs the **2026-07-28 spec removes**: a modern server doesn't call back into your client mid-request, it hands the request back to you as part of the tool result (**Multi-round-trip requests**). The callbacks themselves are not dead. When an `InputRequiredResult` carries a `CreateMessageRequest` or a `ListRootsRequest`, `Client`'s auto-loop dispatches it to the same `sampling_callback` or `list_roots_callback` you registered here. The whole list is in **Deprecated features**.
113
117
114
118
You still need the callbacks to talk to servers that haven't moved. The signatures:
Copy file name to clipboardExpand all lines: docs/tutorial/elicitation.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -149,5 +149,6 @@ Now swap in the URL-mode `server.py` and point the same `main()` at `pay_deposit
149
149
*`result.action` is `"accept"`, `"decline"` or `"cancel"`; `result.data` exists only on accept.
150
150
*`await ctx.elicit_url(message, url, elicitation_id)` is for everything that must not pass through the model; `ctx.session.send_elicit_complete(elicitation_id)` says the out-of-band part is done.
151
151
* The client answers with one `elicitation_callback`, branching on the params type; registering it is what declares the capability.
152
+
* On a 2026-07-28 connection the server returns the question instead of pushing it; the same callback is fed by **Multi-round-trip requests**.
152
153
153
154
A tool that can ask is good. A tool that says how far along it is (**Progress**) is next.
0 commit comments