Skip to content

v2.13.0: Cache Me If You Can

Choose a tag to compare

@jlowin jlowin released this 25 Oct 12:53
· 228 commits to main since this release
716e50d

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:

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 🔧

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_async by @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-code by @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 🛫

Docs 📚

Dependencies 📦

Other Changes 🦾

New Contributors

Full Changelog: v2.12.4...v2.13.0