FastMCP 4.2.0a3 consolidates skills around Skill, SkillCatalogProvider, and the new strict SkillsDirectoryProvider in fastmcp.skills.provider. Directory loading validates each skill before publication, and skills with structured metadata or YAML allowed-tools lists are accepted without changing their values. This alpha also fixes stale proxy discovery caches, preserves OpenAPI schema references and explicit null values, and improves client connection recovery. Skills support remains experimental; this prerelease is intended for integration testing.
If you import the 4.1 skills providers directly, they keep their behavior in 4.2 and now warn ahead of removal in 4.3. Move directory loading to from fastmcp.skills.provider import SkillsDirectoryProvider; its startup errors and the legacy providers' warnings identify folders that need fixing. For a single skill, use Skill.from_directory(...) with SkillCatalogProvider from fastmcp.skills.provider. Client.list_skill_resources() remains available for servers without the Skills extension. The old experimental_skills=True path redirects to the new provider for the base class and rejects subclasses to preserve access controls. Legacy Skill wire-model construction still works with a warning, wire entries retain isinstance(entry, Skill) behavior, and existing Pydantic Skill fields still validate wire payloads. Use MCPSkill for wire entries, annotations, and checks, and Skill for authoring. For manifest metadata on resource-only servers, read skill://<name>/_manifest with client.read_resource() and parse its JSON; client.get_skill() requires the Skills extension, while client.read_skill() downloads and validates the whole skill.
Since a2, ClientGroup retains known tool routes after its context exits, OpenAPI tool inputs omit readOnly properties, and header and path parameters follow their declared simple serialization style. OAuth consent bindings survive concurrent approvals, exception middleware matches subclasses, and empty logging method filters mean “log nothing.”
Thanks to our 46 contributors, including 29 first-time contributors.
What's Changed
Breaking Changes ⚠️
- Make Skill a storage-neutral object with folders as one loader by @zzstoatzz in #6065
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
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
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 and @BlueX888 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 @taltal-beep 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
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
Other Changes 🦾
- chore(deps): Update dependency ruff to v0.17.2 by @prefect-renovate in #6233
- chore(deps): Pin dependencies by @prefect-renovate in #6064
New Contributors
- @adam-zovos made their first contribution in #6039
- @alpaylan made their first contribution in #6126
- @BlueLi66 made their first contribution in #5716
- @eli-yip made their first contribution in #5810
- @fprieto14 made their first contribution in #6077
- @gaker made their first contribution in #6168
- @gdut4140 made their first contribution in #5727
- @gl1tchdust made their first contribution in #5976
- @hntrl made their first contribution in #6268
- @ianw made their first contribution in #6255
- @KashifManzer made their first contribution in #6119
- @keremoktener made their first contribution in #6077
- @likecake made their first contribution in #6191
- @mheidari98 made their first contribution in #6242
- @mssaleh made their first contribution in #6141
- @mumu-bird made their first contribution in #5633
- @nosmile99 made their first contribution in #6242
- @PennEwan made their first contribution in #6200
- @prassu017 made their first contribution in #6104
- @RS-ITACHI made their first contribution in #6130
- @serhiizghama made their first contribution in #5230
- @sonmaximum made their first contribution in #6252
- @taltal-beep made their first contribution in #6248
- @whoskn made their first contribution in #6097
- @xubenqiang made their first contribution in #6027
- @Yash-Tripath1 made their first contribution in #6104
- @YingzuoLiu made their first contribution in #6268
- @yongpange made their first contribution in #6240
- @zurmag made their first contribution in #6257
Full Changelog: v4.1.6...v4.2.0a3