Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/advanced/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ The SDK has no opinion about what a valid token looks like. You tell it, by impl

!!! tip
`examples/servers/simple-auth/` in the SDK repository has an `IntrospectionTokenVerifier` that calls
a real authorization server's RFC 7662 endpoint. It's the shape most production verifiers take.
a real authorization server's [RFC 7662](https://datatracker.ietf.org/doc/html/rfc7662) endpoint. It's the shape most production verifiers take.

## What you get over HTTP

Authorization lives in HTTP headers, so it exists only on the HTTP transports. Run it on the one you deploy: `mcp.run(transport="streamable-http")` puts it on `http://127.0.0.1:8000/mcp`, and **Running your server** has the rest. The app now has two routes:
Authorization lives in HTTP headers, so it exists only on the HTTP transports. Run it on the one you deploy: `mcp.run(transport="streamable-http")` puts it on `http://127.0.0.1:8000/mcp`, and **[Running your server](../run/index.md)** has the rest. The app now has two routes:

```text
/mcp
Expand All @@ -47,7 +47,7 @@ You registered one tool. The second route is the SDK's.

### Discovery

`GET` that well-known path and you get **RFC 9728 Protected Resource Metadata**, built straight from your `AuthSettings`:
`GET` that well-known path and you get **[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata**, built straight from your `AuthSettings`:

```json
{
Expand Down Expand Up @@ -109,15 +109,15 @@ To watch all three parties move, run `examples/servers/simple-auth/` from the SD
server inside your MCP server. It predates the AS/RS separation that the MCP authorization spec
is built around. New servers should not reach for it.

An authorization server can also accept an enterprise identity provider's signed assertion in place of a user clicking through a consent screen, and the SDK supports both sides of that exchange. The grant, and the client that presents it, is **Identity assertion**.
An authorization server can also accept an enterprise identity provider's signed assertion in place of a user clicking through a consent screen, and the SDK supports both sides of that exchange. The grant, and the client that presents it, is **[Identity assertion](identity-assertion.md)**.

## Recap

* Over Streamable HTTP your server is an OAuth 2.1 **resource server**: it verifies tokens, it never issues them.
* `TokenVerifier` is the whole integration surface: one async method, token in, `AccessToken | None` out.
* `token_verifier=` and `auth=AuthSettings(issuer_url=..., resource_server_url=..., required_scopes=[...])` always travel together.
* The SDK publishes RFC 9728 Protected Resource Metadata at `/.well-known/oauth-protected-resource/...` and answers unauthenticated requests with a 401 whose `WWW-Authenticate` header points at it. That is the entire discovery story.
* The SDK publishes [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata at `/.well-known/oauth-protected-resource/...` and answers unauthenticated requests with a 401 whose `WWW-Authenticate` header points at it. That is the entire discovery story.
* `get_access_token()` in any handler is who's calling.
* Authorization is an HTTP concern. `stdio` and the in-memory client never see it.

The other side of the handshake, a client that discovers your authorization server and fetches the token for you, is **OAuth clients**.
The other side of the handshake, a client that discovers your authorization server and fetches the token for you, is **[OAuth clients](oauth-clients.md)**.
14 changes: 7 additions & 7 deletions docs/advanced/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ The table below names each deprecated feature, why it is going away, and the rep

| Deprecated | Why | What you do instead |
|---|---|---|
| **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**). |
| **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**). |
| **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**). |
| **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](multi-round-trip.md)**). |
| **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](multi-round-trip.md)**). |
| **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](../tutorial/logging.md)**). |
| **`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. |
| **Client->server progress**: `client.send_progress_notification()` | 2026-07-28 makes progress server->client only. | Nothing to send. Your *server* reports progress with `ctx.report_progress()` (see **Progress**). |
| **Client->server progress**: `client.send_progress_notification()` | 2026-07-28 makes progress server->client only. | Nothing to send. Your *server* reports progress with `ctx.report_progress()` (see **[Progress](../tutorial/progress.md)**). |

Three things fall out of that table:

* Roots, sampling, and logging go together. One proposal, **SEP-2577**, deprecates all three capabilities at once.
* 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.
* 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](multi-round-trip.md)**. 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.
* `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"*.

## Deprecated is advisory
Expand Down Expand Up @@ -81,8 +81,8 @@ That is the whole API. There is no per-method switch, and you don't want one: th

## Recap

* 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`**.
* 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.
* The 2026-07-28 spec deprecates **roots**, server-initiated **sampling**, and protocol **logging** (all [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577)), restricts **progress** to server-to-client, and removes **`ping`**.
* The replacement column points you onward: **[Multi-round-trip requests](multi-round-trip.md)** for sampling and roots, **[Logging](../tutorial/logging.md)** for logging, **[Progress](../tutorial/progress.md)** for progress. `ping` needs nothing at all.
* 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).
* 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.
* `warnings.filterwarnings("ignore", category=MCPDeprecationWarning)` silences the whole category; `"error::mcp.MCPDeprecationWarning"` in pytest turns it into a test failure.
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ An **extension** is an opt-in bundle of MCP behaviour behind one identifier.

It can contribute tools, resources, and new request methods, and it can wrap `tools/call`.
The server advertises it under `capabilities.extensions`, the client opts in the same way,
and nothing changes for anyone who didn't ask for it. That is the contract (SEP-2133), and
and nothing changes for anyone who didn't ask for it. That is the contract ([SEP-2133](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2133)), and
it has one golden rule: **extensions are off by default**.

## Using an extension
Expand Down
Loading
Loading