Skip to content

Commit 63ba33d

Browse files
committed
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."
1 parent a46eeea commit 63ba33d

17 files changed

Lines changed: 24 additions & 24 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
**The documentation lives at <https://py.sdk.modelcontextprotocol.io/v2/>.**
2626

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/).
2828

2929
## What is MCP?
3030

@@ -82,7 +82,7 @@ Call `add` with `a=1`, `b=2` and you get `3` back.
8282

8383
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.
8484

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.
8686

8787
## A client in 10 lines
8888

docs/advanced/multi-round-trip.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ That's the whole protocol. Every leg is an ordinary request from the client to t
1919

2020
## The server side
2121

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

2424
```python title="server.py" hl_lines="44-47"
2525
--8<-- "docs_src/mrtr/tutorial001.py"

docs/advanced/opentelemetry.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,4 @@ mcp._lowlevel_server.middleware[:] = [
104104
with no change to your server.
105105
* Client-to-server trace context propagates automatically when both sides run the SDK.
106106

107-
Next, the thing that decides whether a request runs at all: **[Authorization](authorization.md)**.
107+
The thing that decides whether a request runs at all is **[Authorization](authorization.md)**.

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ You wrote two Python functions with type hints and a docstring. The SDK does the
8989

9090
## Where to go next
9191

92-
* The **[Tutorial](tutorial/index.md)** walks through everything a server can do, one small step at a time.
92+
* **[Get started](tutorial/index.md)** takes you from install to a working, tested server.
9393
* Migrating from v1? Start with the **[Migration Guide](migration.md)**.
9494
* Hunting for an exact signature? The **[API Reference](api/mcp/index.md)** is generated from the source.
9595
* Reading with an LLM? This documentation is also published in the [llms.txt](https://llmstxt.org/) format:

docs/run/asgi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ASGI
1+
# Add to an existing app
22

33
`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.
44

docs/run/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Each transport has its own keyword arguments, all on `run()`:
6767
* `streamable_http_path`: where the MCP endpoint lives. Default `/mcp`.
6868
* `json_response=True`: answer with plain JSON instead of an SSE stream.
6969
* `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`.
7171

7272
!!! warning
7373
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()`:
7878
TypeError: MCPServer.__init__() got an unexpected keyword argument 'port'
7979
```
8080

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)**.
8282

8383
## Server settings
8484

@@ -143,4 +143,4 @@ uv run mcp install server.py -v API_KEY=abc123 -f .env
143143
* `mcp dev` for the Inspector, `mcp run` to execute a file, `mcp install` for Claude Desktop, `mcp version` for the version.
144144
* The transport never changes what your server *is*: all three files on this page expose the identical tool.
145145

146-
When `run()` itself is the limit (your server inside an app that already exists), the next step is **[ASGI](asgi.md)**.
146+
When `run()` itself is the limit (your server inside an app that already exists), the next step is **[Add to an existing app](asgi.md)**.

docs/tutorial/completions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ Drop `context_arguments=` and the same call returns `[]`. The handler can't know
122122
* `context.arguments` holds the already-resolved values; the client supplies them as `context_arguments=`.
123123
* The `completions` capability appears the moment you register the handler. Without it, the request is `Method not found`.
124124

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

docs/tutorial/dependencies.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,4 @@ That's the right default for a precondition: no answer, no order. When declining
142142
* Bad graphs fail at registration with `InvalidSignature`, not mid-call.
143143
* Return `Elicit(message, Model)` to ask the user, only when you have to. Unwrapped annotations abort on decline; `ElicitationResult[T]` lets the tool branch.
144144

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

docs/tutorial/elicitation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,4 @@ Now swap in the URL-mode `server.py` and point the same `main()` at `pay_deposit
169169
* The client answers with one `elicitation_callback`, branching on the params type; registering it is what declares the capability.
170170
* 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)**.
171171

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

docs/tutorial/first-steps.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ That dictionary is the server's half of the handshake:
113113
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.
114114

115115
!!! 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)**.
118118

119119
## What you did not write
120120

@@ -136,4 +136,4 @@ That ratio is the whole point of the SDK.
136136
* The server's **capabilities** are declared for you, and a client only asks for what a server declares.
137137
* `Client(mcp)` connects to the server object in memory: your test harness from day one.
138138

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

Comments
 (0)