Addresses code review feedback:
- Extract `get_task_capabilities()` to avoid duplicating the SEP-1686
capability structure across transports
- Add `_should_enable_component()` check before task routing for tools,
resources, and prompts to respect enable/tag filtering
- Simplify tasks/__init__.py to avoid circular import issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The task protocol (SEP-1686) is now always enabled - server always
registers task handlers and advertises task capabilities. Users still
opt into background execution at the server level (tasks=True) or
component level (task=True on tools, prompts, resources).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The base Tool class now has an optional `execution` field for storing
task execution metadata (SEP-1686). This lets gateways/proxies preserve
execution info when forwarding tools from backends - previously this
metadata was lost because Tool had no way to store it.
FunctionTool continues to derive execution from task_config as before.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When multiple servers with task-enabled tools are mounted into a parent,
their functions were all registered with Docket using `fn.__name__`. This
meant two mounted servers each having a function named `add` would both
register under `"add"`, with the second overwriting the first.
Now mounted functions use prefixed names matching their client-facing tool
names (e.g., `c1_add`, `c2_add`). Root server functions still use their
original names with no prefix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When a server is mounted on another, both were creating their own
Docket and Worker instances. With memory:// URLs they share the same
FakeServer queue but have separate result_storage instances. This
caused a race condition where results could be stored in one Docket's
storage but looked up in another's, returning None.
The fix marks mounted servers with `_is_mounted=True` flag so they
skip creating their own Docket/Worker. The parent's Docket handles
all task execution for mounted servers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplifies the task support story for proxies and mounts:
- Mounts get full SEP-1686 task support (unchanged)
- Proxies explicitly forbid task execution
The cross-session task forwarding for proxies turned out to be complex
since each client connection creates a new server lifespan with a new
Docket context, and task keys include session_id. Rather than introduce
that complexity, proxies now explicitly refuse task-augmented execution.
Key changes:
- All proxy components (ProxyTool, ProxyPrompt, ProxyResource,
ProxyTemplate) now have task_config.mode="forbidden"
- Proxy tests verify forbidden behavior (sync execution works,
task=True returns error/raises McpError)
- Fixed prompt task handler to check hasattr(prompt, "task_config")
instead of isinstance(prompt, FunctionPrompt) so it applies to
ProxyPrompt too
- Added test suites for both proxy and mount task behavior
Also includes minor fixes:
- Fixed result.meta_ -> result.meta in ProxyTool.run()
- Fixed client handling of returned_immediately without taskId
- Bumped pydocket>=0.15.2
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace custom VersionBadge implementation with Mintlify's native Badge component while preserving custom color and border styling via CSS. This leverages Mintlify's built-in sizing, typography, and icon support while maintaining the original visual design.
- Lead with concepts instead of code
- Explain MCP background tasks vs general Python concurrency
- Document Docket's Prefect origins and battle-tested infrastructure
- Add sections on graceful degradation and embedded workers
- Fix version badge to 2.14.0
- Link to SEP-1686 spec
Follow-up to PR #2563 which fixed the signature handling in
create_function_without_params. These tests ensure the fix
works end-to-end for all object types that support Context injection.
* Fix: Include signature modification in create_function_without_params
When excluding parameters via create_function_without_params(), only
__annotations__ was being updated but not __signature__. This caused
Pydantic's _arguments_schema() to fail when it iterated over signature
parameters that didn't exist in the type hints dictionary.
The fix adds proper signature reconstruction matching the pattern used
in without_injected_parameters().
Fixes KeyError: 'ctx' when using @mcp.tool() with Context parameters.
* fix: add regression tests for create_function_without_params
The test_pydantic_typeadapter_compatibility test specifically reproduces the issue from #2562 and verifies the fix.
* fix: linter for test function
---------
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
* Fix type errors for ty 0.0.1-alpha.31 upgrade
Add type ignores and fixes for ty's stricter checking:
- Path(None) guards in cli.py
- isinstance checks for ElicitRequestFormParams (URL elicitation support)
- TODO(ty) comments for match/isinstance narrowing bugs
- Method override type ignores for generic covariance
- Starlette Middleware typing workarounds
- Dynamic type construction ignores in json_schema_type.py
* Fix remaining type errors for ty 0.0.1-alpha.31
- Add asserts for optional attribute access in tests
- Add type ignores for dynamic httpx transport internals
- Add TODO(ty) comments for `in` operator on str|bytes
- Add TODO(ty) comments for Starlette Middleware typing
- Use cast for prompt.fn async validation in server.py
* Upgrade ty to 0.0.1-alpha.31
Fixes additional test file type errors discovered after upgrade.
Docket stores a shared FakeServer as a class attribute (_memory_server).
When many tests run in parallel, shared state can cause issues on Windows.
Add autouse fixture to reset the shared server before each test.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fakeredis doesn't implement blocking xread properly - it returns
immediately instead of waiting. This causes Docket._monitor_strikes
to busy-loop, overwhelming pytest-xdist workers on Windows.
Mock the method to just sleep, since strike coordination isn't useful
with in-memory backends anyway.
See: https://github.com/cunla/fakeredis-py/issues/274🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Windows ProactorEventLoop has known memory corruption issues that cause
pytest-xdist worker crashes with "node down: Not properly terminated".
Setting WindowsSelectorEventLoopPolicy in conftest.py avoids this issue.
See: https://github.com/python/cpython/issues/116773🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When pytest-xdist terminates worker processes on Windows, the event loop
may close before cleanup can complete. Adding a 2-second timeout to the
worker cancellation prevents indefinite hanging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Docket provides background task execution and is now always available
for all FastMCP servers. Only `enable_tasks` remains to control the
SEP-1686 task protocol support.
Changes:
- Remove `enable_docket` setting and related validation
- Docket/Worker lifecycle is always active in server lifespan
- CurrentDocket and CurrentWorker dependencies work without config
- Add server readiness signaling via `_started` event
- Fix test timing issues with proper port probing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Raise ValueError when sync functions have task=True
Move validation from server.py decorators to the from_function() class
methods on FunctionTool, FunctionPrompt, FunctionResource, and
FunctionResourceTemplate. This ensures the check runs regardless of how
the objects are created.
* Fix async check for callable classes and staticmethods
Move the task=True async validation to run AFTER callable classes and
staticmethods are unwrapped, preventing false positives for async
callable classes with sync-looking signatures.
* Implement MCP background tasks (SEP-1686) using Docket
Adds support for background task execution via the MCP task protocol,
powered by Docket for task queue management.
- Tools, resources, and prompts can be marked with `task=True` to run async
- Progress dependency for tracking task progress
- CurrentDocket and CurrentWorker dependencies for advanced use cases
- Client API with `.call_tool(..., task=True)` returns task handles
- Task status notifications via subscriptions
- CLI worker command for distributed task processing
Configuration via environment:
- FASTMCP_ENABLE_DOCKET=true
- FASTMCP_ENABLE_TASKS=true
- FASTMCP_DOCKET_URL=redis://... (or memory:// for single-process)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix tasks example import (TaskStatusResponse → GetTaskResult)
The example was using a non-existent TaskStatusResponse type.
Updated to use mcp.types.GetTaskResult which is what the
on_status_change callback actually receives.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix env var name in Docket error messages
The error messages referenced FASTMCP_EXPERIMENTAL_ENABLE_DOCKET but the
actual setting is FASTMCP_ENABLE_DOCKET.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove deprecated code re-added from pre-#2329 branch
- Remove ExtendedEnvSettingsSource (FASTMCP_SERVER_ prefix support)
- Remove dependencies parameter from FastMCP.__init__
* Replace fakeredis git pin with PyPI release
* Remove redundant fakeredis dev dep (pulled via pydocket)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
The link to FastMCP Server Documentation was pointing to /servers/fastmcp which returns 404. Changed to /servers/server.
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
When the MCP SDK's transport tries to terminate a session during cleanup,
it can hang if the server is unresponsive (e.g., rate-limited). Adding a
5-second timeout ensures we don't block forever during `__aexit__`.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
When GitHub's API rate limits cause asyncio shutdown issues, the test
times out rather than failing with the underlying 429 error. Updated the
detection logic to check for 429 indicators in the captured output when
a timeout occurs.
Also increased the per-test timeout from 15s to 30s to give remote API
calls more breathing room.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
All OAuth providers now return correct invalid_client error codes
instead of unauthorized_client for auth failures. Previously only
OAuthProxy had this fix; now OAuthProvider (and InMemoryOAuthProvider)
also benefit.