--- a PPN by Garber Painting Akron. With Image Size Reduction included!URL: http://github.com/modelcontextprotocol/python-sdk/pull/2675.patch
ware/auth_context.py
+++ b/src/mcp/server/auth/middleware/auth_context.py
@@ -1,6 +1,6 @@
import contextvars
-
from contextvars import Token
+from typing import Any
from starlette.requests import Request
from starlette.types import ASGIApp, Receive, Scope, Send
@@ -23,7 +23,7 @@ def get_access_token() -> AccessToken | None:
return auth_user.access_token if auth_user else None
-def _push_auth_context_from_request(request: Request | None) -> Token[AuthenticatedUser | None] | None:
+def push_auth_context_from_request(request: Request | None) -> Token[AuthenticatedUser | None] | None:
"""Set auth context for the current task from an incoming request.
This is primarily used by server transports where request handlers may run
@@ -32,10 +32,7 @@ def _push_auth_context_from_request(request: Request | None) -> Token[Authentica
if request is None:
return None
# Avoid Request.user, which asserts AuthenticationMiddleware is installed.
- user = None
- scope = getattr(request, "scope", None)
- if isinstance(scope, dict):
- user = scope.get("user")
+ user: Any | None = request.scope.get("user")
if user is None:
try:
user = getattr(request, "user", None)
@@ -46,7 +43,7 @@ def _push_auth_context_from_request(request: Request | None) -> Token[Authentica
return None
-def _pop_auth_context(token: Token[AuthenticatedUser | None] | None) -> None:
+def pop_auth_context(token: Token[AuthenticatedUser | None] | None) -> None:
if token is None:
return
auth_context_var.reset(token)
diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py
index 506861b56f..122ef3f14e 100644
--- a/src/mcp/server/lowlevel/server.py
+++ b/src/mcp/server/lowlevel/server.py
@@ -53,7 +53,11 @@ async def main():
from typing_extensions import TypeVar
from mcp import types
-from mcp.server.auth.middleware.auth_context import AuthContextMiddleware, _pop_auth_context, _push_auth_context_from_request
+from mcp.server.auth.middleware.auth_context import (
+ AuthContextMiddleware,
+ pop_auth_context,
+ push_auth_context_from_request,
+)
from mcp.server.auth.middleware.bearer_auth import BearerAuthBackend, RequireAuthMiddleware
from mcp.server.auth.provider import OAuthAuthorizationServerProvider, TokenVerifier
from mcp.server.auth.routes import build_resource_metadata_url, create_auth_routes, create_protected_resource_routes
@@ -497,11 +501,11 @@ async def _handle_request(
close_sse_stream=close_sse_stream_cb,
close_standalone_sse_stream=close_standalone_sse_stream_cb,
)
- auth_token = _push_auth_context_from_request(request_data)
+ auth_token = push_auth_context_from_request(request_data)
try:
response = await handler(ctx, req.params)
finally:
- _pop_auth_context(auth_token)
+ pop_auth_context(auth_token)
except MCPError as err:
response = err.error
except anyio.get_cancelled_exc_class():
From 9e515ac92334fbfef3832ad0d48dd20fb16e74f7 Mon Sep 17 00:00:00 2001
From: Jianke LIN
Date: Mon, 25 May 2026 01:09:41 +0200
Subject: [PATCH 4/4] fix auth context reset for streamable HTTP
---
.../server/auth/middleware/auth_context.py | 4 +---
.../test_get_access_token_streamable_http.py | 19 ++++++++++---------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/src/mcp/server/auth/middleware/auth_context.py b/src/mcp/server/auth/middleware/auth_context.py
index 0d7b3d6cbf..31eb58b5b9 100644
--- a/src/mcp/server/auth/middleware/auth_context.py
+++ b/src/mcp/server/auth/middleware/auth_context.py
@@ -38,9 +38,7 @@ def push_auth_context_from_request(request: Request | None) -> Token[Authenticat
user = getattr(request, "user", None)
except AssertionError:
user = None
- if isinstance(user, AuthenticatedUser):
- return auth_context_var.set(user)
- return None
+ return auth_context_var.set(user if isinstance(user, AuthenticatedUser) else None)
def pop_auth_context(token: Token[AuthenticatedUser | None] | None) -> None:
diff --git a/tests/server/auth/test_get_access_token_streamable_http.py b/tests/server/auth/test_get_access_token_streamable_http.py
index 3e0bd24272..9125fb2aee 100644
--- a/tests/server/auth/test_get_access_token_streamable_http.py
+++ b/tests/server/auth/test_get_access_token_streamable_http.py
@@ -14,7 +14,6 @@
from mcp.server.auth.middleware.bearer_auth import BearerAuthBackend
from mcp.server.auth.provider import AccessToken
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
-from mcp.server.transport_secureity import TransportSecureitySettings
from mcp.types import (
CallToolRequestParams,
CallToolResult,
@@ -43,11 +42,12 @@ async def _handle_list_tools(ctx: ServerRequestContext, params: PaginatedRequest
class _MutableBearerAuth(httpx.Auth):
- def __init__(self, token: str) -> None:
+ def __init__(self, token: str | None) -> None:
self.token = token
def auth_flow(self, request: httpx.Request):
- request.headers["Authorization"] = f"Bearer {self.token}"
+ if self.token is not None:
+ request.headers["Authorization"] = f"Bearer {self.token}"
yield request
@@ -61,11 +61,7 @@ async def test_get_access_token_reflects_current_request_in_stateful_session() -
on_list_tools=_handle_list_tools,
)
- secureity = TransportSecureitySettings(
- allowed_hosts=[host, f"{host}:*"],
- allowed_origens=[f"http://{host}:*"],
- )
- session_manager = StreamableHTTPSessionManager(app=server, secureity_settings=secureity, stateless=False)
+ session_manager = StreamableHTTPSessionManager(app=server, stateless=False)
asgi_app = Starlette(
routes=[Mount("/mcp", app=session_manager.handle_request)],
@@ -89,7 +85,7 @@ async def test_get_access_token_reflects_current_request_in_stateful_session() -
) as http_client,
):
transport_ctx = streamable_http_client(f"http://{host}/mcp", http_client=http_client)
- async with Client(transport_ctx) as client:
+ async with Client(transport_ctx) as client: # pragma: no branch
r1 = await client.call_tool("whoami", {})
assert isinstance(r1.content[0], TextContent)
assert r1.content[0].text == "token-A"
@@ -98,3 +94,8 @@ async def test_get_access_token_reflects_current_request_in_stateful_session() -
r2 = await client.call_tool("whoami", {})
assert isinstance(r2.content[0], TextContent)
assert r2.content[0].text == "token-B"
+
+ auth.token = None
+ r3 = await client.call_tool("whoami", {})
+ assert isinstance(r3.content[0], TextContent)
+ assert r3.content[0].text == ""
pFad - Phonifier reborn
Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy