FastMCP 4.2.0a4 requires Python 3.11 or newer and adds Annotated dependencies. Depends(...) and built-ins such as CurrentContext() can now be declared as Annotated metadata, so a type alias like Config = Annotated[dict, Depends(get_config)] works across tools, resources, and prompts. Skill discovery over plain resources no longer lists a nested supporting SKILL.md as its own skill, and download_skill URIs now encode manifest paths.
Since a3, the redirect URI helpers normalize raw strings the way browsers read them, the joserfc and Authlib floors pick up security fixes, and fixes land for OpenAPI request bodies, CIMD redirect URIs, multi-select elicitation schemas, search indexing, and docstring parsing. Skills support remains experimental; this prerelease is intended for integration testing.
Thanks to our 68 contributors, including 40 first-time contributors.
What's Changed
Breaking Changes ⚠️
- Make Skill a storage-neutral object with folders as one loader by @zzstoatzz in #6065
- Require Python 3.11 by @zzstoatzz in #6377
Enhancements ✨
- Rename the resource-era list_skills helper to list_skill_summaries by @zzstoatzz in #6051
- Discover skills through mounted servers by @zzstoatzz in #6067
- Share Prefab renderer resources across equivalent tools by @jlowin, @fprieto14, and @keremoktener in #6077
- Export Skill from fastmcp by @zzstoatzz in #6071
- Add skills discovery to ClientGroup by @zzstoatzz in #6072
- Add --skills to fastmcp list by @zzstoatzz in #6073
- Add Client.read_skill and tighten skills docs by @zzstoatzz in #6087
- Verify and export skills with resource-manifest fallback by @zzstoatzz in #6086
- Forward Skills discovery through proxies by @jakekaplan in #5788
- Share strict skill snapshot projection by @zzstoatzz in #6089
- Use scoped local tests and leave full suites to CI by @zzstoatzz in #6094
- Share ClientGroup skill client lookup by @zzstoatzz in #6101
- Share filesystem skill supporting-file reads by @zzstoatzz in #6102
- Deliver concurrent triage reviews, draft fixes and mutation proposals by @zzstoatzz in #6116
- Post Marvin's dedupe and too-long comments from workflow steps by @gaker in #6170
- Remove the unused triage mutation batch by @zzstoatzz in #6208
- Restore the status site by @zzstoatzz in #6216
- Add agno, Agent Framework, and OpenAI Agents SDK to downstream smoke by @zzstoatzz in #6222
- Close external PRs until their author is assigned again by @zzstoatzz in #6227
- Let private triage sweeps run without the Sol reviewer by @zzstoatzz in #6229
- Add named model tiers to the agentic triage plans by @zzstoatzz in #6228
- Add reproducible public triage leads to backlog dashboard by @zzstoatzz in #6293
- Add a strict SkillsDirectoryProvider to fastmcp.skills.provider by @zzstoatzz in #6278
- Point experimental_skills at the new provider and drop alpha-only skills code by @zzstoatzz in #6279
- Deprecate the 4.1 skills API for removal in 4.3 by @zzstoatzz in #6280
- Add app restart to the smart home Fire TV example by @zzstoatzz in #6356
- Add a workflow that deploys agentic triage to Prefect Cloud by @zzstoatzz in #6380
- Support Annotated dependencies by @zzstoatzz and @Kludex in #6378
- Post triage outcomes instead of run starts, and skip maintainer events by @zzstoatzz in #6382
Security 🔒
- Verify advertised skill frontmatter when reading content by @zzstoatzz in #6090
- Check skill limits before reading directory and remote files by @zzstoatzz in #6092
- fix: preserve _list_query_params in FastMCPProviderResourceTemplate.wrap by @RS-ITACHI in #6130
- Read composite action inputs from env and pin actions by digest by @gaker in #6168
- Scope the /marvin App token to the permissions it uses by @zzstoatzz in #6206
- Require patched Authlib in client and server extras by @zzstoatzz and @zhuweid in #6337
- Update example locks past the schema-parsing security fix by @zzstoatzz in #6339
- Redact passwords from the worker's backend URL by @jaeminbird and @mbishflavien in #6113
- fix(auth): collapse a repeated
issin the client redirect by @shi-felix and @alpaylan in #6352 - Normalize raw-string redirect URIs through AnyUrl before validation by @uhhgxg and @alpaylan in #6315
Fixes 🐞
- Make the version-check InvalidURL regression independent of proxy parsing by @HootRock in #6048
- Build the Prefab renderer page on read, not on resources/list by @adam-zovos in #6039
- Install mounted skills under their own name in sync_skills by @zzstoatzz in #6078
- Stage skill exports before replacing installed files by @zzstoatzz in #6091
- fix: Prefix backend hash addresses with double underscores by @jlowin and @BlueX888 in #6100
- Rebind pre-4.2 Prefab backend addresses through 4.2 proxies by @jakekaplan in #6108
- Isolate and bound triage verification by @zzstoatzz in #6109
- Improve OpenAPI upstream error details by @zzstoatzz and @mssaleh in #6141
- Compare JSON const and enum values by JSON equality by @prassu017 and @alpaylan in #6126
- Bound Skills proxy backend pagination by @prassu017 and @Yash-Tripath1 in #6104
- fix: forward script arguments in FastMCPStdioTransport by @KashifManzer and @BlueX888 in #6119
- Return invalid params for prompts/get with a missing required argument by @asasemahmed and @xubenqiang in #6027
- Fix kept-alive stdio transports ignoring client timeouts by @HootRock in #6156
- perf(schema): skip unnecessary reference sibling restoration by @andreivince in #6161
- fix(cli): prefer Claude Code project servers by @mikamikasuki in #5522
- fix(cli): preserve JSON content block fields by @mikamikasuki in #5530
- Keep schema definitions when hydrating a wrapped tool result by @asasemahmed in #5927
- Reject undeclared OpenAPI tool arguments under strict input validation by @prassu017 and @mssaleh in #6140
- fix(resources): reverse hostless URIs through Namespace unchanged by @serhiizghama and @andreivince in #5230
- fix(openapi): preserve timeouts so the server maps them to the actionable message by @BlueX888 in #5847
- Keep posted review receipts on partial delivery and reject differing reviews by @zzstoatzz in #6178
- Drop client context holds left by finished tasks by @zzstoatzz in #6205
- Let clients with different timeouts share a kept-alive stdio session by @zzstoatzz in #6223
- fix(cli): preserve explicit null in generated tool commands by @likecake in #6191
- Honor empty tag inclusion filters in multi-server configs by @PennEwan in #6200
- fix(mcp-config): reuse one OAuth client per configured server by @kbkb628 and @whoskn in #6097
- Fix and quiet the triage alerts from 2026-11-02 by @zzstoatzz in #6235
- fix(tasks): send task IDs in routing headers by @eli-yip in #5810
- fix(middleware): treat an empty methods allowlist as "log nothing" by @gdut4140 in #5727
- Fix namespaced file resource reads while preserving URI normalization by @BlueLi66 in #5716
- fix(server): pass typed list request messages to list middleware hooks by @BlueX888 in #5732
- Stop OpenAPI end-to-end tests from hitting the network by @zzstoatzz in #6249
- fix(auth): Preserve browser consent bindings across concurrent OAuth approvals by @mikamikasuki in #5541
- fix(openapi): serialize header and path parameters per the simple style by @Harsh23Kashyap in #5091
- Fall back to method and path when an OpenAPI name slugs to nothing by @asasemahmed in #5699
- Convert OpenAPI 3.0 boolean exclusive bounds to numeric bounds by @asasemahmed in #5697
- Rewrite component refs under not, if/then/else and similar keywords by @asasemahmed in #5698
- fix(openapi): keep media-type $defs beside component schemas by @BlueX888 in #5709
- Omit readOnly properties from OpenAPI tool input schemas by @AarnavNoble in #5753
- fix: name root self-references after the generated root class by @BlueX888 in #5671
- fix(proxy): keep stale list results out of cache by @mikamikasuki in #5521
- Match Claude Code project keys by path on Windows by @zzstoatzz and @yongpange in #6240
- Stop preloading the server before launching the Inspector by @zzstoatzz and @mikamikasuki in #6241
- Cull expired OAuth state from the default OAuthProxy file store by @zzstoatzz, @nosmile99, and @mheidari98 in #6242
- Reuse the stdio session after a cancelled startup by @zzstoatzz and @mikamikasuki in #6243
- Match Gemini function responses to tool-use IDs by @zzstoatzz and @mikamikasuki in #6244
- Replace parent type keywords when an ArgTransform changes the type by @zzstoatzz, @syf2211, @HootRock, and @chrikrah in #6246
- Expire idle per-client rate limiters by @zzstoatzz and @mikamikasuki in #6247
- Match resource templates that spell out a literal query by @zzstoatzz and @arieleven in #6248
- fix(openapi): preserve explicit null in nullable JSON body properties by @mumu-bird in #5633
- Keep OpenAPI refs that point into a component schema intact by @zzstoatzz and @AarnavNoble in #6245
- fix(telemetry): record mounted and nested server spans as INTERNAL by @zzstoatzz and @sonmaximum in #6252
- fix(client): identify as fastmcp in clientInfo by default by @zzstoatzz in #6254
- fix(openapi): keep both values when a query object property matches another parameter by @zzstoatzz and @alpaylan in #6256
- fix(middleware): map exception subclasses in ErrorHandlingMiddleware by @zzstoatzz and @zurmag in #6257
- fix(client): report a lost connection instead of 'Client is not connected' by @zzstoatzz and @alex-feel in #6259
- fix(client): keep ClientGroup tool routes after the group context exits by @zzstoatzz, @hntrl, and @YingzuoLiu in #6268
- Accept structured skill metadata and allowed-tools lists by @jakekaplan in #6292
- Preserve 4.1 skills type checks and resource-only manifest migration by @zzstoatzz in #6305
- Fix generated CLIs for tools named app, console or Client by @andreivince in #6056
- Disambiguate colliding parameter flags in generate-cli by @mohitdixit02 and @andreivince in #6311
- fix: preserve CRLF descriptions in generated CLI parameter help by @chris00234 in #6075
- fix(agentic): repair baseline collection verification by @zzstoatzz in #6313
- Reject non-positive event retention limits by @mikamikasuki in #5535
- fix(search): rebuild the BM25 index when the tool name set changes by @shi-felix in #6282
- fix(tools): keep hidden parameter factories out of visible defaults by @shi-felix in #6283
- fix(auth): accept private-use scheme redirect URIs in CIMD documents by @ColePBryan in #6335
- Report the stop reason from sampling handlers when no tools are offered by @AarnavNoble in #6342
- fix(auth): preserve empty authority on custom-scheme redirect URIs by @codesphere-u and @alpaylan in #6347
- Declare items.type on multi-select list shorthand elicitations by @zzstoatzz, @shi-felix, @Vivek1898, and @alpaylan in #6361
- Mask prompt handler exceptions when mask_error_details=True by @pratyu2h and @maxmorrish in #6277
- Send {} for required OpenAPI object bodies with no fields by @rome-xi and @wang1299 in #6340
- fix(client): keep the response cache inert on legacy connections (#6298) by @xunWhale and @alpaylan in #6321
- Encode manifest paths in download_skill URIs by @zzstoatzz, @67-luck, and @BlueX888 in #6376
- Fix skill discovery for nested supporting files by @mahekara28 and @alpaylan in #6310
Docs 📚
- Consolidate skills docs into one Skills over MCP page by @zzstoatzz in #6049
- Rewrite skills docs around Skill and SkillCatalogProvider by @zzstoatzz in #6066
- Tighten skills docs examples by @zzstoatzz in #6070
- Shorten the skills docs page by @zzstoatzz in #6079
- Badge the skills page as 4.2.0 by @zzstoatzz in #6083
- Consolidate skills examples around verified Skill values by @zzstoatzz in #6093
- docs: add v4.2.0a1 changelog entries by @zzstoatzz in #6105
- Add MCP tool annotations to get_file example by @gl1tchdust in #5976
- Fix dead links in current documentation by @zzstoatzz and @Wilson0511 in #6142
- docs: rename Horizon to FastMCP Gateway in current docs by @parkedwards in #5653
- Document strict-mode handling of undeclared OpenAPI arguments by @zzstoatzz in #6169
- docs: add v4.2.0a2 changelog entries by @zzstoatzz in #6224
- docs(settings): explain what FASTMCP_DEBUG actually does by @zzstoatzz and @ianw in #6255
- docs: pass referrers on outbound links, add organization schema and page descriptions by @madureira-gabriel in #6287
- docs: add v4.2.0a3 changelog entries by @zzstoatzz in #6306
- docs: preserve docs routing metadata and release guidance by @zzstoatzz in #6320
- Correct how tools docs describe bytes return values by @DivyaNarahari97 in #6275
Other Changes 🦾
- chore(deps): Update dependency ruff to v0.17.2 by @prefect-renovate[bot] in #6233
- chore(deps): Pin dependencies by @prefect-renovate[bot] in #6064
- Require patched joserfc by @zzstoatzz in #6371
- Keep colon-terminated prose lines in docstring tool descriptions by @zzstoatzz, @jlx1999s, and @ptrailblazer89 in #6372
New Contributors
- @fprieto14 made their first contribution in #6077
- @keremoktener made their first contribution in #6077
- @gaker made their first contribution in #6170
- @zhuweid made their first contribution in #6337
- @jaeminbird made their first contribution in #6113
- @mbishflavien made their first contribution in #6113
- @shi-felix made their first contribution in #6352
- @adam-zovos made their first contribution in #6039
- @Yash-Tripath1 made their first contribution in #6104
- @likecake made their first contribution in #6191
- @PennEwan made their first contribution in #6200
- @whoskn made their first contribution in #6097
- @eli-yip made their first contribution in #5810
- @gdut4140 made their first contribution in #5727
- @BlueLi66 made their first contribution in #5716
- @yongpange made their first contribution in #6240
- @nosmile99 made their first contribution in #6242
- @mheidari98 made their first contribution in #6242
- @arieleven made their first contribution in #6248
- @mumu-bird made their first contribution in #5633
- @sonmaximum made their first contribution in #6252
- @zurmag made their first contribution in #6257
- @mohitdixit02 made their first contribution in #6311
- @chris00234 made their first contribution in #6075
- @ColePBryan made their first contribution in #6335
- @codesphere-u made their first contribution in #6347
- @Vivek1898 made their first contribution in #6361
- @pratyu2h made their first contribution in #6277
- @maxmorrish made their first contribution in #6277
- @rome-xi made their first contribution in #6340
- @wang1299 made their first contribution in #6340
- @xunWhale made their first contribution in #6321
- @67-luck made their first contribution in #6376
- @mahekara28 made their first contribution in #6310
- @gl1tchdust made their first contribution in #5976
- @ianw made their first contribution in #6255
- @madureira-gabriel made their first contribution in #6287
- @DivyaNarahari97 made their first contribution in #6275
- @jlx1999s made their first contribution in #6372
- @ptrailblazer89 made their first contribution in #6372
Full Changelog: v4.1.6...v4.2.0a4