* Update docs for required scopes
* add scopes
* Fix Azure scope validation
Azure returns unprefixed scopes in JWT tokens but requires prefixed scopes in authorization requests. The previous implementation incorrectly validated tokens against prefixed scopes, causing "invalid_token" errors.
Simplified AzureProvider to use standard JWTVerifier with unprefixed scopes for validation. Scopes are only prefixed when building the Azure authorization URL via _build_upstream_authorize_url() override.
Closes#2263
* Improve OAuth client token storage security documentation
Updated warning message and documentation to address security concerns
around storing OAuth credentials for multiple MCP servers.
* Update Azure sidebar title to include Entra ID
Co-authored-by: Jeremiah Lowin <jlowin@users.noreply.github.com>
* Update Azure title to emphasize Microsoft Entra ID
Co-authored-by: Jeremiah Lowin <jlowin@users.noreply.github.com>
* Update Azure title to emphasize Azure over Entra ID
Co-authored-by: Jeremiah Lowin <jlowin@users.noreply.github.com>
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Jeremiah Lowin <jlowin@users.noreply.github.com>
* Update docs for required scopes
* add scopes
* Fix Azure scope validation
Azure returns unprefixed scopes in JWT tokens but requires prefixed scopes in authorization requests. The previous implementation incorrectly validated tokens against prefixed scopes, causing "invalid_token" errors.
Simplified AzureProvider to use standard JWTVerifier with unprefixed scopes for validation. Scopes are only prefixed when building the Azure authorization URL via _build_upstream_authorize_url() override.
Closes#2263
* Add list_resources, list_prompts, and get_prompt methods to Context
- Add Context.list_resources() to list all available resources
- Add Context.list_prompts() to list all available prompts
- Add Context.get_prompt() to get a specific prompt with arguments
- Update ToolInjectionMiddleware to use new Context methods instead of creating temporary Client instances
- Remove unused Client and FastMCPTransport imports from tool_injection.py
This improves API consistency by allowing middleware/tools to use Context methods directly without needing to create temporary Client instances.
Fixes#2245
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Update docs
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
* Checkpoint progress
* Checkpoint progress
* add derive b64 method
* PR clean-up
* refactor da proxy
* Updates to tests
* Make jwt_signing_key required for oauth proxy
* use typing_extensions and fix tests
* PR Cleanup
* also adjust integration tests
* Update docs, use client secret to derive jwt signing key
* You win some you lose some, gg claude
* check for both in derive
* update documentation / clean up
* Update http.mdx
---------
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
* Add compatibility tools contrib module
Implements four standalone tools that expose resources and prompts
as callable tools for clients that only support the tools capability.
Features:
- list_resources: List all available resources
- get_resource: Read a resource by URI
- list_prompts: List all available prompts
- get_prompt: Get a prompt with optional arguments
The tools use Context to access the server instance and can be easily
added to any FastMCP server using the add_compatibility_tools helper
or by adding individual tool instances directly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Simplify compatibility tools to return raw MCP protocol objects
Return raw MCP protocol objects (ListResourcesResult, ReadResourceResult,
ListPromptsResult, GetPromptResult) instead of custom dictionaries. This
makes the tools simpler and more predictable by directly exposing what
the client methods return.
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Add tool injection middleware
* cleanup contrib module
* More clean-up
* Clean up tool injection middleware.
* Update src/fastmcp/server/middleware/tool_injection.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add tool injection docs
* Small cleanup of prompt middleware
* PR Feedback
* Fix tool injection tests
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat: use abstract collection types in FastMCP.__init__
Use Sequence, Collection, and Mapping from collections.abc for more
flexible typing in FastMCP.__init__ parameters. This allows downstream
developers to pass tuples, sets, and other collection types instead of
being restricted to list and dict.
Changes:
- middleware: list -> Sequence (converted to list internally)
- tools: list -> Sequence
- tool_transformations: dict -> Mapping (ToolManager updated)
- include_tags: set -> Collection
- exclude_tags: set -> Collection
- dependencies: kept as list per maintainer request
Closes#2212
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Concrete types in class inits
* Small imports cleanup
* Fix include/exclude tag handling
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
* Fix Azure scope mismatch causing MCP client validation errors
The AzureProvider was prefixing scopes during authorization but not in
token validation or Protected Resource Metadata, causing MCP clients to
reject tokens with "Server granted unauthorized scopes".
Changes:
- Prefix required_scopes once during __init__ and use consistently
- Pass prefixed scopes to JWTVerifier for token validation
- PRM now advertises prefixed scopes to MCP clients
- Remove unnecessary idempotent prefixing logic in authorize()
- Update comprehensive documentation explaining scope handling
- Update tests to reflect corrected behavior
Closes#2151
* Clarify that identifier_uri is optional in docstring
This test makes external HTTP requests to GitHub and is subject to
network latency, causing CI timeouts. Marking it as an integration test
excludes it from default test runs while keeping it available for
explicit integration testing.
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
All OAuth providers and OIDCProxy now expose jwt_signing_key,
token_encryption_key, and client_storage parameters for production
deployments requiring persistent token management across server restarts.
* Enhance OAuth Proxy error responses with branded HTML pages
OAuth Proxy authentication errors now show styled HTML error pages in browsers
instead of raw JSON, with content negotiation for API clients. Enhanced error
messages explain common causes (ephemeral storage, server restarts) and provide
clear remediation steps.
Changes:
- Created enhanced authorization handler that extends SDK's AuthorizationHandler
- Created enhanced auth middleware that extends SDK's RequireAuthMiddleware
- HTML error pages use server branding (icon, name) from FastMCP instance
- Added comprehensive troubleshooting section to OAuth Proxy docs
- Added FAQ entry linking to detailed troubleshooting
* Add comprehensive tests for enhanced OAuth error responses
Tests cover:
- HTML error pages for browser requests with server branding
- Enhanced JSON responses with registration endpoint hints
- Content negotiation between HTML and JSON
- Enhanced middleware error messages for invalid_token
- WWW-Authenticate header format consistency with SDK
* Update language for new storage defaults
* update docs
* Update tests for simplified error messages
* Clean up messages
* Add comprehensive keyring integration tests
Prevents OS keyring pollution during testing by adding a global mock in
conftest.py. Tests verify keyring behavior across platforms and fallback
scenarios without writing to the actual system keyring.
- Add global mock_keyring fixture to tests/conftest.py
- Add TestOAuthProxyKeyring class with 6 keyring-specific tests
- Remove try/except ImportError for keyring (now required dependency)
- Add keyring extra to py-key-value-aio dependency
- Clean up extraneous implementation comments in oauth_proxy.py
* Update OAuth keyring documentation
Update all OAuth-related documentation to reflect keyring-based key management:
- Add version badges to jwt_signing_key, token_encryption_key, and client_storage parameters
- Standardize "Default behavior (`None`):" formatting with backticks
- Ensure consistent messaging about development-only defaults across all docs
- Update oauth-proxy.mdx, oidc-proxy.mdx, http.mdx, storage-backends.mdx, and upgrade-guide.mdx
Update documentation links from py-key-value-aio to py-key-value repository.
The py-key-value-aio package lives in the py-key-value monorepo.
Co-authored-by: William Easton <strawgate@users.noreply.github.com>
Changes settings.home from `Path.home() / ".fastmcp"` to use platformdirs.user_data_dir(), following platform conventions (~/Library/Application Support on macOS, ~/.local/share on Linux, %APPDATA% on Windows).
* bug fix in `fastmcp install claude-code`
Calling the CLI like below command doenst end up working:
```
fastmcp install claude-code "$SERVER_FILE" \
--python 3.12 \
--env "DOCS_DIR=$DOCS_DIR" \
--env "ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY" \
--with fastmcp \
--with anthropic \
--with click
```
It errors out like:
```
Failed to install 'foo-mcp' in Claude Code: Invalid environment variable format: foo-mcp, environment variables should be added as: -e KEY1=value1
-e KEY2=value2
```
The fix was simply ensuring that the claude code mcp command gets mcp name directly.
* Apply suggestion from @jlowin
---------
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
* Add optional authorization consent screen for OAuth providers
Adds `require_authorization_consent` parameter (default True) to OAuthProxy and all providers. When disabled, authorization skips the consent screen for local development/testing. Logs security warning when disabled.
* Update warning message to use 'authorization consent screen'