Metadata-Version: 2.4
Name: fastmcp-tasks
Version: 4.0.0a2
Summary: Background task execution for FastMCP servers via the io.modelcontextprotocol/tasks extension (SEP-2663).
Project-URL: Homepage, https://gofastmcp.com
Project-URL: Repository, https://github.com/PrefectHQ/fastmcp
Project-URL: Documentation, https://gofastmcp.com
Author: Jeremiah Lowin
License-Expression: Apache-2.0
Keywords: background tasks,fastmcp,fastmcp tasks,mcp,model context protocol
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: burner-redis<0.1.7; sys_platform == 'win32'
Requires-Dist: fastmcp-slim[server]==4.0.0a2
Requires-Dist: pydocket>=0.20.0
Description-Content-Type: text/markdown

# fastmcp-tasks

A complete implementation of background tasks for the Model Context Protocol — the `io.modelcontextprotocol/tasks` extension defined in [SEP-2663](https://github.com/modelcontextprotocol/ext-tasks).

The MCP tasks extension is a Final SEP, but as of this writing it ships in the ecosystem as a schema and a prose specification — no language SDK provides a working runtime for it. `fastmcp-tasks` is, to our knowledge, the first: a full server-side implementation of the protocol, built on the durable execution engine ([docket](https://github.com/chrisguidry/docket)) that FastMCP has run in production since v3. If you want to actually *run* MCP background tasks today, this is the implementation.

## What background tasks are

Most tool calls are synchronous: the client sends `tools/call` and holds the request open until the tool returns. That breaks down for work that takes minutes or hours — a long analysis, a batch job, a slow external API. The tasks extension lets a server answer such a call *immediately* with a durable task handle, then run the work in the background while the client polls for completion on its own schedule.

The model is poll-based and stateless by construction, which is what makes it survive disconnects, server restarts, and load balancers:

1. A client that supports tasks issues a normal `tools/call` with a per-request opt-in.
2. The server decides whether to run it as a task. If it does, it returns a `CreateTaskResult` carrying a server-generated task id — right away, before the work starts.
3. The client polls `tasks/get` until the task reaches a terminal state, then reads the result inlined in the response.
4. `tasks/cancel` requests cancellation; `tasks/update` answers any input the task asks for mid-run.

The server owns the task's durable state, so the client can poll across independent requests — from any process, after a crash, through any replica — with no session affinity required.

## Usage

Install it as the `tasks` extra on FastMCP:

```bash
uv pip install "fastmcp[tasks]"
```

Register the extension on your server and mark the tools that may run as tasks. The extension is where the backend is configured — point it at Redis for a distributed deployment, or leave it on the in-memory default for a single process:

```python
from fastmcp import FastMCP
from fastmcp_tasks import TasksExtension

mcp = FastMCP("Analytics")
mcp.add_extension(TasksExtension(url="redis://localhost:6379/0"))


@mcp.tool(task=True)
async def analyze(dataset: str) -> str:
    # Long-running work. The client gets a task handle immediately and
    # polls for the result; this runs in a background worker.
    ...
```

`task=True` is a declaration of intent — this tool *may* run as a task — while the server, per the spec, decides per call whether to actually task it. Use `TaskConfig` for finer control:

```python
from fastmcp.utilities.tasks import TaskConfig


@mcp.tool(task=TaskConfig(mode="required"))
async def must_run_async(n: int) -> int:
    # Always runs as a task; a client that has not opted in is told so.
    ...
```

Registering `TasksExtension` is required to serve `task=True` tools — the tool declares intent, the extension provides the engine. A `task=True` tool on a server with no tasks extension registered fails loudly at startup rather than silently running inline.

### Running out-of-process workers

For distributed deployments backed by Redis, run dedicated worker processes alongside your server:

```bash
python -m fastmcp_tasks.worker_cli worker server.py
```

Workers and servers that share a backend URL and queue name share a task queue, so you can scale execution independently of your request-serving frontends.

## Configuration

The backend is configured on the extension. Every option also has a `FASTMCP_DOCKET_*` environment variable, so an env-configured deployment can construct `TasksExtension()` with no arguments:

| Option | Env var | Default | Description |
| --- | --- | --- | --- |
| `url` | `FASTMCP_DOCKET_URL` | `memory://` | Backend URL. `memory://` for single-process; `redis://host:port/db` for distributed workers. |
| `name` | `FASTMCP_DOCKET_NAME` | `fastmcp` | Queue name. Servers and workers sharing a name and URL share a queue. |
| `concurrency` | `FASTMCP_DOCKET_CONCURRENCY` | `10` | Maximum concurrent tasks per worker. |

See the [FastMCP task documentation](https://gofastmcp.com/servers/tasks) for the full reference.

## Status

The tasks extension is an experimental MCP extension, and `fastmcp-tasks` tracks its draft schema. The protocol's shape is settled — SEP-2663 is Final — but field-level details may still move; this package versions independently so it can follow the schema without waiting on a FastMCP release.
