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: retitle hand-offs and link text to match the new nav
The pages chain into each other with end-of-page "Next: ..." hand-offs.
Under the regrouped nav some of those pointed backward, or across a
section boundary, or at a page by a title it no longer carries. Fix each
one to hand off to the page that actually follows it in its section, or
to the next section where it is the last page.
Also:
- "ASGI" (the page H1 and every link to it) becomes "Add to an existing
app". The old title named a Python interface standard; the page's
content is mounting into an existing Starlette/FastAPI app, the
DNS-rebinding 421, and CORS -- none of which anyone finds under the
word "ASGI". (#1798 is literally a user asking for a "Guide" to
content that already exists on that page.)
- The landing page and README stop calling the docs "the tutorial"; the
section they named is now "Get started" and the body of the docs is a
reference, not a course.
- Three sentences that said "this tutorial" now say "these docs"; there
is no longer a tutorial for them to be in.
- A pre-existing factual error on completions.md is fixed while its
closing line is retargeted: completions apply to prompt arguments and
resource-template parameters, never to a tool's, but the sentence said
"Suggestions help before a tool runs."
Copy file name to clipboardExpand all lines: README.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@
24
24
25
25
**The documentation lives at <https://py.sdk.modelcontextprotocol.io/v2/>.**
26
26
27
-
It has the full [tutorial](https://py.sdk.modelcontextprotocol.io/v2/tutorial/), the [API reference](https://py.sdk.modelcontextprotocol.io/v2/api/mcp/), and the [migration guide](https://py.sdk.modelcontextprotocol.io/v2/migration/).
27
+
It has a [Get started guide](https://py.sdk.modelcontextprotocol.io/v2/tutorial/), the [API reference](https://py.sdk.modelcontextprotocol.io/v2/api/mcp/), and the [migration guide](https://py.sdk.modelcontextprotocol.io/v2/migration/).
28
28
29
29
## What is MCP?
30
30
@@ -82,7 +82,7 @@ Call `add` with `a=1`, `b=2` and you get `3` back.
82
82
83
83
Notice what you did **not** write: no JSON Schema (`a: int, b: int`_is_ the schema), no request parsing, no validation code, no protocol handling. Two type-hinted Python functions and a docstring.
84
84
85
-
[The tutorial](https://py.sdk.modelcontextprotocol.io/v2/tutorial/) takes it from here.
85
+
[Get started](https://py.sdk.modelcontextprotocol.io/v2/tutorial/) takes it from here.
Copy file name to clipboardExpand all lines: docs/advanced/multi-round-trip.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
@@ -19,7 +19,7 @@ That's the whole protocol. Every leg is an ordinary request from the client to t
19
19
20
20
## The server side
21
21
22
-
On `@mcp.tool()` you rarely build this by hand: declare a dependency that asks the user and the SDK returns the `InputRequiredResult` for you - that form is the **[Dependencies](../tutorial/dependencies.md)**tutorial. The two forms don't mix: a call has one `input_responses`/`request_state` channel, so a tool that uses `Resolve(...)` parameters cannot also return `InputRequiredResult` from its body. A declared `InputRequiredResult` return is rejected at registration (`InvalidSignature`), and an undeclared one fails the call at runtime. The manual form is the **low-level**`Server`, whose `on_call_tool` handler is allowed to return either result type:
22
+
On `@mcp.tool()` you rarely build this by hand: declare a dependency that asks the user and the SDK returns the `InputRequiredResult` for you - that form is the **[Dependencies](../tutorial/dependencies.md)**page. The two forms don't mix: a call has one `input_responses`/`request_state` channel, so a tool that uses `Resolve(...)` parameters cannot also return `InputRequiredResult` from its body. A declared `InputRequiredResult` return is rejected at registration (`InvalidSignature`), and an undeclared one fails the call at runtime. The manual form is the **low-level**`Server`, whose `on_call_tool` handler is allowed to return either result type:
Copy file name to clipboardExpand all lines: docs/run/asgi.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
@@ -1,4 +1,4 @@
1
-
# ASGI
1
+
# Add to an existing app
2
2
3
3
`mcp.run("streamable-http")` starts a web server for you. Sometimes you don't want that: your MCP server is one piece of a larger web application, or you already have an ASGI deployment.
Copy file name to clipboardExpand all lines: docs/run/index.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
@@ -67,7 +67,7 @@ Each transport has its own keyword arguments, all on `run()`:
67
67
*`streamable_http_path`: where the MCP endpoint lives. Default `/mcp`.
68
68
*`json_response=True`: answer with plain JSON instead of an SSE stream.
69
69
*`stateless_http=True`: a fresh transport per request, no session tracking.
70
-
*`event_store`, `retry_interval`, `transport_security`: resumability and DNS-rebinding protection. They can wait, until you deploy somewhere other than localhost; **[ASGI](asgi.md)** covers `transport_security`.
70
+
*`event_store`, `retry_interval`, `transport_security`: resumability and DNS-rebinding protection. They can wait, until you deploy somewhere other than localhost; **[Add to an existing app](asgi.md)** covers `transport_security`.
71
71
72
72
!!! warning
73
73
Transport options go to `run()`, **not** to `MCPServer(...)`. The constructor describes what
@@ -78,7 +78,7 @@ Each transport has its own keyword arguments, all on `run()`:
78
78
TypeError: MCPServer.__init__() got an unexpected keyword argument 'port'
79
79
```
80
80
81
-
`run()` is the short road. The moment you need more (your server mounted inside an existing app, two servers in one process, CORS for browser clients), you build the ASGI app yourself and hand it to any ASGI host. That is **[ASGI](asgi.md)**.
81
+
`run()` is the short road. The moment you need more (your server mounted inside an existing app, two servers in one process, CORS for browser clients), you build the ASGI app yourself and hand it to any ASGI host. That is **[Add to an existing app](asgi.md)**.
Copy file name to clipboardExpand all lines: docs/tutorial/completions.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
@@ -122,4 +122,4 @@ Drop `context_arguments=` and the same call returns `[]`. The handler can't know
122
122
*`context.arguments` holds the already-resolved values; the client supplies them as `context_arguments=`.
123
123
* The `completions` capability appears the moment you register the handler. Without it, the request is `Method not found`.
124
124
125
-
Suggestions help *before* a tool runs. To ask the user a question in the *middle* of one, you want **[Elicitation](elicitation.md)**.
125
+
Suggestions help while the user is still *filling in* a prompt or template; to ask them a question in the *middle* of a tool call, you want **[Elicitation](elicitation.md)**. Next: everything a tool can return besides text, in **[Images, audio & icons](media.md)**.
Copy file name to clipboardExpand all lines: docs/tutorial/dependencies.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
@@ -142,4 +142,4 @@ That's the right default for a precondition: no answer, no order. When declining
142
142
* Bad graphs fail at registration with `InvalidSignature`, not mid-call.
143
143
* Return `Elicit(message, Model)` to ask the user, only when you have to. Unwrapped annotations abort on decline; `ElicitationResult[T]` lets the tool branch.
144
144
145
-
Next: what happens when your tool fails, and how to choose who finds out, in **[Handling errors](handling-errors.md)**.
145
+
Next: state your server builds once at startup, and how a handler reaches it, in the **[Lifespan](lifespan.md)**.
Copy file name to clipboardExpand all lines: docs/tutorial/elicitation.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
@@ -169,4 +169,4 @@ Now swap in the URL-mode `server.py` and point the same `main()` at `pay_deposit
169
169
* The client answers with one `elicitation_callback`, branching on the params type; registering it is what declares the capability.
170
170
* 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](../advanced/multi-round-trip.md)**.
171
171
172
-
A tool that can ask is good. A tool that says how far along it is (**[Progress](progress.md)**) is next.
172
+
Everything underneath that return — the retry loop, protecting `requestState`, driving it yourself — is **[Multi-round-trip requests](../advanced/multi-round-trip.md)**.
Copy file name to clipboardExpand all lines: docs/tutorial/first-steps.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
@@ -113,8 +113,8 @@ That dictionary is the server's half of the handshake:
113
113
Notice what isn't there. `completions` (argument autocomplete for resource templates and prompts) needs a handler you write, this server doesn't have one, so the capability is absent and a well-behaved client won't ask. That's the rule for everything optional: register the thing and the capability appears; **[Completions](completions.md)** proves it.
114
114
115
115
!!! info
116
-
`Client(mcp)` is the same in-memory client every example in this tutorial is tested with, and
117
-
it's how you'll test yours. It gets a whole chapter: **[Testing](testing.md)**.
116
+
`Client(mcp)` is the same in-memory client every example in these docs is tested with, and
117
+
it's how you'll test yours. It gets a whole page: **[Testing](testing.md)**.
118
118
119
119
## What you did not write
120
120
@@ -136,4 +136,4 @@ That ratio is the whole point of the SDK.
136
136
* The server's **capabilities** are declared for you, and a client only asks for what a server declares.
137
137
*`Client(mcp)` connects to the server object in memory: your test harness from day one.
138
138
139
-
Each primitive now gets its own chapter, starting with the one the model drives: **[Tools](tools.md)**.
139
+
Next: **[Testing](testing.md)** — one page, one in-memory client, and you're never guessing whether it works. Then each primitive gets its own page, starting with the one the model drives: **[Tools](tools.md)**.
0 commit comments