Object-typed query parameters with explode=true (the default) were
passed as raw Python dicts to httpx, which called str() on them —
producing Python repr syntax (single quotes, capitalized booleans)
instead of proper query parameter serialization.
Per the OpenAPI specification, style=form with explode=true on objects
expands each property as a separate query parameter (e.g.
?myAttribute=true). This change handles dict values in both the
explode=true and explode=false branches of _serialize_query_params,
using the existing _query_scalar_to_str helper for correct boolean
formatting.
Fixes#2857
* feat: add TokenCache utility and caching to GitHubTokenVerifier
Extract the caching machinery from IntrospectionTokenVerifier into a
shared TokenCache class in fastmcp.utilities.token_cache, then wire
it into both IntrospectionTokenVerifier and GitHubTokenVerifier.
* Remove dead constant, validate negative cache params
* Fix overwrite eviction bug, skip cache on scope lookup failure
* pin pydantic-monty to 0.0.8
* rename tool/prompt/resource base modules to avoid decorator name shadow
* add sys.modules shims for old submodule import paths
* preserve original module paths in deprecation warnings
* clarify when sys.modules shims can be removed
* fix: prevent path traversal in skill download via malicious skill names
Co-authored-by: Claude <noreply@anthropic.com>
* fix: resolve skill_dir once and use consistently to prevent overwrite bypass
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix: URL-encode path params in OpenAPI provider to prevent SSRF/path traversal
Co-authored-by: Claude <noreply@anthropic.com>
* Exempt too-long from core-category requirement in triage
* fix: also encode dots in path params to prevent bare .. traversal
* fix: only encode .. (not all dots) to preserve valid dotted values
* fix: encode all dots in path params to prevent single-dot normalization
* fix: check decoded path stays within prefix in double-encoding test
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Fix async partial callables rejected by iscoroutinefunction (#3423)
Add `is_coroutine_function()` utility that unwraps `functools.partial`
before checking, and guard `isroutine` checks so partials aren't
misrouted through `__call__`.
* Also check asyncio.iscoroutinefunction in is_coroutine_function
* Update repository references from jlowin/fastmcp to prefecthq/fastmcp
* Retrigger CI after repo transfer
* chore: Update SDK documentation
* Only run deep triage on bug issues for jlowin
---------
Co-authored-by: marvin-context-protocol[bot] <225465937+marvin-context-protocol[bot]@users.noreply.github.com>
Rename Visibility to Enabled, collapse VisibilityRule into the transform,
and move enabled filtering from Provider to Server level so server-level
transforms can override provider-level disables.
* Consolidate tool transformation logic into TransformingProvider
Tool transformations were previously scattered across LocalProvider,
ProxyProvider, and MCPConfig. This consolidates all transformation
logic into TransformingProvider via with_transforms(tool_transforms={...}).
- Add tool_transforms parameter to TransformingProvider
- Add tool_transforms to Provider.with_transforms()
- Remove transformation storage from LocalProvider and ProxyProvider
- Remove add_tool_transformation() and remove_tool_transformation() from FastMCP
- Add tool_transforms parameter to factory methods (from_openapi, from_fastapi, create_proxy)
- Update tests to use new patterns
* Fix: reject tool lookups by pre-transform name
* Add collision validation for tool_transforms and fix docstring examples
- Validate duplicate target names in tool_transforms raise ValueError
- Fix docstring examples to use arguments/ArgTransformConfig (not args/ArgTransform)
- Add test for collision validation
* Add server-level tool transform APIs and fix task registration
- Add AggregateProvider to present multiple providers as one
- Add _get_root_provider() to apply server-level transforms uniformly
- Fix _docket_lifespan to use root provider (ensures renamed tools
register with correct keys for background execution)
- Add tool_transforms kwarg to __init__ (non-deprecated)
- Add add_tool_transform(), remove_tool_transform(), tool_transforms property
- Deprecate old API names (tool_transformations, add_tool_transformation, etc.)
- Update tests to use new API
* Add graceful degradation for provider errors in AggregateProvider
* Match original behavior: parallel queries with DEBUG logging
* Refactor transforms to middleware-style call_next pattern
Replaces the ad-hoc transformation system with a unified Transform
abstraction using the same call_next pattern as server middleware.
Key changes:
- New src/fastmcp/server/transforms/ module with Transform base class
- Namespace, ToolTransform, Visibility all implement the same interface
- Transforms compose via functools.partial chain building
- Visibility is now just the first transform in provider._transforms
- Server-level transforms apply after provider aggregation
- Task registration now applies full transform chain
Removes TransformingProvider, _BoundTransform, ComponentSource protocol.
User-facing API unchanged: mount(), add_transform(), enable/disable all
work as before.
* Add comprehensive transforms and visibility documentation
New docs/servers/providers/transforms.mdx covering:
- Mental model for middleware-style transform pattern
- Built-in transforms (Namespace, ToolTransform)
- Server vs provider-level transforms and ordering
- Tool modification (immediate vs deferred)
- Custom transform creation
New docs/servers/visibility.mdx covering:
- Enable/disable API for runtime visibility control
- Keys and tags for targeting components
- Allowlist mode with only=True
- Server vs provider visibility layering
Updates existing docs to reference new pages and simplifies
redundant content. Visibility is documented as a user feature,
not as an implementation detail.
* Restructure transforms docs and delete tool-transformation pattern
* Cleanup: simplify get_tasks and remove unused Provider.get_component
* Update loq
* Update loq limits and add loq note to AGENTS.md
* Deprecate add_tool_transformation and tool_transformations param
* Address PR review feedback: remove redundant imports, fix path reference
* Add missing imports to code examples in v3-features.mdx
* 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
* 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/
* 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.
* 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>
Allow traceback-related kwargs to override defaults by building a dict
with defaults first, then updating with user-provided values.
Fixes#2356
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Bump ty to >=0.0.1a25 with type fixes
Follow-up to #2295. Updates ty and fixes compatibility issues with alpha 25, including:
- Updated ignore comment syntax (possibly-unbound-attribute → possibly-missing-attribute)
- Fixed async generator type handling with anext()
- Fixed type narrowing for timeout parameters
- Converted base_url assignments to AnyHttpUrl after string manipulation
- Added CallToolResult to return type annotations
- Removed redundant type casts
- Fixed test form data to use strings instead of bytes
ty alpha 25 has limitations with isinstance() narrowing on unions (see pyproject.toml for details), requiring some targeted type ignores.
* Pin ty to ==0.0.1a25
Alpha releases can have breaking changes, so pin to the tested version.