Skip to content

Commit 077f7ad

Browse files
committed
Apply the current request's auth context while handling a request (#1250)
1 parent 52e64dd commit 077f7ad

1 file changed

Lines changed: 17 additions & 0 deletions

File tree

‎src/mcp/server/lowlevel/server.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ async def main():
8383
from typing_extensions import TypeVar, deprecated
8484

8585
import mcp.types as types
86+
from mcp.server.auth.middleware.auth_context import auth_context_var
87+
from mcp.server.auth.middleware.bearer_auth import AuthenticatedUser
8688
from mcp.server.experimental.request_context import Experimental
8789
from mcp.server.lowlevel.experimental import ExperimentalHandlers
8890
from mcp.server.lowlevel.func_inspection import create_call_wrapper
@@ -736,6 +738,7 @@ async def _handle_request(
736738
logger.debug("Dispatching request of type %s", type(req).__name__)
737739

738740
token = None
741+
auth_token: contextvars.Token[AuthenticatedUser | None] | None = None
739742
try:
740743
# Extract request context and close_sse_stream from message metadata
741744
request_data = None
@@ -756,6 +759,18 @@ async def _handle_request(
756759
task_metadata = None
757760
if hasattr(req, "params") and req.params is not None:
758761
task_metadata = getattr(req.params, "task", None)
762+
# The HTTP transports attach the current request, and its scope
763+
# carries the user authenticated for this request. Handlers run
764+
# in the session's long-lived task, where the auth_context_var
765+
# set by AuthContextMiddleware still holds the session-opening
766+
# request's user, so a refreshed token never reaches the handler
767+
# (#1250). Apply this request's user for the handler's duration.
768+
if request_data is not None:
769+
scope = getattr(request_data, "scope", None)
770+
if isinstance(scope, dict):
771+
user = cast(dict[str, Any], scope).get("user")
772+
if isinstance(user, AuthenticatedUser):
773+
auth_token = auth_context_var.set(user)
759774
token = request_ctx.set(
760775
RequestContext(
761776
message.request_id,
@@ -794,6 +809,8 @@ async def _handle_request(
794809
response = types.ErrorData(code=0, message=str(err), data=None)
795810
finally:
796811
# Reset the global state after we are done
812+
if auth_token is not None:
813+
auth_context_var.reset(auth_token)
797814
if token is not None: # pragma: no branch
798815
request_ctx.reset(token)
799816
else: # pragma: no cover

0 commit comments

Comments
 (0)