PrefectHQ/fastmcp · error · RuntimeError

Task-enabled tools ({names}) require the tasks extension, bu

Error message

Task-enabled tools ({names}) require the tasks extension, but no extension with identifier {TASKS_EXTENSION_ID!r} is registered. Install it with `pip install 'fastmcp[tasks]'` and register it via `mcp.add_extension(TasksExtension(...))`.

What it means

A RuntimeError raised during server startup (_validate_task_extension_registered, invoked by the lifespan manager) when task-enabled tools are registered but the tasks extension (identifier TASKS_EXTENSION_ID) is absent. Docket-backed task execution requires that extension; the error lists the offending tool names and the exact install/registration steps.

Source

Thrown at fastmcp_slim/fastmcp/server/mixins/lifespan.py:142

        # fail a child that legitimately relies on the root's registration.
        if _lifespan_root_active.get():
            return

        if TASKS_EXTENSION_ID in self._extensions:
            return

        candidates = list(await self.get_tasks())

        # ``get_tasks()`` applies server-level transforms, which can inject
        # non-task tools (e.g. ResourcesAsTools' synthetic list/read tools) into
        # the result, so re-filter by the actual task config here — mirroring the
        # guard the old per-component docket registration applied.
        task_components = [c for c in candidates if c.task_config.supports_tasks()]
        if not task_components:
            return

        names = ", ".join(sorted(c.name for c in task_components))
        raise RuntimeError(
            f"Task-enabled tools ({names}) require the tasks extension, but no "
            f"extension with identifier {TASKS_EXTENSION_ID!r} is registered. "
            "Install it with `pip install 'fastmcp[tasks]'` and register it via "
            "`mcp.add_extension(TasksExtension(...))`."
        )

    def _capture_shared_context(self: FastMCP) -> None:
        """Snapshot the live ``SharedContext`` ContextVar values.

        The SDK v2 dispatcher runs each request handler in the *message
        sender's* contextvars (via ``ContextReceiveStream.last_context``), not
        the server-lifespan context. App-scoped ``Shared()`` dependencies rely
        on ``uncalled_for.SharedContext`` ContextVars set during the lifespan,
        which are therefore invisible to handlers. We capture those values here
        so ``FastMCPServerMiddleware`` can re-apply them per request.
        """
        try:
            self._shared_context_snapshot = {

View on GitHub (pinned to 1f02114297)

Solutions

  1. Install the extra: pip install 'fastmcp[tasks]'.
  2. Register the extension at startup: mcp.add_extension(TasksExtension(...)).
  3. If background execution is not intended, remove the task_config/task=True settings from the listed tools so they run inline.

Example fix

// before
mcp = FastMCP("server")

@mcp.tool(task=True)
def report(): ...
# RuntimeError at startup

// after
from fastmcp.server.extensions.tasks import TasksExtension
mcp = FastMCP("server")
mcp.add_extension(TasksExtension())

@mcp.tool(task=True)
def report(): ...
Defensive patterns

Strategy: validation

Validate before calling

from fastmcp.server.extensions import TASKS_EXTENSION_ID

registered = {getattr(ext, "identifier", None) for ext in mcp.extensions}
task_tools = [t for t in mcp._tool_manager if getattr(t, "task_config", None) and t.task_config.supports_tasks()]
if task_tools and TASKS_EXTENSION_ID not in registered:
    raise RuntimeError(f"install fastmcp[tasks] and add_extension(TasksExtension()) for: {[t.name for t in task_tools]}")

Try / catch

try:
    mcp.run()
except RuntimeError as e:
    if "require the tasks extension" in str(e):
        # surface install/registration instructions at deploy time
        raise SystemExit(f"deployment misconfiguration: {e}")
    raise

Prevention

When it happens

Trigger: Decorating tools with task_config that supports_tasks() (e.g. @mcp.tool(task=True) or a task_config with mode other than forbid) while never calling mcp.add_extension(TasksExtension(...)); happens at lifespan startup, not at decoration time.

Common situations: Upgrading FastMCP and adopting the tasks extension without adding the dependency or registration; deploying with the base package where `fastmcp[tasks]` extra was not installed; copying task-enabled example code into an existing server.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/8fa17c236f5f81a5. Report an issue: GitHub.