Split the monolithic Client class into focused mixin classes:
- ClientToolsMixin (tools_client.py)
- ClientPromptsMixin (prompts.py)
- ClientResourcesMixin (resources.py)
- ClientTaskManagementMixin (task_management.py)
Also:
- Extract timeout normalization helpers to utilities/timeout.py
- Split SSETransport into its own module (transports/sse.py)
- Clean up unused imports across client modules
- Fix bare except clauses to catch specific McpError
Note: ty reports unresolved-attribute errors on mixin classes because
it doesn't understand that mixins will be composed with Client. This is
a known limitation of mixin typing in Python. The code is functionally
correct and all tests pass.
* Replace type: ignore[attr-defined] with isinstance assertions in tests
* Fix isinstance assertions in failing tests
- Fix enum test to check for ResponseEnum instead of str
- Fix binary resource test to check for BlobResourceContents instead of TextResourceContents
- Fix Root type tests to check attributes directly instead of isinstance checks
* Fix type errors without using type: ignore
- Remove execution methods from TransformingProvider (only handles transformations)
- Add execution methods to base Provider class with default implementations
- Fix type narrowing in tests using cast() instead of type: ignore
- Fix PromptResult type handling in prompt render tests
- Fix type narrowing in middleware test for arguments and structured_content
When a prompt function returned `mcp.types.PromptMessage` objects directly
and was executed as a task, the result serialization failed with
"'PromptMessage' object has no attribute 'to_mcp'".
The task result converter was calling `.to_mcp()` on what it thought was a
FastMCP wrapper type, but the import actually pulls in `mcp.types.PromptMessage`
directly, which is already the final MCP type. Removed the unnecessary
conversion.
🤖 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>
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>
* 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>