FastMCP 2.12 represents one of our most significant releases to date, both in scope and community involvement. After extensive testing and iteration with the community, we're shipping major improvements to authentication, configuration, and MCP feature adoption.
🔐 OAuth Proxy for Broader Provider Support addresses a fundamental challenge: while MCP requires Dynamic Client Registration (DCR), many popular OAuth providers don't support it. The new OAuth proxy bridges this gap, enabling FastMCP servers to authenticate with providers like GitHub, Google, WorkOS, and Azure through minimal configuration. These native integrations ship today, with more providers planned based on community needs.
📋 Declarative JSON Configuration introduces a standardized, portable way to describe and deploy MCP servers. The fastmcp.json configuration file becomes the single source of truth for dependencies, transport settings, entrypoints, and server metadata. This foundation sets the stage for future capabilities like transformations and remote sources, moving toward a world where MCP servers are as portable and shareable as container images.
🧠 Sampling API Fallback tackles the chicken-and-egg problem limiting adoption of advanced MCP features. Sampling—where servers request LLM completions from clients—is powerful but underutilized due to limited client support. FastMCP now lets server authors define fallback handlers that generate sampling completions server-side when clients don't support the feature, encouraging adoption while maintaining compatibility.
This release took longer than usual to ship, and for good reason: the community's aggressive testing and feedback on the authentication system helped us reach a level of stability we're confident in. There's certainly more work ahead, but these foundations position FastMCP to handle increasingly complex use cases while remaining approachable for developers.
Thank you to our new contributors and everyone who tested preview builds. Your feedback directly shaped these features.
What's Changed
New Features 🎉
- Add OAuth proxy that allows authentication with social IDPs without DCR support by @jlowin in #1434
- feat: introduce declarative JSON configuration system by @jlowin in #1517
- ✨ Fallback to a Completions API when Sampling is not available by @strawgate in #1145
- Implement typed source system for FastMCP declarative configuration by @jlowin in #1607
Enhancements 🔧
- Support importing custom_route endpoints when mounting servers by @jlowin in #1470
- Remove unnecessary asserts by @jlowin in #1484
- Add Claude issue triage by @jlowin in #1510
- Inline dedupe prompt by @jlowin in #1512
- Improve stdio and mcp_config clean-up by @strawgate in #1444
- involve kwargs to pass parameters on creating RichHandler for logging customization. by @itaru2622 in #1504
- Move SDK docs generation to post-merge workflow by @jlowin in #1513
- Improve label triage guidance by @jlowin in #1516
- Add code review guidelines for agents by @jlowin in #1520
- Remove trailing slash in unit tests by @jlowin in #1535
- Update OAuth callback UI branding by @jlowin in #1536
- Fix Marvin workflow to support development tools by @jlowin in #1537
- Add mounted_components_raise_on_load_error setting for debugging by @jlowin in #1534
- feat: Add --workspace flag to fastmcp install cursor by @jlowin in #1522
- switch from
pyrighttotyby @zzstoatzz in #1545 - feat: trigger Marvin workflow on PR body content by @jlowin in #1549
- Add WorkOS and Azure OAuth providers by @jlowin in #1550
- Adjust timeout for slow MCP Server shutdown test by @strawgate in #1561
- Update banner by @jlowin in #1567
- Added import of AuthProxy to auth init by @KaliszS in #1568
- Add configurable redirect URI validation for OAuth providers by @jlowin in #1582
- Remove invalid-argument-type ignore and fix type errors by @jlowin in #1588
- Remove generate-schema from public CLI by @jlowin in #1591
- Skip flaky windows test / mulit-client garbage collection by @jlowin in #1592
- Add setting to disable logging configuration by @isra17 in #1575
- Improve debug logging for nested Servers / Clients by @strawgate in #1604
- Add GitHub pull request template by @strawgate in #1581
- chore: Automate docs and schema updates via PRs by @jlowin in #1611
- Experiment with haiku for limited workflows by @jlowin in #1613
- feat: Improve GitHub workflow automation for schema and SDK docs by @jlowin in #1615
- Consolidate server loading logic into FileSystemSource by @jlowin in #1614
- Prevent Haiku Marvin from commenting when there are no duplicates by @jlowin in #1622
- chore: Add clarifying note to automated PR bodies by @jlowin in #1623
- feat: introduce inline snapshots by @strawgate in #1605
- Improve fastmcp.json environment configuration and project-based deployments by @jlowin in #1631
- fix: allow passing query params in OAuthProxy upstream authorization url by @danb27 in #1630
- Support multiple --with-editable flags in CLI commands by @jlowin in #1634
- feat: support comma separated oauth scopes by @jlowin in #1642
- Add allowed_client_redirect_uris to OAuth provider subclasses by @jlowin in #1662
- Consolidate CLI config parsing and prevent infinite loops by @jlowin in #1660
- Internal refactor: mcp server config by @jlowin in #1672
- Refactor Environment to support multiple runtime types by @jlowin in #1673
- Add type field to Environment base class by @jlowin in #1676
Fixes 🐞
- Fix breaking change: restore output_schema=False compatibility by @jlowin in #1482
- Fix #1506: Update tool filtering documentation from _meta to meta by @maybenotconnor in #1511
- Fix pytest warnings by @jlowin in #1559
- nest schemas under assets by @jlowin in #1593
- Skip flaky windows test by @jlowin in #1596
- ACTUALLY move schemas to fastmcp.json by @jlowin in #1597
- Fix and centralize CLI path resolution by @jlowin in #1590
- Remove client info modifications by @jlowin in #1620
- Fix $defs being discarded in input schema of transformed tool by @pldesch-chift in #1578
- Fix enum elicitation to use inline schemas for MCP compatibility by @jlowin in #1632
- Reuse session for
StdioTransportinClient.newby @strawgate in #1635 - Feat: Configurable LoggingMiddleware payload serialization by @vl-kp in #1636
- Fix OAuth redirect URI validation for DCR compatibility by @jlowin in #1661
- Add default scope handling in OAuth proxy by @romanusyk in #1667
- Fix OAuth token expiry handling by @jlowin in #1671
- Add resource_server_url parameter to OAuth proxy providers by @jlowin in #1682
Breaking Changes 🛫
Docs 📚
- Update changelog by @jlowin in #1453
- Update banner by @jlowin in #1472
- Update logo files by @jlowin in #1473
- Update deployment docs by @jlowin in #1486
- Update FastMCP Cloud screenshot by @jlowin in #1487
- Update authentication note in docs by @jlowin in #1488
- chore: Update installation.mdx version snippet by @thomas-te in #1496
- Update fastmcp cloud server requirements by @jlowin in #1497
- Fix oauth pyright type checking by @strawgate in #1498
- docs: Fix type annotation in return value documentation by @MaikelVeen in #1499
- Fix PromptMessage usage in docs example by @jlowin in #1515
- Create CODE_OF_CONDUCT.md by @jlowin in #1523
- Fixed wrong import path in new docs page by @KaliszS in #1538
- Document symmetric key JWT verification support by @jlowin in #1586
- Update fastmcp.json schema path by @jlowin in #1595
Dependencies 📦
- Bump actions/create-github-app-token from 1 to 2 by @dependabot[bot] in #1436
- Bump astral-sh/setup-uv from 4 to 6 by @dependabot[bot] in #1532
- Bump actions/checkout from 4 to 5 by @dependabot[bot] in #1533
Other Changes 🦾
- Add dedupe workflow by @jlowin in #1454
- Update AGENTS.md by @jlowin in #1471
- Give Marvin the power of the Internet by @strawgate in #1475
- Update
justerror message for static checks by @jlowin in #1483 - Remove labeler by @jlowin in #1509
- update aproto server to handle rich links by @zzstoatzz in #1556
- fix: enable triage bot for fork PRs using pull_request_target by @jlowin in #1557
New Contributors
- @thomas-te made their first contribution in #1496
- @maybenotconnor made their first contribution in #1511
- @MaikelVeen made their first contribution in #1499
- @KaliszS made their first contribution in #1538
- @isra17 made their first contribution in #1575
- @marvin-context-protocol[bot] made their first contribution in #1616
- @pldesch-chift made their first contribution in #1578
- @vl-kp made their first contribution in #1636
- @romanusyk made their first contribution in #1667
Full Changelog: v2.11.3...v2.12.0