github PrefectHQ/fastmcp v3.2.4
v3.2.4: Patch Me If You Can

7 hours ago

A grab bag of fixes, hardening, and polish.

The headline behavior change: background tasks are now scoped to the authorization context rather than the MCP session, so a task kicked off by an authenticated user survives session churn and stays tied to who started it. This is a breaking change for anyone relying on the old session-scoped semantics.

Security got three meaningful upgrades. FileUpload now validates actual decoded base64 size instead of trusting the client-reported number, so an attacker can't claim "10 bytes" and deliver 10MB. The proxy client stops forwarding inbound HTTP headers to unrelated remote servers — previously a header meant for server A could leak to server B. And AuthKit now auto-binds token audience to the resource URL per RFC 8707, closing a token-reuse gap across MCP resources.

Schema handling had a rough-edges pass. json_schema_to_type no longer crashes on Python keywords, boolean schemas, empty enums, or name collisions, and we added a 232K-schema crash test from APIs.guru to keep it honest. Gemini 2.5 Flash compatibility is fixed by stripping title fields the model rejects. Parameter descriptions are now extracted from docstrings automatically, so your tool signatures document themselves.

Plus a Keycloak OAuth provider for enterprise auth, improvements to ctx.elicit() (new response_title/response_description, deprecation warning when called without response_type), and dozens of smaller fixes across transforms, retry middleware, resource templates, and client disconnect handling.

What's Changed

Breaking Changes ⚠️

Enhancements ✨

  • Bump pydocket>=0.19.0, drop fakeredis pin by @chrisguidry in #3822
  • Add real-world schema crash test (232K schemas from APIs.guru) by @strawgate in #3826
  • Enable 7 zero-violation ruff rules by @strawgate in #3841
  • Promote 7 ty rules from ignore to warn by @strawgate in #3852
  • Replace ___ with hash-based backend tool routing and per-tool prefab resources by @jlowin in #3824
  • Enable 4 ruff rules (DTZ, ERA, ISC, INP) and fix 9 violations by @strawgate in #3842
  • Extract parameter descriptions from docstrings by @jlowin in #3872
  • ci: speed up schema crash test (CSafeLoader + xdist-safe aggregation) by @jlowin in #3873
  • test: bump OpenAPI init perf threshold to 200ms for Windows CI by @jlowin in #3879
  • refactor: unify object-schema conversion through _object_schema_to_type by @jlowin in #3884
  • Add Keycloak OAuth Provider for Enterprise Authentication and local dev by @stephaneberle9 in #1937
  • Allow auth providers to override protected resource base URLs by @aaazzam in #3900
  • Enable PERF and T20 ruff rules by @strawgate in #3845
  • Add response_title and response_description to ctx.elicit() by @jlowin in #3912
  • Deprecate ctx.elicit() without response_type by @jlowin in #3916

Security 🔒

  • Validate actual base64 data size in FileUpload, not client-reported size by @strawgate in #3816
  • Stop forwarding inbound HTTP headers to unrelated remote servers by @jlowin in #3837
  • AuthKit: auto-bind token audience to resource URL (RFC 8707) by @jlowin in #3905

Fixes 🐞

  • Version-check is_docket_available() to avoid transitive pydocket crash by @jlowin in #3807
  • fix: materialize generators before result conversion, handle bytes gracefully by @strawgate in #3830
  • Fix json_schema_to_type crashes on keywords, boolean schemas, empty enums, and name collisions by @strawgate in #3818
  • fix: replace or with is not None checks for config/override merging by @strawgate in #3833
  • fix: TransformedTool sync fn crash and schema mutation by @strawgate in #3823
  • fix: cross-provider duplicate detection, error visibility, mask propagation by @strawgate in #3827
  • fix: don't pass HTTP kwargs when transport is unspecified by @strawgate in #3838
  • fix: strip title fields from tool schemas for Gemini 2.5 Flash compatibility by @strawgate in #3861
  • fix: retry when LLM returns text instead of calling final_response by @strawgate in #3850
  • Raise on unhandled content types in sampling handler dispatch chains by @strawgate in #3857
  • Fix broken code examples in docs by @strawgate in #3869
  • fix: GoogleGenaiSamplingHandler leaks thought parts and gives unhelpful errors on empty responses by @strawgate in #3849
  • fix: cap consecutive final_response validation retries by @strawgate in #3851
  • Fix test quality issues by @strawgate in #3854
  • Fix MCP tool on docs welcome page by @lkiesow in #3874
  • Fix CIMD clients getting required_scopes instead of valid_scopes by @jlowin in #3836
  • Rename filesystem-provider example dir to avoid mcp/ collision by @jlowin in #3878
  • fix: drop configurable dedupe from AggregateProvider, always warn by @jlowin in #3877
  • fix: resolve list[dict] return type producing Root() instead of dicts by @KeWang0622 in #3880
  • fix: strip titles from bare-metadata nodes (Gemini 2.5 Flash) by @jlowin in #3881
  • Fix wildcard resource template params in mounted servers by @jlowin in #3899
  • Harden forced client disconnect cleanup by @vonbai in #3885
  • fix: elicitation scalar return, resource auto-serialization, Client.new() state, prompt errors by @strawgate in #3859
  • fix: task.wait() hangs indefinitely when task enters input_required by @mrishav in #3798
  • Fix RetryMiddleware not retrying tool errors by @strawgate in #3858
  • Stop pydantic 2.13 from leaking _WrappedResult docstring into tool output schemas by @jlowin in #3918

Docs 📚

  • Note generate-notes API in release workflow docs by @jlowin in #3806
  • docs: require agents to respect DNM markers on PRs by @jlowin in #3871
  • docs: add uv-managed dependencies and uvx examples to mcp-json configuration by @vincent067 in #3843
  • docs: link fastmcp-keycloak-local companion project from Keycloak integration page by @stephaneberle9 in #3904
  • Overhaul apps docs by @jlowin in #3915

Dependencies 📦

  • chore(deps): bump extractions/setup-just from 3 to 4 by @dependabot[bot] in #3863
  • chore(deps): bump astral-sh/setup-uv from 6 to 7 by @dependabot[bot] in #3865
  • chore(deps): bump actions/checkout from 4 to 6 by @dependabot[bot] in #3864
  • chore(deps-dev): bump pydantic-monty from 0.0.9 to 0.0.10 by @dependabot[bot] in #3809
  • chore(deps): bump the uv group across 2 directories with 1 update by @dependabot[bot] in #3913

New Contributors

Full Changelog: v3.2.3...v3.2.4

Don't miss a new fastmcp release

NewReleases is sending notifications on new releases.