Merge branch 'main' into 2-14-deprecations

This commit is contained in:
Jeremiah Lowin 2025-11-22 12:22:34 -05:00 committed by GitHub
commit 98d9a2b9d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 1266 additions and 373 deletions

View file

@ -510,6 +510,7 @@ When deploying to production, you'll want to optimize your server for performanc
# Run with basic configuration
uvicorn app:app --host 0.0.0.0 --port 8000
# Ensure stateless HTTP mode is enabled (stateless_http=True)
# Run with multiple workers for production
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
```
@ -601,4 +602,4 @@ This guide has shown you how to create an HTTP-accessible MCP server, but you'll
- **Edge platforms** (Cloudflare Workers)
- **Kubernetes clusters** (self-managed or managed)
The key requirements are Python 3.10+ support and the ability to expose an HTTP port. Most providers will require you to package your server (requirements.txt, Dockerfile, etc.) according to their deployment format. For managed, zero-configuration deployment, see [FastMCP Cloud](/deployment/fastmcp-cloud).
The key requirements are Python 3.10+ support and the ability to expose an HTTP port. Most providers will require you to package your server (requirements.txt, Dockerfile, etc.) according to their deployment format. For managed, zero-configuration deployment, see [FastMCP Cloud](/deployment/fastmcp-cloud).

View file

@ -299,17 +299,16 @@ async def test_database_tool():
### Testing Network Transports
While in-memory testing covers most unit testing needs, you'll occasionally need to test actual network transports like HTTP or SSE. FastMCP provides two approaches: in-process async servers using AnyIO task groups (preferred), and separate subprocess servers (for special cases).
While in-memory testing covers most unit testing needs, you'll occasionally need to test actual network transports like HTTP or SSE. FastMCP provides two approaches: in-process async servers (preferred), and separate subprocess servers (for special cases).
#### In-Process Network Testing (Preferred)
<VersionBadge version="2.13.0" />
For most network transport tests, use `run_server_async` with AnyIO task groups. This runs the server as a task in the same process, providing fast, deterministic tests with full debugger support:
For most network transport tests, use `run_server_async` as an async context manager. This runs the server as a task in the same process, providing fast, deterministic tests with full debugger support:
```python
import pytest
from anyio.abc import TaskGroup
from fastmcp import FastMCP, Client
from fastmcp.client.transports import StreamableHttpTransport
from fastmcp.utilities.tests import run_server_async
@ -317,19 +316,19 @@ from fastmcp.utilities.tests import run_server_async
def create_test_server() -> FastMCP:
"""Create a test server instance."""
server = FastMCP("TestServer")
@server.tool
def greet(name: str) -> str:
return f"Hello, {name}!"
return server
@pytest.fixture
async def http_server(task_group: TaskGroup) -> str:
"""Start server in-process using task group."""
async def http_server() -> str:
"""Start server in-process for testing."""
server = create_test_server()
url = await run_server_async(task_group, server, transport="http")
return url
async with run_server_async(server) as url:
yield url
async def test_http_transport(http_server: str):
"""Test actual HTTP transport behavior."""
@ -338,12 +337,12 @@ async def test_http_transport(http_server: str):
) as client:
result = await client.ping()
assert result is True
greeting = await client.call_tool("greet", {"name": "World"})
assert greeting.data == "Hello, World!"
```
The `task_group` fixture is provided globally by `conftest.py` and automatically handles server lifecycle and cleanup. This approach is faster than subprocess-based testing and provides better error messages.
The `run_server_async` context manager automatically handles server lifecycle and cleanup. This approach is faster than subprocess-based testing and provides better error messages.
#### Subprocess Testing (Special Cases)

View file

@ -6,7 +6,7 @@ icon: shield-check
tag: NEW
---
import { VersionBadge } from "/snippets/version-badge.mdx"
import { VersionBadge } from "/snippets/version-badge.mdx";
<VersionBadge version="2.12.4" />
@ -17,28 +17,29 @@ This guide shows you how to secure your FastMCP server using [**Descope**](https
### Prerequisites
Before you begin, you will need:
1. To [sign up](https://www.descope.com/sign-up) for a Free Forever Descope account
2. Your **Project ID** from the [Descope Console](https://app.descope.com/settings/project)
3. Your FastMCP server's URL (can be localhost for development, e.g., `http://localhost:3000`)
2. Your FastMCP server's URL (can be localhost for development, e.g., `http://localhost:3000`)
### Step 1: Configure Descope
<Steps>
<Step title="Enable Dynamic Client Registration">
1. Go to the [Inbound Apps page](https://app.descope.com/apps/inbound) of the Descope Console
2. Click **DCR Settings**
3. Enable **Dynamic Client Registration (DCR)**
4. Define allowed scopes
<Step title="Create an MCP Server">
1. Go to the [MCP Servers page](https://app.descope.com/mcp-servers) of the Descope Console, and create a new MCP Server.
2. Give the MCP server a name and description.
3. Ensure that **Dynamic Client Registration (DCR)** is enabled. Then click **Create**.
4. Once you've created the MCP Server, note your Well-Known URL.
<Warning>
DCR is required for FastMCP clients to automatically register with your authentication server.
</Warning>
</Step>
<Step title="Note Your Project ID">
Save your Project ID from [Project Settings](https://app.descope.com/settings/project):
<Step title="Note Your Well-Known URL">
Save your Well-Known URL from [MCP Server Settings](https://app.descope.com/mcp-servers):
```
Project ID: P2abc...123
Well-Known URL: https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration
```
</Step>
</Steps>
@ -48,15 +49,10 @@ Before you begin, you will need:
Create a `.env` file with your Descope configuration:
```bash
DESCOPE_PROJECT_ID=P2abc...123 # Your Descope Project ID
DESCOPE_BASE_URL=https://api.descope.com # Descope API URL
DESCOPE_CONFIG_URL=https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration # Your Descope Well-Known URL
SERVER_URL=http://localhost:3000 # Your server's base URL
```
<Note>
You can find your project's Descope Base URL in the [Multi-Region Support Guide](https://docs.descope.com/management/project-settings/multi-regional).
</Note>
### Step 3: FastMCP Configuration
Create your FastMCP server file and use the DescopeProvider to handle all the OAuth integration automatically:
@ -68,9 +64,8 @@ from fastmcp.server.auth.providers.descope import DescopeProvider
# The DescopeProvider automatically discovers Descope endpoints
# and configures JWT token validation
auth_provider = DescopeProvider(
project_id=DESCOPE_PROJECT_ID, # Your Descope Project ID
config_url=https://.../.well-known/openid-configuration, # Your MCP Server .well-known URL
base_url=SERVER_URL, # Your server's public URL
descope_base_url=DESCOPE_BASE_URL, # Descope API base URL
)
# Create FastMCP server with auth
@ -80,7 +75,7 @@ mcp = FastMCP(name="My Descope Protected Server", auth=auth_provider)
## Testing
To test your server, you can use the `fastmcp` CLI to run it locally. Assuming you've saved the above code to `server.py` (after replacing the `project_id`, `base_url`, and `descope_base_url` with your actual values!), you can run the following command:
To test your server, you can use the `fastmcp` CLI to run it locally. Assuming you've saved the above code to `server.py` (after replacing the environment variables with your actual values!), you can run the following command:
```bash
fastmcp run server.py --transport http --port 8000
@ -102,7 +97,6 @@ if __name__ == "__main__":
## Environment Variables
For production deployments, use environment variables instead of hardcoding credentials.
### Provider Selection
@ -110,9 +104,10 @@ For production deployments, use environment variables instead of hardcoding cred
Setting this environment variable allows the Descope provider to be used automatically without explicitly instantiating it in code.
<Card>
<ParamField path="FASTMCP_SERVER_AUTH" default="Not set">
Set to `fastmcp.server.auth.providers.descope.DescopeProvider` to use Descope authentication.
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH" default="Not set">
Set to `fastmcp.server.auth.providers.descope.DescopeProvider` to use
Descope authentication.
</ParamField>
</Card>
### Descope-Specific Configuration
@ -120,28 +115,25 @@ Set to `fastmcp.server.auth.providers.descope.DescopeProvider` to use Descope au
These environment variables provide default values for the Descope provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`.
<Card>
<ParamField path="FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_PROJECT_ID" required>
Your Descope Project ID from the [Descope Console](https://app.descope.com/settings/project)
<ParamField path="FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_CONFIG_URL" required>
Your Well-Known URL from the [Descope Console](https://app.descope.com/mcp-servers)
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_BASE_URL" required>
Public URL of your FastMCP server (e.g., `https://your-server.com` or `http://localhost:8000` for development)
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_DESCOPE_BASE_URL" default="https://api.descope.com">
Descope API base URL for your [region/environment](https://docs.descope.com/management/project-settings/multi-regional)
Public URL of your FastMCP server (e.g., `https://your-server.com` or
`http://localhost:8000` for development)
</ParamField>
</Card>
Example `.env` file:
```bash
# Use the Descope provider
FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.descope.DescopeProvider
# Descope configuration
FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_PROJECT_ID=P2abc...123
FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_CONFIG_URL=https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration
FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_BASE_URL=https://your-server.com
FASTMCP_SERVER_AUTH_DESCOPEPROVIDER_DESCOPE_BASE_URL=https://api.descope.com
```
With environment variables set, your server code simplifies to:
@ -151,4 +143,4 @@ from fastmcp import FastMCP
# Authentication is automatically configured from environment
mcp = FastMCP(name="My Descope Protected Server")
```
```

View file

@ -8,19 +8,16 @@ tag: NEW
import { VersionBadge } from "/snippets/version-badge.mdx"
<VersionBadge version="2.12.5" />
<VersionBadge version="2.13.0" />
Install auth stack to your FastMCP server with [Scalekit](https://scalekit.com) using the [Remote OAuth](/servers/auth/remote-oauth) pattern: Scalekit handles user authentication, and the MCP server validates issued tokens.
## Configuration
### Prerequisites
Before you begin
1. Get a [Scalekit account](https://app.scalekit.com/) and grab API credentials such as **Client ID**, **Client Secret** and **Environment URL** from _Dashboard > Developers > Settings_.
2. Have your FastMCP server's endpoint ready (can be localhost for development, e.g., `http://localhost:8000/mcp`)
1. Get a [Scalekit account](https://app.scalekit.com/) and grab your **Environment URL** from _Dashboard > Settings_ .
2. Have your FastMCP server's base URL ready (can be localhost for development, e.g., `http://localhost:8000/`)
### Step 1: Configure MCP server in Scalekit environment
@ -36,9 +33,10 @@ In your FastMCP project's `.env`:
```sh
SCALEKIT_ENVIRONMENT_URL=<YOUR_APP_ENVIRONMENT_URL>
SCALEKIT_CLIENT_ID=<YOUR_APP_CLIENT_ID> # skc_7008EXAMPLE46
SCALEKIT_RESOURCE_ID=<YOUR_APP_RESOURCE_ID> # res_926EXAMPLE5878
MCP_URL=http://localhost:8000/mcp
BASE_URL=http://localhost:8000/
# Optional: additional scopes tokens must have
# SCALEKIT_REQUIRED_SCOPES=read,write
```
</Step>
@ -48,6 +46,8 @@ MCP_URL=http://localhost:8000/mcp
Create your FastMCP server file and use the ScalekitProvider to handle all the OAuth integration automatically:
> **Warning:** The legacy `mcp_url` and `client_id` parameters are deprecated and will be removed in a future release. Use `base_url` instead of `mcp_url` and remove `client_id` from your configuration.
```python server.py
from fastmcp import FastMCP
from fastmcp.server.auth.providers.scalekit import ScalekitProvider
@ -55,9 +55,9 @@ from fastmcp.server.auth.providers.scalekit import ScalekitProvider
# Discovers Scalekit endpoints and set up JWT token validation
auth_provider = ScalekitProvider(
environment_url=SCALEKIT_ENVIRONMENT_URL, # Scalekit environment URL
client_id=SCALEKIT_CLIENT_ID, # OAuth client ID
resource_id=SCALEKIT_RESOURCE_ID, # Resource server ID
mcp_url=SERVER_URL, # Is also aud claim
base_url=SERVER_URL, # Public MCP endpoint
required_scopes=["read"], # Optional scope enforcement
)
# Create FastMCP server with auth
@ -75,6 +75,10 @@ def auth_status() -> dict:
```
<Tip>
Set `required_scopes` when you need tokens to carry specific permissions. Leave it unset to allow any token issued for the resource.
</Tip>
## Testing
### Start the MCP server
@ -104,16 +108,18 @@ These environment variables provide default values for the Scalekit provider, wh
Your Scalekit environment URL from the Admin Portal (e.g., `https://your-env.scalekit.com`)
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_CLIENT_ID" required>
Your Scalekit OAuth application client ID from the Applications section
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_RESOURCE_ID" required>
Your Scalekit resource server ID from the Resources section
Your Scalekit resource server ID from the MCP Servers section
</ParamField>
<ParamField path="FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_MCP_URL" required>
Public URL of your FastMCP server (e.g., `https://your-server.com` or `http://localhost:8000/mcp` for development)
<ParamField path="FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_BASE_URL" required>
Public URL of your FastMCP server (e.g., `https://your-server.com` or `http://localhost:8000/` for development)
</ParamField>
Legacy `FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_MCP_URL` is still recognized for backward compatibility but will be removed soon-rename it to `...BASE_URL`.
<ParamField path="FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_REQUIRED_SCOPES" default="[]">
Comma-, space-, or JSON-separated list of scopes that tokens must include to access your server
</ParamField>
</Card>
@ -125,9 +131,10 @@ FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.scalekit.ScalekitProvider
# Scalekit configuration
FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_ENVIRONMENT_URL=https://your-env.scalekit.com
FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_CLIENT_ID=skc_123
FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_RESOURCE_ID=res_456
FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_MCP_URL=https://your-server.com/mcp
FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_BASE_URL=https://your-server.com/
# FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_REQUIRED_SCOPES=read,write
# FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_MCP_URL=https://your-server.com/ # Deprecated
```
With environment variables set, your server code simplifies to:

View file

@ -5,21 +5,18 @@ sidebarTitle: descope
# `fastmcp.server.auth.providers.descope`
Descope authentication provider for FastMCP.
This module provides DescopeProvider - a complete authentication solution that integrates
with Descope's OAuth 2.1 and OpenID Connect services, supporting Dynamic Client Registration (DCR)
for seamless MCP client authentication.
## Classes
### `DescopeProviderSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/descope.py#L25" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `DescopeProvider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/descope.py#L37" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Descope metadata provider for DCR (Dynamic Client Registration).
This provider implements Descope integration using metadata forwarding.
@ -29,20 +26,20 @@ as a resource server.
IMPORTANT SETUP REQUIREMENTS:
1. Enable Dynamic Client Registration in Descope Console:
- Go to the [Inbound Apps page](https://app.descope.com/apps/inbound) of the Descope Console
- Click **DCR Settings**
- Enable **Dynamic Client Registration (DCR)**
- Define allowed scopes
1. Create an MCP Server in Descope Console:
2. Note your Project ID:
- Save your Project ID from [Project Settings](https://app.descope.com/settings/project)
- Example: P2abc...123
- Go to the [MCP Servers page](https://app.descope.com/mcp-servers) of the Descope Console
- Create a new MCP Server
- Ensure that **Dynamic Client Registration (DCR)** is enabled
- Note your Well-Known URL
2. Note your Well-Known URL:
- Save your Well-Known URL from [MCP Server Settings](https://app.descope.com/mcp-servers)
- Format: `https://.../v1/apps/agentic/P.../M.../.well-known/openid-configuration`
For detailed setup instructions, see:
https://docs.descope.com/identity-federation/inbound-apps/creating-inbound-apps#method-2-dynamic-client-registration-dcr
**Methods:**
#### `get_routes` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/descope.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
@ -57,6 +54,6 @@ This returns the standard protected resource routes plus an authorization server
metadata endpoint that forwards Descope's OAuth metadata to clients.
**Args:**
- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp")
This is used to advertise the resource URL in metadata.
- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp")
This is used to advertise the resource URL in metadata.

View file

@ -37,9 +37,9 @@ IMPORTANT SETUP REQUIREMENTS:
2. Environment Configuration:
- Set SCALEKIT_ENVIRONMENT_URL (e.g., https://your-env.scalekit.com)
- Set SCALEKIT_CLIENT_ID from your OAuth application
- Set SCALEKIT_RESOURCE_ID from your created resource
- Set MCP_URL to your FastMCP server's public URL
- Set BASE_URL to your FastMCP server's public URL
- (Optional) Set SCALEKIT_REQUIRED_SCOPES to enforce token scopes
For detailed setup instructions, see:
https://docs.scalekit.com/mcp/overview/
@ -61,4 +61,3 @@ metadata endpoint that forwards Scalekit's OAuth metadata to clients.
**Args:**
- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp")
This is used to advertise the resource URL in metadata.

View file

@ -354,7 +354,9 @@ Field provides several validation and documentation features:
You can exclude certain arguments from the tool schema shown to the LLM. This is useful for arguments that are injected at runtime (such as `state`, `user_id`, or credentials) and should not be exposed to the LLM or client. Only arguments with default values can be excluded; attempting to exclude a required argument will raise an error.
Example:
**Note:** `exclude_args` will be deprecated in FastMCP 2.14 in favor of dependency injection with `Depends()` for better lifecycle management and more explicit dependency handling. `exclude_args` will continue to work until then.
Example with `exclude_args`:
```python
@mcp.tool(