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
Copy file name to clipboardExpand all lines: docs/advanced/low-level-server.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -181,7 +181,7 @@ The handshake belongs to the runner. `server/discover`, `ping`, and every other
181
181
182
182
Each of these is one idea you now have the vocabulary for; each has its own chapter.
183
183
184
-
*`on_call_tool`may return an `InputRequiredResult` instead of a `CallToolResult` to pause the call and ask the client for input; see **[Multi-round-trip requests](multi-round-trip.md)**.
184
+
*`on_call_tool`, `on_get_prompt`, and `on_read_resource`may return an `InputRequiredResult` instead of their normal result to pause the call and ask the client for input; see **[Multi-round-trip requests](multi-round-trip.md)**.
185
185
*`on_list_resources`, `on_read_resource`, `on_list_prompts`, `on_get_prompt`, `on_completion` are the same `(ctx, params) -> result` shape for the other primitives.
186
186
*`server.streamable_http_app()` returns the same Starlette app `MCPServer`'s does; deploy it the way **[Running your server](../run/index.md)** deploys any other ASGI app. There is no `server.run(transport=...)` down here: `server.run(read_stream, write_stream, server.create_initialization_options())` drives one connection over a pair of streams, and that one line is the whole story.
Copy file name to clipboardExpand all lines: docs/advanced/multi-round-trip.md
+14Lines changed: 14 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,6 +31,19 @@ On `@mcp.tool()` you rarely build this by hand: declare a dependency that asks t
31
31
32
32
Everything else in that file (the explicit `input_schema`, the hand-built `CallToolResult`) is the ordinary low-level `Server`, covered in **[The low-level Server](low-level-server.md)**. This page only adds the second return type.
33
33
34
+
## Beyond tools
35
+
36
+
`tools/call` is not special: at 2026-07-28 a server may answer `prompts/get` and `resources/read` the same way. On `MCPServer`, an `@mcp.prompt()` function — or an `@mcp.resource()`**template** function — returns the `InputRequiredResult` itself and reads the retry's answers off the context:
37
+
38
+
```python title="server.py" hl_lines="21 23 25"
39
+
--8<--"docs_src/mrtr/tutorial004.py"
40
+
```
41
+
42
+
* The first round returns the `InputRequiredResult`. On the retry, `ctx.input_responses` holds the answers under the same keys and the function returns its ordinary result — prompt messages here, resource content for a template resource.
43
+
* An `@mcp.tool()` function can return the result directly the same way, when the dependency form doesn't fit.
44
+
* Static `@mcp.resource()` functions don't participate: they take no `Context`, so they could never read the retry. Only template resources can ask.
45
+
* The era rules below apply unchanged: returning an `InputRequiredResult` on a pre-2026 session is the same `-32603` the warning describes.
46
+
34
47
## The client side
35
48
36
49
`Client` runs the loop for you.
@@ -94,5 +107,6 @@ Drop to the underlying session, where `allow_input_required=True` hands you the
94
107
*`Client` runs the retry loop for you: register `elicitation_callback` / `sampling_callback` / `list_roots_callback` and `call_tool` returns a plain `CallToolResult`. `input_required_max_rounds` (default 10) bounds it.
95
108
* To inspect or persist rounds, use `client.session.call_tool(..., allow_input_required=True)` and own the `while isinstance(result, InputRequiredResult)` loop yourself.
96
109
* On `@mcp.tool()`, a dependency that asks the user produces this result for you (**[Dependencies](../tutorial/dependencies.md)**); the **low-level**`Server` is the manual form.
110
+
* Prompts and resources participate too: an `@mcp.prompt()` or template `@mcp.resource()` function returns the `InputRequiredResult` itself and reads `ctx.input_responses` on the retry.
97
111
98
112
This is the mechanism that replaces server-initiated sampling and the rest of the push-style back-channel; see **[Deprecated features](deprecated.md)**.
0 commit comments