mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
TasksExtension serves io.modelcontextprotocol/tasks on the extension API: a decide-and-task tools/call interceptor (era-gated to modern connections), tasks/get with inlined results and inputRequests, tasks/update delivering poll-based in-task elicitation, tasks/cancel, durable creation, and auth-scoped task isolation. Wire models validate against the vendored ext-tasks schema. Worker-side Context hooks are refcounted so sibling servers cannot strand each other's workers. Co-Authored-By: Claude <noreply@anthropic.com>
40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
"""Advertisement of the SEP-2663 tasks extension capability.
|
|
|
|
A server with the tasks extension registered advertises the
|
|
`io.modelcontextprotocol/tasks` extension in its capabilities; a server without
|
|
it does not.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastmcp import FastMCP
|
|
from fastmcp.client import Client
|
|
from fastmcp.utilities.tasks import TASKS_EXTENSION_ID
|
|
from fastmcp_tasks import TasksExtension
|
|
|
|
|
|
async def test_extension_capability_advertised():
|
|
"""The tasks extension is advertised when registered."""
|
|
mcp = FastMCP("capability-test")
|
|
mcp.add_extension(TasksExtension())
|
|
|
|
@mcp.tool(task=True)
|
|
async def my_tool() -> str:
|
|
return "ok"
|
|
|
|
async with Client(mcp, mode="auto") as client:
|
|
extensions = client.server_capabilities.extensions or {}
|
|
assert extensions.get(TASKS_EXTENSION_ID) == {}
|
|
|
|
|
|
async def test_extension_capability_absent_without_extension():
|
|
"""The tasks extension is not advertised when no extension is registered."""
|
|
mcp = FastMCP("capability-test")
|
|
|
|
@mcp.tool
|
|
async def my_tool() -> str:
|
|
return "ok"
|
|
|
|
async with Client(mcp, mode="auto") as client:
|
|
extensions = client.server_capabilities.extensions or {}
|
|
assert TASKS_EXTENSION_ID not in extensions
|