v2.13.0: Cache Me If You Can
FastMCP 2.13.0 "Cache Me If You Can" represents a fundamental maturation of the framework. After months of community feedback on authentication and state management, this release delivers the infrastructure FastMCP needs to handle production workloads: persistent storage, response caching, and pragmatic OAuth improvements that reflect real-world deployment challenges.
💾 Pluggable storage backends bring persistent state to FastMCP servers. Built on py-key-value-aio, a new library from FastMCP maintainer Bill Easton (@strawgate), the storage layer provides encrypted disk storage by default, platform-aware token management, and a simple key-value interface for application state. We're excited to bring this elegantly designed library into the FastMCP ecosystem - it's both powerful and remarkably easy to use, including wrappers to add encryption, TTLs, caching, and more to backends ranging from Elasticsearch, Redis, DynamoDB, filesystem, in-memory, and more! OAuth providers now automatically persist tokens across restarts, and developers can store arbitrary state without reaching for external databases. This foundation enables long-running sessions, cached credentials, and stateful applications built on MCP.
🔐 OAuth maturity brings months of production learnings into the framework. The new consent screen prevents confused deputy and authorization bypass attacks discovered in earlier versions while providing a clean UX with customizable branding. The OAuth proxy now issues its own tokens with automatic key derivation from client secrets, and RFC 7662 token introspection support enables enterprise auth flows. Path prefix mounting enables OAuth-protected servers to integrate into existing web applications under custom paths like /api, and MCP 1.17+ compliance with RFC 9728 ensures protocol compatibility. Combined with improved error handling and platform-aware token storage, OAuth is now production-ready and security-hardened for serious applications.
FastMCP now supports out-of-the-box authentication with:
- WorkOS and AuthKit
- GitHub
- Azure (Entra ID)
- AWS Cognito
- Auth0
- Descope
- Scalekit
- JWTs
- RFC 7662 token introspection
⚡ Response Caching Middleware dramatically improves performance for expensive operations. Cache tool and resource responses with configurable TTLs, reducing redundant API calls and speeding up repeated queries.
🔄 Server lifespans provide proper initialization and cleanup hooks that run once per server instance instead of per client session. This fixes a long-standing source of confusion in the MCP SDK and enables proper resource management for database connections, background tasks, and other server-level state. Note: this is a breaking behavioral change if you were using the lifespan parameter.
✨ Developer experience improvements include Pydantic input validation for better type safety, icon support for richer UX, RFC 6570 query parameters for resource templates, improved Context API methods (list_resources, list_prompts, get_prompt), and async file/directory resources.
This release includes contributions from 20 new contributors and represents the largest feature set in a while. Thank you to everyone who tested preview builds and filed issues - your feedback shaped these improvements!
What's Changed
New Features 🎉
- Add RFC 6570 query parameter support to resource templates by @jlowin in #1971
- Add Storage to FastMCP and switch OAuth to use it by @strawgate in #1913
- Add Pydantic-compatible input validation by @jlowin in #2073
- Add RFC 7662 token introspection provider by @jlowin in #2074
- Add Response Caching Middleware by @strawgate in #1845
- Support mounting OAuth-protected servers under path prefixes by @jlowin in #2119
- OAuth proxy issues its own tokens by @jlowin in #2109
- Implement icon support by @jlowin in #2121
- Add ToolInjectionMiddleware + Tools for Read/List Resource/Prompt for Client Compat by @strawgate in #2142
Enhancements 🔧
- Add Scalekit Provider for Enterprise Authentication by @AkshayParihar33 in #1927
- Add AuthKit DCR example by @jlowin in #1935
- Remove redirect path for authkit example by @jlowin in #1938
- feat: Follow OAuth 2.1 spec requirements on auth failures by @tcarac in #1923
- Refactor OAuth 2.1 error handling with TokenHandler subclass by @jlowin in #1948
- Expand timeouts by @jlowin in #1954
- Upgrade GitHub workflows to claude-code-action@v1 by @jlowin in #1956
- Add --model claude-sonnet-4-5-20250929 to all workflows by @jlowin in #1963
- Improve env vars for marvin by @jlowin in #1972
- Add Any annotations to args and kwargs by @strawgate in #1994
- Mark GitHub Integration tests as flaky by @strawgate in #2000
- Internal refactor of MCP handlers by @jlowin in #2005
- Support
initializerequests in middleware by @jlowin in #1546 - Updates to Logging Middleware by @strawgate in #1974
- add supabase-auth by @aaazzam in #1997
- Allow direct instantiation of Prompt and Resource classes by @jlowin in #2031
- Support customizable env file location by @jlowin in #2036
- Improve Tracebacks for narrow terminals by @jlowin in #1939
- Refactor mounting logic from managers to server by @jlowin in #2069
- feat: expose errlog on stdio transport by @mpuhacz in #1991
- feat: Add title, annotations and meta to mixin decorators by @AnkeshThakur in #2033
- Add warnings regarding memory store by @strawgate in #2052
- Also push client messages (info/warn/debug) to server debug log by @strawgate in #2063
- feat: add azp claim by @roee-hersh in #1945
- bump kv dependency to 0.2.2 by @strawgate in #2089
- Add auto-close workflow for issues needing MRE by @jlowin in #2100
- Add client_storage property to aws provider by @rparme in #2107
- Update version badge for azure auth docs by @jlowin in #2120
- Disable parallel test execution on Windows by @jlowin in #2128
- Support custom server name, icons, and link in OAuth Proxy consent page by @jlowin in #2135
- Replace subprocess tests with in-process async servers by @jlowin in #2006
- Progress replacing asyncio with anyio by @jlowin in #2143
- Update CLI logo by @jlowin in #2159
- Change auth init log to debug by @jlowin in #2160
- allow non write users for marvin flows by @jlowin in #2161
- Redesign OAuth consent screen for better UX by @jlowin in #2170
- Allow authorization consent screen to be disabled by @jlowin in #2172
- example: update server init usage by @zzstoatzz in #2200
- Update smart home example again by @zzstoatzz in #2201
- Use platformdirs for settings.home by @jlowin in #2213
- Add platform-aware OAuth token persistence by @jlowin in #2218
- Update CLI logo by @jlowin in #2220
- Improve OAuth error messages with custom handlers and middleware by @jlowin in #2221
- Fix martian concurrency controls and dedupe issues mcp servers by @strawgate in #2240
- Use abstract types for FastMCP class instantiation by @strawgate in #2219
- Derive
jwt_signing_keyfrom Client Secret, default to Encrypted Disk Store by @strawgate in #2223 - Delete performance ratio in unit test by @jlowin in #2250
- Small Clean-up by @strawgate in #2247
- Add list_resources, list_prompts, and get_prompt methods to Context by @strawgate in #2249
- Remove redundant None checks from Context methods by @jlowin in #2251
Fixes 🐞
- Fix Python 3.13 websockets deprecation warning by @jlowin in #1949
- Fix path resolution in install commands by @jlowin in #1951
- Fix SSE endpoint accepting POST requests instead of returning 405 by @jlowin in #1953
- Fix claude-code-action@v1 authentication by @jlowin in #1958
- cli: fix banner width by removing emoji variation selectors by @zzstoatzz in #1975
- Fix improper conversion of list[Audio | File | Image] helpers by @joshrubin-p360 in #1970
- Update doc for tool-transformation regarding output_schema by @geraint0923 in #2009
- Azure (Entra) OAuth: Validate token against FastMCP app, not Graph. by @nbaju1 in #1891
- Default to FastMCP version when server version not specified by @jlowin in #2022
- Check if refresh_token is None by @Kyle-Dinh in #2025
- fix: wrong server name in explicit server entrypoint doc by @alDuncanson in #2046
- fixed a comment in File class by @Anurag-gg in #2066
- Prevent confused deputy attacks in OAuth proxy by @jlowin in #2056
- Fix: add missing json_response parameter to
run_http_asyncby @tradeqvest in #2071 - Change middleware return types from list to Sequence by @strawgate in #2058
- Fix asyncio error when running FastMCP 1.x servers by @chrisguidry in #2084
- Escape all HTML to prevent XSS attack by @jlowin in #2090
- Remove shell=True from Windows subprocess calls by @jlowin in #2091
- Fix experimental parser missing top-level response schemas (#2087) by @jlowin in #2092
- Fix nullable enum validation in OpenAPI converter by @jlowin in #2093
- Remove obsolete claude.py with Windows path bug by @jlowin in #2101
- Fix log handler to accept any JSON-serializable data type by @jlowin in #2102
- Fix missing import in Tool Transformation docs. by @andrew-mclachlan in #2108
- transform NotFoundError to standard MCP error by @omeraha in #2133
- Fix google scope example by @jlowin in #2144
- Update content type in advanced_tool function by @hyeonjae in #2147
- Make CORS opt-in via middleware parameter by @jlowin in #2150
- Remove warning message in common scenario of all client redirect uri'… by @jlowin in #2156
- Remove fonts which weren't rendering in all browsers by @jlowin in #2174
- Update environment vars in uvx transport by @derluke in #2169
- Restore gray monospace styling for OAuth callback screen by @jlowin in #2173
- bug fix in
fastmcp install claude-codeby @valayDave in #2165 - Expose OAuth token management parameters across all providers by @jlowin in #2222
- Mark test_github_api_schema_performance as integration test by @strawgate in #2242
- Fix Azure scope mismatch causing MCP client validation errors by @jlowin in #2243
- Add exc_info=True to inspect command error logging by @aaazzam in #2232
- Add version badge for run_server_async in tests docs by @jlowin in #2237
- Async FileResource and DirectoryResource by @strawgate in #2241
Breaking Changes 🛫
- Switch Lifespan to being a Server Lifespan by @strawgate in #2013
- Upgrade to MCP 1.17+ with RFC 9728 compliance by @jlowin in #2122
Docs 📚
- Add updates for 2.12.4 by @jlowin in #1929
- Update FastAPI docs by @jlowin in #1934
- Update ChatGPT docs for Chat mode with Developer Mode by @jlowin in #1936
- Additional Tool Transformation Examples for Client Wrapping by @strawgate in #2002
- Improve docs on prefix rules by @jlowin in #2028
- Add version badge to on_initialize docs by @jlowin in #2029
- Delete outdated root docs by @jlowin in #2075
- Clarify context is scoped to single MCP request by @jlowin in #2099
- Document container limitations for Image/Audio/File objects by @jlowin in #2118
- Add security policy by @jlowin in #2117
- Add storage backend documentation by @jlowin in #2137
- Docs by @jlowin in #2145
- Update changelog for 2.12.5 by @jlowin in #2146
- docs: Add AWS Cognito resource server requirement and CORS guidance by @jlowin in #2149
- Move sampling fallback handler docs to server section by @jlowin in #2163
- Fix dead links to py-key-value repository by @strawgate in #2217
- Fix middleware example: add context parameter to call_next() by @jlowin in #2215
- Add Documentation for FastMCP Server Testing by @strawgate in #2244
Dependencies 📦
- Bump py-key-value-aio to 0.2.6 by @strawgate in #2196
Other Changes 🦾
- Fix prompt_file input and bot attribution by @jlowin in #1960
- Improve Marvin and add a Martian by @strawgate in #1982
- Improve the Martian by @strawgate in #1983
- Fix Marvin labeling and shorten Martian responses by @strawgate in #1987
New Contributors
- @AkshayParihar33 made their first contribution in #1927
- @tcarac made their first contribution in #1923
- @joshrubin-p360 made their first contribution in #1970
- @geraint0923 made their first contribution in #2009
- @nbaju1 made their first contribution in #1891
- @aaazzam made their first contribution in #1997
- @Kyle-Dinh made their first contribution in #2025
- @alDuncanson made their first contribution in #2046
- @Anurag-gg made their first contribution in #2066
- @tradeqvest made their first contribution in #2071
- @mpuhacz made their first contribution in #1991
- @AnkeshThakur made their first contribution in #2033
- @chrisguidry made their first contribution in #2084
- @roee-hersh made their first contribution in #1945
- @rparme made their first contribution in #2107
- @andrew-mclachlan made their first contribution in #2108
- @omeraha made their first contribution in #2133
- @hyeonjae made their first contribution in #2147
- @derluke made their first contribution in #2169
- @valayDave made their first contribution in #2165
Full Changelog: v2.12.4...v2.13.0