* Add test_custom_subclass_tasks.py
* Refactor provider execution: delegate to middleware via wrapper components
- Remove execution methods (call_tool, read_resource, etc.) from Provider base
- Add FastMCPProvider* wrapper classes that delegate to child server middleware
- Move task routing to Tool._run() using contextvars (_task_metadata, _tool_call_key)
- Add convert_to_tool_result(result, output_schema) utility for Docket results
- Add convert_to_prompt_result() utility for prompt task results
- Pass namespaced key via add_to_docket(name=) for mounted tool lookup
* Standardize add_to_docket() with fn_key/task_key parameters
All components now use explicit fn_key (function lookup) and task_key
(result storage) parameters instead of relying on implicit key handling.
This fixes mounted component task execution where the MCP-visible key
differs from the Docket-registered function name.
* Add middleware chain tests for three-level mount hierarchy
Tests verify middleware runs at parent, child, and grandchild levels
for tools, resources, prompts, and resource templates.
* WIP: Provider refactor - unified submit_to_docket, template _read() in progress
Work in progress on refactoring execution to use component _read()/_run()/_render() methods.
Template background tasks not yet working - needs fix for Docket key lookup.
* Fix conversion functions to take full component for attribute access
Pass Tool/Prompt/Resource/Template to conversion functions instead of
individual attributes, ensuring access to serializer, output_schema,
mime_type, etc. Also fixes mixed-content output schema validation.
* Refactor: unified convert_result() methods and check_background_task helper
- Add convert_result() instance methods to all component types (Tool, Prompt, Resource, ResourceTemplate)
- Extract duplicated task routing logic into check_background_task() helper
- Fix type annotations on FastMCPProviderResource.read() and FastMCPProviderPrompt.render()
- Update protocol.py to use component.convert_result() uniformly
* Update tests to use namespace= instead of deprecated prefix= parameter
* Simplify .key as computed property
Keep .key as the standard lookup interface for all components but
implement it as a computed property instead of a stored field.
- Remove _key private attribute and custom model_copy(key=...)
- .key returns .name for tools/prompts, str(.uri) for resources,
.uri_template for templates
- Use .key universally for component lookups in managers
- MountedProvider: prefix URIs only for resources/templates, not names
- Docket registration: tools/prompts use .key, resources use .name
(matches fn.__name__ for function lookup)
* Simplify .key as computed property
Keep .key as the standard lookup interface for all components but
implement it as a computed property instead of a stored field.
- Remove _key private attribute and custom model_copy(key=...)
- .key returns .name for tools/prompts, str(.uri) for resources,
.uri_template for templates
- Use .key universally for component lookups and Docket registration
- MountedProvider: prefix URIs only for resources/templates, not names
- Add _backend_* fields to proxy classes to preserve original identifiers
for backend calls when prefixed via import_server
* Standardize .key as computed property
- .key is now a read-only computed property:
- Tools/Prompts: returns .name
- Resources: returns str(.uri)
- Templates: returns .uri_template
- Prefixing uses model_copy(update={...}) to change underlying field
- Resource/template names are NOT prefixed, only URIs
- Move import_server tests to tests/deprecated/
* Simplify Provider interface and consolidate docket registration
- Remove get_http_routes from Provider (unused)
- Remove ProviderLifespanConfig, _base_lifespan, _register_tasks
- Remove supports_tasks flag from Provider.__init__
- Consolidate all docket registration in server._docket_lifespan()
- Simplify lifespan() to take no parameters
- Move MountedProvider to separate module
* Fix control flow in ComponentService resource methods
* Move providers to server/providers
* Ensure MountedProvider get_* methods go through middleware
* Fix get_resource to only return concrete resources
Reverts template-checking in get_resource that broke task execution.
Tasks need access to the original template, not instantiated resources.
* Move prefix utilities into mounted.py, deprecate import_server
- Add resource prefix functions (add/remove/has_resource_prefix) to mounted.py
- Deprecate import_server with warning to use mount() instead
- Add tool_names uniqueness validation in MountedProvider
* Fix provider iteration order and remove dead _is_mounted flag
- Remove unused _is_mounted flag (MountedProvider.lifespan() calls _lifespan
not _lifespan_manager, so the flag was never checked)
- Fix provider iteration: change reversed() to forward order in execution
methods (_call_tool, _read_resource_middleware, _get_prompt_content_middleware)
to match documented "first non-None wins" semantics
- Fix ComponentService to handle prefix-less mounted servers using
_strip_tool_prefix()/_strip_resource_prefix() methods
- Update conflict resolution tests to expect first-registered provider wins
- Add regression tests for Docket behavior and prefix-less ComponentService
* Add TaskComponents type and exception handling for provider task registration
- Create TaskComponents dataclass with FunctionTool/FunctionResource/etc. types
for proper typing of get_tasks() return value
- Add try/except wrapper around provider.get_tasks() in _docket_lifespan for
consistent error handling (warn + continue or raise based on settings)
- Remove type: ignore comments from server.py task registration loop
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.
Single-element lists like [1] were being incorrectly unwrapped to "1"
in unstructured content while multi-element lists remained as lists.
This created inconsistent behavior where the structure was lost for
single items.
This fix ensures lists always preserve their structure in unstructured
content regardless of length, making behavior consistent and predictable.
Also removes pretty-printing from JSON serialization for more compact
output across tools, prompts, and resources.
Fixes#1064🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Because the server now validates inputs, its no longer viable to provide a JSON string where e.g. an array is expected, so we can entirely remove FastMCP's "legacy json parsing" support from 1.x.
This is a breaking change (for legacy opt-in behavior)
Implements comprehensive notification system for tools, resources, and prompts with automatic client updates and flexible message handlers.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>