Skip to content

Commit 7411f44

Browse files
Merge branch 'main' into fix-1664-forward-user-agent-auth-flow
2 parents 40f173f + 0fe16dd commit 7411f44

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+640
-419
lines changed

.github/workflows/claude-code-review.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ jobs:
1919

2020
steps:
2121
- name: Checkout repository
22-
uses: actions/checkout@v6
22+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2323
with:
2424
fetch-depth: 1
2525

2626
- name: Run Claude Code Review
2727
id: claude-review
28-
uses: anthropics/claude-code-action@v1
28+
uses: anthropics/claude-code-action@2f8ba26a219c06cfb0f468eef8d97055fa814f97 # v1.0.53
2929
with:
3030
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
3131
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"

.github/workflows/claude.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ jobs:
2727
actions: read # Required for Claude to read CI results on PRs
2828
steps:
2929
- name: Checkout repository
30-
uses: actions/checkout@v6
30+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3131
with:
3232
fetch-depth: 1
3333

3434
- name: Run Claude Code
3535
id: claude
36-
uses: anthropics/claude-code-action@v1
36+
uses: anthropics/claude-code-action@2f8ba26a219c06cfb0f468eef8d97055fa814f97 # v1.0.53
3737
with:
3838
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
3939
use_commit_signing: true

.github/workflows/publish-docs-manually.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ jobs:
3131
3232
- run: uv sync --frozen --group docs
3333
- run: uv run --frozen --no-sync mkdocs gh-deploy --force
34+
env:
35+
ENABLE_SOCIAL_CARDS: "true"

.github/workflows/weekly-lockfile-update.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ jobs:
1414
update-lockfile:
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/checkout@v6
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1818

19-
- uses: astral-sh/setup-uv@v7.2.1
19+
- uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
2020
with:
2121
version: 0.9.5
2222

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ This document contains critical information about working with this codebase. Fo
3131
- IMPORTANT: Before pushing, verify 100% branch coverage on changed files by running
3232
`uv run --frozen pytest -x` (coverage is configured in `pyproject.toml` with `fail_under = 100`
3333
and `branch = true`). If any branch is uncovered, add a test for it before pushing.
34+
- Avoid `anyio.sleep()` with a fixed duration to wait for async operations. Instead:
35+
- Use `anyio.Event` — set it in the callback/handler, `await event.wait()` in the test
36+
- For stream messages, use `await stream.receive()` instead of `sleep()` + `receive_nowait()`
37+
- Exception: `sleep()` is appropriate when testing time-based features (e.g., timeouts)
38+
- Wrap indefinite waits (`event.wait()`, `stream.receive()`) in `anyio.fail_after(5)` to prevent hangs
3439

3540
Test files mirror the source tree: `src/mcp/client/streamable_http.py``tests/client/test_streamable_http.py`
3641
Add tests to the existing file for that module.

SECURITY.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
# Security Policy
22

3-
Thank you for helping us keep the SDKs and systems they interact with secure.
3+
Thank you for helping keep the Model Context Protocol and its ecosystem secure.
44

55
## Reporting Security Issues
66

7-
This SDK is maintained by [Anthropic](https://www.anthropic.com/) as part of the Model Context Protocol project.
7+
If you discover a security vulnerability in this repository, please report it through
8+
the [GitHub Security Advisory process](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability)
9+
for this repository.
810

9-
The security of our systems and user data is Anthropic’s top priority. We appreciate the work of security researchers acting in good faith in identifying and reporting potential vulnerabilities.
11+
Please **do not** report security vulnerabilities through public GitHub issues, discussions,
12+
or pull requests.
1013

11-
Our security program is managed on HackerOne and we ask that any validated vulnerability in this functionality be reported through their [submission form](https://hackerone.com/anthropic-vdp/reports/new?type=team&report_type=vulnerability).
14+
## What to Include
1215

13-
## Vulnerability Disclosure Program
16+
To help us triage and respond quickly, please include:
1417

15-
Our Vulnerability Program Guidelines are defined on our [HackerOne program page](https://hackerone.com/anthropic-vdp).
18+
- A description of the vulnerability
19+
- Steps to reproduce the issue
20+
- The potential impact
21+
- Any suggested fixes (optional)

docs/migration.md

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ async def handle_call_tool(ctx: ServerRequestContext, params: CallToolRequestPar
371371
server = Server("my-server", on_call_tool=handle_call_tool)
372372
```
373373

374-
### `RequestContext` and `ProgressContext` type parameters simplified
374+
### `RequestContext` type parameters simplified
375375

376376
The `RequestContext` class has been split to separate shared fields from server-specific fields. The shared `RequestContext` now only takes 1 type parameter (the session type) instead of 3.
377377

@@ -380,40 +380,59 @@ The `RequestContext` class has been split to separate shared fields from server-
380380
- Type parameters reduced from `RequestContext[SessionT, LifespanContextT, RequestT]` to `RequestContext[SessionT]`
381381
- Server-specific fields (`lifespan_context`, `experimental`, `request`, `close_sse_stream`, `close_standalone_sse_stream`) moved to new `ServerRequestContext` class in `mcp.server.context`
382382

383-
**`ProgressContext` changes:**
384-
385-
- Type parameters reduced from `ProgressContext[SendRequestT, SendNotificationT, SendResultT, ReceiveRequestT, ReceiveNotificationT]` to `ProgressContext[SessionT]`
386-
387383
**Before (v1):**
388384

389385
```python
390386
from mcp.client.session import ClientSession
391387
from mcp.shared.context import RequestContext, LifespanContextT, RequestT
392-
from mcp.shared.progress import ProgressContext
393388

394389
# RequestContext with 3 type parameters
395390
ctx: RequestContext[ClientSession, LifespanContextT, RequestT]
396-
397-
# ProgressContext with 5 type parameters
398-
progress_ctx: ProgressContext[SendRequestT, SendNotificationT, SendResultT, ReceiveRequestT, ReceiveNotificationT]
399391
```
400392

401393
**After (v2):**
402394

403395
```python
404396
from mcp.client.context import ClientRequestContext
405-
from mcp.client.session import ClientSession
406397
from mcp.server.context import ServerRequestContext, LifespanContextT, RequestT
407-
from mcp.shared.progress import ProgressContext
408398

409399
# For client-side context (sampling, elicitation, list_roots callbacks)
410400
ctx: ClientRequestContext
411401

412402
# For server-specific context with lifespan and request types
413403
server_ctx: ServerRequestContext[LifespanContextT, RequestT]
404+
```
405+
406+
### `ProgressContext` and `progress()` context manager removed
407+
408+
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.
409+
410+
**Before:**
411+
412+
```python
413+
from mcp.shared.progress import progress
414414

415-
# ProgressContext with 1 type parameter
416-
progress_ctx: ProgressContext[ClientSession]
415+
with progress(ctx, total=100) as p:
416+
await p.progress(25)
417+
```
418+
419+
**After — use `Context.report_progress()` (recommended):**
420+
421+
```python
422+
@server.tool()
423+
async def my_tool(x: int, ctx: Context) -> str:
424+
await ctx.report_progress(25, 100)
425+
return "done"
426+
```
427+
428+
**After — use `session.send_progress_notification()` (low-level):**
429+
430+
```python
431+
await session.send_progress_notification(
432+
progress_token=progress_token,
433+
progress=25,
434+
total=100,
435+
)
417436
```
418437

419438
### Resource URI type changed from `AnyUrl` to `str`

examples/snippets/clients/url_elicitation_client.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424

2525
import asyncio
2626
import json
27-
import subprocess
28-
import sys
2927
import webbrowser
3028
from typing import Any
3129
from urllib.parse import urlparse
@@ -56,15 +54,19 @@ async def handle_elicitation(
5654
)
5755

5856

57+
ALLOWED_SCHEMES = {"http", "https"}
58+
59+
5960
async def handle_url_elicitation(
6061
params: types.ElicitRequestParams,
6162
) -> types.ElicitResult:
6263
"""Handle URL mode elicitation - show security warning and optionally open browser.
6364
6465
This function demonstrates the security-conscious approach to URL elicitation:
65-
1. Display the full URL and domain for user inspection
66-
2. Show the server's reason for requesting this interaction
67-
3. Require explicit user consent before opening any URL
66+
1. Validate the URL scheme before prompting the user
67+
2. Display the full URL and domain for user inspection
68+
3. Show the server's reason for requesting this interaction
69+
4. Require explicit user consent before opening any URL
6870
"""
6971
# Extract URL parameters - these are available on URL mode requests
7072
url = getattr(params, "url", None)
@@ -75,6 +77,12 @@ async def handle_url_elicitation(
7577
print("Error: No URL provided in elicitation request")
7678
return types.ElicitResult(action="cancel")
7779

80+
# Reject dangerous URL schemes before prompting the user
81+
parsed = urlparse(str(url))
82+
if parsed.scheme.lower() not in ALLOWED_SCHEMES:
83+
print(f"\nRejecting URL with disallowed scheme '{parsed.scheme}': {url}")
84+
return types.ElicitResult(action="decline")
85+
7886
# Extract domain for security display
7987
domain = extract_domain(url)
8088

@@ -105,7 +113,11 @@ async def handle_url_elicitation(
105113

106114
# Open the browser
107115
print(f"\nOpening browser to: {url}")
108-
open_browser(url)
116+
try:
117+
webbrowser.open(url)
118+
except Exception as e:
119+
print(f"Failed to open browser: {e}")
120+
print(f"Please manually open: {url}")
109121

110122
print("Waiting for you to complete the interaction in your browser...")
111123
print("(The server will continue once you've finished)")
@@ -121,20 +133,6 @@ def extract_domain(url: str) -> str:
121133
return "unknown"
122134

123135

124-
def open_browser(url: str) -> None:
125-
"""Open URL in the default browser."""
126-
try:
127-
if sys.platform == "darwin":
128-
subprocess.run(["open", url], check=False)
129-
elif sys.platform == "win32":
130-
subprocess.run(["start", url], shell=True, check=False)
131-
else:
132-
webbrowser.open(url)
133-
except Exception as e:
134-
print(f"Failed to open browser: {e}")
135-
print(f"Please manually open: {url}")
136-
137-
138136
async def call_tool_with_error_handling(
139137
session: ClientSession,
140138
tool_name: str,

mkdocs.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ watch:
112112

113113
plugins:
114114
- search
115-
- social
115+
- social:
116+
enabled: !ENV [ENABLE_SOCIAL_CARDS, false]
116117
- glightbox
117118
- mkdocstrings:
118119
handlers:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ dev = [
7575
docs = [
7676
"mkdocs>=1.6.1",
7777
"mkdocs-glightbox>=0.4.0",
78-
"mkdocs-material>=9.5.45",
78+
"mkdocs-material[imaging]>=9.5.45",
7979
"mkdocstrings-python>=2.0.1",
8080
]
8181

0 commit comments

Comments
 (0)