Skip to content

Commit 7dbd488

Browse files
committed
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.
1 parent b4cb9ca commit 7dbd488

4 files changed

Lines changed: 17 additions & 6 deletions

File tree

docs/advanced/deprecated.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The table below names each deprecated feature, why it is going away, and the rep
88

99
| Deprecated | Why | What you do instead |
1010
|---|---|---|
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**). |
1212
| **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**). |
1313
| **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**). |
1414
| **`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
1717
Three things fall out of that table:
1818

1919
* 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.
2121
* `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"*.
2222

2323
## 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
8282
## Recap
8383

8484
* 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.
8686
* 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).
8787
* 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.
8888
* `warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` silences the whole category; `"error::mcp.MCPDeprecationWarning"` in pytest turns it into a test failure.

docs/advanced/multi-round-trip.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Register the callbacks the server might ask for (`elicitation_callback`, `sampli
4141
--8<-- "docs_src/mrtr/tutorial003.py"
4242
```
4343

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.
4545
* `call_tool` returns a plain `CallToolResult`. The intermediate rounds are invisible to the caller.
4646
* `get_prompt` and `read_resource` drive the same loop.
4747

@@ -54,7 +54,13 @@ The loop is bounded. `Client(..., input_required_max_rounds=10)` is the default
5454

5555
### Driving the loop yourself
5656

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:
5864

5965
```python title="client.py" hl_lines="13 14 20"
6066
--8<-- "docs_src/mrtr/tutorial002.py"

docs/client/callbacks.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ One `tools/call` from you, one `elicitation/create` back from the server, answer
6161
protocol does, in-memory and over a URL alike. Pin `mode="legacy"` whenever your client has
6262
to answer one; every test behind this page does. **Protocol versions** has the whole story.
6363

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+
6468
## A callback is a capability
6569

6670
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
109113

110114
`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.
111115

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**.
113117

114118
You still need the callbacks to talk to servers that haven't moved. The signatures:
115119

docs/tutorial/elicitation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,5 +149,6 @@ Now swap in the URL-mode `server.py` and point the same `main()` at `pay_deposit
149149
* `result.action` is `"accept"`, `"decline"` or `"cancel"`; `result.data` exists only on accept.
150150
* `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.
151151
* 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**.
152153

153154
A tool that can ask is good. A tool that says how far along it is (**Progress**) is next.

0 commit comments

Comments
 (0)