mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-20 12:34:17 +02:00
Simplify ContextVar management - trust Context to set them at request time
Remove redundant ContextVar handling: - _lifespan_manager no longer re-sets ContextVars in early-return branch - Handler fallback logic removed (no more `if docket is None: docket = server._docket`) The authoritative place for request-context ContextVars is now Context.__aenter__, which sets _current_docket and _current_worker from server instance attributes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5cea6ba575
commit
687889c598
2 changed files with 9 additions and 37 deletions
|
|
@ -613,32 +613,13 @@ class FastMCP(Generic[LifespanResultT]):
|
|||
logger.info(f"[{instance_id}] _lifespan_manager ENTERING")
|
||||
|
||||
if self._lifespan_result_set:
|
||||
# Lifespan already ran in a parent async context. We need to set ContextVars
|
||||
# again in THIS context because ContextVars don't propagate across different
|
||||
# async contexts (e.g., Starlette's ASGI lifespan vs FastMCP's outer lifespan).
|
||||
# Request handlers inherit from Starlette's context, so we must set here.
|
||||
from fastmcp.server.dependencies import (
|
||||
_current_docket,
|
||||
_current_server,
|
||||
_current_worker,
|
||||
)
|
||||
|
||||
# Lifespan already ran - ContextVars will be set by Context.__aenter__
|
||||
# at request time, so we just yield here.
|
||||
logger.info(
|
||||
f"[{instance_id}] _lifespan_manager: already set, setting ContextVars "
|
||||
f"for this context (docket={self._docket}, worker={self._worker})"
|
||||
f"[{instance_id}] _lifespan_manager: already set, yielding "
|
||||
f"(ContextVars managed by Context at request time)"
|
||||
)
|
||||
|
||||
server_token = _current_server.set(weakref.ref(self))
|
||||
docket_token = _current_docket.set(self._docket) if self._docket else None
|
||||
worker_token = _current_worker.set(self._worker) if self._worker else None
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
_current_server.reset(server_token)
|
||||
if docket_token is not None:
|
||||
_current_docket.reset(docket_token)
|
||||
if worker_token is not None:
|
||||
_current_worker.reset(worker_token)
|
||||
yield
|
||||
return
|
||||
|
||||
logger.info(
|
||||
|
|
|
|||
|
|
@ -63,16 +63,11 @@ async def handle_tool_as_task(
|
|||
ctx = get_context()
|
||||
session_id = ctx.session_id
|
||||
|
||||
# Try ContextVar first, fall back to server instance attribute.
|
||||
# ContextVars don't propagate to request handlers in ASGI servers because
|
||||
# request tasks are created from the main event loop, not the lifespan context.
|
||||
# Get Docket from ContextVar (set by Context.__aenter__ at request time)
|
||||
docket = _current_docket.get()
|
||||
if docket is None:
|
||||
docket = server._docket
|
||||
_logger.info(
|
||||
f"[{instance_id}] handle_tool_as_task: tool={tool_name}, "
|
||||
f"_current_docket.get()={_current_docket.get()}, server._docket={server._docket}, "
|
||||
f"using docket={docket}"
|
||||
f"_current_docket.get()={docket}"
|
||||
)
|
||||
if docket is None:
|
||||
_logger.error(
|
||||
|
|
@ -225,10 +220,8 @@ async def handle_prompt_as_task(
|
|||
ctx = get_context()
|
||||
session_id = ctx.session_id
|
||||
|
||||
# Try ContextVar first, fall back to server instance attribute
|
||||
# Get Docket from ContextVar (set by Context.__aenter__ at request time)
|
||||
docket = _current_docket.get()
|
||||
if docket is None:
|
||||
docket = server._docket
|
||||
if docket is None:
|
||||
raise McpError(
|
||||
ErrorData(
|
||||
|
|
@ -337,10 +330,8 @@ async def handle_resource_as_task(
|
|||
ctx = get_context()
|
||||
session_id = ctx.session_id
|
||||
|
||||
# Try ContextVar first, fall back to server instance attribute
|
||||
# Get Docket from ContextVar (set by Context.__aenter__ at request time)
|
||||
docket = _current_docket.get()
|
||||
if docket is None:
|
||||
docket = server._docket
|
||||
if docket is None:
|
||||
raise McpError(
|
||||
ErrorData(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue