Claude here: opened on behalf of @dsfaccini, verified the MRE locally.
Summary
is_docket_available() only checks import docket — it doesn't verify the version. When another package (e.g. prefect) brings in pydocket<0.18.0, the check passes but subsequent imports of current_execution from docket.dependencies fail at runtime:
ImportError: cannot import name 'current_execution' from 'docket.dependencies'
This happens even though fastmcp[tasks] is not installed — the mere presence of an old pydocket in the environment is enough to trigger it.
Location
fastmcp/server/dependencies.py — get_task_context() (around line 117):
if is_docket_available():
from docket.dependencies import current_execution # crashes if pydocket < 0.18.0
Reproduction
# /// script
# requires-python = ">=3.10"
# dependencies = ["fastmcp==3.2.2", "pydocket==0.16.6"]
# ///
from fastmcp import FastMCP
server = FastMCP('test')
@server.tool()
def hello() -> str:
return 'hello'
if __name__ == '__main__':
import asyncio
from fastmcp.client import Client
from fastmcp.client.transports import FastMCPTransport
async def main():
async with Client(transport=FastMCPTransport(server)) as client:
tools = await client.list_tools()
print(tools)
asyncio.run(main())
Context
This is a practical issue for projects with large dependency trees. For example, pydantic-ai depends on both fastmcp>=3.2.1 and prefect, and prefect declares pydocket>=0.16.2 (no upper bound). The lockfile resolver picks 0.16.6, which is valid for prefect but breaks fastmcp.
Previously reported in #3447 and closed, but the fix described there (using fastmcp[tasks]) doesn't apply here — we don't want or use docket/tasks, we just happen to have an old pydocket installed transitively.
Suggested fix
Make is_docket_available() version-aware, e.g.:
def is_docket_available() -> bool:
try:
import docket.dependencies
return hasattr(docket.dependencies, 'current_execution')
except ImportError:
return False
Or guard the import with a try/except at the call site.
Claude here: opened on behalf of @dsfaccini, verified the MRE locally.
Summary
is_docket_available()only checksimport docket— it doesn't verify the version. When another package (e.g.prefect) brings inpydocket<0.18.0, the check passes but subsequent imports ofcurrent_executionfromdocket.dependenciesfail at runtime:This happens even though
fastmcp[tasks]is not installed — the mere presence of an oldpydocketin the environment is enough to trigger it.Location
fastmcp/server/dependencies.py—get_task_context()(around line 117):Reproduction
Context
This is a practical issue for projects with large dependency trees. For example,
pydantic-aidepends on bothfastmcp>=3.2.1andprefect, andprefectdeclarespydocket>=0.16.2(no upper bound). The lockfile resolver picks 0.16.6, which is valid for prefect but breaks fastmcp.Previously reported in #3447 and closed, but the fix described there (using
fastmcp[tasks]) doesn't apply here — we don't want or use docket/tasks, we just happen to have an old pydocket installed transitively.Suggested fix
Make
is_docket_available()version-aware, e.g.:Or guard the import with a try/except at the call site.