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
21 changes: 21 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,27 @@ await ctx.log(level="info", data="hello")

Positional calls (`await ctx.info("hello")`) are unaffected.

### `Context.client_id` removed

`Context.client_id` has been removed. It never returned an authenticated client identity: it echoed a non-standard `client_id` key from the request's `_meta`, which nothing in the SDK or the MCP spec populates, so it was `None` unless a caller injected `meta={"client_id": ...}` by hand. The name also collided with the OAuth `client_id`, which is what callers usually mean by "the client".

If you were reading a custom `_meta` key, read it from the meta dict directly. If you want the authenticated OAuth client, use the access token:

```python
# Before (v1)
client_id = ctx.client_id

# After (v2) — the raw _meta key, if you were setting it yourself
meta = ctx.request_context.meta
client_id = meta.get("client_id") if meta else None

# After (v2) — the authenticated OAuth client (usually what you want)
from mcp.server.auth.middleware.auth_context import get_access_token

token = get_access_token()
client_id = token.client_id if token else None
```

### `ProgressContext` and `progress()` context manager removed

The `mcp.shared.progress` module (`ProgressContext`, `Progress`, and the `progress()` context manager) has been removed. This module had no real-world adoption — all users send progress notifications via `Context.report_progress()` or `session.send_progress_notification()` directly.
Expand Down
11 changes: 0 additions & 11 deletions src/mcp/server/mcpserver/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ async def my_tool(x: int, ctx: Context) -> str:

# Get request info
request_id = ctx.request_id
client_id = ctx.client_id

return str(x)
```
Expand Down Expand Up @@ -275,16 +274,6 @@ async def log(
related_request_id=self.request_id,
)

# TODO(maxisbey): see if this is needed otherwise remove
@property
def client_id(self) -> str | None:
"""Get the client ID if available.

Note: this reads from the MCP request's `_meta` params, not the OAuth
bearer token. For that, use `get_access_token().client_id`.
"""
return self.request_context.meta.get("client_id") if self.request_context.meta else None # pragma: no cover

@property
def headers(self) -> Mapping[str, str] | None:
"""Request headers carried by this message, when the transport has them.
Expand Down
Loading