Merge pull request #3363 from PrefectHQ/main

Fast-forward published-docs to v3.1.0
This commit is contained in:
Jeremiah Lowin 2026-03-02 21:54:36 -05:00 committed by GitHub
commit 328afe0fdb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
206 changed files with 22228 additions and 7942 deletions

26
.claude/hooks/session-init.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
set -e
# Only run in remote/cloud environments
if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then
exit 0
fi
command -v gh &> /dev/null && exit 0
LOCAL_BIN="$HOME/.local/bin"
mkdir -p "$LOCAL_BIN"
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
VERSION=$(curl -fsSL https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
TARBALL="gh_${VERSION#v}_linux_${ARCH}.tar.gz"
echo "Installing gh ${VERSION}..."
TEMP=$(mktemp -d)
trap 'rm -rf "$TEMP"' EXIT
curl -fsSL "https://github.com/cli/cli/releases/download/${VERSION}/${TARBALL}" | tar -xz -C "$TEMP"
cp "$TEMP"/gh_*/bin/gh "$LOCAL_BIN/gh"
chmod 755 "$LOCAL_BIN/gh"
[ -n "$CLAUDE_ENV_FILE" ] && echo "export PATH=\"$LOCAL_BIN:\$PATH\"" >> "$CLAUDE_ENV_FILE"
echo "gh installed: $("$LOCAL_BIN/gh" --version | head -1)"

15
.claude/settings.json Normal file
View file

@ -0,0 +1,15 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-init.sh",
"timeout": 120
}
]
}
]
}
}

View file

@ -17,6 +17,8 @@ body:
- 🔄 **Make sure you're testing on the latest version of FastMCP** - many issues are already fixed in newer versions
- 🔍 **Check if someone else has already reported this issue** or if it's been fixed on the main branch
- 📋 **You MUST include a copy/pasteable and properly formatted MRE** (minimal reproducible example) below or your issue may be closed without response
- 💡 **The ideal issue is a clear problem description and an MRE — that's it.** If you've done a genuine investigation and have a non-obvious insight into the root cause, include it. But please don't speculate or ask an LLM to generate a diagnosis or proposed fix. We have LLMs too, and an incorrect analysis is harder to work with than none at all.
- ✂️ **Keep it short.** A one-paragraph description and a working MRE is the ideal bug report. Issues that are difficult to parse — due to length, speculation, or generated content — may be closed without response.
Thanks for helping to make FastMCP better! 🚀

View file

@ -17,6 +17,7 @@ body:
- 🔍 **Check if this has already been requested** - search existing issues first
- 💭 **Think about the broader impact** - how would this affect other users?
- 📋 **Consider implementation complexity** - is this a small change or a major feature?
- ✂️ **Keep it short.** Describe the problem you're trying to solve and why existing behavior falls short. Skip proposed implementations unless you have a specific, well-considered suggestion — we don't need LLM-generated API designs. Requests that are difficult to parse may be closed without response.
Thanks for helping to make FastMCP better! 🚀

115
AGENTS.md
View file

@ -1,115 +0,0 @@
# FastMCP Development Guidelines
> **Audience**: LLM-driven engineering agents and human developers
FastMCP is a comprehensive Python framework (Python ≥3.10) for building Model Context Protocol (MCP) servers and clients. This is the actively maintained v2.0 providing a complete toolkit for the MCP ecosystem.
## Required Development Workflow
**CRITICAL**: Always run these commands in sequence before committing.
```bash
uv sync # Install dependencies
uv run pytest -n auto # Run full test suite
```
In addition, you must pass static checks. This is generally done as a pre-commit hook with `prek` but you can run it manually with:
```bash
uv run prek run --all-files # Ruff + Prettier + ty
```
**Tests must pass and lint/typing must be clean before committing.**
## Repository Structure
| Path | Purpose |
| ----------------- | -------------------------------------- |
| `src/fastmcp/` | Library source code |
| `├─server/` | Server implementation |
| `│ ├─auth/` | Authentication providers |
| `│ └─middleware/` | Error handling, logging, rate limiting |
| `├─client/` | Client SDK |
| `│ └─auth/` | Client authentication |
| `├─tools/` | Tool definitions |
| `├─resources/` | Resources and resource templates |
| `├─prompts/` | Prompt templates |
| `├─cli/` | CLI commands |
| `└─utilities/` | Shared utilities |
| `tests/` | Pytest suite |
| `docs/` | Mintlify docs (gofastmcp.com) |
## Core MCP Objects
When modifying MCP functionality, changes typically need to be applied across all object types:
- **Tools** (`src/tools/`)
- **Resources** (`src/resources/`)
- **Resource Templates** (`src/resources/`)
- **Prompts** (`src/prompts/`)
## Development Rules
### Git & CI
- Prek hooks are required (run automatically on commits)
- Never amend commits to fix prek failures
- Apply PR labels: bugs/breaking/enhancements/features
- Improvements = enhancements (not features) unless specified
- **NEVER** force-push on collaborative repos
- **ALWAYS** run prek before PRs
- **NEVER** create a release, comment on an issue, or open a PR unless specifically instructed to do so.
### Commit Messages and Agent Attribution
- **Agents NOT acting on behalf of @jlowin MUST identify themselves** (e.g., "🤖 Generated with Claude Code" in commits/PRs)
- Keep commit messages brief - ideally just headlines, not detailed messages
- Focus on what changed, not how or why
- Always read issue comments for follow-up information (treat maintainers as authoritative)
### PR Messages - Required Structure
- 1-2 paragraphs: problem/tension + solution (PRs are documentation!)
- Focused code example showing key capability
- **Avoid:** bullet summaries, exhaustive change lists, verbose closes/fixes, marketing language
- **Do:** Be opinionated about why change matters, show before/after scenarios
- Minor fixes: keep body short and concise
- No "test plan" sections or testing summaries
### Code Standards
- Python ≥ 3.10 with full type annotations
- Follow existing patterns and maintain consistency
- **Prioritize readable, understandable code** - clarity over cleverness
- Avoid obfuscated or confusing patterns even if they're shorter
- Each feature needs corresponding tests
### Module Exports
- **Be intentional about re-exports** - don't blindly re-export everything to parent namespaces
- Core types that define a module's purpose should be exported (e.g., `Middleware` from `fastmcp.server.middleware`)
- Specialized features can live in submodules (e.g., `fastmcp.server.middleware.dynamic`)
- Only re-export to `fastmcp.*` for the most fundamental types (e.g., `FastMCP`, `Client`)
- When in doubt, prefer users importing from the specific submodule over re-exporting
### Documentation
- Uses Mintlify framework
- Files must be in docs.json to be included
- Do not manually modify `docs/python-sdk/**` — these files are auto-generated from source code by a bot and maintained via a long-lived PR. Do not include changes to these files in contributor PRs.
- Do not manually modify `docs/public/schemas/**` or `src/fastmcp/utilities/mcp_server_config/v1/schema.json` — these are auto-generated and maintained via a long-lived PR.
- **Core Principle:** A feature doesn't exist unless it is documented!
### Documentation Guidelines
- **Code Examples:** Explain before showing code, make blocks fully runnable (include imports)
- **Structure:** Headers form navigation guide, logical H2/H3 hierarchy
- **Content:** User-focused sections, motivate features (why) before mechanics (how)
- **Style:** Prose over code comments for important information
## Critical Patterns
- Never use bare `except` - be specific with exception types
- File sizes enforced by [loq](https://github.com/jlowin/loq). Edit `loq.toml` to raise limits; `loq baseline` to ratchet down.
- Always `uv sync` first when debugging build issues
- Default test timeout is 5s - optimize or mark as integration tests

1
AGENTS.md Symbolic link
View file

@ -0,0 +1 @@
CLAUDE.md

View file

@ -1 +0,0 @@
AGENTS.md

119
CLAUDE.md Normal file
View file

@ -0,0 +1,119 @@
# FastMCP Development Guidelines
> **Audience**: LLM-driven engineering agents and human developers
> **Note**: `AGENTS.md` is a symlink to this file. Edit `CLAUDE.md` directly.
FastMCP is a comprehensive Python framework (Python ≥3.10) for building Model Context Protocol (MCP) servers and clients. This is the actively maintained v2.0 providing a complete toolkit for the MCP ecosystem.
## Required Development Workflow
**CRITICAL**: Always run these commands in sequence before committing.
```bash
uv sync # Install dependencies
uv run pytest -n auto # Run full test suite
```
In addition, you must pass static checks. This is generally done as a pre-commit hook with `prek` but you can run it manually with:
```bash
uv run prek run --all-files # Ruff + Prettier + ty
```
**Tests must pass and lint/typing must be clean before committing.**
## Repository Structure
| Path | Purpose |
| ----------------- | -------------------------------------- |
| `src/fastmcp/` | Library source code |
| `├─server/` | Server implementation |
| `│ ├─auth/` | Authentication providers |
| `│ └─middleware/` | Error handling, logging, rate limiting |
| `├─client/` | Client SDK |
| `│ └─auth/` | Client authentication |
| `├─tools/` | Tool definitions |
| `├─resources/` | Resources and resource templates |
| `├─prompts/` | Prompt templates |
| `├─cli/` | CLI commands |
| `└─utilities/` | Shared utilities |
| `tests/` | Pytest suite |
| `docs/` | Mintlify docs (gofastmcp.com) |
## Core MCP Objects
When modifying MCP functionality, changes typically need to be applied across all object types:
- **Tools** (`src/tools/`)
- **Resources** (`src/resources/`)
- **Resource Templates** (`src/resources/`)
- **Prompts** (`src/prompts/`)
## Development Rules
### Git & CI
- Prek hooks are required (run automatically on commits)
- Never amend commits to fix prek failures
- Apply PR labels: bugs/breaking/enhancements/features
- Improvements = enhancements (not features) unless specified
- **NEVER** force-push on collaborative repos
- **ALWAYS** run prek before PRs
- **NEVER** create a release, comment on an issue, or open a PR unless specifically instructed to do so.
### Commit Messages and Agent Attribution
- **Agents NOT acting on behalf of @jlowin MUST identify themselves** (e.g., "🤖 Generated with Claude Code" in commits/PRs)
- Keep commit messages brief - ideally just headlines, not detailed messages
- Focus on what changed, not how or why
- Always read issue comments for follow-up information (treat maintainers as authoritative)
- **Treat proposed solutions in issues skeptically.** This applies to solutions proposed by *users* in issue reports — not to feedback from configured review bots (CodeRabbit, chatgpt-codex-connector, etc.), which should be evaluated on their merits. The ideal issue contains a concise problem description and an MRE — nothing more. Proposed solutions are only worth considering if they clearly reflect genuine, non-obvious investigation of the codebase. If a solution reads like speculation, or like it was generated by an LLM without deep framework knowledge, ignore it and diagnose from the repro. Most reporters — human or AI — do not have sufficient understanding of FastMCP internals to correctly diagnose anything beyond a trivial bug. We can ask the same questions of an LLM when implementing; we don't need the reporter to do it for us, and a wrong diagnosis is worse than none.
### PR Messages - Required Structure
- 1-2 paragraphs: problem/tension + solution (PRs are documentation!)
- Focused code example showing key capability
- **Avoid:** bullet summaries, exhaustive change lists, verbose closes/fixes, marketing language
- **Do:** Be opinionated about why change matters, show before/after scenarios
- Minor fixes: keep body short and concise
- No "test plan" sections or testing summaries
### Code Standards
- Python ≥ 3.10 with full type annotations
- Follow existing patterns and maintain consistency
- **Prioritize readable, understandable code** - clarity over cleverness
- Avoid obfuscated or confusing patterns even if they're shorter
- Each feature needs corresponding tests
### Module Exports
- **Be intentional about re-exports** - don't blindly re-export everything to parent namespaces
- Core types that define a module's purpose should be exported (e.g., `Middleware` from `fastmcp.server.middleware`)
- Specialized features can live in submodules (e.g., `fastmcp.server.middleware.dynamic`)
- Only re-export to `fastmcp.*` for the most fundamental types (e.g., `FastMCP`, `Client`)
- When in doubt, prefer users importing from the specific submodule over re-exporting
### Documentation
- Uses Mintlify framework
- Files must be in docs.json to be included
- Do not manually modify `docs/python-sdk/**` — these files are auto-generated from source code by a bot and maintained via a long-lived PR. Do not include changes to these files in contributor PRs.
- Do not manually modify `docs/public/schemas/**` or `src/fastmcp/utilities/mcp_server_config/v1/schema.json` — these are auto-generated and maintained via a long-lived PR.
- **Core Principle:** A feature doesn't exist unless it is documented!
### Documentation Guidelines
- **Code Examples:** Explain before showing code, make blocks fully runnable (include imports)
- **Code Formatting:** Keep code blocks visually clean — avoid deeply nested function calls. Extract intermediate values into named variables rather than inlining everything into one expression. Code in docs is read more than it's run; optimize for scannability.
- **Structure:** Headers form navigation guide, logical H2/H3 hierarchy
- **Content:** User-focused sections, motivate features (why) before mechanics (how)
- **Style:** Prose over code comments for important information
## Critical Patterns
- Never use bare `except` - be specific with exception types
- File sizes enforced by [loq](https://github.com/jakekaplan/loq). Edit `loq.toml` to raise limits; `loq baseline` to ratchet down.
- Always `uv sync` first when debugging build issues
- Default test timeout is 5s - optimize or mark as integration tests

View file

@ -1,7 +1,7 @@
---
title: Low-Level API
sidebarTitle: Low-Level API
description: Integrate directly with the MCP Apps extension to build interactive tool UIs.
title: Custom HTML Apps
sidebarTitle: Custom HTML
description: Build apps with your own HTML, CSS, and JavaScript using the MCP Apps extension directly.
icon: code
tag: NEW
---
@ -10,9 +10,9 @@ import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
The [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) (`io.modelcontextprotocol/ui`) lets tools return interactive UIs — an HTML page rendered in a sandboxed iframe inside the host client. Instead of returning plain text or JSON, a tool can show a chart, a form, an image viewer, or anything you can build with HTML and JavaScript.
The [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) is an open protocol that lets tools return interactive UIs — an HTML page rendered in a sandboxed iframe inside the host client. [Prefab UI](/apps/prefab) builds on this protocol so you never have to think about it, but when you need full control — custom rendering, a specific JavaScript framework, maps, 3D, video — you can use the MCP Apps extension directly.
This page covers the low-level extension API directly. FastMCP provides typed models for app configuration, automatic `ui://` resource handling, and CSP/permission management.
This page covers how to write custom HTML apps and wire them up in FastMCP. You'll be working with the [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) JavaScript SDK for host communication, and FastMCP's `AppConfig` for resource and CSP management.
## How It Works

View file

@ -10,22 +10,67 @@ import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
MCP Apps let your tools return interactive UIs — rendered in a sandboxed iframe right inside the host client's conversation. Instead of returning plain text or JSON, a tool can show a chart, a form, an image viewer, or anything you can build with HTML and JavaScript.
MCP Apps let your tools return interactive UIs — rendered in a sandboxed iframe right inside the host client's conversation. Instead of returning plain text, a tool can show a chart, a sortable table, a form, or anything you can build with HTML.
FastMCP implements the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps), so you can start building apps today. FastMCP 3.1 will introduce a full Python-native app framework that makes building rich UIs dramatically simpler — no HTML or JavaScript required.
FastMCP implements the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) and provides two approaches:
## What's Available Today
## Prefab Apps (Recommended)
FastMCP provides typed models and helpers for working with the MCP Apps extension directly:
<VersionBadge version="3.1.0" />
- **`AppConfig`** to link tools to UI resources and control visibility
- **`ui://` resources** that automatically serve HTML with the correct MIME type
- **`ResourceCSP`** and **`ResourcePermissions`** for security and sandboxing
<Tip>
[Prefab](https://prefab.prefect.io) is in extremely early, active development — its API changes frequently and breaking changes can occur with any release. The FastMCP integration is equally new and under rapid development. These docs are included for users who want to work on the cutting edge; production use is not recommended. Always [pin `prefab-ui` to a specific version](/apps/prefab#getting-started) in your dependencies.
</Tip>
This is the [low-level API](/apps/low-level) — you write the HTML yourself and wire up communication with the host via the `@modelcontextprotocol/ext-apps` JavaScript SDK. It gives you full control over the UI.
[Prefab UI](https://prefab.prefect.io) is a declarative UI framework for Python. You describe layouts, charts, tables, forms, and interactive behaviors using a Python DSL — and the framework compiles them to a JSON protocol that a shared renderer interprets. It started as a component library inside FastMCP and grew into its own framework with [comprehensive documentation](https://prefab.prefect.io).
## What's Coming in 3.1
```python
from prefab_ui.components import Column, Heading, BarChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
FastMCP 3.1 will ship a Python-native app framework that lets you build interactive UIs entirely in Python. Define layouts, handle events, and manage state without writing any HTML or JavaScript — FastMCP generates the app for you.
mcp = FastMCP("Dashboard")
Stay tuned. In the meantime, the [low-level API](/apps/low-level) is ready to use.
@mcp.tool(app=True)
def sales_chart(year: int) -> PrefabApp:
"""Show sales data as an interactive chart."""
data = get_sales_data(year)
with Column(gap=4, css_class="p-6") as view:
Heading(f"{year} Sales")
BarChart(
data=data,
series=[ChartSeries(data_key="revenue", label="Revenue")],
x_axis="month",
)
return PrefabApp(view=view)
```
Install with `pip install "fastmcp[apps]"` and see [Prefab Apps](/apps/prefab) for the integration guide.
## Custom HTML Apps
The [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps) is an open protocol, and you can use it directly when you need full control. You write your own HTML/CSS/JavaScript and communicate with the host via the [`@modelcontextprotocol/ext-apps`](https://github.com/modelcontextprotocol/ext-apps) SDK.
This is the right choice for custom rendering (maps, 3D, video), specific JavaScript frameworks, or capabilities beyond what the component library offers.
```python
from fastmcp import FastMCP
from fastmcp.server.apps import AppConfig, ResourceCSP
mcp = FastMCP("Custom App")
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/view.html"))
def my_tool() -> str:
return '{"values": [1, 2, 3]}'
@mcp.resource(
"ui://my-app/view.html",
app=AppConfig(csp=ResourceCSP(resource_domains=["https://unpkg.com"])),
)
def view() -> str:
return "<html>...</html>"
```
See [Custom HTML Apps](/apps/low-level) for the full reference.

483
docs/apps/patterns.mdx Normal file
View file

@ -0,0 +1,483 @@
---
title: Patterns
sidebarTitle: Patterns
description: Charts, tables, forms, and other common tool UIs.
icon: grid-2-plus
tag: SOON
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.1.0" />
<Tip>
[Prefab](https://prefab.prefect.io) is in extremely early, active development — its API changes frequently and breaking changes can occur with any release. The FastMCP integration is equally new and under rapid development. These docs are included for users who want to work on the cutting edge; production use is not recommended. Always pin `prefab-ui` to a specific version in your dependencies.
</Tip>
The most common use of Prefab is giving your tools a visual representation — a chart instead of raw numbers, a sortable table instead of a text dump, a status dashboard instead of a list of booleans. Each pattern below is a complete, copy-pasteable tool.
## Charts
Prefab includes [bar, line, area, pie, radar, and radial charts](https://prefab.prefect.io/docs/components/charts). They all render client-side with tooltips, legends, and responsive sizing.
### Bar Chart
```python
from prefab_ui.components import Column, Heading, BarChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Charts")
@mcp.tool(app=True)
def quarterly_revenue(year: int) -> PrefabApp:
"""Show quarterly revenue as a bar chart."""
data = [
{"quarter": "Q1", "revenue": 42000, "costs": 28000},
{"quarter": "Q2", "revenue": 51000, "costs": 31000},
{"quarter": "Q3", "revenue": 47000, "costs": 29000},
{"quarter": "Q4", "revenue": 63000, "costs": 35000},
]
with Column(gap=4, css_class="p-6") as view:
Heading(f"{year} Revenue vs Costs")
BarChart(
data=data,
series=[
ChartSeries(data_key="revenue", label="Revenue"),
ChartSeries(data_key="costs", label="Costs"),
],
x_axis="quarter",
show_legend=True,
)
return PrefabApp(view=view)
```
Multiple `ChartSeries` entries plot different data keys. Add `stacked=True` to stack bars, or `horizontal=True` to flip the axes.
### Area Chart
`LineChart` and `AreaChart` share the same API as `BarChart`, with `curve` for interpolation (`"linear"`, `"smooth"`, `"step"`) and `show_dots` for data points:
```python
from prefab_ui.components import Column, Heading, AreaChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Charts")
@mcp.tool(app=True)
def usage_trend() -> PrefabApp:
"""Show API usage over time."""
data = [
{"date": "Feb 1", "requests": 1200},
{"date": "Feb 2", "requests": 1350},
{"date": "Feb 3", "requests": 980},
{"date": "Feb 4", "requests": 1500},
{"date": "Feb 5", "requests": 1420},
]
with Column(gap=4, css_class="p-6") as view:
Heading("API Usage")
AreaChart(
data=data,
series=[ChartSeries(data_key="requests", label="Requests")],
x_axis="date",
curve="smooth",
height=250,
)
return PrefabApp(view=view)
```
### Pie and Donut Charts
`PieChart` uses `data_key` (the numeric value) and `name_key` (the label) instead of series. Set `inner_radius` for a donut:
```python
from prefab_ui.components import Column, Heading, PieChart
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Charts")
@mcp.tool(app=True)
def ticket_breakdown() -> PrefabApp:
"""Show open tickets by category."""
data = [
{"category": "Bug", "count": 23},
{"category": "Feature", "count": 15},
{"category": "Docs", "count": 8},
{"category": "Infra", "count": 12},
]
with Column(gap=4, css_class="p-6") as view:
Heading("Open Tickets")
PieChart(
data=data,
data_key="count",
name_key="category",
show_legend=True,
inner_radius=60,
)
return PrefabApp(view=view)
```
## Data Tables
[DataTable](https://prefab.prefect.io/docs/components/data-display/data-table) provides sortable columns, full-text search, and pagination — all running client-side in the browser.
```python
from prefab_ui.components import Column, Heading, DataTable, DataTableColumn
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Directory")
@mcp.tool(app=True)
def employee_directory() -> PrefabApp:
"""Show a searchable, sortable employee directory."""
employees = [
{"name": "Alice Chen", "department": "Engineering", "role": "Staff Engineer", "location": "SF"},
{"name": "Bob Martinez", "department": "Design", "role": "Lead Designer", "location": "NYC"},
{"name": "Carol Johnson", "department": "Engineering", "role": "Senior Engineer", "location": "London"},
{"name": "David Kim", "department": "Product", "role": "Product Manager", "location": "SF"},
{"name": "Eva Müller", "department": "Engineering", "role": "Engineer", "location": "Berlin"},
]
with Column(gap=4, css_class="p-6") as view:
Heading("Employee Directory")
DataTable(
columns=[
DataTableColumn(key="name", header="Name", sortable=True),
DataTableColumn(key="department", header="Department", sortable=True),
DataTableColumn(key="role", header="Role"),
DataTableColumn(key="location", header="Office", sortable=True),
],
rows=employees,
searchable=True,
paginated=True,
page_size=15,
)
return PrefabApp(view=view)
```
## Forms
A form collects input, but it needs somewhere to send that input. The [`CallTool`](https://prefab.prefect.io/docs/concepts/actions) action connects a form to a tool on your MCP server — so you need two tools: one that renders the form, and one that handles the submission.
```python
from prefab_ui.components import (
Column, Heading, Row, Muted, Badge, Input, Select,
Textarea, Button, Form, ForEach, Separator,
)
from prefab_ui.actions import ShowToast
from prefab_ui.actions.mcp import CallTool
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Contacts")
contacts_db: list[dict] = [
{"name": "Zaphod Beeblebrox", "email": "zaphod@galaxy.gov", "category": "Partner"},
]
@mcp.tool(app=True)
def contact_form() -> PrefabApp:
"""Show a contact list with a form to add new contacts."""
with Column(gap=6, css_class="p-6") as view:
Heading("Contacts")
with ForEach("contacts"):
with Row(gap=2, align="center"):
Muted("{{ name }}")
Muted("{{ email }}")
Badge("{{ category }}")
Separator()
with Form(
on_submit=CallTool(
"save_contact",
result_key="contacts",
on_success=ShowToast("Contact saved!", variant="success"),
on_error=ShowToast("{{ $error }}", variant="error"),
)
):
Input(name="name", label="Full Name", required=True)
Input(name="email", label="Email", input_type="email", required=True)
Select(
name="category",
label="Category",
options=["Customer", "Vendor", "Partner", "Other"],
)
Textarea(name="notes", label="Notes", placeholder="Optional notes...")
Button("Save Contact")
return PrefabApp(view=view, state={"contacts": list(contacts_db)})
@mcp.tool
def save_contact(
name: str,
email: str,
category: str = "Other",
notes: str = "",
) -> list[dict]:
"""Save a new contact and return the updated list."""
contacts_db.append({"name": name, "email": email, "category": category, "notes": notes})
return list(contacts_db)
```
When the user submits the form, the renderer calls `save_contact` on the server with all named input values as arguments. Because `result_key="contacts"` is set, the returned list replaces the `contacts` state — and the `ForEach` re-renders with the new data automatically.
The `save_contact` tool is a regular MCP tool. The LLM can also call it directly in conversation. Your UI actions and your conversational tools are the same thing.
### Pydantic Model Forms
For complex forms, `Form.from_model()` generates the entire form from a Pydantic model — inputs, labels, validation, and submit wiring:
```python
from typing import Literal
from pydantic import BaseModel, Field
from prefab_ui.components import Column, Heading, Form
from prefab_ui.actions.mcp import CallTool
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Bug Tracker")
class BugReport(BaseModel):
title: str = Field(title="Bug Title")
severity: Literal["low", "medium", "high", "critical"] = Field(
title="Severity", default="medium"
)
description: str = Field(title="Description")
steps_to_reproduce: str = Field(title="Steps to Reproduce")
@mcp.tool(app=True)
def report_bug() -> PrefabApp:
"""Show a bug report form."""
with Column(gap=4, css_class="p-6") as view:
Heading("Report a Bug")
Form.from_model(BugReport, on_submit=CallTool("create_bug_report"))
return PrefabApp(view=view)
@mcp.tool
def create_bug_report(data: dict) -> str:
"""Create a bug report from the form submission."""
report = BugReport(**data)
# save to database...
return f"Created bug report: {report.title}"
```
`str` fields become text inputs, `Literal` becomes a select, `bool` becomes a checkbox. The `on_submit` CallTool receives all field values under a `data` key.
## Status Displays
Cards, badges, progress bars, and grids combine naturally for dashboards. See the [Prefab layout](https://prefab.prefect.io/docs/concepts/composition) and [container](https://prefab.prefect.io/docs/components/containers) docs for the full set of layout and display components.
```python
from prefab_ui.components import (
Column, Row, Grid, Heading, Text, Muted, Badge,
Card, CardContent, Progress, Separator,
)
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Monitoring")
@mcp.tool(app=True)
def system_status() -> PrefabApp:
"""Show current system health."""
services = [
{"name": "API Gateway", "status": "healthy", "ok": True, "latency_ms": 12, "uptime_pct": 99.9},
{"name": "Database", "status": "healthy", "ok": True, "latency_ms": 3, "uptime_pct": 99.99},
{"name": "Cache", "status": "degraded", "ok": False, "latency_ms": 45, "uptime_pct": 98.2},
{"name": "Queue", "status": "healthy", "ok": True, "latency_ms": 8, "uptime_pct": 99.8},
]
all_ok = all(s["ok"] for s in services)
with Column(gap=4, css_class="p-6") as view:
with Row(gap=2, align="center"):
Heading("System Status")
Badge(
"All Healthy" if all_ok else "Degraded",
variant="success" if all_ok else "destructive",
)
Separator()
with Grid(columns=2, gap=4):
for svc in services:
with Card():
with CardContent():
with Row(gap=2, align="center"):
Text(svc["name"], css_class="font-medium")
Badge(
svc["status"],
variant="success" if svc["ok"] else "destructive",
)
Muted(f"Response: {svc['latency_ms']}ms")
Progress(value=svc["uptime_pct"])
return PrefabApp(view=view)
```
## Conditional Content
[`If`, `Elif`, and `Else`](https://prefab.prefect.io/docs/concepts/composition#conditional-rendering) show or hide content based on state. Changes are instant — no server round-trip.
```python
from prefab_ui.components import Column, Heading, Switch, Separator, Alert, If
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Flags")
@mcp.tool(app=True)
def feature_flags() -> PrefabApp:
"""Toggle feature flags with live preview."""
with Column(gap=4, css_class="p-6") as view:
Heading("Feature Flags")
Switch(name="dark_mode", label="Dark Mode")
Switch(name="beta_features", label="Beta Features")
Separator()
with If("{{ dark_mode }}"):
Alert(title="Dark mode enabled", description="UI will use dark theme.")
with If("{{ beta_features }}"):
Alert(
title="Beta features active",
description="Experimental features are now visible.",
variant="warning",
)
return PrefabApp(view=view, state={"dark_mode": False, "beta_features": False})
```
## Tabs
[Tabs](https://prefab.prefect.io/docs/components/containers/tabs) organize content into switchable views. Switching is client-side — no server round-trip.
```python
from prefab_ui.components import (
Column, Heading, Text, Muted, Badge, Row,
DataTable, DataTableColumn, Tabs, Tab, ForEach,
)
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Projects")
@mcp.tool(app=True)
def project_overview(project_id: str) -> PrefabApp:
"""Show project details organized in tabs."""
project = {
"name": "FastMCP v3",
"description": "Next generation MCP framework with Apps support.",
"status": "Active",
"created_at": "2025-01-15",
"members": [
{"name": "Alice Chen", "role": "Lead"},
{"name": "Bob Martinez", "role": "Design"},
],
"activity": [
{"timestamp": "2 hours ago", "message": "Merged PR #342"},
{"timestamp": "1 day ago", "message": "Released v3.0.1"},
],
}
with Column(gap=4, css_class="p-6") as view:
Heading(project["name"])
with Tabs():
with Tab("Overview"):
Text(project["description"])
with Row(gap=4):
Badge(project["status"])
Muted(f"Created: {project['created_at']}")
with Tab("Members"):
DataTable(
columns=[
DataTableColumn(key="name", header="Name", sortable=True),
DataTableColumn(key="role", header="Role"),
],
rows=project["members"],
)
with Tab("Activity"):
with ForEach("activity"):
with Row(gap=2):
Muted("{{ timestamp }}")
Text("{{ message }}")
return PrefabApp(view=view, state={"activity": project["activity"]})
```
## Accordion
[Accordion](https://prefab.prefect.io/docs/components/containers/accordion) collapses sections to save space. `multiple=True` lets users expand several items at once:
```python
from prefab_ui.components import (
Column, Heading, Row, Text, Badge, Progress,
Accordion, AccordionItem,
)
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("API Monitor")
@mcp.tool(app=True)
def api_health() -> PrefabApp:
"""Show health details for each API endpoint."""
endpoints = [
{"path": "/api/users", "status": 200, "healthy": True, "avg_ms": 45, "p99_ms": 120, "uptime_pct": 99.9},
{"path": "/api/orders", "status": 200, "healthy": True, "avg_ms": 82, "p99_ms": 250, "uptime_pct": 99.7},
{"path": "/api/search", "status": 200, "healthy": True, "avg_ms": 150, "p99_ms": 500, "uptime_pct": 99.5},
{"path": "/api/webhooks", "status": 503, "healthy": False, "avg_ms": 2000, "p99_ms": 5000, "uptime_pct": 95.1},
]
with Column(gap=4, css_class="p-6") as view:
Heading("API Health")
with Accordion(multiple=True):
for ep in endpoints:
with AccordionItem(ep["path"]):
with Row(gap=4):
Badge(
f"{ep['status']}",
variant="success" if ep["healthy"] else "destructive",
)
Text(f"Avg: {ep['avg_ms']}ms")
Text(f"P99: {ep['p99_ms']}ms")
Progress(value=ep["uptime_pct"])
return PrefabApp(view=view)
```
## Next Steps
- **[Custom HTML Apps](/apps/low-level)** — When you need your own HTML, CSS, and JavaScript
- **[Prefab UI Docs](https://prefab.prefect.io)** — Components, state, expressions, and actions

195
docs/apps/prefab.mdx Normal file
View file

@ -0,0 +1,195 @@
---
title: Prefab Apps
sidebarTitle: Prefab Apps
description: Build interactive tool UIs in pure Python — no HTML or JavaScript required.
icon: palette
tag: SOON
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.1.0" />
<Tip>
[Prefab](https://prefab.prefect.io) is in extremely early, active development — its API changes frequently and breaking changes can occur with any release. The FastMCP integration is equally new and under rapid development. These docs are included for users who want to work on the cutting edge; production use is not recommended. Always pin `prefab-ui` to a specific version in your dependencies (see below).
</Tip>
[Prefab UI](https://prefab.prefect.io) is a declarative UI framework for Python. You describe what your interface should look like — a chart, a table, a form — and return it from your tool. FastMCP takes care of everything else: registering the renderer, wiring the protocol metadata, and delivering the component tree to the host.
Prefab started as a component library inside FastMCP and grew into a full framework for building interactive applications — with its own state management, reactive expression system, and action model. The [Prefab documentation](https://prefab.prefect.io) covers all of this in depth. This page focuses on the FastMCP integration: what you return from a tool, and what FastMCP does with it.
```bash
pip install "fastmcp[apps]"
```
<Tip>
Prefab UI is in active early development and its API changes frequently. We strongly recommend pinning `prefab-ui` to a specific version in your project's dependencies. Installing `fastmcp[apps]` pulls in `prefab-ui` but won't pin it — so a routine `pip install --upgrade` could introduce breaking changes.
```toml
# pyproject.toml
dependencies = [
"fastmcp[apps]",
"prefab-ui==0.8.0", # pin to a known working version
]
```
</Tip>
Here's the simplest possible Prefab App — a tool that returns a bar chart:
```python
from prefab_ui.components import Column, Heading, BarChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Dashboard")
@mcp.tool(app=True)
def revenue_chart(year: int) -> PrefabApp:
"""Show annual revenue as an interactive bar chart."""
data = [
{"quarter": "Q1", "revenue": 42000},
{"quarter": "Q2", "revenue": 51000},
{"quarter": "Q3", "revenue": 47000},
{"quarter": "Q4", "revenue": 63000},
]
with Column(gap=4, css_class="p-6") as view:
Heading(f"{year} Revenue")
BarChart(
data=data,
series=[ChartSeries(data_key="revenue", label="Revenue")],
x_axis="quarter",
)
return PrefabApp(view=view)
```
That's it — you declare a layout using Python's `with` statement, and return it. When the host calls this tool, the user sees an interactive bar chart instead of a JSON blob. The [Patterns](/apps/patterns) page has more examples: area charts, data tables, forms, status dashboards, and more.
## What You Return
### Components
The simplest way to get started. If you're returning a visual representation of data and don't need Prefab's more advanced features like initial state or stylesheets, just return the components directly. FastMCP wraps them in a `PrefabApp` automatically:
```python
from prefab_ui.components import Column, Heading, Badge
from fastmcp import FastMCP
mcp = FastMCP("Status")
@mcp.tool(app=True)
def status_badge() -> Column:
"""Show system status."""
with Column(gap=2) as view:
Heading("All Systems Operational")
Badge("Healthy", variant="success")
return view
```
Want a chart? Return a chart. Want a table? Return a table. FastMCP handles the wiring.
### PrefabApp
When you need more control — setting initial state values that components can read and react to, or configuring the rendering engine — return a `PrefabApp` explicitly:
```python
from prefab_ui.components import Column, Heading, Text, Button, If, Badge
from prefab_ui.actions import ToggleState
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
mcp = FastMCP("Demo")
@mcp.tool(app=True)
def toggle_demo() -> PrefabApp:
"""Interactive toggle with state."""
with Column(gap=4, css_class="p-6") as view:
Button("Toggle", on_click=ToggleState("show"))
with If("{{ show }}"):
Badge("Visible!", variant="success")
return PrefabApp(view=view, state={"show": False})
```
The `state` dict provides the initial values. Components reference state with `{{ expression }}` templates. State mutations like `ToggleState` happen entirely in the browser — no server round-trip. The [Prefab state guide](https://prefab.prefect.io/docs/concepts/state) covers this in detail.
### ToolResult
Every tool result has two audiences: the renderer (which displays the UI) and the LLM (which reads the text content to understand what happened). By default, Prefab Apps send `"[Rendered Prefab UI]"` as the text content, which tells the LLM almost nothing.
If you want the LLM to understand the result — so it can reference the data in conversation, summarize it, or decide what to do next — wrap your return in a `ToolResult` with a meaningful `content` string:
```python
from prefab_ui.components import Column, Heading, BarChart, ChartSeries
from prefab_ui.app import PrefabApp
from fastmcp import FastMCP
from fastmcp.tools import ToolResult
mcp = FastMCP("Sales")
@mcp.tool(app=True)
def sales_overview(year: int) -> ToolResult:
"""Show sales data visually and summarize for the model."""
data = get_sales_data(year)
total = sum(row["revenue"] for row in data)
with Column(gap=4, css_class="p-6") as view:
Heading("Sales Overview")
BarChart(data=data, series=[ChartSeries(data_key="revenue")])
return ToolResult(
content=f"Total revenue for {year}: ${total:,} across {len(data)} quarters",
structured_content=view,
)
```
The user sees the chart. The LLM sees `"Total revenue for 2025: $203,000 across 4 quarters"` and can reason about it.
## Type Inference
If your tool's return type annotation is a Prefab type — `PrefabApp`, `Component`, or their `Optional` variants — FastMCP detects this and enables app rendering automatically:
```python
@mcp.tool
def greet(name: str) -> PrefabApp:
return PrefabApp(view=Heading(f"Hello, {name}!"))
```
This is equivalent to `@mcp.tool(app=True)`. Explicit `app=True` is recommended for clarity, and is required when the return type doesn't reveal a Prefab type (e.g., `-> ToolResult`).
## How It Works
Behind the scenes, when a tool returns a Prefab component or `PrefabApp`, FastMCP:
1. **Registers a shared renderer** — a `ui://prefab/renderer.html` resource containing the JavaScript rendering engine, fetched once by the host and reused across all your Prefab tools.
2. **Wires the tool metadata** — so the host knows to load the renderer iframe when displaying the tool result.
3. **Serializes the component tree** — your Python components become `structuredContent` on the tool result, which the renderer interprets and displays.
None of this requires any configuration. The `app=True` flag (or type inference) is the only thing you need.
## Mixing with Custom HTML Apps
Prefab tools and [custom HTML tools](/apps/low-level) coexist in the same server. Prefab tools share a single renderer resource; custom tools point to their own. Both use the same MCP Apps protocol:
```python
from fastmcp.server.apps import AppConfig
@mcp.tool(app=True)
def team_directory() -> PrefabApp:
...
@mcp.tool(app=AppConfig(resource_uri="ui://my-app/map.html"))
def map_view() -> str:
...
```
## Next Steps
- **[Patterns](/apps/patterns)** — Charts, tables, forms, and other common tool UIs
- **[Custom HTML Apps](/apps/low-level)** — When you need your own HTML, CSS, and JavaScript
- **[Prefab UI Docs](https://prefab.prefect.io)** — Components, state, expressions, and actions

85
docs/cli/auth.mdx Normal file
View file

@ -0,0 +1,85 @@
---
title: Auth Utilities
sidebarTitle: Auth
description: Create and validate CIMD documents for OAuth
icon: key
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
The `fastmcp auth` commands help with CIMD (Client ID Metadata Document) management — part of MCP's OAuth authentication flow. A CIMD is a JSON document you host at an HTTPS URL to identify your client application to MCP servers.
## Creating a CIMD
`fastmcp auth cimd create` generates a CIMD document:
```bash
fastmcp auth cimd create \
--name "My App" \
--redirect-uri "http://localhost:*/callback"
```
```json
{
"client_id": "https://your-domain.com/oauth/client.json",
"client_name": "My App",
"redirect_uris": ["http://localhost:*/callback"],
"token_endpoint_auth_method": "none"
}
```
The generated document includes a placeholder `client_id` — update it to match the URL where you'll host the document before deploying.
### Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Name | `--name` | **Required.** Human-readable client name |
| Redirect URI | `--redirect-uri` | **Required.** Allowed redirect URIs (repeatable) |
| Client URI | `--client-uri` | Client's home page URL |
| Logo URI | `--logo-uri` | Client's logo URL |
| Scope | `--scope` | Space-separated list of scopes |
| Output | `--output`, `-o` | Save to file (default: stdout) |
| Pretty | `--pretty` | Pretty-print JSON (default: true) |
### Example
```bash
fastmcp auth cimd create \
--name "My Production App" \
--redirect-uri "http://localhost:*/callback" \
--redirect-uri "https://myapp.example.com/callback" \
--client-uri "https://myapp.example.com" \
--scope "read write" \
--output client.json
```
## Validating a CIMD
`fastmcp auth cimd validate` fetches a hosted CIMD and verifies it conforms to the spec:
```bash
fastmcp auth cimd validate https://myapp.example.com/oauth/client.json
```
The validator checks that the URL is valid (HTTPS, non-root path), the document is valid JSON, the `client_id` matches the URL, and no shared-secret auth methods are used.
On success:
```
→ Fetching https://myapp.example.com/oauth/client.json...
✓ Valid CIMD document
Document details:
client_id: https://myapp.example.com/oauth/client.json
client_name: My App
token_endpoint_auth_method: none
redirect_uris:
• http://localhost:*/callback
```
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Timeout | `--timeout`, `-t` | HTTP request timeout in seconds (default: 10) |

140
docs/cli/client.mdx Normal file
View file

@ -0,0 +1,140 @@
---
title: Client Commands
sidebarTitle: Client
description: List tools, call them, and discover configured servers
icon: satellite-dish
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
The CLI can act as an MCP client — connecting to any server (local or remote) to list what it exposes and call its tools directly. This is useful for development, debugging, scripting, and giving shell-capable LLM agents access to MCP servers.
## Listing Tools
`fastmcp list` connects to a server and prints its tools as function signatures, showing parameter names, types, and descriptions at a glance:
```bash
fastmcp list http://localhost:8000/mcp
fastmcp list server.py
fastmcp list weather # name-based resolution
```
When you need the full JSON Schema for a tool's inputs or outputs — for understanding nested objects, enum constraints, or complex types — opt in with `--input-schema` or `--output-schema`:
```bash
fastmcp list server.py --input-schema
```
### Resources and Prompts
By default, only tools are shown. Add `--resources` or `--prompts` to include those:
```bash
fastmcp list server.py --resources --prompts
```
### Machine-Readable Output
The `--json` flag switches to structured JSON with full schemas included. This is the format to use when feeding tool definitions to an LLM or building automation:
```bash
fastmcp list server.py --json
```
### Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Command | `--command` | Connect via stdio (e.g., `'npx -y @mcp/server'`) |
| Transport | `--transport`, `-t` | Force `http` or `sse` for URL targets |
| Resources | `--resources` | Include resources in output |
| Prompts | `--prompts` | Include prompts in output |
| Input Schema | `--input-schema` | Show full input schemas |
| Output Schema | `--output-schema` | Show full output schemas |
| JSON | `--json` | Structured JSON output |
| Timeout | `--timeout` | Connection timeout in seconds |
| Auth | `--auth` | `oauth` (default for HTTP), a bearer token, or `none` |
## Calling Tools
`fastmcp call` invokes a single tool on a server. Pass arguments as `key=value` pairs — the CLI fetches the tool's schema and coerces your string values to the right types automatically:
```bash
fastmcp call server.py greet name=World
fastmcp call http://localhost:8000/mcp search query=hello limit=5
```
Type coercion is schema-driven: `"5"` becomes the integer `5` when the schema expects an integer. Booleans accept `true`/`false`, `yes`/`no`, and `1`/`0`. Arrays and objects are parsed as JSON.
### Complex Arguments
For tools with nested or structured parameters, `key=value` syntax gets awkward. Pass a single JSON object instead:
```bash
fastmcp call server.py create_item '{"name": "Widget", "tags": ["sale"], "metadata": {"color": "blue"}}'
```
Or use `--input-json` to provide a base dictionary, then override individual keys with `key=value` pairs:
```bash
fastmcp call server.py search --input-json '{"query": "hello", "limit": 5}' limit=10
```
### Error Handling
If you misspell a tool name, the CLI suggests corrections via fuzzy matching. Missing required arguments produce a clear message with the tool's signature as a reminder. Tool execution errors are printed with a non-zero exit code, making the CLI straightforward to use in scripts.
### Structured Output
`--json` emits the raw result including content blocks, error status, and structured content:
```bash
fastmcp call server.py get_weather city=London --json
```
### Interactive Elicitation
Some tools request additional input during execution through MCP's elicitation mechanism. When this happens, the CLI prompts you in the terminal — showing each field's name, type, and whether it's required. You can type `decline` to skip a question or `cancel` to abort the call entirely.
### Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Command | `--command` | Connect via stdio |
| Transport | `--transport`, `-t` | Force `http` or `sse` |
| Input JSON | `--input-json` | Base arguments as JSON (merged with `key=value`) |
| JSON | `--json` | Raw JSON output |
| Timeout | `--timeout` | Connection timeout in seconds |
| Auth | `--auth` | `oauth`, a bearer token, or `none` |
## Discovering Configured Servers
`fastmcp discover` scans your machine for MCP servers configured in editors and tools. It checks:
- **Claude Desktop** — `claude_desktop_config.json`
- **Claude Code** — `~/.claude.json`
- **Cursor** — `.cursor/mcp.json` (walks up from current directory)
- **Gemini CLI** — `~/.gemini/settings.json`
- **Goose** — `~/.config/goose/config.yaml`
- **Project** — `./mcp.json` in the current directory
```bash
fastmcp discover
```
The output groups servers by source, showing each server's name and transport. Filter by source or get machine-readable output:
```bash
fastmcp discover --source claude-code
fastmcp discover --source cursor --source gemini --json
```
Any server that appears here can be used by name with `list`, `call`, and other commands — so you can go from "I have a server in Claude Code" to querying it without copying URLs or paths.
## LLM Agent Integration
For LLM agents that can execute shell commands but don't have native MCP support, the CLI provides a clean bridge. The agent calls `fastmcp list --json` to discover available tools with full schemas, then `fastmcp call --json` to invoke them with structured results.
Because the CLI handles connection management, transport selection, and type coercion internally, the agent doesn't need to understand MCP protocol details — it just reads JSON and constructs shell commands.

106
docs/cli/generate-cli.mdx Normal file
View file

@ -0,0 +1,106 @@
---
title: Generate CLI
sidebarTitle: Generate CLI
description: Scaffold a standalone typed CLI from any MCP server
icon: wand-magic-sparkles
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.0.0" />
`fastmcp list` and `fastmcp call` are general-purpose — you always specify the server, the tool name, and the arguments from scratch. `fastmcp generate-cli` goes further: it connects to a server, reads its tool schemas, and writes a standalone Python script where every tool is a proper subcommand with typed flags, help text, and tab completion. The result is a CLI that feels hand-written for that specific server.
MCP tool schemas already contain everything a CLI framework needs — parameter names, types, descriptions, required/optional status, and defaults. `generate-cli` maps that into [cyclopts](https://cyclopts.readthedocs.io/) commands, so JSON Schema types become Python type annotations, descriptions become `--help` text, and required parameters become mandatory flags.
## Generating a Script
Point the command at any [server target](/cli/overview#server-targets) and it writes a CLI script:
```bash
fastmcp generate-cli weather
fastmcp generate-cli http://localhost:8000/mcp
fastmcp generate-cli server.py my_weather_cli.py
```
The second positional argument sets the output path (defaults to `cli.py`). If the file already exists, pass `-f` to overwrite:
```bash
fastmcp generate-cli weather -f
```
## What You Get
The generated script is a regular Python file — executable, editable, and yours:
```
$ python cli.py call-tool --help
Usage: weather-cli call-tool COMMAND
Call a tool on the server
Commands:
get_forecast Get the weather forecast for a city.
search_city Search for a city by name.
```
Each tool has typed parameters with help text pulled directly from the server's schema:
```
$ python cli.py call-tool get_forecast --help
Usage: weather-cli call-tool get_forecast [OPTIONS]
Get the weather forecast for a city.
Options:
--city [str] City name (required)
--days [int] Number of forecast days (default: 3)
```
Beyond tool commands, the script includes generic MCP operations — `list-tools`, `list-resources`, `read-resource`, `list-prompts`, and `get-prompt` — that always reflect the server's current state, even if tools have changed since generation.
## Parameter Handling
Parameters are mapped based on their JSON Schema type:
**Simple types** (`string`, `integer`, `number`, `boolean`) become typed flags:
```bash
python cli.py call-tool get_forecast --city London --days 3
```
**Arrays of simple types** become repeatable flags:
```bash
python cli.py call-tool tag_items --tags python --tags fastapi --tags mcp
```
**Complex types** (objects, nested arrays, unions) accept JSON strings. The `--help` output shows the full schema so you know what structure to pass:
```bash
python cli.py call-tool create_user \
--name John \
--metadata '{"role": "admin", "dept": "engineering"}'
```
## Agent Skill
Alongside the CLI script, `generate-cli` writes a `SKILL.md` file — a [Claude Code agent skill](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/skills) that documents every tool's exact invocation syntax, parameter flags, types, and descriptions. An agent can pick up the CLI immediately without running `--help` or experimenting with flag names.
To skip skill generation:
```bash
fastmcp generate-cli weather --no-skill
```
## How It Works
The generated script is a *client*, not a server — it connects to the server on every invocation rather than bundling it. A `CLIENT_SPEC` variable at the top holds the resolved transport (a URL string or `StdioTransport` with baked-in command and arguments).
The most common edit is changing `CLIENT_SPEC` — for example, pointing a script generated from a dev server at production. Beyond that, the helper functions (`_call_tool`, `_print_tool_result`) are thin wrappers around `fastmcp.Client` that are easy to adapt.
The script requires `fastmcp` as a dependency. If it lives outside a project that already has FastMCP installed:
```bash
uv run --with fastmcp python cli.py call-tool get_forecast --city London
```

72
docs/cli/inspecting.mdx Normal file
View file

@ -0,0 +1,72 @@
---
title: Inspecting Servers
sidebarTitle: Inspecting
description: View a server's components and metadata
icon: magnifying-glass
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="2.9.0" />
`fastmcp inspect` loads a server and reports what it contains — its tools, resources, prompts, version, and metadata. The default output is a human-readable summary:
```bash
fastmcp inspect server.py
```
```
Server: MyServer
Instructions: A helpful MCP server
Version: 1.0.0
Components:
Tools: 5
Prompts: 2
Resources: 3
Templates: 1
Environment:
FastMCP: 2.0.0
MCP: 1.0.0
Use --format [fastmcp|mcp] for complete JSON output
```
## JSON Output
For programmatic use, two JSON formats are available:
**FastMCP format** (`--format fastmcp`) includes everything FastMCP knows about the server — tool tags, enabled status, output schemas, annotations, and custom metadata. Field names use `snake_case`. This is the format for debugging and introspecting FastMCP servers.
**MCP protocol format** (`--format mcp`) shows exactly what MCP clients see through the protocol — only standard MCP fields, `camelCase` names, no FastMCP-specific extensions. This is the format for verifying client compatibility and debugging what clients actually receive.
```bash
# Full FastMCP metadata to stdout
fastmcp inspect server.py --format fastmcp
# MCP protocol view saved to file
fastmcp inspect server.py --format mcp -o manifest.json
```
## Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Format | `--format`, `-f` | `fastmcp` or `mcp` (required when using `-o`) |
| Output File | `--output`, `-o` | Save to file instead of stdout |
## Entrypoints
The `inspect` command supports the same local entrypoints as [`fastmcp run`](/cli/running): inferred instances, explicit entrypoints, factory functions, and `fastmcp.json` configs.
```bash
fastmcp inspect server.py # inferred instance
fastmcp inspect server.py:my_server # explicit entrypoint
fastmcp inspect server.py:create_server # factory function
fastmcp inspect fastmcp.json # config file
```
<Warning>
`inspect` only works with local files and `fastmcp.json` — it doesn't connect to remote URLs or standard MCP config files.
</Warning>

141
docs/cli/install-mcp.mdx Normal file
View file

@ -0,0 +1,141 @@
---
title: Install MCP Servers
sidebarTitle: Install MCPs
description: Install MCP servers into Claude, Cursor, Gemini, and other clients
icon: download
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="2.10.3" />
`fastmcp install` registers a server with an MCP client application so the client can launch it automatically. Each MCP client runs servers in its own isolated environment, which means dependencies need to be explicitly declared — you can't rely on whatever happens to be installed locally.
```bash
fastmcp install claude-desktop server.py
fastmcp install claude-code server.py --with pandas --with matplotlib
fastmcp install cursor server.py -e .
```
<Warning>
`uv` must be installed and available in your system PATH. Both Claude Desktop and Cursor run servers in isolated environments managed by `uv`. On macOS, install it globally with Homebrew for Claude Desktop compatibility: `brew install uv`.
</Warning>
## Supported Clients
| Client | Install method |
| ------ | -------------- |
| `claude-code` | Claude Code's built-in MCP management |
| `claude-desktop` | Direct config file modification |
| `cursor` | Deeplink that opens Cursor for confirmation |
| `gemini-cli` | Gemini CLI's built-in MCP management |
| `goose` | Deeplink that opens Goose for confirmation (uses `uvx`) |
| `mcp-json` | Generates standard MCP JSON config for manual use |
| `stdio` | Outputs the shell command to run via stdio |
## Declaring Dependencies
Because MCP clients run servers in isolation, you need to tell the install command what your server needs. There are two approaches:
**Command-line flags** let you specify dependencies directly:
```bash
fastmcp install claude-desktop server.py --with pandas --with "sqlalchemy>=2.0"
fastmcp install cursor server.py -e . --with-requirements requirements.txt
```
**`fastmcp.json`** configuration files declare dependencies alongside the server definition. When you install from a config file, dependencies are picked up automatically:
```bash
fastmcp install claude-desktop fastmcp.json
fastmcp install claude-desktop # auto-detects fastmcp.json in current directory
```
See [Server Configuration](/deployment/server-configuration) for the full config format.
## Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Server Name | `--server-name`, `-n` | Custom name for the server |
| Editable Package | `--with-editable`, `-e` | Install a directory in editable mode |
| Extra Packages | `--with` | Additional packages (repeatable) |
| Environment Variables | `--env` | `KEY=VALUE` pairs (repeatable) |
| Environment File | `--env-file`, `-f` | Load env vars from a `.env` file |
| Python | `--python` | Python version (e.g., `3.11`) |
| Project | `--project` | Run within a uv project directory |
| Requirements | `--with-requirements` | Install from a requirements file |
## Examples
```bash
# Basic install with auto-detected server instance
fastmcp install claude-desktop server.py
# Install from fastmcp.json with auto-detection
fastmcp install claude-desktop
# Explicit entrypoint with dependencies
fastmcp install claude-desktop server.py:my_server \
--server-name "My Analysis Server" \
--with pandas
# With environment variables
fastmcp install claude-code server.py \
--env API_KEY=secret \
--env DEBUG=true
# With env file
fastmcp install cursor server.py --env-file .env
# Specific Python version and requirements file
fastmcp install claude-desktop server.py \
--python 3.11 \
--with-requirements requirements.txt
```
## Generating MCP JSON
The `mcp-json` target generates standard MCP configuration JSON instead of installing into a specific client. This is useful for clients that FastMCP doesn't directly support, for CI/CD environments, or for sharing server configs:
```bash
fastmcp install mcp-json server.py
```
The output follows the standard format used by Claude Desktop, Cursor, and other MCP clients:
```json
{
"server-name": {
"command": "uv",
"args": ["run", "--with", "fastmcp", "fastmcp", "run", "/path/to/server.py"],
"env": {
"API_KEY": "value"
}
}
}
```
Use `--copy` to send it to your clipboard instead of stdout.
## Generating Stdio Commands
The `stdio` target outputs the shell command an MCP host would use to start your server over stdio:
```bash
fastmcp install stdio server.py
# Output: uv run --with fastmcp fastmcp run /absolute/path/to/server.py
```
When installing from a `fastmcp.json`, dependencies from the config are included automatically:
```bash
fastmcp install stdio fastmcp.json
# Output: uv run --with fastmcp --with pillow --with 'qrcode[pil]>=8.0' fastmcp run /path/to/server.py
```
Use `--copy` to copy to clipboard.
<Tip>
`fastmcp install` is designed for local server files with stdio transport. For remote servers running over HTTP, use your client's native configuration — FastMCP's value here is simplifying the complex local setup with `uv`, dependencies, and environment variables.
</Tip>

103
docs/cli/overview.mdx Normal file
View file

@ -0,0 +1,103 @@
---
title: CLI
sidebarTitle: Overview
description: The fastmcp command-line interface
icon: terminal
---
import { VersionBadge } from '/snippets/version-badge.mdx'
The `fastmcp` CLI is installed automatically with FastMCP. It's the primary way to run, test, install, and interact with MCP servers from your terminal.
```bash
fastmcp --help
```
## Commands at a Glance
| Command | What it does |
| ------- | ------------ |
| [`run`](/cli/running) | Run a server (local file, factory function, remote URL, or config file) |
| [`dev inspector`](/cli/running#development-with-the-inspector) | Launch a server inside the MCP Inspector for interactive testing |
| [`install`](/cli/install-mcp) | Install a server into Claude Code, Claude Desktop, Cursor, Gemini CLI, or Goose |
| [`inspect`](/cli/inspecting) | Print a server's tools, resources, and prompts as a summary or JSON report |
| [`list`](/cli/client) | List a server's tools (and optionally resources and prompts) |
| [`call`](/cli/client#calling-tools) | Call a single tool with arguments |
| [`discover`](/cli/client#discovering-configured-servers) | Find MCP servers configured in your editors and tools |
| [`generate-cli`](/cli/generate-cli) | Scaffold a standalone typed CLI from a server's tool schemas |
| [`project prepare`](/cli/running#pre-building-environments) | Pre-install dependencies into a reusable uv project |
| [`auth cimd`](/cli/auth) | Create and validate CIMD documents for OAuth |
| `version` | Print version info (`--copy` to copy to clipboard) |
## Server Targets
Most commands need to know *which server* to talk to. You pass a "server spec" as the first argument, and FastMCP resolves the right transport automatically.
**URLs** connect to a running HTTP server:
```bash
fastmcp list http://localhost:8000/mcp
fastmcp call http://localhost:8000/mcp get_forecast city=London
```
**Python files** are loaded directly — no `mcp.run()` boilerplate needed. FastMCP finds a server instance named `mcp`, `server`, or `app` in the file, or you can specify one explicitly:
```bash
fastmcp list server.py
fastmcp run server.py:my_custom_server
```
**Config files** work too — both FastMCP's own `fastmcp.json` format and standard MCP config files with an `mcpServers` key:
```bash
fastmcp run fastmcp.json
fastmcp list mcp-config.json
```
**Stdio commands** connect to any MCP server that speaks over standard I/O. Use `--command` instead of a positional argument:
```bash
fastmcp list --command 'npx -y @modelcontextprotocol/server-github'
```
### Name-Based Resolution
If your servers are already configured in an editor or tool, you can refer to them by name. FastMCP scans configs from Claude Desktop, Claude Code, Cursor, Gemini CLI, and Goose:
```bash
fastmcp list weather
fastmcp call weather get_forecast city=London
```
When the same name appears in multiple configs, use the `source:name` form to be specific:
```bash
fastmcp list claude-code:my-server
fastmcp call cursor:weather get_forecast city=London
```
Run [`fastmcp discover`](/cli/client#discovering-configured-servers) to see what's available on your machine.
## Authentication
When targeting an HTTP URL, the CLI enables OAuth authentication by default. If the server requires it, you'll be guided through the flow (typically opening a browser). If it doesn't, the setup is a silent no-op.
To skip authentication entirely — useful for local development servers — pass `--auth none`:
```bash
fastmcp call http://localhost:8000/mcp my_tool --auth none
```
You can also pass a bearer token directly:
```bash
fastmcp list http://localhost:8000/mcp --auth "Bearer sk-..."
```
## Transport Override
FastMCP defaults to Streamable HTTP for URL targets. If the server only supports Server-Sent Events (SSE), force the older transport:
```bash
fastmcp list http://localhost:8000 --transport sse
```

141
docs/cli/running.mdx Normal file
View file

@ -0,0 +1,141 @@
---
title: Running Servers
sidebarTitle: Running
description: Start, develop, and configure servers from the command line
icon: play
---
import { VersionBadge } from '/snippets/version-badge.mdx'
## Starting a Server
`fastmcp run` starts a server. Point it at a Python file, a factory function, a remote URL, or a config file:
```bash
fastmcp run server.py
fastmcp run server.py:create_server
fastmcp run https://example.com/mcp
fastmcp run fastmcp.json
```
By default, the server runs over **stdio** — the transport that MCP clients like Claude Desktop expect. To serve over HTTP instead, specify the transport:
```bash
fastmcp run server.py --transport http
fastmcp run server.py --transport http --host 0.0.0.0 --port 9000
```
### Entrypoints
FastMCP supports several ways to locate and start your server:
**Inferred instance** — FastMCP imports the file and looks for a variable named `mcp`, `server`, or `app`:
```bash
fastmcp run server.py
```
**Explicit instance** — point at a specific variable:
```bash
fastmcp run server.py:my_server
```
**Factory function** — FastMCP calls the function and uses the returned server. Useful when your server needs async setup or configuration that runs before startup:
```bash
fastmcp run server.py:create_server
```
**Remote URL** — starts a local proxy that bridges to a remote server. Handy for local development against a deployed server, or for bridging a remote HTTP server to stdio:
```bash
fastmcp run https://example.com/mcp
```
**FastMCP config** — uses a `fastmcp.json` file that declaratively specifies the server, its dependencies, and deployment settings. When you run `fastmcp run` with no arguments, it auto-detects `fastmcp.json` in the current directory:
```bash
fastmcp run
fastmcp run my-config.fastmcp.json
```
See [Server Configuration](/deployment/server-configuration) for the full `fastmcp.json` format.
**MCP config** — runs servers defined in a standard MCP configuration file (any `.json` with an `mcpServers` key):
```bash
fastmcp run mcp.json
```
<Warning>
`fastmcp run` completely ignores the `if __name__ == "__main__"` block. Any setup code in that block won't execute. If you need initialization logic to run, use a [factory function](/cli/overview#factory-functions).
</Warning>
### Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Transport | `--transport`, `-t` | `stdio` (default), `http`, or `sse` |
| Host | `--host` | Bind address for HTTP (default: `127.0.0.1`) |
| Port | `--port`, `-p` | Bind port for HTTP (default: `8000`) |
| Path | `--path` | URL path for HTTP (default: `/mcp/`) |
| Log Level | `--log-level`, `-l` | `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
| No Banner | `--no-banner` | Suppress the startup banner |
| Auto-Reload | `--reload` / `--no-reload` | Watch for file changes and restart automatically |
| Reload Dirs | `--reload-dir` | Directories to watch (repeatable) |
| Skip Env | `--skip-env` | Don't set up a uv environment (use when already in one) |
| Python | `--python` | Python version to use (e.g., `3.11`) |
| Extra Packages | `--with` | Additional packages to install (repeatable) |
| Project | `--project` | Run within a specific uv project directory |
| Requirements | `--with-requirements` | Install from a requirements file |
### Dependency Management
By default, `fastmcp run` uses your current Python environment directly. When you pass `--python`, `--with`, `--project`, or `--with-requirements`, it switches to running via `uv run` in a subprocess, which handles dependency isolation automatically.
The `--skip-env` flag is useful when you're already inside an activated venv, a Docker container with pre-installed dependencies, or a uv-managed project — it prevents uv from trying to set up another environment layer.
## Development with the Inspector
`fastmcp dev inspector` launches your server inside the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), a browser-based tool for interactively testing MCP servers. Auto-reload is on by default, so your server restarts when you save changes.
```bash
fastmcp dev inspector server.py
fastmcp dev inspector server.py -e . --with pandas
```
<Tip>
The Inspector always runs your server via `uv run` in a subprocess — it never uses your local environment directly. Specify dependencies with `--with`, `--with-editable`, `--with-requirements`, or through a `fastmcp.json` file.
</Tip>
<Warning>
The Inspector connects over **stdio only**. When it launches, you may need to select "STDIO" from the transport dropdown and click connect. To test a server over HTTP, start it separately with `fastmcp run server.py --transport http` and point the Inspector at the URL.
</Warning>
| Option | Flag | Description |
| ------ | ---- | ----------- |
| Editable Package | `--with-editable`, `-e` | Install a directory in editable mode |
| Extra Packages | `--with` | Additional packages (repeatable) |
| Inspector Version | `--inspector-version` | MCP Inspector version to use |
| UI Port | `--ui-port` | Port for the Inspector UI |
| Server Port | `--server-port` | Port for the Inspector proxy |
| Auto-Reload | `--reload` / `--no-reload` | File watching (default: on) |
| Reload Dirs | `--reload-dir` | Directories to watch (repeatable) |
| Python | `--python` | Python version |
| Project | `--project` | Run within a uv project directory |
| Requirements | `--with-requirements` | Install from a requirements file |
## Pre-Building Environments
`fastmcp project prepare` creates a persistent uv project from a `fastmcp.json` file, pre-installing all dependencies. This separates environment setup from server execution — install once, run many times.
```bash
# Step 1: Build the environment (slow, does dependency resolution)
fastmcp project prepare fastmcp.json --output-dir ./env
# Step 2: Run using the prepared environment (fast, no install step)
fastmcp run fastmcp.json --project ./env
```
The prepared directory contains a `pyproject.toml`, a `.venv` with all packages installed, and a `uv.lock` for reproducibility. This is particularly useful in deployment scenarios where you want deterministic, pre-built environments.

View file

@ -90,9 +90,9 @@ async with client:
"expertise": "python programming"
})
# Typically returns messages with role="system"
system_message = result.messages[0]
print(f"System prompt: {system_message.content}")
# Access the returned messages
message = result.messages[0]
print(f"Prompt: {message.content}")
```
Conversation templates generate multi-turn flows:

View file

@ -97,7 +97,7 @@ client = Client(
## Built-in Handlers
FastMCP provides built-in handlers for OpenAI and Anthropic APIs that support the full sampling API including tool use.
FastMCP provides built-in handlers for OpenAI, Anthropic, and Google Gemini APIs that support the full sampling API including tool use.
### OpenAI Handler
@ -149,6 +149,24 @@ client = Client(
Install the Anthropic handler with `pip install fastmcp[anthropic]`.
</Note>
### Google Gemini Handler
<VersionBadge version="3.1.0" />
```python
from fastmcp import Client
from fastmcp.client.sampling.handlers.google_genai import GoogleGenAISamplingHandler
client = Client(
"my_mcp_server.py",
sampling_handler=GoogleGenAISamplingHandler(default_model="gemini-2.0-flash"),
)
```
<Note>
Install the Google Gemini handler with `pip install fastmcp[gemini]`.
</Note>
## Sampling Capabilities
When you provide a `sampling_handler`, FastMCP automatically advertises full sampling capabilities to the server, including tool support. To disable tool support for simpler handlers:

View file

@ -1,3 +1,7 @@
html:not([data-page-mode="wide"]) #content-area {
max-width: 44rem !important;
}
img.nav-logo {
max-width: 200px;
}

View file

@ -725,6 +725,134 @@ Both parameters are required for production. Without an explicit signing key, ke
For more details on the token architecture and key management, see [OAuth Proxy Key and Storage Management](/servers/auth/oauth-proxy#key-and-storage-management).
## Reverse Proxy (nginx)
In production, you'll typically run your FastMCP server behind a reverse proxy like nginx. A reverse proxy provides TLS termination, domain-based routing, static file serving, and an additional layer of security between the internet and your application.
### Running FastMCP as a Linux Service
Before configuring nginx, you need your FastMCP server running as a background service. A systemd unit file ensures your server starts automatically and restarts on failure.
Create a file at `/etc/systemd/system/fastmcp.service`:
```ini
[Unit]
Description=FastMCP Server
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/fastmcp
ExecStart=/opt/fastmcp/.venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=5
Environment="PATH=/opt/fastmcp/.venv/bin"
[Install]
WantedBy=multi-user.target
```
Enable and start the service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable fastmcp
sudo systemctl start fastmcp
```
This assumes your ASGI application is in `/opt/fastmcp/app.py` with a virtual environment at `/opt/fastmcp/.venv`. Adjust paths to match your deployment layout.
### nginx Configuration
FastMCP's Streamable HTTP transport uses Server-Sent Events (SSE) for streaming responses. This requires specific nginx settings to prevent buffering from breaking the event stream.
Create a site configuration at `/etc/nginx/sites-available/fastmcp`:
```nginx
server {
listen 80;
server_name mcp.example.com;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE (Server-Sent Events) streaming
proxy_buffering off;
proxy_cache off;
# Allow long-lived connections for streaming responses
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
```
Enable the site and reload nginx:
```bash
sudo ln -s /etc/nginx/sites-available/fastmcp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Your FastMCP server is now accessible at `https://mcp.example.com/mcp`.
<Warning>
**SSE buffering is the most common issue.** If clients connect but never receive streaming responses (progress updates, tool results), verify that `proxy_buffering off` is set. Without it, nginx buffers the entire SSE stream and delivers it only when the connection closes, which breaks real-time communication.
</Warning>
### Key Considerations
When deploying FastMCP behind a reverse proxy, keep these points in mind:
- **Disable buffering**: SSE requires `proxy_buffering off` so events reach clients immediately. This is the single most important setting.
- **Increase timeouts**: The default nginx `proxy_read_timeout` is 60 seconds. Long-running MCP tools will cause the connection to drop. Set timeouts to at least 300 seconds, or higher if your tools run longer. For tools that may exceed any timeout, use [SSE Polling](#sse-polling-for-long-running-operations) to gracefully handle proxy disconnections.
- **Use HTTP/1.1**: Set `proxy_http_version 1.1` and `proxy_set_header Connection ''` to enable keep-alive connections between nginx and your server. Clearing the `Connection` header prevents clients from sending `Connection: close` to your upstream, which would break SSE streams. Both settings are required for proper SSE support.
- **Forward headers**: Pass `X-Forwarded-For` and `X-Forwarded-Proto` so your FastMCP server can determine the real client IP and protocol. This is important for logging and for OAuth redirect URLs.
- **TLS termination**: Let nginx handle TLS certificates (e.g., via Let's Encrypt with Certbot). Your FastMCP server can then run on plain HTTP internally.
### Mounting Under a Path Prefix
If you want your MCP server available at a subpath like `https://example.com/api/mcp` instead of at the root domain, adjust the nginx `location` block:
```nginx
location /api/ {
proxy_pass http://127.0.0.1:8000/;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE streaming
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
```
Note the trailing `/` on both `location /api/` and `proxy_pass http://127.0.0.1:8000/` — this ensures nginx strips the `/api` prefix before forwarding to your server. If you're using OAuth authentication with a mount prefix, see [Mounting Authenticated Servers](#mounting-authenticated-servers) for additional configuration.
## Testing Your Deployment
Once your server is deployed, you'll need to verify it's accessible and functioning correctly. For comprehensive testing strategies including connectivity tests, client testing, and authentication testing, see the [Testing Your Server](/development/tests) guide.

View file

@ -157,7 +157,7 @@ fastmcp run database_server.py -- --database-path /tmp/db.sqlite --debug
This is useful for servers that need configuration files, database paths, API keys, or other runtime options.
For more CLI features including development mode with the MCP Inspector, see the [CLI documentation](/patterns/cli).
For more CLI features including development mode with the MCP Inspector, see the [CLI documentation](/cli/running).
### Auto-Reload for Development

View file

@ -23,6 +23,38 @@ result = await ctx.sample(
)
```
### Google GenAI Sampling Handler
FastMCP now includes a sampling handler for Google's Gemini models ([#2977](https://github.com/jlowin/fastmcp/pull/2977)). This enables MCP clients to use Google's GenAI models with the sampling protocol, including full tool calling support.
```python
from fastmcp import Client
from fastmcp.client.sampling.handlers import GoogleGenaiSamplingHandler
from google.genai import Client as GoogleGenaiClient
# Initialize the handler
handler = GoogleGenaiSamplingHandler(
default_model="gemini-2.0-flash-exp",
client=GoogleGenaiClient(), # Optional - creates one if not provided
)
# Use with MCP sampling (handler is configured at Client construction)
async with Client("http://server/mcp", sampling_handler=handler) as client:
result = await client.sample(
messages=[...],
tools=[...],
)
```
Key features:
- Converts MCP tool schemas to Google's function calling format
- Supports all Google GenAI models that implement function calling
- Handles nullable types, nested objects, and arrays in tool schemas
- Properly maps tool choices (`auto`, `required`, `none`) to Google's configuration
- Preserves model preferences from MCP sampling parameters
The handler joins the existing Anthropic and OpenAI handlers, providing a consistent interface for model-agnostic sampling across providers.
### Concurrent Tool Execution in Sampling
When an LLM returns multiple tool calls in a single sampling response, they can now be executed concurrently ([#3022](https://github.com/PrefectHQ/fastmcp/pull/3022)). Default behavior remains sequential; opt in with `tool_concurrency`. Tools can declare `sequential=True` to force sequential execution even when concurrency is enabled.
@ -153,7 +185,7 @@ Key features:
- Fuzzy tool name matching suggests alternatives on typos
- Interactive terminal elicitation for tools that request user input mid-execution
Documentation: [Client CLI](/clients/cli)
Documentation: [CLI Querying](/cli/client)
### CLI: `fastmcp discover` and name-based resolution
@ -175,7 +207,7 @@ fastmcp call cursor:weather get_forecast city=London
fastmcp discover --source claude-code --source cursor
```
Documentation: [Client CLI](/clients/cli)
Documentation: [CLI Querying](/cli/client)
### CLI: Expanded Reload File Watching
@ -283,7 +315,7 @@ python my_weather_cli.py read-resource docs://readme
The generated script embeds the resolved transport (URL or stdio command), so it's self-contained — users don't need to know about MCP or FastMCP to use it. Supports `-f` to overwrite existing files, and name-based resolution via `fastmcp discover`.
Documentation: [Generate CLI](/clients/generate-cli)
Documentation: [Generate CLI](/cli/generate-cli)
### CLI: Goose Integration

View file

@ -88,18 +88,7 @@
"pages": [
"getting-started/welcome",
"getting-started/installation",
"getting-started/quickstart",
{
"collapsed": true,
"group": "Upgrade",
"icon": "up",
"tag": "NEW",
"pages": [
"getting-started/upgrading/from-fastmcp-2",
"getting-started/upgrading/from-mcp-sdk",
"getting-started/upgrading/from-low-level-sdk"
]
}
"getting-started/quickstart"
]
},
{
@ -120,10 +109,10 @@
{
"collapsed": true,
"group": "Features",
"tag": "NEW",
"icon": "stars",
"pages": [
"servers/tasks",
"servers/composition",
"servers/dependency-injection",
"servers/elicitation",
"servers/icons",
@ -135,13 +124,14 @@
"servers/sampling",
"servers/storage-backends",
"servers/telemetry",
"servers/testing",
"servers/versioning"
]
],
"tag": "UPDATED"
},
{
"collapsed": true,
"group": "Providers",
"tag": "NEW",
"icon": "layer-group",
"pages": [
"servers/providers/overview",
@ -149,35 +139,39 @@
"servers/providers/filesystem",
"servers/providers/proxy",
"servers/providers/skills",
"servers/providers/custom",
"servers/providers/mounting"
]
"servers/providers/custom"
],
"tag": "NEW"
},
{
"collapsed": true,
"group": "Transforms",
"tag": "NEW",
"icon": "wand-magic-sparkles",
"pages": [
"servers/transforms/transforms",
"servers/transforms/namespace",
"servers/transforms/tool-transformation",
"servers/visibility",
"servers/transforms/code-mode",
"servers/transforms/tool-search",
"servers/transforms/resources-as-tools",
"servers/transforms/prompts-as-tools"
]
],
"tag": "NEW"
},
{
"collapsed": true,
"group": "Authentication",
"icon": "key",
"tag": "UPDATED",
"pages": [
"servers/auth/authentication",
"servers/auth/token-verification",
"servers/auth/remote-oauth",
"servers/auth/oauth-proxy",
"servers/auth/oidc-proxy",
"servers/auth/full-oauth-server"
"servers/auth/full-oauth-server",
"servers/auth/multi-auth"
]
},
"servers/authorization",
@ -189,9 +183,7 @@
"deployment/running-server",
"deployment/http",
"deployment/prefect-horizon",
"deployment/server-configuration",
"patterns/cli",
"patterns/testing"
"deployment/server-configuration"
]
}
]
@ -200,6 +192,8 @@
"group": "Apps",
"pages": [
"apps/overview",
"apps/prefab",
"apps/patterns",
"apps/low-level"
]
},
@ -208,16 +202,6 @@
"pages": [
"clients/client",
"clients/transports",
{
"collapsed": true,
"group": "CLI",
"tag": "NEW",
"icon": "terminal",
"pages": [
"clients/cli",
"clients/generate-cli"
]
},
{
"collapsed": true,
"group": "Core Operations",
@ -232,6 +216,7 @@
"collapsed": true,
"group": "Handlers",
"icon": "hand",
"tag": "UPDATED",
"pages": [
"clients/notifications",
"clients/sampling",
@ -245,13 +230,13 @@
{
"collapsed": true,
"group": "Authentication",
"tag": "NEW",
"icon": "key",
"pages": [
"clients/auth/oauth",
"clients/auth/cimd",
"clients/auth/bearer"
]
],
"tag": "UPDATED"
}
]
},
@ -269,14 +254,15 @@
"integrations/azure",
"integrations/descope",
"integrations/discord",
"integrations/eunomia-authorization",
"integrations/github",
"integrations/google",
"integrations/oci",
"integrations/permit",
"integrations/propelauth",
"integrations/scalekit",
"integrations/supabase",
"integrations/workos",
"integrations/eunomia-authorization",
"integrations/permit"
"integrations/workos"
]
},
{
@ -298,8 +284,7 @@
"integrations/claude-desktop",
"integrations/cursor",
"integrations/gemini-cli",
"integrations/goose",
"integrations/mcp-json-configuration"
"integrations/goose"
]
},
{
@ -311,18 +296,55 @@
"integrations/gemini",
"integrations/openai"
]
}
},
"integrations/mcp-json-configuration"
]
},
{
"group": "Development",
"group": "CLI",
"pages": [
"development/contributing",
"development/tests",
"development/releases",
"updates",
"changelog",
"patterns/contrib"
"cli/overview",
"cli/running",
"cli/install-mcp",
"cli/inspecting",
"cli/client",
"cli/generate-cli",
"cli/auth"
]
},
{
"group": "More",
"pages": [
{
"collapsed": true,
"group": "Upgrading",
"icon": "up",
"pages": [
"getting-started/upgrading/from-fastmcp-2",
"getting-started/upgrading/from-mcp-sdk",
"getting-started/upgrading/from-low-level-sdk"
]
},
{
"collapsed": true,
"group": "Development",
"icon": "code",
"pages": [
"development/contributing",
"development/tests",
"development/releases",
"patterns/contrib"
]
},
{
"collapsed": true,
"group": "What's New",
"icon": "sparkles",
"pages": [
"updates",
"changelog"
]
}
]
}
],
@ -428,6 +450,26 @@
}
]
},
{
"group": "fastmcp.experimental",
"pages": [
"python-sdk/fastmcp-experimental-__init__",
{
"group": "sampling",
"pages": [
"python-sdk/fastmcp-experimental-sampling-__init__",
"python-sdk/fastmcp-experimental-sampling-handlers"
]
},
{
"group": "transforms",
"pages": [
"python-sdk/fastmcp-experimental-transforms-__init__",
"python-sdk/fastmcp-experimental-transforms-code_mode"
]
}
]
},
{
"group": "fastmcp.prompts",
"pages": [
@ -487,6 +529,7 @@
"python-sdk/fastmcp-server-auth-providers-introspection",
"python-sdk/fastmcp-server-auth-providers-jwt",
"python-sdk/fastmcp-server-auth-providers-oci",
"python-sdk/fastmcp-server-auth-providers-propelauth",
"python-sdk/fastmcp-server-auth-providers-scalekit",
"python-sdk/fastmcp-server-auth-providers-supabase",
"python-sdk/fastmcp-server-auth-providers-workos"
@ -616,9 +659,19 @@
"group": "transforms",
"pages": [
"python-sdk/fastmcp-server-transforms-__init__",
"python-sdk/fastmcp-server-transforms-catalog",
"python-sdk/fastmcp-server-transforms-namespace",
"python-sdk/fastmcp-server-transforms-prompts_as_tools",
"python-sdk/fastmcp-server-transforms-resources_as_tools",
{
"group": "search",
"pages": [
"python-sdk/fastmcp-server-transforms-search-__init__",
"python-sdk/fastmcp-server-transforms-search-base",
"python-sdk/fastmcp-server-transforms-search-bm25",
"python-sdk/fastmcp-server-transforms-search-regex"
]
},
"python-sdk/fastmcp-server-transforms-tool_transform",
"python-sdk/fastmcp-server-transforms-version_filter",
"python-sdk/fastmcp-server-transforms-visibility"
@ -911,6 +964,22 @@
]
},
"redirects": [
{
"destination": "/cli/overview",
"source": "/patterns/cli"
},
{
"destination": "/servers/testing",
"source": "/patterns/testing"
},
{
"destination": "/cli/client",
"source": "/clients/cli"
},
{
"destination": "/cli/generate-cli",
"source": "/clients/generate-cli"
},
{
"destination": "/deployment/prefect-horizon",
"source": "/deployment/fastmcp-cloud"
@ -932,7 +1001,7 @@
"source": "/patterns/proxy"
},
{
"destination": "/servers/providers/mounting",
"destination": "/servers/composition",
"source": "/patterns/composition"
},
{
@ -940,8 +1009,8 @@
"source": "/servers/proxy"
},
{
"destination": "/servers/providers/mounting",
"source": "/servers/composition"
"destination": "/servers/composition",
"source": "/servers/providers/mounting"
},
{
"destination": "/servers/transforms/transforms",

View file

@ -62,15 +62,17 @@ Alternatively, wait for the stable v5 release. See [this issue](https://github.c
</Info>
## Upgrading
### From FastMCP 2.x
### From FastMCP 2.0
See the [Upgrade Guide](/getting-started/upgrading/from-fastmcp-2) for a complete list of breaking changes and migration steps.
### From FastMCP 1.0 (in the Low-Level SDK)
### From the MCP SDK
If you're using FastMCP 1.0 via the `mcp` package (`from mcp.server.fastmcp import FastMCP`), upgrading is straightforward — for most servers, it's a single import change. See the [full upgrade guide](/getting-started/upgrading/from-mcp-sdk) for details.
#### From FastMCP 1.0
### From the Low-Level Server API
If you're using FastMCP 1.0 via the `mcp` package (meaning you import FastMCP as `from mcp.server.fastmcp import FastMCP`), upgrading is straightforward — for most servers, it's a single import change. See the [full upgrade guide](/getting-started/upgrading/from-mcp-sdk) for details.
#### From the Low-Level Server API
If you built your server directly on the `mcp` package's `Server` class — with `list_tools()`/`call_tool()` handlers and hand-written JSON Schema — see the [migration guide](/getting-started/upgrading/from-low-level-sdk) for a full walkthrough.
@ -86,18 +88,6 @@ fastmcp>=3.0.0 # Bad - may install breaking changes
See the full [versioning and release policy](/development/releases#versioning-policy) for details on our public API, deprecation practices, and breaking change philosophy.
### Looking Ahead: FastMCP 4.0
The MCP Python SDK v2 is expected in early 2026 and will include breaking changes. When released, FastMCP will incorporate these upstream changes in a new major version (FastMCP 4.0).
To avoid unexpected breaking changes, we recommend pinning your dependency with an upper bound:
```
fastmcp>=3.0,<4
```
We'll provide migration guidance when FastMCP 4.0 is released.
## Contributing to FastMCP
Interested in contributing to FastMCP? See the [Contributing Guide](/development/contributing) for details on:

View file

@ -3,7 +3,6 @@ title: Upgrading from FastMCP 2
sidebarTitle: "From FastMCP 2"
description: Migration instructions for upgrading between FastMCP versions
icon: up
tag: NEW
---
This guide covers breaking changes and migration steps when upgrading FastMCP.

View file

@ -3,7 +3,6 @@ title: Upgrading from the MCP Low-Level SDK
sidebarTitle: "From MCP Low-Level SDK"
description: Upgrade your MCP server from the low-level Python SDK's Server class to FastMCP
icon: up
tag: NEW
---
If you've been building MCP servers directly on the `mcp` package's `Server` class — writing `list_tools()` and `call_tool()` handlers, hand-crafting JSON Schema dicts, and wiring up transport boilerplate — this guide is for you. FastMCP replaces all of that machinery with a declarative, Pythonic API where your functions *are* the protocol surface.
@ -583,11 +582,11 @@ if __name__ == "__main__":
Once you've upgraded, you have access to everything FastMCP provides beyond the basics:
- **[Server composition](/servers/providers/mounting)** — Mount sub-servers to build modular applications
- **[Server composition](/servers/composition)** — Mount sub-servers to build modular applications
- **[Middleware](/servers/middleware)** — Add logging, rate limiting, error handling, and caching
- **[Proxy servers](/servers/providers/proxy)** — Create a proxy to any existing MCP server
- **[OpenAPI integration](/integrations/openapi)** — Generate an MCP server from an OpenAPI spec
- **[Authentication](/servers/auth/authentication)** — Built-in OAuth and token verification
- **[Testing](/patterns/testing)** — Test your server directly in Python without running a subprocess
- **[Testing](/servers/testing)** — Test your server directly in Python without running a subprocess
Explore the full documentation at [gofastmcp.com](https://gofastmcp.com).

View file

@ -3,7 +3,6 @@ title: Upgrading from the MCP SDK
sidebarTitle: "From MCP SDK"
description: Upgrade from FastMCP in the MCP Python SDK to the standalone FastMCP framework
icon: up
tag: NEW
---
If your server starts with `from mcp.server.fastmcp import FastMCP`, you're using FastMCP 1.0 — the version bundled with v1 of the `mcp` package. Upgrading to the standalone FastMCP framework is easy. **For most servers, it's a single import change.**

View file

@ -0,0 +1,164 @@
---
title: PropelAuth 🤝 FastMCP
sidebarTitle: PropelAuth
description: Secure your FastMCP server with PropelAuth
icon: shield-check
---
import { VersionBadge } from "/snippets/version-badge.mdx";
<VersionBadge version="3.1.0" />
This guide shows you how to secure your FastMCP server using [**PropelAuth**](https://www.propelauth.com), a complete authentication and user management solution. This integration uses the [**Remote OAuth**](/servers/auth/remote-oauth) pattern, where PropelAuth handles user login, consent management, and your FastMCP server validates the tokens.
## Configuration
### Prerequisites
Before you begin, you will need:
1. A [PropelAuth](https://www.propelauth.com) account
2. Your FastMCP server's base URL (can be localhost for development, e.g., `http://localhost:8000`)
### Step 1: Configure PropelAuth
<Steps>
<Step title="Enable MCP Authentication">
Navigate to the **MCP** section in your PropelAuth dashboard, click **Enable MCP**, and choose which environments to enable it for (Test, Staging, Prod).
</Step>
<Step title="Configure Allowed MCP Clients">
Under **MCP > Allowed MCP Clients**, add redirect URIs for each MCP client you want to allow. PropelAuth provides templates for popular clients like Claude, Cursor, and ChatGPT.
</Step>
<Step title="Configure Scopes">
Under **MCP > Scopes**, define the permissions available to MCP clients (e.g., `read:user_data`).
</Step>
<Step title="Choose How Users Create OAuth Clients">
Under **MCP > Settings > How Do Users Create OAuth Clients?**, you can optionally enable:
- **Dynamic Client Registration** — clients self-register automatically via the DCR protocol
- **Manually via Hosted Pages** — PropelAuth creates a UI for your users to register OAuth clients
You can enable neither, one, or both. If you enable neither, you'll manage OAuth client creation yourself.
</Step>
<Step title="Generate Introspection Credentials">
Go to **MCP > Request Validation** and click **Create Credentials**. Note the **Client ID** and **Client Secret** - you'll need these to validate tokens.
</Step>
<Step title="Note Your Auth URL">
Find your Auth URL in the **Backend Integration** section of the dashboard (e.g., `https://auth.yourdomain.com`).
</Step>
</Steps>
For more details, see the [PropelAuth MCP documentation](https://docs.propelauth.com/mcp-authentication/overview).
### Step 2: Environment Setup
Create a `.env` file with your PropelAuth configuration:
```bash
PROPELAUTH_AUTH_URL=https://auth.yourdomain.com # From Backend Integration page
PROPELAUTH_INTROSPECTION_CLIENT_ID=your-client-id # From MCP > Request Validation
PROPELAUTH_INTROSPECTION_CLIENT_SECRET=your-client-secret # From MCP > Request Validation
SERVER_URL=http://localhost:8000 # Your server's base URL
```
### Step 3: FastMCP Configuration
Create your FastMCP server file and use the PropelAuthProvider to handle all the OAuth integration automatically:
```python server.py
import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.propelauth import PropelAuthProvider
auth_provider = PropelAuthProvider(
auth_url=os.environ["PROPELAUTH_AUTH_URL"],
introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"],
introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"],
base_url=os.environ["SERVER_URL"],
required_scopes=["read:user_data"], # Optional scope enforcement
)
mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth_provider)
```
## Testing
With your `.env` loaded, start the server:
```bash
fastmcp run server.py --transport http --port 8000
```
Then use a FastMCP client to verify authentication works:
```python
from fastmcp import Client
import asyncio
async def main():
async with Client("http://localhost:8000/mcp", auth="oauth") as client:
assert await client.ping()
if __name__ == "__main__":
asyncio.run(main())
```
## Accessing User Information
You can use `get_access_token()` inside your tools to identify the authenticated user:
```python server.py
import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.propelauth import PropelAuthProvider
from fastmcp.server.dependencies import get_access_token
auth = PropelAuthProvider(
auth_url=os.environ["PROPELAUTH_AUTH_URL"],
introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"],
introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"],
base_url=os.environ["SERVER_URL"],
required_scopes=["read:user_data"],
)
mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth)
@mcp.tool
def whoami() -> dict:
"""Return the authenticated user's ID."""
token = get_access_token()
if token is None:
return {"error": "Not authenticated"}
user_id = token.claims.get("sub")
return {"user_id": user_id}
```
## Advanced Configuration
The `PropelAuthProvider` supports optional overrides for token introspection behavior, including caching and request timeouts:
```python server.py
import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.propelauth import PropelAuthProvider
auth = PropelAuthProvider(
auth_url=os.environ["PROPELAUTH_AUTH_URL"],
introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"],
introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"],
base_url=os.environ.get("BASE_URL", "https://your-server.com"),
required_scopes=["read:user_data"],
resource="https://your-server.com/mcp", # Restrict to tokens intended for this server (RFC 8707)
token_introspection_overrides={
"cache_ttl_seconds": 300, # Cache introspection results for 5 minutes
"max_cache_size": 1000, # Maximum cached tokens
"timeout_seconds": 15, # HTTP request timeout
},
)
mcp = FastMCP(name="My PropelAuth Protected Server", auth=auth)
```

View file

@ -50,7 +50,7 @@ Run an MCP server with the MCP Inspector for development.
- `server_spec`: Python file to run, optionally with \:object suffix, or None to auto-detect fastmcp.json
### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L322" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L337" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(server_spec: str | None = None, *server_args: str) -> None
@ -66,6 +66,7 @@ The server can be specified in several ways:
4. MCPConfig file: "mcp.json" - runs as a proxy server for the MCP Servers in the MCPConfig file
5. FastMCP config: "fastmcp.json" - runs server using FastMCP configuration
6. No argument: looks for fastmcp.json in current directory
7. Module mode: "-m my_module" - runs the module directly via python -m
Server arguments can be passed after -- :
fastmcp run server.py -- --config config.json --debug
@ -74,7 +75,7 @@ fastmcp run server.py -- --config config.json --debug
- `server_spec`: Python file, object specification (file\:obj), config file, URL, or None to auto-detect
### `inspect` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L624" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `inspect` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L712" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
inspect(server_spec: str | None = None) -> None
@ -105,7 +106,7 @@ fastmcp inspect # auto-detect fastmcp.json
- `server_spec`: Python file to inspect, optionally with \:object suffix, or fastmcp.json
### `prepare` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L866" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `prepare` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/cli.py#L954" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(config_path: Annotated[str | None, cyclopts.Parameter(help='Path to fastmcp.json configuration file')] = None, output_dir: Annotated[str | None, cyclopts.Parameter(help='Directory to create the persistent environment in')] = None, skip_source: Annotated[bool, cyclopts.Parameter(help='Skip source preparation (e.g., git clone)')] = False) -> None

View file

@ -10,7 +10,7 @@ Client-side CLI commands for querying and invoking MCP servers.
## Functions
### `resolve_server_spec` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L43" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `resolve_server_spec` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L42" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
resolve_server_spec(server_spec: str | None) -> str | dict[str, Any] | ClientTransport
@ -32,7 +32,7 @@ When ``command`` is provided, the string is shell-split into a
``StdioTransport(command, args)``.
### `coerce_value` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L265" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `coerce_value` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L263" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
coerce_value(raw: str, schema: dict[str, Any]) -> Any
@ -42,7 +42,7 @@ coerce_value(raw: str, schema: dict[str, Any]) -> Any
Coerce a string CLI value according to a JSON-Schema type hint.
### `parse_tool_arguments` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L299" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `parse_tool_arguments` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L297" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
parse_tool_arguments(raw_args: tuple[str, ...], input_json: str | None, input_schema: dict[str, Any]) -> dict[str, Any]
@ -56,7 +56,7 @@ A single JSON object argument is treated as the full argument dict.
Values are coerced using the tool's ``inputSchema``.
### `format_tool_signature` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L371" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `format_tool_signature` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L369" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
format_tool_signature(tool: mcp.types.Tool) -> str
@ -66,7 +66,7 @@ format_tool_signature(tool: mcp.types.Tool) -> str
Build ``name(param: type, ...) -> return_type`` from a tool's JSON schemas.
### `list_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L627" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `list_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L625" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_command(server_spec: Annotated[str | None, cyclopts.Parameter(help='Server URL, Python file, MCPConfig JSON, or .js file')] = None) -> None
@ -84,7 +84,7 @@ fastmcp list --command 'npx -y @mcp/server' --resources
fastmcp list http://server/mcp --transport sse
### `call_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L776" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `call_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L774" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_command(server_spec: Annotated[str | None, cyclopts.Parameter(help='Server URL, Python file, MCPConfig JSON, or .js file')] = None, target: Annotated[str, cyclopts.Parameter(help='Tool name, resource URI, or prompt name (with --prompt)')] = '', *arguments: str) -> None
@ -110,7 +110,7 @@ fastmcp call http://server/mcp create --input-json '{"tags": ["a","b"]}'
```
### `discover_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L877" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `discover_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/client.py#L875" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
discover_command() -> None

View file

@ -10,7 +10,7 @@ FastMCP run command implementation with enhanced type hints.
## Functions
### `is_url` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L81" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `is_url` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L83" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_url(path: str) -> bool
@ -20,7 +20,7 @@ is_url(path: str) -> bool
Check if a string is a URL.
### `create_client_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L87" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_client_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L89" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_client_server(url: str) -> Any
@ -36,7 +36,7 @@ Create a FastMCP server from a client URL.
- A FastMCP server instance
### `create_mcp_config_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L107" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_mcp_config_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L109" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]
@ -46,7 +46,7 @@ create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]
Create a FastMCP server from a MCPConfig.
### `load_mcp_server_config` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L116" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `load_mcp_server_config` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L118" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_mcp_server_config(config_path: Path) -> MCPServerConfig
@ -62,7 +62,7 @@ Load a FastMCP configuration from a fastmcp.json file.
- MCPServerConfig object
### `run_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L133" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L135" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_command(server_spec: str, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, server_args: list[str] | None = None, show_banner: bool = True, use_direct_import: bool = False, skip_source: bool = False, stateless: bool = False) -> None
@ -85,7 +85,26 @@ Run a MCP server or connect to a remote one.
- `stateless`: Whether to run in stateless mode (no session)
### `run_v1_server_async` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L258" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_module_command` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L260" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_module_command(module_name: str) -> None
```
Run a Python module directly using ``python -m <module>``.
When ``-m`` is used, the module manages its own server startup.
No server-object discovery or transport overrides are applied.
**Args:**
- `module_name`: Dotted module name (e.g. ``my_package``).
- `env_command_builder`: An optional callable that wraps a command list
with environment setup (e.g. ``UVEnvironment.build_command``).
- `extra_args`: Extra arguments forwarded after the module name.
### `run_v1_server_async` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L299" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_v1_server_async(server: FastMCP1x, host: str | None = None, port: int | None = None, transport: TransportType | None = None) -> None
@ -101,7 +120,7 @@ Run a FastMCP 1.x server using async methods.
- `transport`: Transport protocol to use
### `run_with_reload` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L323" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_with_reload` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/cli/run.py#L364" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_with_reload(cmd: list[str], reload_dirs: list[Path] | None = None, is_stdio: bool = False) -> None

View file

@ -85,7 +85,7 @@ async with client:
**Methods:**
#### `session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L343" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L340" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
session(self) -> ClientSession
@ -94,7 +94,7 @@ session(self) -> ClientSession
Get the current active session. Raises RuntimeError if not connected.
#### `initialize_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L353" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `initialize_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L350" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
initialize_result(self) -> mcp.types.InitializeResult | None
@ -103,7 +103,7 @@ initialize_result(self) -> mcp.types.InitializeResult | None
Get the result of the initialization request.
#### `set_roots` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L357" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_roots` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L354" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_roots(self, roots: RootsList | RootsHandler) -> None
@ -112,7 +112,7 @@ set_roots(self, roots: RootsList | RootsHandler) -> None
Set the roots for the client. This does not automatically call `send_roots_list_changed`.
#### `set_sampling_callback` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L361" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_sampling_callback` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L358" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_sampling_callback(self, sampling_callback: SamplingHandler, sampling_capabilities: mcp.types.SamplingCapability | None = None) -> None
@ -121,7 +121,7 @@ set_sampling_callback(self, sampling_callback: SamplingHandler, sampling_capabil
Set the sampling callback for the client.
#### `set_elicitation_callback` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L377" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_elicitation_callback` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L373" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
@ -130,7 +130,7 @@ set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
Set the elicitation callback for the client.
#### `is_connected` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L385" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `is_connected` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L381" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_connected(self) -> bool
@ -139,7 +139,7 @@ is_connected(self) -> bool
Check if the client is currently connected.
#### `new` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L389" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `new` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L385" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
new(self) -> Client[ClientTransportT]
@ -155,7 +155,7 @@ share state with the original client.
- A new Client instance with the same configuration but disconnected state.
#### `initialize` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L434" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `initialize` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L430" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
initialize(self, timeout: datetime.timedelta | float | int | None = None) -> mcp.types.InitializeResult
@ -183,13 +183,13 @@ capabilities, protocol version, and optional instructions.
- `RuntimeError`: If the client is not connected or initialization times out.
#### `close` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L735" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `close` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L731" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
close(self)
```
#### `ping` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L741" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `ping` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L737" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
ping(self) -> bool
@ -198,7 +198,7 @@ ping(self) -> bool
Send a ping request.
#### `cancel` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L746" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `cancel` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L742" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
cancel(self, request_id: str | int, reason: str | None = None) -> None
@ -207,7 +207,7 @@ cancel(self, request_id: str | int, reason: str | None = None) -> None
Send a cancellation notification for an in-progress request.
#### `progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L763" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L759" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
progress(self, progress_token: str | int, progress: float, total: float | None = None, message: str | None = None) -> None
@ -216,7 +216,7 @@ progress(self, progress_token: str | int, progress: float, total: float | None =
Send a progress notification.
#### `set_logging_level` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L775" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_logging_level` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L771" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_logging_level(self, level: mcp.types.LoggingLevel) -> None
@ -225,7 +225,7 @@ set_logging_level(self, level: mcp.types.LoggingLevel) -> None
Send a logging/setLevel request.
#### `send_roots_list_changed` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L779" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `send_roots_list_changed` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L775" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
send_roots_list_changed(self) -> None
@ -234,7 +234,7 @@ send_roots_list_changed(self) -> None
Send a roots/list_changed notification.
#### `complete_mcp` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L785" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `complete_mcp` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L781" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
complete_mcp(self, ref: mcp.types.ResourceTemplateReference | mcp.types.PromptReference, argument: dict[str, str], context_arguments: dict[str, Any] | None = None) -> mcp.types.CompleteResult
@ -257,7 +257,7 @@ containing the completion and any additional metadata.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
#### `complete` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L816" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `complete` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L812" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
complete(self, ref: mcp.types.ResourceTemplateReference | mcp.types.PromptReference, argument: dict[str, str], context_arguments: dict[str, Any] | None = None) -> mcp.types.Completion
@ -279,7 +279,7 @@ include with the completion request. Defaults to None.
- `McpError`: If the request results in a TimeoutError | JSONRPCError
#### `generate_name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L843" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `generate_name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/client.py#L839" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate_name(cls, name: str | None = None) -> str

View file

@ -0,0 +1,17 @@
---
title: google_genai
sidebarTitle: google_genai
---
# `fastmcp.client.sampling.handlers.google_genai`
Google GenAI sampling handler with tool support for FastMCP 3.0.
## Classes
### `GoogleGenaiSamplingHandler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/sampling/handlers/google_genai.py#L54" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Sampling handler that uses the Google GenAI API with tool support.

View file

@ -65,7 +65,7 @@ async with client:
connect_session(self, **session_kwargs: Unpack[SessionKwargs]) -> AsyncIterator[ClientSession]
```
#### `close` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/transports/config.py#L165" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `close` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/client/transports/config.py#L198" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
close(self)

View file

@ -8,11 +8,10 @@ sidebarTitle: dependencies
Dependency injection exports for FastMCP.
This module re-exports dependency injection symbols from Docket and FastMCP
to provide a clean, centralized import location for all dependency-related
functionality.
This module re-exports dependency injection symbols to provide a clean,
centralized import location for all dependency-related functionality.
DI features (Depends, CurrentContext, CurrentFastMCP) work without pydocket
using a vendored DI engine. Only task-related dependencies (CurrentDocket,
using the uncalled-for DI engine. Only task-related dependencies (CurrentDocket,
CurrentWorker) and background task execution require fastmcp[tasks].

View file

@ -0,0 +1,8 @@
---
title: __init__
sidebarTitle: __init__
---
# `fastmcp.experimental`
*This module is empty or contains only private/internal implementations.*

View file

@ -0,0 +1,8 @@
---
title: __init__
sidebarTitle: __init__
---
# `fastmcp.experimental.sampling`
*This module is empty or contains only private/internal implementations.*

View file

@ -0,0 +1,8 @@
---
title: handlers
sidebarTitle: handlers
---
# `fastmcp.experimental.sampling.handlers`
*This module is empty or contains only private/internal implementations.*

View file

@ -0,0 +1,8 @@
---
title: __init__
sidebarTitle: __init__
---
# `fastmcp.experimental.transforms`
*This module is empty or contains only private/internal implementations.*

View file

@ -0,0 +1,121 @@
---
title: code_mode
sidebarTitle: code_mode
---
# `fastmcp.experimental.transforms.code_mode`
## Classes
### `SandboxProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L73" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Interface for executing LLM-generated Python code in a sandbox.
WARNING: The ``code`` parameter passed to ``run`` contains untrusted,
LLM-generated Python. Implementations MUST execute it in an isolated
sandbox — never with plain ``exec()``. Use ``MontySandboxProvider``
(backed by ``pydantic-monty``) for production workloads.
**Methods:**
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L82" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(self, code: str) -> Any
```
### `MontySandboxProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L91" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Sandbox provider backed by `pydantic-monty`.
**Args:**
- `limits`: Resource limits for sandbox execution. Supported keys\:
``max_duration_secs`` (float), ``max_allocations`` (int),
``max_memory`` (int), ``max_recursion_depth`` (int),
``gc_interval`` (int). All are optional; omit a key to
leave that limit uncapped.
**Methods:**
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L109" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(self, code: str) -> Any
```
### `Search` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L180" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Discovery tool factory that searches the catalog by query.
**Args:**
- `search_fn`: Async callable ``(tools, query) -> matching_tools``.
Defaults to BM25 ranking.
- `name`: Name of the synthetic tool exposed to the LLM.
- `default_detail`: Default detail level for search results.
``"brief"`` returns tool names and descriptions only.
``"detailed"`` returns compact markdown with parameter schemas.
``"full"`` returns complete JSON tool definitions.
### `GetSchemas` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L245" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Discovery tool factory that returns schemas for tools by name.
**Args:**
- `name`: Name of the synthetic tool exposed to the LLM.
- `default_detail`: Default detail level for schema results.
``"brief"`` returns tool names and descriptions only.
``"detailed"`` renders compact markdown with parameter names,
types, and required markers.
``"full"`` returns the complete JSON schema.
### `GetTags` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L306" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Discovery tool factory that lists tool tags from the catalog.
Reads ``tool.tags`` from the catalog and groups tools by tag. Tools
without tags appear under ``"untagged"``.
**Args:**
- `name`: Name of the synthetic tool exposed to the LLM.
- `default_detail`: Default detail level.
``"brief"`` returns tag names with tool counts.
``"full"`` lists all tools under each tag.
### `CodeMode` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L382" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Transform that collapses all tools into discovery + execute meta-tools.
Discovery tools are composable via the ``discovery_tools`` parameter.
Each is a callable that receives catalog access and returns a ``Tool``.
By default, ``Search`` and ``GetSchemas`` are included for
progressive disclosure: search finds candidates, get_schema retrieves
parameter details, and execute runs code.
The ``execute`` tool is always present and provides a sandboxed Python
environment with ``call_tool(name, params)`` in scope.
**Methods:**
#### `transform_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L432" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]
```
#### `get_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/experimental/transforms/code_mode.py#L435" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
```

View file

@ -27,7 +27,7 @@ read(self) -> ResourceResult
Read the text content.
### `BinaryResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L33" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `BinaryResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L37" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A resource that reads from bytes.
@ -35,7 +35,7 @@ A resource that reads from bytes.
**Methods:**
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L38" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L42" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult
@ -44,7 +44,7 @@ read(self) -> ResourceResult
Read the binary content.
### `FileResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L45" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `FileResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A resource that reads from a file.
@ -54,7 +54,7 @@ Set is_binary=True to read file as binary data instead of text.
**Methods:**
#### `validate_absolute_path` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L67" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `validate_absolute_path` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L75" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
validate_absolute_path(cls, path: Path) -> Path
@ -63,7 +63,7 @@ validate_absolute_path(cls, path: Path) -> Path
Ensure path is absolute.
#### `set_binary_from_mime_type` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L75" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_binary_from_mime_type` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L83" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_binary_from_mime_type(cls, is_binary: bool, info: ValidationInfo) -> bool
@ -72,7 +72,7 @@ set_binary_from_mime_type(cls, is_binary: bool, info: ValidationInfo) -> bool
Set is_binary based on mime_type if not explicitly set.
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L83" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L91" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult
@ -81,7 +81,7 @@ read(self) -> ResourceResult
Read the file content.
### `HttpResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L97" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `HttpResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L105" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A resource that reads from an HTTP endpoint.
@ -89,7 +89,7 @@ A resource that reads from an HTTP endpoint.
**Methods:**
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L106" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L114" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult
@ -98,7 +98,7 @@ read(self) -> ResourceResult
Read the HTTP content.
### `DirectoryResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L118" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `DirectoryResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A resource that lists files in a directory.
@ -106,7 +106,7 @@ A resource that lists files in a directory.
**Methods:**
#### `validate_absolute_path` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L138" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `validate_absolute_path` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L146" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
validate_absolute_path(cls, path: Path) -> Path
@ -115,7 +115,7 @@ validate_absolute_path(cls, path: Path) -> Path
Ensure path is absolute.
#### `list_files` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L144" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_files` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L152" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_files(self) -> list[Path]
@ -124,7 +124,7 @@ list_files(self) -> list[Path]
List files in the directory.
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L160" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/resources/types.py#L168" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult

View file

@ -254,7 +254,66 @@ Get routes for this provider.
Creates protected resource metadata routes (RFC 9728).
### `OAuthProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L472" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `MultiAuth` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L472" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Composes an optional auth server with additional token verifiers.
Use this when a single server needs to accept tokens from multiple sources.
For example, an OAuth proxy for interactive clients combined with a JWT
verifier for machine-to-machine tokens.
Token verification tries the server first (if present), then each verifier
in order, returning the first successful result. Routes and OAuth metadata
come from the server; verifiers contribute only token verification.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L537" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
```
Verify a token by trying the server, then each verifier in order.
Each source is tried independently. If a source raises an exception,
it is logged and treated as a non-match so that remaining sources
still get a chance to verify the token.
#### `set_mcp_path` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L558" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_mcp_path(self, mcp_path: str | None) -> None
```
Propagate MCP path to the server and all verifiers.
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L566" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self, mcp_path: str | None = None) -> list[Route]
```
Delegate route creation to the server.
#### `get_well_known_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L572" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_well_known_routes(self, mcp_path: str | None = None) -> list[Route]
```
Delegate well-known route creation to the server.
This ensures that server-specific well-known route logic (e.g.,
OAuthProvider's RFC 8414 path-aware discovery) is preserved.
### `OAuthProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L583" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
OAuth Authorization Server provider.
@ -265,7 +324,7 @@ authorization flows, token issuance, and token verification.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L535" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L646" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -283,7 +342,7 @@ to our existing load_access_token method.
- AccessToken object if valid, None if invalid or expired
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L550" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L661" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self, mcp_path: str | None = None) -> list[Route]
@ -299,7 +358,7 @@ This method creates the full set of OAuth routes including:
- List of OAuth routes
#### `get_well_known_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L629" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_well_known_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/auth.py#L740" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_well_known_routes(self, mcp_path: str | None = None) -> list[Route]

View file

@ -14,7 +14,7 @@ using the OAuth Proxy pattern for non-DCR OAuth flows.
## Functions
### `EntraOBOToken` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L680" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `EntraOBOToken` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L681" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
EntraOBOToken(scopes: list[str]) -> str
@ -43,7 +43,7 @@ or OBO exchange fails
## Classes
### `AzureProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L33" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AzureProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L35" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Azure (Microsoft Entra) OAuth provider for FastMCP.
@ -78,7 +78,7 @@ Setup:
**Methods:**
#### `authorize` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L243" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `authorize` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L250" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str
@ -98,7 +98,7 @@ scopes to determine the resource/audience instead of a separate parameter.
- Authorization URL to redirect the user to Azure AD
#### `get_obo_credential` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L469" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_obo_credential` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L476" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_obo_credential(self, user_assertion: str) -> OnBehalfOfCredential
@ -120,7 +120,7 @@ calls multiple tools with the same scopes.
- `ImportError`: If azure-identity is not installed (requires fastmcp[azure]).
#### `close_obo_credentials` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L510" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `close_obo_credentials` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L517" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
close_obo_credentials(self) -> None
@ -129,7 +129,7 @@ close_obo_credentials(self) -> None
Close all cached OBO credentials.
### `AzureJWTVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L521" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AzureJWTVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L528" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
JWT verifier pre-configured for Azure AD / Microsoft Entra ID.
@ -166,7 +166,7 @@ Example::
**Methods:**
#### `scopes_supported` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L601" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `scopes_supported` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/azure.py#L608" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
scopes_supported(self) -> list[str]

View file

@ -29,7 +29,7 @@ Example:
## Classes
### `DiscordTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `DiscordTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L41" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Token verifier for Discord OAuth tokens.
@ -40,7 +40,7 @@ by calling Discord's tokeninfo API to check if they're valid and get user info.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L62" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L68" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -49,7 +49,7 @@ verify_token(self, token: str) -> AccessToken | None
Verify Discord OAuth token by calling Discord's tokeninfo API.
### `DiscordProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L144" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `DiscordProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/discord.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Complete Discord OAuth provider for FastMCP.

View file

@ -29,7 +29,7 @@ Example:
## Classes
### `GitHubTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L37" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `GitHubTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L39" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Token verifier for GitHub OAuth tokens.
@ -40,7 +40,7 @@ by calling GitHub's API to check if they're valid and get user info.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L59" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L66" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -49,7 +49,7 @@ verify_token(self, token: str) -> AccessToken | None
Verify GitHub OAuth token by calling GitHub API.
### `GitHubProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L142" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `GitHubProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/github.py#L153" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Complete GitHub OAuth provider for FastMCP.

View file

@ -29,7 +29,7 @@ Example:
## Classes
### `GoogleTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L39" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `GoogleTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Token verifier for Google OAuth tokens.
@ -40,7 +40,7 @@ by calling Google's tokeninfo API to check if they're valid and get user info.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L61" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L67" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -49,7 +49,7 @@ verify_token(self, token: str) -> AccessToken | None
Verify Google OAuth token by calling Google's tokeninfo API.
### `GoogleProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L158" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `GoogleProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/google.py#L168" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Complete Google OAuth provider for FastMCP.

View file

@ -31,7 +31,7 @@ Example:
## Classes
### `IntrospectionTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/introspection.py#L42" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `IntrospectionTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/introspection.py#L54" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
OAuth 2.0 Token Introspection verifier (RFC 7662).
@ -52,10 +52,14 @@ Use this when:
- Your tokens require real-time revocation checking
- Your authorization server supports RFC 7662 introspection
Caching is disabled by default to preserve real-time revocation semantics.
Set ``cache_ttl_seconds`` to enable caching and reduce load on the
introspection endpoint (e.g., ``cache_ttl_seconds=300`` for 5 minutes).
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/introspection.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/introspection.py#L278" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -67,6 +71,9 @@ This method makes a POST request to the introspection endpoint with the token,
authenticated using the configured client authentication method (client_secret_basic
or client_secret_post).
Results are cached in-memory to reduce load on the introspection endpoint.
Cache TTL and size are configurable via constructor parameters.
**Args:**
- `token`: The opaque token string to validate

View file

@ -10,19 +10,19 @@ TokenVerifier implementations for FastMCP.
## Classes
### `JWKData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L26" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `JWKData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L27" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
JSON Web Key data structure.
### `JWKSData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L39" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `JWKSData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
JSON Web Key Set data structure.
### `RSAKeyPair` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L46" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `RSAKeyPair` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L47" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
RSA key pair for JWT testing.
@ -30,7 +30,7 @@ RSA key pair for JWT testing.
**Methods:**
#### `generate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `generate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L54" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate(cls) -> RSAKeyPair
@ -42,7 +42,7 @@ Generate an RSA key pair for testing.
- Generated key pair
#### `create_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L88" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `create_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L89" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_token(self, subject: str = 'fastmcp-user', issuer: str = 'https://fastmcp.example.com', audience: str | list[str] | None = None, scopes: list[str] | None = None, expires_in_seconds: int = 3600, additional_claims: dict[str, Any] | None = None, kid: str | None = None) -> str
@ -60,7 +60,7 @@ Generate a test JWT token for testing purposes.
- `kid`: Key ID to include in header
### `JWTVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L141" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `JWTVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L142" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
JWT token verifier supporting both asymmetric (RSA/ECDSA) and symmetric (HMAC) algorithms.
@ -82,7 +82,7 @@ Use this when:
**Methods:**
#### `load_access_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L353" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_access_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L372" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_access_token(self, token: str) -> AccessToken | None
@ -97,7 +97,7 @@ Validate a JWT bearer token and return an AccessToken when the token is valid.
- AccessToken | None: An AccessToken populated from token claims if the token is valid; `None` if the token is expired, has an invalid signature or format, fails issuer/audience/scope validation, or any other validation error occurs.
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L471" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L490" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -115,7 +115,7 @@ to our existing load_access_token method.
- AccessToken object if valid, None if invalid or expired
### `StaticTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L487" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `StaticTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L506" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Simple static token verifier for testing and development.
@ -136,7 +136,7 @@ WARNING: Never use this in production - tokens are stored in plain text!
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L521" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/jwt.py#L540" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None

View file

@ -0,0 +1,69 @@
---
title: propelauth
sidebarTitle: propelauth
---
# `fastmcp.server.auth.providers.propelauth`
PropelAuth authentication provider for FastMCP.
Example:
```python
from fastmcp import FastMCP
from fastmcp.server.auth.providers.propelauth import PropelAuthProvider
auth = PropelAuthProvider(
auth_url="https://auth.yourdomain.com",
introspection_client_id="your-client-id",
introspection_client_secret="your-client-secret",
base_url="https://your-fastmcp-server.com",
required_scopes=["read:user_data"],
)
mcp = FastMCP("My App", auth=auth)
```
## Classes
### `PropelAuthTokenIntrospectionOverrides` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/propelauth.py#L36" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `PropelAuthProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/propelauth.py#L43" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
PropelAuth resource server provider using OAuth 2.1 token introspection.
This provider validates access tokens via PropelAuth's introspection endpoint
and forwards authorization server metadata for OAuth discovery.
For detailed setup instructions, see:
https://docs.propelauth.com/mcp-authentication/overview
**Methods:**
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/propelauth.py#L130" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self, mcp_path: str | None = None) -> list[Route]
```
Get routes for this provider.
Includes the standard routes from the RemoteAuthProvider (protected resource metadata routes (RFC 9728)),
and creates an authorization server metadata route that forwards to PropelAuth's route
**Args:**
- `mcp_path`: The path where the MCP endpoint is mounted (e.g., "/mcp")
This is used to advertise the resource URL in metadata.
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/propelauth.py#L174" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
```
Verify token and check the ``aud`` claim against the configured resource.

View file

@ -18,7 +18,7 @@ Choose based on your WorkOS setup and authentication requirements.
## Classes
### `WorkOSTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L28" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `WorkOSTokenVerifier` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L30" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Token verifier for WorkOS OAuth tokens.
@ -29,7 +29,7 @@ the /oauth2/userinfo endpoint to check validity and get user info.
**Methods:**
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `verify_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
verify_token(self, token: str) -> AccessToken | None
@ -38,7 +38,7 @@ verify_token(self, token: str) -> AccessToken | None
Verify WorkOS OAuth token by calling userinfo endpoint.
### `WorkOSProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L100" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `WorkOSProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L111" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Complete WorkOS OAuth provider for FastMCP.
@ -59,7 +59,7 @@ Setup Requirements:
4. Note your Client ID and Client Secret
### `AuthKitProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L214" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AuthKitProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L230" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
AuthKit metadata provider for DCR (Dynamic Client Registration).
@ -85,7 +85,7 @@ https://workos.com/docs/authkit/mcp/integrating/token-verification
**Methods:**
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L301" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_routes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L317" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self, mcp_path: str | None = None) -> list[Route]

View file

@ -7,7 +7,7 @@ sidebarTitle: context
## Functions
### `set_transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L87" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `set_transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L88" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_transport(transport: TransportType) -> Token[TransportType | None]
@ -17,7 +17,7 @@ set_transport(transport: TransportType) -> Token[TransportType | None]
Set the current transport type. Returns token for reset.
### `reset_transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L94" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `reset_transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L95" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
reset_transport(token: Token[TransportType | None]) -> None
@ -27,7 +27,7 @@ reset_transport(token: Token[TransportType | None]) -> None
Reset transport to previous value.
### `set_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L124" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `set_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L125" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_context(context: Context) -> Generator[Context, None, None]
@ -35,7 +35,7 @@ set_context(context: Context) -> Generator[Context, None, None]
## Classes
### `LogData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L100" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `LogData` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L101" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Data object for passing log arguments to client-side handlers.
@ -44,7 +44,7 @@ This provides an interface to match the Python standard library logging,
for compatibility with structured logging.
### `Context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L133" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L134" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Context object providing access to MCP capabilities.
@ -99,7 +99,7 @@ The context is optional - tools that don't need it can omit the parameter.
**Methods:**
#### `is_background_task` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L204" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `is_background_task` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L207" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_background_task(self) -> bool
@ -112,7 +112,7 @@ task-aware implementations that can pause the task and wait for
client input.
#### `task_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L223" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `task_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L226" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
task_id(self) -> str | None
@ -123,7 +123,20 @@ Get the background task ID if running in a background task.
Returns None if not running in a background task context.
#### `fastmcp` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L231" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `origin_request_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L234" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
origin_request_id(self) -> str | None
```
Get the request ID that originated this execution, if available.
In foreground request mode, this is the current request_id.
In background task mode, this is the request_id captured when the task
was submitted, if one was available.
#### `fastmcp` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L246" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
fastmcp(self) -> FastMCP
@ -132,7 +145,7 @@ fastmcp(self) -> FastMCP
Get the FastMCP instance.
#### `request_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L296" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `request_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L321" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
request_context(self) -> RequestContext[ServerSession, Any, Request] | None
@ -161,7 +174,7 @@ async def on_request(self, context, call_next):
```
#### `lifespan_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L325" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `lifespan_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L350" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
lifespan_context(self) -> dict[str, Any]
@ -188,7 +201,7 @@ def my_tool(ctx: Context) -> str:
```
#### `report_progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L356" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `report_progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L381" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
report_progress(self, progress: float, total: float | None = None, message: str | None = None) -> None
@ -205,7 +218,7 @@ Works in both foreground (MCP progress notifications) and background
- `message`: Optional status message describing current progress
#### `list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L450" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L474" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources(self) -> list[SDKResource]
@ -217,7 +230,7 @@ List all available resources from the server.
- List of Resource objects available on the server
#### `list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L466" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L490" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts(self) -> list[SDKPrompt]
@ -229,7 +242,7 @@ List all available prompts from the server.
- List of Prompt objects available on the server
#### `get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L482" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L506" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult
@ -245,7 +258,7 @@ Get a prompt by name with optional arguments.
- The prompt result
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L501" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L525" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str | AnyUrl) -> ResourceResult
@ -260,7 +273,7 @@ Read a resource by URI.
- ResourceResult with contents
#### `log` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L517" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `log` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L541" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
log(self, message: str, level: LoggingLevel | None = None, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@ -278,7 +291,7 @@ Messages sent to Clients are also logged to the `fastmcp.server.context.to_clien
- `extra`: Optional mapping for additional arguments
#### `transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L546" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `transport` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L571" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transport(self) -> TransportType | None
@ -290,7 +303,7 @@ Returns the transport type used to run this server: "stdio", "sse",
or "streamable-http". Returns None if called outside of a server context.
#### `client_supports_extension` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L554" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `client_supports_extension` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L579" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
client_supports_extension(self, extension_id: str) -> bool
@ -315,7 +328,7 @@ Example::
return "text-only client"
#### `client_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L582" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `client_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L607" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
client_id(self) -> str | None
@ -324,7 +337,7 @@ client_id(self) -> str | None
Get the client ID if available.
#### `request_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L591" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `request_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L616" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
request_id(self) -> str
@ -335,7 +348,7 @@ Get the unique ID for this request.
Raises RuntimeError if MCP request context is not available.
#### `session_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L604" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `session_id` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L629" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
session_id(self) -> str
@ -352,7 +365,7 @@ the same client session.
- for other transports.
#### `session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L661" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L686" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
session(self) -> ServerSession
@ -366,7 +379,7 @@ In background task mode: Returns the session stored at Context creation.
Raises RuntimeError if no session is available.
#### `debug` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L687" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `debug` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L712" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
debug(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@ -377,7 +390,7 @@ Send a `DEBUG`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
#### `info` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L703" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `info` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L728" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
info(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@ -388,7 +401,7 @@ Send a `INFO`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
#### `warning` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L719" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `warning` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L744" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
warning(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@ -399,7 +412,7 @@ Send a `WARNING`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
#### `error` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L735" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `error` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L760" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
error(self, message: str, logger_name: str | None = None, extra: Mapping[str, Any] | None = None) -> None
@ -410,7 +423,7 @@ Send a `ERROR`-level message to the connected MCP Client.
Messages sent to Clients are also logged to the `fastmcp.server.context.to_client` logger with a level of `DEBUG`.
#### `list_roots` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L751" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_roots` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L776" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_roots(self) -> list[Root]
@ -419,7 +432,7 @@ list_roots(self) -> list[Root]
List the roots available to the server, as indicated by the client.
#### `send_notification` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L756" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `send_notification` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L781" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
send_notification(self, notification: mcp.types.ServerNotificationType) -> None
@ -431,7 +444,7 @@ Send a notification to the client immediately.
- `notification`: An MCP notification instance (e.g., ToolListChangedNotification())
#### `close_sse_stream` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L766" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `close_sse_stream` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L791" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
close_sse_stream(self) -> None
@ -449,7 +462,7 @@ Instead of holding a connection open for minutes, you can periodically close
and let the client reconnect.
#### `sample_step` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L805" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `sample_step` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L830" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
sample_step(self, messages: str | Sequence[str | SamplingMessage]) -> SampleStep
@ -492,7 +505,7 @@ regardless of this setting.
- - .text: The text content (if any)
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L884" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L909" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT]
@ -501,7 +514,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[
Overload: With result_type, returns SamplingResult[ResultT].
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L900" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L925" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[str]
@ -510,7 +523,7 @@ sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[
Overload: Without result_type, returns SamplingResult[str].
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L915" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `sample` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L940" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
sample(self, messages: str | Sequence[str | SamplingMessage]) -> SamplingResult[ResultT] | SamplingResult[str]
@ -558,43 +571,43 @@ regardless of this setting.
- - .history: All messages exchanged during sampling
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L990" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1015" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: None) -> AcceptedElicitation[dict[str, Any]] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1002" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1027" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: type[T]) -> AcceptedElicitation[T] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1012" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1037" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: list[str]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1022" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1047" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: dict[str, dict[str, str]]) -> AcceptedElicitation[str] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1032" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1057" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: list[list[str]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1044" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1069" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: list[dict[str, dict[str, str]]]) -> AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
```
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1056" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `elicit` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1081" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
elicit(self, message: str, response_type: type[T] | list[str] | dict[str, dict[str, str]] | list[list[str]] | list[dict[str, dict[str, str]]] | None = None) -> AcceptedElicitation[T] | AcceptedElicitation[dict[str, Any]] | AcceptedElicitation[str] | AcceptedElicitation[list[str]] | DeclinedElicitation | CancelledElicitation
@ -623,7 +636,7 @@ type or dataclass or BaseModel. If it is a primitive type, an
object schema with a single "value" field will be generated.
#### `set_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1195" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_state(self, key: str, value: Any) -> None
@ -644,7 +657,7 @@ requests.
The key is automatically prefixed with the session identifier.
#### `get_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1212" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1237" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_state(self, key: str) -> Any
@ -658,7 +671,7 @@ then falls back to the session-scoped state store.
Returns None if the key is not found.
#### `delete_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1226" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `delete_state` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1251" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
delete_state(self, key: str) -> None
@ -669,7 +682,7 @@ Delete a value from the state store.
Removes from both request-scoped and session-scoped stores.
#### `enable_components` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1247" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `enable_components` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1272" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
enable_components(self) -> None
@ -693,7 +706,7 @@ ResourceListChangedNotification, and PromptListChangedNotification.
- `match_all`: If True, matches all components regardless of other criteria.
#### `disable_components` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1285" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `disable_components` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1310" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
disable_components(self) -> None
@ -717,7 +730,7 @@ ResourceListChangedNotification, and PromptListChangedNotification.
- `match_all`: If True, matches all components regardless of other criteria.
#### `reset_visibility` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1323" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `reset_visibility` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/context.py#L1348" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
reset_visibility(self) -> None

View file

@ -9,13 +9,13 @@ sidebarTitle: dependencies
Dependency injection for FastMCP.
DI features (Depends, CurrentContext, CurrentFastMCP) work without pydocket
using a vendored DI engine. Only task-related dependencies (CurrentDocket,
using the uncalled-for DI engine. Only task-related dependencies (CurrentDocket,
CurrentWorker) and background task execution require fastmcp[tasks].
## Functions
### `get_task_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L95" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_task_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L97" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_task_context() -> TaskContextInfo | None
@ -31,7 +31,7 @@ Returns None if not running in a task context (e.g., foreground execution).
- TaskContextInfo with task_id and session_id, or None if not in a task.
### `register_task_session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L133" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `register_task_session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L135" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
register_task_session(session_id: str, session: ServerSession) -> None
@ -49,7 +49,7 @@ client disconnects.
- `session`: The ServerSession instance
### `get_task_session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L147" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_task_session` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L149" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_task_session(session_id: str) -> ServerSession | None
@ -65,7 +65,7 @@ Get a registered session by ID if still alive.
- The ServerSession if found and alive, None otherwise
### `is_docket_available` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L183" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `is_docket_available` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L185" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_docket_available() -> bool
@ -75,7 +75,7 @@ is_docket_available() -> bool
Check if pydocket is installed.
### `require_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L196" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `require_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L198" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
require_docket(feature: str) -> None
@ -89,7 +89,7 @@ Raise ImportError with install instructions if docket not available.
"CurrentDocket()"). Will be included in the error message.
### `transform_context_annotations` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L238" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `transform_context_annotations` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L223" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_context_annotations(fn: Callable[..., Any]) -> Callable[..., Any]
@ -115,7 +115,7 @@ allows them to have defaults in any order.
- Function with modified signature (same function object, updated __signature__)
### `get_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L389" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_context` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L364" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_context() -> Context
@ -125,7 +125,7 @@ get_context() -> Context
Get the current FastMCP Context instance directly.
### `get_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L399" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L374" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_server() -> FastMCP
@ -141,7 +141,7 @@ Get the current FastMCP server instance directly.
- `RuntimeError`: If no server in context
### `get_http_request` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L417" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_http_request` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L392" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_http_request() -> Request
@ -153,10 +153,10 @@ Get the current HTTP request.
Tries MCP SDK's request_ctx first, then falls back to FastMCP's HTTP context.
### `get_http_headers` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L437" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_http_headers` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L412" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_http_headers(include_all: bool = False) -> dict[str, str]
get_http_headers(include_all: bool = False, include: set[str] | None = None) -> dict[str, str]
```
@ -165,11 +165,16 @@ Extract headers from the current HTTP request if available.
Never raises an exception, even if there is no active HTTP request (in which case
an empty dict is returned).
By default, strips problematic headers like `content-length` that cause issues
if forwarded to downstream clients. If `include_all` is True, all headers are returned.
By default, strips problematic headers like `content-length` and `authorization`
that cause issues if forwarded to downstream services. If `include_all` is True,
all headers are returned.
The `include` parameter allows specific headers to be included even if they would
normally be excluded. This is useful for proxy transports that need to forward
authorization headers to upstream MCP servers.
### `get_access_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L483" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `get_access_token` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L469" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_access_token() -> AccessToken | None
@ -188,7 +193,7 @@ token snapshot stored in Redis at task submission time.
- The access token if an authenticated user is available, None otherwise.
### `without_injected_parameters` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L555" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `without_injected_parameters` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L541" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
without_injected_parameters(fn: Callable[..., Any]) -> Callable[..., Any]
@ -213,7 +218,7 @@ Handles:
- Async wrapper function without injected parameters
### `resolve_dependencies` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L704" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `resolve_dependencies` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L690" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
resolve_dependencies(fn: Callable[..., Any], arguments: dict[str, Any]) -> AsyncGenerator[dict[str, Any], None]
@ -239,7 +244,7 @@ time, so all injection goes through the unified DI system.
which will be filtered out)
### `CurrentContext` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L845" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentContext` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L893" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentContext() -> Context
@ -258,7 +263,17 @@ current MCP operation (tool/resource/prompt call).
- `RuntimeError`: If no active context found (during resolution)
### `CurrentDocket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L888" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `OptionalCurrentContext` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L918" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
OptionalCurrentContext() -> Context | None
```
Get the current FastMCP Context, or None when no context is active.
### `CurrentDocket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L941" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentDocket() -> Docket
@ -278,7 +293,7 @@ automatically creates for background task scheduling.
- `ImportError`: If fastmcp[tasks] not installed
### `CurrentWorker` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L933" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentWorker` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L986" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentWorker() -> Worker
@ -298,7 +313,7 @@ automatically creates for background task processing.
- `ImportError`: If fastmcp[tasks] not installed
### `CurrentFastMCP` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L975" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentFastMCP` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1028" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentFastMCP() -> FastMCP
@ -316,7 +331,7 @@ This dependency provides access to the active FastMCP server.
- `RuntimeError`: If no server in context (during resolution)
### `CurrentRequest` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1010" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentRequest` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1063" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentRequest() -> Request
@ -336,7 +351,7 @@ current HTTP request. Only available when running over HTTP transports
- `RuntimeError`: If no HTTP request in context (e.g., STDIO transport)
### `CurrentHeaders` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1046" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentHeaders` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1099" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentHeaders() -> dict[str, str]
@ -345,15 +360,16 @@ CurrentHeaders() -> dict[str, str]
Get the current HTTP request headers.
This dependency provides access to the HTTP headers for the current request.
Returns an empty dictionary when no HTTP request is available, making it
safe to use in code that might run over any transport.
This dependency provides access to the HTTP headers for the current request,
including the authorization header. Returns an empty dictionary when no HTTP
request is available, making it safe to use in code that might run over any
transport.
**Returns:**
- A dependency that resolves to a dictionary of header name -> value
### `CurrentAccessToken` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1236" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CurrentAccessToken` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1318" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
CurrentAccessToken() -> AccessToken
@ -372,7 +388,7 @@ authenticated request. Raises an error if no authentication is present.
- `RuntimeError`: If no authenticated user (use get_access_token() for optional)
### `TokenClaim` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1288" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `TokenClaim` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1370" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
TokenClaim(name: str) -> str
@ -397,7 +413,7 @@ without needing the full token object.
## Classes
### `TaskContextInfo` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L81" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `TaskContextInfo` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L83" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Information about the current background task context.
@ -406,7 +422,7 @@ Returned by ``get_task_context()`` when running inside a Docket worker.
Contains identifiers needed to communicate with the MCP session.
### `ProgressLike` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1073" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProgressLike` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1127" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Protocol for progress tracking interface.
@ -417,7 +433,7 @@ and Docket's Progress (worker context).
**Methods:**
#### `current` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1081" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `current` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1135" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
current(self) -> int | None
@ -426,7 +442,7 @@ current(self) -> int | None
Current progress value.
#### `total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1086" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1140" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
total(self) -> int
@ -435,7 +451,7 @@ total(self) -> int
Total/target progress value.
#### `message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1091" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1145" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
message(self) -> str | None
@ -444,7 +460,7 @@ message(self) -> str | None
Current progress message.
#### `set_total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1095" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1149" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_total(self, total: int) -> None
@ -453,7 +469,7 @@ set_total(self, total: int) -> None
Set the total/target value for progress tracking.
#### `increment` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1099" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `increment` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1153" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
increment(self, amount: int = 1) -> None
@ -462,7 +478,7 @@ increment(self, amount: int = 1) -> None
Atomically increment the current progress value.
#### `set_message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1103" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1157" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_message(self, message: str | None) -> None
@ -471,7 +487,7 @@ set_message(self, message: str | None) -> None
Update the progress status message.
### `InMemoryProgress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1108" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `InMemoryProgress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1162" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
In-memory progress tracker for immediate tool execution.
@ -483,25 +499,25 @@ progress doesn't need to be observable across processes.
**Methods:**
#### `current` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1128" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `current` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1182" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
current(self) -> int | None
```
#### `total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1132" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1186" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
total(self) -> int
```
#### `message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1136" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1190" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
message(self) -> str | None
```
#### `set_total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1139" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1193" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_total(self, total: int) -> None
@ -510,7 +526,7 @@ set_total(self, total: int) -> None
Set the total/target value for progress tracking.
#### `increment` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1145" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `increment` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1199" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
increment(self, amount: int = 1) -> None
@ -519,7 +535,7 @@ increment(self, amount: int = 1) -> None
Atomically increment the current progress value.
#### `set_message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1208" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_message(self, message: str | None) -> None
@ -528,7 +544,7 @@ set_message(self, message: str | None) -> None
Update the progress status message.
### `Progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1159" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Progress` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1213" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
FastMCP Progress dependency that works in both server and worker contexts.
@ -542,3 +558,59 @@ This allows tools to use Progress() regardless of whether they're called
immediately or as background tasks, and regardless of whether pydocket
is installed.
**Methods:**
#### `current` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1250" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
current(self) -> int | None
```
Current progress value.
#### `total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1256" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
total(self) -> int
```
Total/target progress value.
#### `message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1262" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
message(self) -> str | None
```
Current progress message.
#### `set_total` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1267" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_total(self, total: int) -> None
```
Set the total/target value for progress tracking.
#### `increment` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1272" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
increment(self, amount: int = 1) -> None
```
Atomically increment the current progress value.
#### `set_message` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/dependencies.py#L1277" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_message(self, message: str | None) -> None
```
Update the progress status message.

View file

@ -61,7 +61,7 @@ on_list_tools(self, context: MiddlewareContext[mt.ListToolsRequest], call_next:
Filter tools/list response based on auth checks.
#### `on_call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L110" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L113" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_call_tool(self, context: MiddlewareContext[mt.CallToolRequestParams], call_next: CallNext[mt.CallToolRequestParams, ToolResult]) -> ToolResult
@ -70,7 +70,7 @@ on_call_tool(self, context: MiddlewareContext[mt.CallToolRequestParams], call_ne
Check auth before tool execution.
#### `on_list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L153" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L156" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_list_resources(self, context: MiddlewareContext[mt.ListResourcesRequest], call_next: CallNext[mt.ListResourcesRequest, Sequence[Resource]]) -> Sequence[Resource]
@ -79,7 +79,7 @@ on_list_resources(self, context: MiddlewareContext[mt.ListResourcesRequest], cal
Filter resources/list response based on auth checks.
#### `on_read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L177" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L183" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_read_resource(self, context: MiddlewareContext[mt.ReadResourceRequestParams], call_next: CallNext[mt.ReadResourceRequestParams, ResourceResult]) -> ResourceResult
@ -88,7 +88,7 @@ on_read_resource(self, context: MiddlewareContext[mt.ReadResourceRequestParams],
Check auth before resource read.
#### `on_list_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L220" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_list_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L226" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_list_resource_templates(self, context: MiddlewareContext[mt.ListResourceTemplatesRequest], call_next: CallNext[mt.ListResourceTemplatesRequest, Sequence[ResourceTemplate]]) -> Sequence[ResourceTemplate]
@ -97,7 +97,7 @@ on_list_resource_templates(self, context: MiddlewareContext[mt.ListResourceTempl
Filter resource templates/list response based on auth checks.
#### `on_list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L246" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_list_prompts(self, context: MiddlewareContext[mt.ListPromptsRequest], call_next: CallNext[mt.ListPromptsRequest, Sequence[Prompt]]) -> Sequence[Prompt]
@ -106,7 +106,7 @@ on_list_prompts(self, context: MiddlewareContext[mt.ListPromptsRequest], call_ne
Filter prompts/list response based on auth checks.
#### `on_get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L270" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/middleware/authorization.py#L282" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_get_prompt(self, context: MiddlewareContext[mt.GetPromptRequestParams], call_next: CallNext[mt.GetPromptRequestParams, PromptResult]) -> PromptResult

View file

@ -10,7 +10,7 @@ Lifespan and Docket task infrastructure for FastMCP Server.
## Classes
### `LifespanMixin` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/mixins/lifespan.py#L22" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `LifespanMixin` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/mixins/lifespan.py#L24" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Mixin providing lifespan and Docket task infrastructure for FastMCP.
@ -18,7 +18,7 @@ Mixin providing lifespan and Docket task infrastructure for FastMCP.
**Methods:**
#### `docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/mixins/lifespan.py#L26" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/mixins/lifespan.py#L28" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
docket(self: FastMCP) -> Docket | None

View file

@ -14,7 +14,7 @@ registration functionality to LocalProvider.
## Classes
### `ToolDecoratorMixin` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L34" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ToolDecoratorMixin` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L146" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Mixin class providing tool decorator functionality for LocalProvider.
@ -26,7 +26,7 @@ This mixin contains all methods related to:
**Methods:**
#### `add_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L42" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_tool(self: LocalProvider, tool: Tool | Callable[..., Any]) -> Tool
@ -37,19 +37,19 @@ Add a tool to this provider's storage.
Accepts either a Tool object or a decorated function with __fastmcp__ metadata.
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L93" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L206" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self: LocalProvider, name_or_fn: F) -> F
```
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L115" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L228" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self: LocalProvider, name_or_fn: str | None = None) -> Callable[[F], F]
```
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L140" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/local_provider/decorators/tools.py#L253" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self: LocalProvider, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool]

View file

@ -27,7 +27,7 @@ run(self, arguments: dict[str, Any]) -> ToolResult
Execute the HTTP request using RequestDirector.
### `OpenAPIResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L233" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `OpenAPIResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L235" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Resource implementation for OpenAPI endpoints.
@ -35,7 +35,7 @@ Resource implementation for OpenAPI endpoints.
**Methods:**
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L263" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L265" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult
@ -44,7 +44,7 @@ read(self) -> ResourceResult
Fetch the resource data by making an HTTP request.
### `OpenAPIResourceTemplate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L347" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `OpenAPIResourceTemplate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L349" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Resource template implementation for OpenAPI endpoints.
@ -52,7 +52,7 @@ Resource template implementation for OpenAPI endpoints.
**Methods:**
#### `create_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L379" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `create_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/openapi/components.py#L381" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_resource(self, uri: str, params: dict[str, Any], context: Context | None = None) -> Resource

View file

@ -15,7 +15,7 @@ classes that forward execution to remote servers.
## Functions
### `default_proxy_roots_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L720" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_proxy_roots_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L723" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_proxy_roots_handler(context: RequestContext[ClientSession, LifespanContextT]) -> RootsList
@ -25,7 +25,7 @@ default_proxy_roots_handler(context: RequestContext[ClientSession, LifespanConte
Forward list roots request from remote server to proxy's connected clients.
### `default_proxy_sampling_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L728" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_proxy_sampling_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L731" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_proxy_sampling_handler(messages: list[mcp.types.SamplingMessage], params: mcp.types.CreateMessageRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> mcp.types.CreateMessageResult
@ -35,7 +35,7 @@ default_proxy_sampling_handler(messages: list[mcp.types.SamplingMessage], params
Forward sampling request from remote server to proxy's connected clients.
### `default_proxy_elicitation_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L751" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_proxy_elicitation_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L754" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_proxy_elicitation_handler(message: str, response_type: type, params: mcp.types.ElicitRequestParams, context: RequestContext[ClientSession, LifespanContextT]) -> ElicitResult
@ -45,7 +45,7 @@ default_proxy_elicitation_handler(message: str, response_type: type, params: mcp
Forward elicitation request from remote server to proxy's connected clients.
### `default_proxy_log_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L773" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_proxy_log_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L776" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_proxy_log_handler(message: LogMessage) -> None
@ -55,7 +55,7 @@ default_proxy_log_handler(message: LogMessage) -> None
Forward log notification from remote server to proxy's connected clients.
### `default_proxy_progress_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L781" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_proxy_progress_handler` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L784" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_proxy_progress_handler(progress: float, total: float | None, message: str | None) -> None
@ -102,13 +102,13 @@ run(self, arguments: dict[str, Any], context: Context | None = None) -> ToolResu
Executes the tool by making a call through the client.
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L163" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L166" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_span_attributes(self) -> dict[str, Any]
```
### `ProxyResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProxyResource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L173" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A Resource that represents and reads a resource from a remote server.
@ -116,7 +116,7 @@ A Resource that represents and reads a resource from a remote server.
**Methods:**
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L195" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L198" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
model_copy(self, **kwargs: Any) -> ProxyResource
@ -125,7 +125,7 @@ model_copy(self, **kwargs: Any) -> ProxyResource
Override to preserve _backend_uri when uri changes.
#### `from_mcp_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L205" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_mcp_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L208" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_mcp_resource(cls, client_factory: ClientFactoryT, mcp_resource: mcp.types.Resource) -> ProxyResource
@ -134,7 +134,7 @@ from_mcp_resource(cls, client_factory: ClientFactoryT, mcp_resource: mcp.types.R
Factory method to create a ProxyResource from a raw MCP resource schema.
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L225" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L228" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read(self) -> ResourceResult
@ -143,13 +143,13 @@ read(self) -> ResourceResult
Read the resource content from the remote server.
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L270" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L273" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_span_attributes(self) -> dict[str, Any]
```
### `ProxyTemplate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L277" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProxyTemplate` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L280" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A ResourceTemplate that represents and creates resources from a remote server template.
@ -157,7 +157,7 @@ A ResourceTemplate that represents and creates resources from a remote server te
**Methods:**
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L294" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L297" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
model_copy(self, **kwargs: Any) -> ProxyTemplate
@ -166,7 +166,7 @@ model_copy(self, **kwargs: Any) -> ProxyTemplate
Override to preserve _backend_uri_template when uri_template changes.
#### `from_mcp_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L304" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_mcp_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L307" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_mcp_template(cls, client_factory: ClientFactoryT, mcp_template: mcp.types.ResourceTemplate) -> ProxyTemplate
@ -175,7 +175,7 @@ from_mcp_template(cls, client_factory: ClientFactoryT, mcp_template: mcp.types.R
Factory method to create a ProxyTemplate from a raw MCP template schema.
#### `create_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L323" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `create_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L326" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_resource(self, uri: str, params: dict[str, Any], context: Context | None = None) -> ProxyResource
@ -184,13 +184,13 @@ create_resource(self, uri: str, params: dict[str, Any], context: Context | None
Create a resource from the template by calling the remote server.
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L385" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L388" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_span_attributes(self) -> dict[str, Any]
```
### `ProxyPrompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L392" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProxyPrompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L395" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A Prompt that represents and renders a prompt from a remote server.
@ -198,7 +198,7 @@ A Prompt that represents and renders a prompt from a remote server.
**Methods:**
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L409" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `model_copy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L412" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
model_copy(self, **kwargs: Any) -> ProxyPrompt
@ -207,7 +207,7 @@ model_copy(self, **kwargs: Any) -> ProxyPrompt
Override to preserve _backend_name when name changes.
#### `from_mcp_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L419" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_mcp_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L422" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_mcp_prompt(cls, client_factory: ClientFactoryT, mcp_prompt: mcp.types.Prompt) -> ProxyPrompt
@ -216,7 +216,7 @@ from_mcp_prompt(cls, client_factory: ClientFactoryT, mcp_prompt: mcp.types.Promp
Factory method to create a ProxyPrompt from a raw MCP prompt schema.
#### `render` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L443" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L446" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render(self, arguments: dict[str, Any]) -> PromptResult
@ -225,13 +225,13 @@ render(self, arguments: dict[str, Any]) -> PromptResult
Render the prompt by making a call through the client.
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L465" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L468" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_span_attributes(self) -> dict[str, Any]
```
### `ProxyProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L477" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProxyProvider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L480" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Provider that proxies to a remote MCP server via a client factory.
@ -245,7 +245,7 @@ because tasks cannot be executed through a proxy.
**Methods:**
#### `get_tasks` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L602" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tasks` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L605" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@ -258,7 +258,7 @@ server lifespan initialization, which would open the client before any
context is set. All Proxy* components have task_config.mode="forbidden".
### `FastMCPProxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L673" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `FastMCPProxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L676" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A FastMCP server that acts as a proxy to a remote MCP-compliant server.
@ -267,7 +267,7 @@ This is a convenience wrapper that creates a FastMCP server with a
ProxyProvider. For more control, use FastMCP with add_provider(ProxyProvider(...)).
### `ProxyClient` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L829" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ProxyClient` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L848" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A proxy client that forwards advanced interactions between a remote MCP server and the proxy's connected clients.
@ -275,7 +275,7 @@ A proxy client that forwards advanced interactions between a remote MCP server a
Supports forwarding roots, sampling, elicitation, logging, and progress.
### `StatefulProxyClient` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L862" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `StatefulProxyClient` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L881" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
A proxy client that provides a stateful client factory for the proxy server.
@ -296,7 +296,7 @@ it to detect (and correct) staleness.
**Methods:**
#### `clear` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L912" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `clear` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L932" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
clear(self)
@ -305,7 +305,7 @@ clear(self)
Clear all cached clients and force disconnect them.
#### `new_stateful` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L918" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `new_stateful` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/providers/proxy.py#L938" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
new_stateful(self) -> Client[ClientTransportT]

View file

@ -10,7 +10,7 @@ FastMCP - A more ergonomic interface for MCP servers.
## Functions
### `default_lifespan` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L169" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_lifespan` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIterator[Any]
@ -26,7 +26,7 @@ Default lifespan context manager that does nothing.
- An empty dictionary as the lifespan result.
### `create_proxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2079" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_proxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2084" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_proxy(target: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy
@ -54,53 +54,53 @@ use `FastMCPProxy` or `ProxyProvider` directly from `fastmcp.server.providers.pr
## Classes
### `StateValue` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L205" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `StateValue` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L206" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Wrapper for stored context state values.
### `FastMCP` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L211" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `FastMCP` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L212" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
**Methods:**
#### `name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L348" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L353" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
name(self) -> str
```
#### `instructions` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L352" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `instructions` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L357" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
instructions(self) -> str | None
```
#### `instructions` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L356" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `instructions` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L361" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
instructions(self, value: str | None) -> None
```
#### `version` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L360" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `version` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L365" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
version(self) -> str | None
```
#### `website_url` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L364" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `website_url` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L369" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
website_url(self) -> str | None
```
#### `icons` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L368" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `icons` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L373" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
icons(self) -> list[mcp.types.Icon]
```
#### `local_provider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L375" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `local_provider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L380" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
local_provider(self) -> LocalProvider
@ -115,13 +115,13 @@ Use this to remove components:
mcp.local_provider.remove_prompt("my_prompt")
#### `add_middleware` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L397" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_middleware` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L402" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_middleware(self, middleware: Middleware) -> None
```
#### `add_provider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L400" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_provider` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L405" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_provider(self, provider: Provider) -> None
@ -141,7 +141,7 @@ always take precedence over providers.
- Prompts become "namespace_promptname"
#### `get_tasks` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L422" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tasks` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L427" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tasks(self) -> Sequence[FastMCPComponent]
@ -153,7 +153,7 @@ Overrides AggregateProvider.get_tasks() to apply server-level transforms
after aggregation. AggregateProvider handles provider-level namespacing.
#### `add_transform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L451" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_transform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L456" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_transform(self, transform: Transform) -> None
@ -168,7 +168,7 @@ They transform tools, resources, and prompts from ALL providers.
- `transform`: The transform to add.
#### `add_tool_transformation` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L471" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_tool_transformation` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L476" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_tool_transformation(self, tool_name: str, transformation: ToolTransformConfig) -> None
@ -180,7 +180,7 @@ Add a tool transformation.
Use ``add_transform(ToolTransform({...}))`` instead.
#### `remove_tool_transformation` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L488" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `remove_tool_transformation` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L493" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
remove_tool_transformation(self, _tool_name: str) -> None
@ -192,7 +192,7 @@ Remove a tool transformation.
Tool transformations are now immutable. Use enable/disable controls instead.
#### `list_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L503" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L508" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_tools(self) -> Sequence[Tool]
@ -205,7 +205,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L573" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L578" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tool(self, name: str, version: VersionSpec | None = None) -> Tool | None
@ -225,7 +225,7 @@ session transforms can override provider-level disables.
- The tool if found and enabled, None otherwise.
#### `list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L599" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L604" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources(self) -> Sequence[Resource]
@ -238,7 +238,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L671" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L676" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource(self, uri: str, version: VersionSpec | None = None) -> Resource | None
@ -257,7 +257,7 @@ transforms (including session-level) have been applied.
- The resource if found and enabled, None otherwise.
#### `list_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L696" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L701" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resource_templates(self) -> Sequence[ResourceTemplate]
@ -270,7 +270,7 @@ auth filtering, and middleware execution. Returns all versions (no deduplication
Protocol handlers deduplicate for MCP wire format.
#### `get_resource_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L770" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_resource_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L775" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource_template(self, uri: str, version: VersionSpec | None = None) -> ResourceTemplate | None
@ -289,7 +289,7 @@ all transforms (including session-level) have been applied.
- The template if found and enabled, None otherwise.
#### `list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L795" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L800" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts(self) -> Sequence[Prompt]
@ -302,7 +302,7 @@ and middleware execution. Returns all versions (no deduplication).
Protocol handlers deduplicate for MCP wire format.
#### `get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L865" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L870" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt(self, name: str, version: VersionSpec | None = None) -> Prompt | None
@ -321,19 +321,19 @@ transforms (including session-level) have been applied.
- The prompt if found and enabled, None otherwise.
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L891" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L896" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult
```
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L902" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L907" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult
```
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L912" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L917" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None) -> ToolResult | mcp.types.CreateTaskResult
@ -363,19 +363,19 @@ return ToolResult.
- `ValidationError`: If arguments fail validation
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1008" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1013" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> ResourceResult
```
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1018" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1023" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> mcp.types.CreateTaskResult
```
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1027" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1032" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: str) -> ResourceResult | mcp.types.CreateTaskResult
@ -404,19 +404,19 @@ return ResourceResult.
- `ResourceError`: If resource read fails
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1161" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1166" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult
```
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1172" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1177" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.CreateTaskResult
```
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1182" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `render_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1187" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
render_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> PromptResult | mcp.types.CreateTaskResult
@ -446,7 +446,7 @@ return PromptResult.
- `PromptError`: If prompt rendering fails
#### `add_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1258" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1263" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_tool(self, tool: Tool | Callable[..., Any]) -> Tool
@ -464,7 +464,7 @@ with the Context type annotation. See the @tool decorator for examples.
- The tool instance that was added to the server.
#### `remove_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1272" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `remove_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1277" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
remove_tool(self, name: str, version: str | None = None) -> None
@ -483,19 +483,19 @@ Remove tool(s) from the server.
- `NotFoundError`: If no matching tool is found.
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1302" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1307" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: F) -> F
```
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1323" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1328" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: str | None = None) -> Callable[[F], F]
```
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1343" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1348" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionTool] | FunctionTool | partial[Callable[[AnyFunction], FunctionTool] | FunctionTool]
@ -551,7 +551,7 @@ server.tool(my_function, name="custom_name")
```
#### `add_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1442" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1447" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_resource(self, resource: Resource | Callable[..., Any]) -> Resource | ResourceTemplate
@ -566,7 +566,7 @@ Add a resource to the server.
- The resource instance that was added to the server.
#### `add_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1455" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_template` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1460" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_template(self, template: ResourceTemplate) -> ResourceTemplate
@ -581,7 +581,7 @@ Add a resource template to the server.
- The template instance that was added to the server.
#### `resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1466" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `resource` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1471" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
resource(self, uri: str) -> Callable[[F], F]
@ -640,7 +640,7 @@ async def get_weather(city: str) -> str:
```
#### `add_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1585" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1590" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_prompt(self, prompt: Prompt | Callable[..., Any]) -> Prompt
@ -655,19 +655,19 @@ Add a prompt to the server.
- The prompt instance that was added to the server.
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1597" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1602" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: F) -> F
```
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1613" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1618" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: str | None = None) -> Callable[[F], F]
```
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1628" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prompt` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1633" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prompt(self, name_or_fn: str | AnyFunction | None = None) -> Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt | partial[Callable[[AnyFunction], FunctionPrompt] | FunctionPrompt]
@ -744,7 +744,7 @@ Decorator to register a prompt.
```
#### `mount` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1728" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `mount` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1733" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
mount(self, server: FastMCP[LifespanResultT], namespace: str | None = None, as_proxy: bool | None = None, tool_names: dict[str, str] | None = None, prefix: str | None = None) -> None
@ -791,7 +791,7 @@ mounted server.
- `prefix`: Deprecated. Use namespace instead.
#### `import_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1822" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `import_server` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1827" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
import_server(self, server: FastMCP[LifespanResultT], prefix: str | None = None) -> None
@ -832,7 +832,7 @@ templates, and prompts are imported with their original names.
objects are imported with their original names.
#### `from_openapi` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1922" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_openapi` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1927" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_openapi(cls, openapi_spec: dict[str, Any], client: httpx.AsyncClient | None = None, name: str = 'OpenAPI Server', route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, tags: set[str] | None = None, validate_output: bool = True, **settings: Any) -> Self
@ -861,7 +861,7 @@ response structure while still returning structured JSON.
- A FastMCP server with an OpenAPIProvider attached.
#### `from_fastapi` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1973" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_fastapi` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L1978" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_fastapi(cls, app: Any, name: str | None = None, route_maps: list[RouteMap] | None = None, route_map_fn: OpenAPIRouteMapFn | None = None, mcp_component_fn: OpenAPIComponentFn | None = None, mcp_names: dict[str, str] | None = None, httpx_client_kwargs: dict[str, Any] | None = None, tags: set[str] | None = None, **settings: Any) -> Self
@ -885,7 +885,7 @@ Use this to configure timeout and other client settings.
- A FastMCP server with an OpenAPIProvider attached.
#### `as_proxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2028" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `as_proxy` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2033" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
as_proxy(cls, backend: Client[ClientTransportT] | ClientTransport | FastMCP[Any] | FastMCP1Server | AnyUrl | Path | MCPConfig | dict[str, Any] | str, **settings: Any) -> FastMCPProxy
@ -903,7 +903,7 @@ instance or any value accepted as the `transport` argument of
`fastmcp.client.Client` constructor.
#### `generate_name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2065" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `generate_name` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/server.py#L2070" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate_name(cls, name: str | None = None) -> str

View file

@ -16,7 +16,7 @@ This module requires fastmcp[tasks] (pydocket). It is only imported when docket
## Functions
### `subscribe_to_task_updates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/tasks/subscriptions.py#L30" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `subscribe_to_task_updates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/tasks/subscriptions.py#L31" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
subscribe_to_task_updates(task_id: str, task_key: str, session: ServerSession, docket: Docket, poll_interval_ms: int = 5000) -> None

View file

@ -0,0 +1,220 @@
---
title: catalog
sidebarTitle: catalog
---
# `fastmcp.server.transforms.catalog`
Base class for transforms that need to read the real component catalog.
Some transforms replace ``list_tools()`` output with synthetic components
(e.g. a search interface) while still needing access to the *real*
(auth-filtered) catalog at call time. ``CatalogTransform`` provides the
bypass machinery so subclasses can call ``get_tool_catalog()`` without
triggering their own replacement logic.
Re-entrancy problem
-------------------
When a synthetic tool handler calls ``get_tool_catalog()``, that calls
``ctx.fastmcp.list_tools()`` which re-enters the transform pipeline —
including *this* transform's ``list_tools()``. If the subclass overrides
``list_tools()`` directly, the re-entrant call would hit the subclass's
replacement logic again (returning synthetic tools instead of the real
catalog). A ``super()`` call can't prevent this because Python can't
short-circuit a method after ``super()`` returns.
Solution: ``CatalogTransform`` owns ``list_tools()`` and uses a
per-instance ``ContextVar`` to detect re-entrant calls. During bypass,
it passes through to the base ``Transform.list_tools()`` (a no-op).
Otherwise, it delegates to ``transform_tools()`` — the subclass hook
where replacement logic lives. Same pattern for resources, prompts,
and resource templates.
This is *not* the same as the ``Provider._list_tools()`` convention
(which produces raw components with no arguments). ``transform_tools()``
receives the current catalog and returns a transformed version. The
distinct name avoids confusion between the two patterns.
Usage::
class MyTransform(CatalogTransform):
async def transform_tools(self, tools):
return [self._make_search_tool()]
def _make_search_tool(self):
async def search(ctx: Context = None):
real_tools = await self.get_tool_catalog(ctx)
...
return Tool.from_function(fn=search, name="search")
## Classes
### `CatalogTransform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L64" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Transform that needs access to the real component catalog.
Subclasses override ``transform_tools()`` / ``transform_resources()``
/ ``transform_prompts()`` / ``transform_resource_templates()``
instead of the ``list_*()`` methods. The base class owns
``list_*()`` and handles re-entrant bypass automatically — subclasses
never see re-entrant calls from ``get_*_catalog()``.
The ``get_*_catalog()`` methods fetch the real (auth-filtered) catalog
by temporarily setting a bypass flag so that this transform's
``list_*()`` passes through without calling the subclass hook.
**Methods:**
#### `list_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L88" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]
```
#### `list_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L93" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources(self, resources: Sequence[Resource]) -> Sequence[Resource]
```
#### `list_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L98" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resource_templates(self, templates: Sequence[ResourceTemplate]) -> Sequence[ResourceTemplate]
```
#### `list_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L105" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Prompt]
```
#### `transform_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L114" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]
```
Transform the tool catalog.
Override this method to replace, filter, or augment the tool listing.
The default implementation passes through unchanged.
Do NOT override ``list_tools()`` directly — the base class uses it
to handle re-entrant bypass when ``get_tool_catalog()`` reads the
real catalog.
#### `transform_resources` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_resources(self, resources: Sequence[Resource]) -> Sequence[Resource]
```
Transform the resource catalog.
Override this method to replace, filter, or augment the resource listing.
The default implementation passes through unchanged.
Do NOT override ``list_resources()`` directly — the base class uses it
to handle re-entrant bypass when ``get_resource_catalog()`` reads the
real catalog.
#### `transform_resource_templates` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L140" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_resource_templates(self, templates: Sequence[ResourceTemplate]) -> Sequence[ResourceTemplate]
```
Transform the resource template catalog.
Override this method to replace, filter, or augment the template listing.
The default implementation passes through unchanged.
Do NOT override ``list_resource_templates()`` directly — the base class
uses it to handle re-entrant bypass when
``get_resource_template_catalog()`` reads the real catalog.
#### `transform_prompts` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_prompts(self, prompts: Sequence[Prompt]) -> Sequence[Prompt]
```
Transform the prompt catalog.
Override this method to replace, filter, or augment the prompt listing.
The default implementation passes through unchanged.
Do NOT override ``list_prompts()`` directly — the base class uses it
to handle re-entrant bypass when ``get_prompt_catalog()`` reads the
real catalog.
#### `get_tool_catalog` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tool_catalog(self, ctx: Context) -> Sequence[Tool]
```
Fetch the real tool catalog, bypassing this transform.
**Args:**
- `ctx`: The current request context.
- `run_middleware`: Whether to run middleware on the inner call.
Defaults to True because this is typically called from a
tool handler where list_tools middleware has not yet run.
#### `get_resource_catalog` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L187" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource_catalog(self, ctx: Context) -> Sequence[Resource]
```
Fetch the real resource catalog, bypassing this transform.
**Args:**
- `ctx`: The current request context.
- `run_middleware`: Whether to run middleware on the inner call.
Defaults to True because this is typically called from a
tool handler where list_resources middleware has not yet run.
#### `get_prompt_catalog` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L204" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt_catalog(self, ctx: Context) -> Sequence[Prompt]
```
Fetch the real prompt catalog, bypassing this transform.
**Args:**
- `ctx`: The current request context.
- `run_middleware`: Whether to run middleware on the inner call.
Defaults to True because this is typically called from a
tool handler where list_prompts middleware has not yet run.
#### `get_resource_template_catalog` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/catalog.py#L221" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_resource_template_catalog(self, ctx: Context) -> Sequence[ResourceTemplate]
```
Fetch the real resource template catalog, bypassing this transform.
**Args:**
- `ctx`: The current request context.
- `run_middleware`: Whether to run middleware on the inner call.
Defaults to True because this is typically called from a
tool handler where list_resource_templates middleware has
not yet run.

View file

@ -0,0 +1,23 @@
---
title: __init__
sidebarTitle: __init__
---
# `fastmcp.server.transforms.search`
Search transforms for tool discovery.
Search transforms collapse a large tool catalog into a search interface,
letting LLMs discover tools on demand instead of seeing the full list.
Example:
```python
from fastmcp import FastMCP
from fastmcp.server.transforms.search import RegexSearchTransform
mcp = FastMCP("Server")
mcp.add_transform(RegexSearchTransform())
# list_tools now returns only search_tools + call_tool
```

View file

@ -0,0 +1,105 @@
---
title: base
sidebarTitle: base
---
# `fastmcp.server.transforms.search.base`
Base class for search transforms.
Search transforms replace ``list_tools()`` output with a small set of
synthetic tools — a search tool and a call-tool proxy — so LLMs can
discover tools on demand instead of receiving the full catalog.
All concrete search transforms (``RegexSearchTransform``,
``BM25SearchTransform``, etc.) inherit from ``BaseSearchTransform`` and
implement ``_make_search_tool()`` and ``_search()`` to provide their
specific search strategy.
Example::
from fastmcp import FastMCP
from fastmcp.server.transforms.search import RegexSearchTransform
mcp = FastMCP("Server")
@mcp.tool
def add(a: int, b: int) -> int: ...
@mcp.tool
def multiply(x: float, y: float) -> float: ...
# Clients now see only ``search_tools`` and ``call_tool``.
# The original tools are discoverable via search.
mcp.add_transform(RegexSearchTransform())
## Functions
### `serialize_tools_for_output_json` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/base.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
serialize_tools_for_output_json(tools: Sequence[Tool]) -> list[dict[str, Any]]
```
Serialize tools to the same dict format as ``list_tools`` output.
### `serialize_tools_for_output_markdown` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/base.py#L138" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
serialize_tools_for_output_markdown(tools: Sequence[Tool]) -> str
```
Serialize tools to compact markdown, using ~65-70% fewer tokens than JSON.
## Classes
### `BaseSearchTransform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/base.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Replace the tool listing with a search interface.
When this transform is active, ``list_tools()`` returns only:
* Any tools listed in ``always_visible`` (pinned).
* A **search tool** that finds tools matching a query.
* A **call_tool** proxy that executes tools discovered via search.
Hidden tools remain callable — ``get_tool()`` delegates unknown
names downstream, so direct calls and the call-tool proxy both work.
Search results respect the full auth pipeline: middleware, visibility
transforms, and component-level auth checks all apply.
**Args:**
- `max_results`: Maximum number of tools returned per search.
- `always_visible`: Tool names that stay in the ``list_tools``
output alongside the synthetic search/call tools.
- `search_tool_name`: Name of the generated search tool.
- `call_tool_name`: Name of the generated call-tool proxy.
**Methods:**
#### `transform_tools` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/base.py#L199" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
transform_tools(self, tools: Sequence[Tool]) -> Sequence[Tool]
```
Replace the catalog with pinned + synthetic search/call tools.
#### `get_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/base.py#L204" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tool(self, name: str, call_next: GetToolNext) -> Tool | None
```
Intercept synthetic tool names; delegate everything else.

View file

@ -0,0 +1,20 @@
---
title: bm25
sidebarTitle: bm25
---
# `fastmcp.server.transforms.search.bm25`
BM25-based search transform.
## Classes
### `BM25SearchTransform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/bm25.py#L86" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Search transform using BM25 Okapi relevance ranking.
Maintains an in-memory index that is lazily rebuilt when the tool
catalog changes (detected via a hash of tool names).

View file

@ -0,0 +1,20 @@
---
title: regex
sidebarTitle: regex
---
# `fastmcp.server.transforms.search.regex`
Regex-based search transform.
## Classes
### `RegexSearchTransform` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/server/transforms/search/regex.py#L15" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Search transform using regex pattern matching.
Tools are matched against their name, description, and parameter
information using ``re.search`` with ``re.IGNORECASE``.

View file

@ -10,11 +10,11 @@ Function introspection and schema generation for FastMCP tools.
## Classes
### `ParsedFunction` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_parsing.py#L62" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ParsedFunction` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_parsing.py#L82" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
**Methods:**
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_parsing.py#L70" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_parsing.py#L91" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_function(cls, fn: Callable[..., Any], exclude_args: list[str] | None = None, validate: bool = True, wrap_non_object_output_schema: bool = True) -> ParsedFunction

View file

@ -10,7 +10,7 @@ Standalone @tool decorator for FastMCP.
## Functions
### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L371" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L375" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
tool(name_or_fn: str | Callable[..., Any] | None = None) -> Any
@ -25,23 +25,23 @@ using mcp.add_tool().
## Classes
### `DecoratedTool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L54" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `DecoratedTool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L56" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Protocol for functions decorated with @tool.
### `ToolMeta` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L63" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ToolMeta` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L65" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Metadata attached to functions by the @tool decorator.
### `FunctionTool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L85" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `FunctionTool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L87" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
**Methods:**
#### `to_mcp_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L88" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `to_mcp_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L91" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
to_mcp_tool(self, **overrides: Any) -> mcp.types.Tool
@ -52,7 +52,7 @@ Convert the FastMCP tool to an MCP tool.
Extends the base implementation to add task execution mode if enabled.
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L107" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L110" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_function(cls, fn: Callable[..., Any]) -> FunctionTool
@ -68,7 +68,7 @@ individual parameters must not be passed.
Cannot be used together with metadata parameter.
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L249" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L253" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(self, arguments: dict[str, Any]) -> ToolResult
@ -77,7 +77,7 @@ run(self, arguments: dict[str, Any]) -> ToolResult
Run the tool with arguments.
#### `register_with_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L294" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `register_with_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L298" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
register_with_docket(self, docket: Docket) -> None
@ -89,7 +89,7 @@ FunctionTool registers the underlying function, which has the user's
Depends parameters for docket to resolve.
#### `add_to_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L304" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_to_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/function_tool.py#L308" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution

View file

@ -7,7 +7,7 @@ sidebarTitle: tool
## Functions
### `default_serializer` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L56" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_serializer` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L64" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_serializer(data: Any) -> str
@ -15,17 +15,17 @@ default_serializer(data: Any) -> str
## Classes
### `ToolResult` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ToolResult` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L68" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
**Methods:**
#### `to_mcp_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L105" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `to_mcp_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L121" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
to_mcp_result(self) -> list[ContentBlock] | tuple[list[ContentBlock], dict[str, Any]] | CallToolResult
```
### `Tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L121" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L137" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Internal tool registration info.
@ -33,7 +33,7 @@ Internal tool registration info.
**Methods:**
#### `to_mcp_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L163" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `to_mcp_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L179" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
to_mcp_tool(self, **overrides: Any) -> MCPTool
@ -42,7 +42,7 @@ to_mcp_tool(self, **overrides: Any) -> MCPTool
Convert the FastMCP tool to an MCP tool.
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L190" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_function` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L206" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_function(cls, fn: Callable[..., Any]) -> FunctionTool
@ -51,7 +51,7 @@ from_function(cls, fn: Callable[..., Any]) -> FunctionTool
Create a Tool from a function.
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L230" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `run` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L246" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(self, arguments: dict[str, Any]) -> ToolResult
@ -66,7 +66,7 @@ implemented by subclasses.
(list of ContentBlocks, dict of structured output).
#### `convert_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L242" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `convert_result` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L258" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
convert_result(self, raw_value: Any) -> ToolResult
@ -78,7 +78,7 @@ Handles ToolResult passthrough and converts raw values using the tool's
attributes (serializer, output_schema) for proper conversion.
#### `register_with_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L334" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `register_with_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L356" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
register_with_docket(self, docket: Docket) -> None
@ -87,7 +87,7 @@ register_with_docket(self, docket: Docket) -> None
Register this tool with docket for background execution.
#### `add_to_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L340" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `add_to_docket` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L362" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
add_to_docket(self, docket: Docket, arguments: dict[str, Any], **kwargs: Any) -> Execution
@ -103,13 +103,13 @@ Schedule this tool for background execution via docket.
- `**kwargs`: Additional kwargs passed to docket.add()
#### `from_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L364" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_tool` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L386" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_tool(cls, tool: Tool | Callable[..., Any]) -> TransformedTool
```
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L412" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_span_attributes` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/tools/tool.py#L434" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_span_attributes(self) -> dict[str, Any]

View file

@ -20,7 +20,7 @@ clean_schema_for_display(schema: JsonSchema | None) -> JsonSchema | None
Clean up a schema dictionary for display by removing internal/complex fields.
### `extract_output_schema_from_responses` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/utilities/openapi/schemas.py#L461" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `extract_output_schema_from_responses` <sup><a href="https://github.com/PrefectHQ/fastmcp/blob/main/src/fastmcp/utilities/openapi/schemas.py#L474" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
extract_output_schema_from_responses(responses: dict[str, ResponseInfo], schema_definitions: dict[str, Any] | None = None, openapi_version: str | None = None) -> dict[str, Any] | None

View file

@ -178,6 +178,40 @@ This example shows the basic structure of a custom OAuth provider. The actual im
→ **Complete guide**: [Full OAuth Server](/servers/auth/full-oauth-server)
### MultiAuth
<VersionBadge version="3.1.0" />
`MultiAuth` composes multiple authentication sources into a single `auth` provider. When a server needs to accept tokens from different issuers — for example, an OAuth proxy for interactive clients alongside JWT verification for machine-to-machine tokens — `MultiAuth` tries each source in order and accepts the first successful verification.
```python
from fastmcp import FastMCP
from fastmcp.server.auth import MultiAuth, OAuthProxy
from fastmcp.server.auth.providers.jwt import JWTVerifier
auth = MultiAuth(
server=OAuthProxy(
issuer_url="https://login.example.com/...",
client_id="my-app",
client_secret="secret",
base_url="https://my-server.com",
),
verifiers=[
JWTVerifier(
jwks_uri="https://internal-issuer.example.com/.well-known/jwks.json",
issuer="https://internal-issuer.example.com",
audience="my-mcp-server",
),
],
)
mcp = FastMCP("My Server", auth=auth)
```
The server (if provided) owns all OAuth routes and metadata. Verifiers contribute only token verification logic. This keeps the MCP discovery surface clean while supporting multiple token sources.
→ **Complete guide**: [Multiple Auth Sources](/servers/auth/multi-auth)
## Configuration
Authentication providers are configured programmatically by instantiating them directly in your code with their required parameters. This makes dependencies explicit and allows your IDE to provide helpful autocompletion and type checking.
@ -211,6 +245,8 @@ The authentication approach you choose depends on your existing infrastructure,
**Token validation works well when you already have authentication infrastructure that issues structured tokens.** If your organization already uses JWT-based systems, API gateways, or enterprise SSO that can generate tokens, this approach integrates seamlessly while keeping your MCP server focused on its core functionality. The simplicity comes from leveraging existing investment in authentication infrastructure.
**When you need tokens from multiple sources, use MultiAuth.** This is common in hybrid architectures where interactive clients authenticate through an OAuth proxy while backend services send JWT tokens directly. `MultiAuth` composes an optional auth server with additional token verifiers, trying each source in order until one succeeds.
**Full OAuth implementation should be avoided unless you have compelling reasons that external providers cannot address.** Air-gapped environments, specialized compliance requirements, or unique organizational constraints might justify this approach, but it requires significant security expertise and ongoing maintenance commitment. The complexity extends far beyond initial implementation to include threat monitoring, security updates, and keeping pace with evolving attack vectors.
FastMCP's architecture supports migration between these approaches as your requirements evolve. You can integrate with existing token systems initially and migrate to external identity providers as your application scales, or implement custom solutions when your requirements outgrow standard patterns.

View file

@ -0,0 +1,95 @@
---
title: Multiple Auth Sources
sidebarTitle: Multiple Auth Sources
description: Accept tokens from multiple authentication sources with a single server.
icon: layer-group
---
import { VersionBadge } from "/snippets/version-badge.mdx"
<VersionBadge version="3.1.0" />
Production servers often need to accept tokens from multiple authentication sources. An interactive application might authenticate through an OAuth proxy, while a backend service sends machine-to-machine JWT tokens directly. `MultiAuth` composes these sources into a single `auth` provider so every valid token is accepted regardless of where it was issued.
## Understanding MultiAuth
`MultiAuth` wraps an optional auth server (like `OAuthProxy`) together with one or more token verifiers (like `JWTVerifier`). When a request arrives with a bearer token, `MultiAuth` tries each source in order and accepts the first successful verification.
The auth server, if provided, is tried first. It owns all OAuth routes and metadata — the verifiers contribute only token verification logic. This keeps the MCP discovery surface clean: one set of routes, one set of metadata, multiple verification paths.
```python
from fastmcp import FastMCP
from fastmcp.server.auth import MultiAuth, OAuthProxy
from fastmcp.server.auth.providers.jwt import JWTVerifier
auth = MultiAuth(
server=OAuthProxy(
issuer_url="https://login.example.com/...",
client_id="my-app",
client_secret="secret",
base_url="https://my-server.com",
),
verifiers=[
JWTVerifier(
jwks_uri="https://internal-issuer.example.com/.well-known/jwks.json",
issuer="https://internal-issuer.example.com",
audience="my-mcp-server",
),
],
)
mcp = FastMCP("My Server", auth=auth)
```
Interactive MCP clients authenticate through the OAuth proxy as usual. Backend services skip OAuth entirely and send a JWT signed by the internal issuer. Both paths are validated, and the first match wins.
## Verification Order
`MultiAuth` checks sources in a deterministic order:
1. **Server** (if provided) — the full auth provider's `verify_token` runs first
2. **Verifiers** — each `TokenVerifier` is tried in list order
The first source that returns a valid `AccessToken` wins. If every source returns `None`, the request receives a 401 response.
This ordering means the server acts as the "primary" authentication path, with verifiers as fallbacks for tokens the server doesn't recognize.
## Verifiers Only
You don't always need a full OAuth server. If your server only needs to accept tokens from multiple issuers, pass verifiers without a server:
```python
from fastmcp import FastMCP
from fastmcp.server.auth import MultiAuth
from fastmcp.server.auth.providers.jwt import JWTVerifier, StaticTokenVerifier
auth = MultiAuth(
verifiers=[
JWTVerifier(
jwks_uri="https://issuer-a.example.com/.well-known/jwks.json",
issuer="https://issuer-a.example.com",
audience="my-server",
),
JWTVerifier(
jwks_uri="https://issuer-b.example.com/.well-known/jwks.json",
issuer="https://issuer-b.example.com",
audience="my-server",
),
],
)
mcp = FastMCP("Multi-Issuer Server", auth=auth)
```
Without a server, no OAuth routes or metadata are served. This is appropriate for internal systems where clients already know how to obtain tokens.
## API Reference
### MultiAuth
| Parameter | Type | Description |
| --- | --- | --- |
| `server` | `AuthProvider \| None` | Optional auth provider that owns routes and OAuth metadata. Also tried first for token verification. |
| `verifiers` | `list[TokenVerifier] \| TokenVerifier` | One or more token verifiers tried after the server. |
| `base_url` | `str \| None` | Override the base URL. Defaults to the server's `base_url`. |
| `required_scopes` | `list[str] \| None` | Override required scopes. Defaults to the server's scopes. |

View file

@ -321,6 +321,81 @@ print(f"Test token: {test_token}")
This pattern enables comprehensive testing of JWT validation logic without depending on external token issuers. The generated tokens are cryptographically valid and will pass all standard JWT validation checks.
## HTTP Client Customization
<VersionBadge version="2.18.0" />
All token verifiers that make HTTP calls accept an optional `http_client` parameter. This lets you provide your own `httpx.AsyncClient` for connection pooling, custom TLS configuration, or proxy settings.
### Connection Pooling
By default, each token verification call creates a fresh HTTP client. Under high load, this means repeated TCP connections and TLS handshakes. Providing a shared client enables connection pooling across calls:
```python
import httpx
from fastmcp import FastMCP
from fastmcp.server.auth.providers.introspection import IntrospectionTokenVerifier
# Create a shared client with connection pooling
http_client = httpx.AsyncClient(
timeout=10,
limits=httpx.Limits(max_connections=20, max_keepalive_connections=10),
)
verifier = IntrospectionTokenVerifier(
introspection_url="https://auth.yourcompany.com/oauth/introspect",
client_id="mcp-resource-server",
client_secret="your-client-secret",
http_client=http_client,
)
mcp = FastMCP(name="Protected API", auth=verifier)
```
The same pattern works for `JWTVerifier` when using JWKS endpoints:
```python
from fastmcp.server.auth.providers.jwt import JWTVerifier
verifier = JWTVerifier(
jwks_uri="https://auth.yourcompany.com/.well-known/jwks.json",
issuer="https://auth.yourcompany.com",
http_client=http_client,
)
```
<Warning>
`JWTVerifier` does not support `http_client` when `ssrf_safe=True`. SSRF-safe mode requires a hardened transport that validates DNS resolution and connection targets, which cannot be guaranteed with a user-provided client. Attempting to use both will raise a `ValueError`.
</Warning>
<Note>
When you provide an `http_client`, you are responsible for its lifecycle. The verifier will not close it. Use the server's `lifespan` to manage client cleanup:
```python
from contextlib import asynccontextmanager
from fastmcp import FastMCP
from fastmcp.server.auth.providers.introspection import IntrospectionTokenVerifier
http_client = httpx.AsyncClient(timeout=10)
verifier = IntrospectionTokenVerifier(
introspection_url="https://auth.example.com/introspect",
client_id="my-service",
client_secret="secret",
http_client=http_client,
)
@asynccontextmanager
async def lifespan(app):
yield
await http_client.aclose()
mcp = FastMCP(name="My API", auth=verifier, lifespan=lifespan)
```
</Note>
The convenience providers (`GitHubProvider`, `GoogleProvider`, `DiscordProvider`, `WorkOSProvider`, `AzureProvider`) also accept `http_client` and pass it through to their internal token verifier.
## Production Configuration
For production deployments, load sensitive configuration from environment variables:

View file

@ -1,7 +1,7 @@
---
title: Mounting Servers
sidebarTitle: Mounting
description: Compose servers by mounting one inside another
title: Composing Servers
sidebarTitle: Composition
description: Combine multiple servers into one
icon: puzzle-piece
---
@ -9,42 +9,29 @@ import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="2.2.0" />
Mounting lets you combine multiple FastMCP servers into one. When you mount a server, all its components become available through the parent. Under the hood, FastMCP uses `FastMCPProvider` (v3.0.0+) to source components from the mounted server.
As your application grows, you'll want to split it into focused servers — one for weather, one for calendar, one for admin — and combine them into a single server that clients connect to. That's what `mount()` does.
## Why Mount Servers
Large applications benefit from modular organization. Rather than defining all components in one massive file, create focused servers for specific domains and combine them:
- **Modularity**: Break down applications into smaller, focused servers
- **Reusability**: Create utility servers and mount them wherever needed
- **Teamwork**: Different teams can work on separate servers
- **Organization**: Keep related functionality grouped together
## Basic Mounting
Use `mount()` to add another server's components to your server:
When you mount a server, all its tools, resources, and prompts become available through the parent. The connection is live: add a tool to the child after mounting, and it's immediately visible through the parent.
```python
from fastmcp import FastMCP
# Create focused subservers
weather_server = FastMCP("Weather")
weather = FastMCP("Weather")
@weather_server.tool
@weather.tool
def get_forecast(city: str) -> str:
"""Get weather forecast for a city."""
return f"Sunny in {city}"
@weather_server.resource("data://cities")
@weather.resource("data://cities")
def list_cities() -> list[str]:
"""List supported cities."""
return ["London", "Paris", "Tokyo"]
# Create main server and mount the subserver
main = FastMCP("MainApp")
main.mount(weather_server)
main.mount(weather)
# Now main has access to get_forecast and data://cities
# main now serves get_forecast and data://cities
```
## Mounting External Servers
@ -156,20 +143,9 @@ main.mount(calendar, namespace="calendar")
Namespacing uses [transforms](/servers/transforms/transforms) under the hood.
## Mounting vs Importing
## Dynamic Composition
FastMCP offers two ways to combine servers:
| Feature | `mount()` | `import_server()` |
|---------|-----------|-------------------|
| **Link Type** | Live (dynamic) | One-time copy (static) |
| **Updates** | Changes reflected immediately | Changes not reflected |
| **Performance** | Runtime delegation | Faster - no delegation |
| **Use Case** | Modular runtime composition | Bundling finalized components |
### Live Mounting
With `mount()`, changes to the subserver are immediately reflected:
Because `mount()` creates a live link, you can add components to a child server after mounting and they'll be immediately available through the parent:
```python
main = FastMCP("Main")
@ -179,53 +155,8 @@ main.mount(dynamic_server, namespace="dynamic")
@dynamic_server.tool
def added_later() -> str:
return "Added after mounting!"
# This works because mount() creates a live link
```
### Static Importing
With `import_server()`, components are copied once at import time:
```python
main = FastMCP("Main")
async def setup():
await main.import_server(static_server, namespace="static")
# Changes to static_server after this point are NOT reflected in main
```
## Direct vs Proxy Mounting
<VersionBadge version="2.2.7" />
FastMCP supports two mounting modes:
### Direct Mounting (Default)
The parent server directly accesses the mounted server's objects in memory:
```python
main.mount(subserver, namespace="api")
```
- No client lifecycle events on mounted server
- Mounted server's lifespan is not executed
- Communication via direct method calls
### Proxy Mounting
<Warning>
The `as_proxy` parameter is deprecated. Mounted servers now always have their lifespan and middleware invoked. To create a proxy server explicitly, use `create_proxy()` from `fastmcp.server`.
</Warning>
Previously, the parent server could treat the mounted server as a separate entity with its own lifecycle. This behavior is now the default for all mounted servers:
- Full client lifecycle events on mounted server
- Mounted server's lifespan is executed
- Communication via in-memory Client transport
## Tag Filtering
<VersionBadge version="3.0.0" />
@ -253,16 +184,13 @@ prod_app.enable(tags={"production"}, only=True)
## Performance Considerations
When using live mounting, operations like `list_tools()` on the parent server are affected by the performance of all mounted servers. This is particularly noticeable with:
Operations like `list_tools()` on the parent are affected by the performance of all mounted servers. This is particularly noticeable with:
- HTTP-based mounted servers (300-400ms vs 1-2ms for local tools)
- Mounted servers with slow initialization
- Deep mounting hierarchies
If low latency is critical, consider:
- Using `import_server()` for static composition
- Implementing caching strategies
- Limiting mounting depth
If low latency is critical, consider implementing caching strategies or limiting mounting depth.
## Custom Routes

View file

@ -10,7 +10,7 @@ import { VersionBadge } from "/snippets/version-badge.mdx";
FastMCP uses dependency injection to provide runtime values to your tools, resources, and prompts. Instead of passing context through every layer of your code, you declare what you need as parameter defaults—FastMCP resolves them automatically when your function runs.
The dependency injection system is powered by [Docket](https://github.com/chrisguidry/docket). Core DI features like `Depends()` and `CurrentContext()` work without installing Docket. For background tasks and advanced task-related dependencies, install `fastmcp[tasks]`. For comprehensive coverage of dependency patterns, see the [Docket dependency documentation](https://chrisguidry.github.io/docket/dependencies/).
The dependency injection system is powered by [Docket](https://github.com/chrisguidry/docket) and its dependency system [uncalled-for](https://github.com/chrisguidry/uncalled-for). Core DI features like `Depends()` and `CurrentContext()` work without installing Docket. For background tasks and advanced task-related dependencies, install `fastmcp[tasks]`. For comprehensive coverage of dependency patterns, see the [Docket dependency documentation](https://docket.lol/en/latest/dependency-injection/).
<Note>
Dependency parameters are automatically excluded from the MCP schema—clients never see them as callable parameters. This separation keeps your function signatures clean while giving you access to the runtime context you need.

View file

@ -64,7 +64,7 @@ This ordering matters. Place error handling early so it catches exceptions from
### Server Composition
When using [mounted servers](/servers/providers/mounting), middleware behavior follows a clear hierarchy:
When using [mounted servers](/servers/composition), middleware behavior follows a clear hierarchy:
- **Parent middleware** runs for all requests, including those routed to mounted servers
- **Mounted server middleware** only runs for requests handled by that specific server

View file

@ -66,7 +66,7 @@ When a client requests a tool, FastMCP queries providers in registration order.
**You can ignore providers entirely** if you're building a simple server with decorators. Just use `@mcp.tool`, `@mcp.resource`, and `@mcp.prompt` - FastMCP handles the rest.
**Learn about providers when** you want to:
- [Mount another server](/servers/providers/mounting) into yours
- [Mount another server](/servers/composition) into yours
- [Proxy a remote server](/servers/providers/proxy) through yours
- [Control visibility state](/servers/visibility) of components
- [Build dynamic sources](/servers/providers/custom) like database-backed tools
@ -74,7 +74,7 @@ When a client requests a tool, FastMCP queries providers in registration order.
## Next Steps
- [Local](/servers/providers/local) - How decorators work
- [Mounting](/servers/providers/mounting) - Compose servers together
- [Mounting](/servers/composition) - Compose servers together
- [Proxying](/servers/providers/proxy) - Connect to remote servers
- [Transforms](/servers/transforms/transforms) - Namespace, rename, and modify components
- [Visibility](/servers/visibility) - Control which components clients can access

View file

@ -54,7 +54,7 @@ This gives you:
- Session isolation to prevent context mixing
<Tip>
To mount a proxy inside another FastMCP server, see [Mounting External Servers](/servers/providers/mounting#mounting-external-servers).
To mount a proxy inside another FastMCP server, see [Mounting External Servers](/servers/composition#mounting-external-servers).
</Tip>
## Transport Bridging
@ -258,7 +258,7 @@ Proxying introduces network latency:
When mounting proxy servers, this latency affects all operations on the parent server.
For low-latency requirements, consider using [`import_server()`](/servers/providers/mounting#static-importing) to copy tools at startup.
For low-latency requirements, consider caching strategies or limiting mounting depth.
## Advanced Usage

View file

@ -332,15 +332,7 @@ notice_resource = TextResource(
)
mcp.add_resource(notice_resource)
# 3. Using a custom key different from the URI
special_resource = TextResource(
uri="resource://common-notice",
name="Special Notice",
text="This is a special notice with a custom storage key.",
)
mcp.add_resource(special_resource, key="resource://custom-key")
# 4. Exposing a directory listing
# 3. Exposing a directory listing
data_dir_path = Path("./app_data").resolve()
if data_dir_path.is_dir():
data_listing_resource = DirectoryResource(
@ -364,24 +356,6 @@ if data_dir_path.is_dir():
Use these when the content is static or sourced directly from a file/URL, bypassing the need for a dedicated Python function.
#### Custom Resource Keys
<VersionBadge version="2.2.0" />
When adding resources directly with `mcp.add_resource()`, you can optionally provide a custom storage key:
```python
# Creating a resource with standard URI as the key
resource = TextResource(uri="resource://data")
mcp.add_resource(resource) # Will be stored and accessed using "resource://data"
# Creating a resource with a custom key
special_resource = TextResource(uri="resource://special-data")
mcp.add_resource(special_resource, key="internal://data-v2") # Will be stored and accessed using "internal://data-v2"
```
Note that this parameter is only available when using `add_resource()` directly and not through the `@resource` decorator, as URIs are provided explicitly when using the decorator.
### Notifications
<VersionBadge version="2.9.1" />

View file

@ -67,25 +67,14 @@ The `FastMCP` constructor accepts several configuration options. The most common
A list of tools (or functions to convert to tools) to add to the server. In some cases, providing tools programmatically may be more convenient than using the `@mcp.tool` decorator
</ParamField>
<ParamField body="transforms" type="list[Transform] | None">
<VersionBadge version="3.1.0" />
<ParamField body="include_tags" type="set[str] | None">
Only expose components with at least one matching tag
Server-level [transforms](/servers/transforms/transforms) to apply to all components. Transforms modify how tools, resources, and prompts are presented to clients — for example, [search transforms](/servers/transforms/tool-search) replace large catalogs with on-demand discovery, and [CodeMode](/servers/transforms/code-mode) lets LLMs write scripts that chain tool calls in a sandbox
</ParamField>
<ParamField body="exclude_tags" type="set[str] | None">
Hide components with any matching tag
</ParamField>
<ParamField body="on_duplicate_tools" type='Literal["error", "warn", "replace"]' default="error">
How to handle duplicate tool registrations
</ParamField>
<ParamField body="on_duplicate_resources" type='Literal["error", "warn", "replace"]' default="warn">
How to handle duplicate resource registrations
</ParamField>
<ParamField body="on_duplicate_prompts" type='Literal["error", "warn", "replace"]' default="replace">
How to handle duplicate prompt registrations
<ParamField body="on_duplicate" type='Literal["warn", "error", "replace", "ignore"]' default="warn">
How to handle duplicate component registrations
</ParamField>
@ -177,25 +166,28 @@ def admin_tool() -> str:
```
The filtering logic works as follows:
- **Include tags**: If specified, only components with at least one matching tag are exposed
- **Exclude tags**: Components with any matching tag are filtered out
- **Precedence**: Exclude tags always take priority over include tags
- **Enable with `only=True`**: Switches to allowlist mode — only components with at least one matching tag are exposed
- **Disable**: Components with any matching tag are hidden
- **Precedence**: Later calls override earlier ones, so call `disable` after `enable` to exclude from an allowlist
<Tip>
To ensure a component is never exposed, you can set `enabled=False` on the component itself. See the component-specific documentation for details.
</Tip>
Configure tag-based filtering when creating your server.
Configure tag-based filtering after creating your server.
```python
# Only expose components tagged with "public"
mcp = FastMCP(include_tags={"public"})
mcp = FastMCP()
mcp.enable(tags={"public"}, only=True)
# Hide components tagged as "internal" or "deprecated"
mcp = FastMCP(exclude_tags={"internal", "deprecated"})
mcp = FastMCP()
mcp.disable(tags={"internal", "deprecated"})
# Combine both: show admin tools but hide deprecated ones
mcp = FastMCP(include_tags={"admin"}, exclude_tags={"deprecated"})
mcp = FastMCP()
mcp.enable(tags={"admin"}, only=True).disable(tags={"deprecated"})
```
This filtering applies to all component types (tools, resources, resource templates, and prompts) and affects both listing and access.

104
docs/servers/testing.mdx Normal file
View file

@ -0,0 +1,104 @@
---
title: Testing your FastMCP Server
sidebarTitle: Testing
description: How to test your FastMCP server.
icon: vial
---
The best way to ensure a reliable and maintainable FastMCP Server is to test it! The FastMCP Client combined with Pytest provides a simple and powerful way to test your FastMCP servers.
## Prerequisites
Testing FastMCP servers requires `pytest-asyncio` to handle async test functions and fixtures. Install it as a development dependency:
```bash
pip install pytest-asyncio
```
We recommend configuring pytest to automatically handle async tests by setting the asyncio mode to `auto` in your `pyproject.toml`:
```toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
```
This eliminates the need to decorate every async test with `@pytest.mark.asyncio`.
## Testing with Pytest Fixtures
Using Pytest Fixtures, you can wrap your FastMCP Server in a Client instance that makes interacting with your server fast and easy. This is especially useful when building your own MCP Servers and enables a tight development loop by allowing you to avoid using a separate tool like MCP Inspector during development:
```python
import pytest
from fastmcp.client import Client
from fastmcp.client.transports import FastMCPTransport
from my_project.main import mcp
@pytest.fixture
async def main_mcp_client():
async with Client(transport=mcp) as mcp_client:
yield mcp_client
async def test_list_tools(main_mcp_client: Client[FastMCPTransport]):
list_tools = await main_mcp_client.list_tools()
assert len(list_tools) == 5
```
We recommend the [inline-snapshot library](https://github.com/15r10nk/inline-snapshot) for asserting complex data structures coming from your MCP Server. This library allows you to write tests that are easy to read and understand, and are also easy to update when the data structure changes.
```python
from inline_snapshot import snapshot
async def test_list_tools(main_mcp_client: Client[FastMCPTransport]):
list_tools = await main_mcp_client.list_tools()
assert list_tools == snapshot()
```
Simply run `pytest --inline-snapshot=fix,create` to fill in the `snapshot()` with actual data.
<Tip>
For values that change you can leverage the [dirty-equals](https://github.com/samuelcolvin/dirty-equals) library to perform flexible equality assertions on dynamic or non-deterministic values.
</Tip>
Using the pytest `parametrize` decorator, you can easily test your tools with a wide variety of inputs.
```python
import pytest
from my_project.main import mcp
from fastmcp.client import Client
from fastmcp.client.transports import FastMCPTransport
@pytest.fixture
async def main_mcp_client():
async with Client(mcp) as client:
yield client
@pytest.mark.parametrize(
"first_number, second_number, expected",
[
(1, 2, 3),
(2, 3, 5),
(3, 4, 7),
],
)
async def test_add(
first_number: int,
second_number: int,
expected: int,
main_mcp_client: Client[FastMCPTransport],
):
result = await main_mcp_client.call_tool(
name="add", arguments={"x": first_number, "y": second_number}
)
assert result.data is not None
assert isinstance(result.data, int)
assert result.data == expected
```
<Tip>
The [FastMCP Repository contains thousands of tests](https://github.com/PrefectHQ/fastmcp/tree/main/tests) for the FastMCP Client and Server. Everything from connecting to remote MCP servers, to testing tools, resources, and prompts is covered, take a look for inspiration!
</Tip>

View file

@ -126,6 +126,12 @@ def search_products_implementation(query: str, category: str | None = None) -> l
Optional version identifier for this tool. See [Versioning](/servers/versioning) for details.
</ParamField>
<ParamField body="output_schema" type="dict[str, Any] | None">
<VersionBadge version="2.10.0" />
Optional JSON schema for the tool's output. When provided, the tool must return structured output matching this schema. If not provided, FastMCP automatically generates a schema from the function's return type annotation. See [Output Schemas](#output-schemas) for details.
</ParamField>
</Card>
### Using with Methods

View file

@ -0,0 +1,339 @@
---
title: Code Mode
sidebarTitle: Code Mode
description: Let LLMs write Python to orchestrate tools in a sandbox
icon: flask
tag: NEW
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.1.0" />
<Warning>
CodeMode is experimental. The core interface is stable, but the specific discovery tools and their parameters may evolve as we learn more about what works best in practice.
</Warning>
Standard MCP tool usage has two scaling problems. First, every tool in the catalog is loaded into the LLM's context upfront — with hundreds of tools, that's tens of thousands of tokens spent before the LLM even reads the user's request. Second, every tool call is a round-trip: the LLM calls a tool, the result passes back through the context window, the LLM reasons about it, calls another tool, and so on. Intermediate results that only exist to feed the next step still burn tokens flowing through the model.
CodeMode solves both problems. Instead of seeing your entire tool catalog, the LLM gets meta-tools for discovering what's available and for writing and executing code that calls the tools it needs. It discovers on demand, writes a script that chains tool calls in a sandbox, and gets back only the final answer.
The approach was introduced by Cloudflare in [Code Mode](https://blog.cloudflare.com/code-mode/) and explored further by Anthropic in [Code Execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp).
## Getting Started
<Tip>
CodeMode requires the `code-mode` extra for sandbox support. Install it with `pip install "fastmcp[code-mode]"`.
</Tip>
You take a normal server with normally registered tools and add a `CodeMode` transform. The transform wraps your existing tools in the code mode machinery — your tool functions don't change at all:
```python
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
mcp = FastMCP("Server", transforms=[CodeMode()])
@mcp.tool
def add(x: int, y: int) -> int:
"""Add two numbers."""
return x + y
@mcp.tool
def multiply(x: int, y: int) -> int:
"""Multiply two numbers."""
return x * y
```
Clients connecting to this server no longer see `add` and `multiply` directly. Instead, they see the meta-tools that CodeMode provides — tools for discovering what's available and executing code against it. The original tools are still there, but they're accessed through the CodeMode layer.
## Discovery
Before the LLM can write code that calls your tools, it needs to know what tools exist and how to call them. This is the **discovery** process — the LLM uses meta-tools to learn about your tool catalog, then writes code against what it finds.
The fundamental tradeoff is **tokens vs. round-trips**. Each discovery step is an LLM round-trip: the model calls a tool, waits for the response, reasons about it, then decides what to do next. More steps mean less wasted context (each step is targeted) but more latency and API calls. Fewer steps mean the LLM gets information upfront but pays for detail it might not need.
By default, CodeMode gives the LLM three tools — `search`, `get_schema`, and `execute` — creating a three-stage discovery flow:
<Steps>
<Step title="Search for tools">
First, the LLM uses the `search` meta-tool to find tools by keyword.
For example, it might do `search(query="math numbers")` and receive the following response:
```
- add: Add two numbers.
- multiply: Multiply two numbers.
```
This lets the LLM know which tools are available and what they do, significantly reducing the surface area it needs to consider.
</Step>
<Step title="Get parameter details for the tools">
Next, the LLM calls `get_schema` to get parameter details for the tools it found in the previous step.
For example, it might do `get_schema(tools=["add", "multiply"])` and receive the following response:
```
### add
Add two numbers.
**Parameters**
- `x` (integer, required)
- `y` (integer, required)
### multiply
Multiply two numbers.
**Parameters**
- `x` (integer, required)
- `y` (integer, required)
```
Now the LLM knows the parameters for the tools it found, and can write code that chains the tool calls. If it needed more detail, it could have called `get_schema` with `detail="full"` to get the complete JSON schema.
</Step>
<Step title="Write and execute code that chains the tool calls">
Finally, the LLM writes and executes code that chains the tool calls in a Python sandbox. Inside the sandbox, `call_tool(name, params)` is the only function available. The LLM uses this to compose tools into a workflow and return a final result.
For example, it might write the following code and call the `execute` tool with it:
```python
a = await call_tool("add", {"x": 3, "y": 4})
b = await call_tool("multiply", {"x": a, "y": 2})
return b
```
The result is returned to the LLM.
</Step>
</Steps>
This three-stage flow works well for most servers — each step pulls in only the information needed for the next one, keeping context usage minimal. But CodeMode's discovery surface is fully configurable. The sections below explain each built-in discovery tool and how to combine them into different patterns.
## Discovery Tools
CodeMode ships with four built-in discovery tools: `Search`, `GetSchemas`, `GetTags`, and `ListTools`. By default, only `Search` and `GetSchemas` are enabled. Each tool supports a `default_detail` parameter that sets the default verbosity level, and the LLM can override the detail level on any individual call.
### Detail Levels
`Search` and `GetSchemas` share the same three detail levels, so the same `detail` value produces the same output format regardless of which tool the LLM calls:
| Level | Output | Token cost |
|---|---|---|
| `"brief"` | Tool names and one-line descriptions | Cheapest — good for scanning |
| `"detailed"` | Compact markdown with parameter names, types, and required markers | Medium — often enough to write code |
| `"full"` | Complete JSON schema | Most expensive — everything |
`Search` defaults to `"brief"` and `GetSchemas` defaults to `"detailed"`.
### Search
`Search` finds tools by natural-language query using BM25 ranking. At its default `"brief"` detail, results include just tool names and descriptions — enough to decide which tools are worth inspecting further. The LLM can request `"detailed"` to get parameter schemas inline, or `"full"` for the complete JSON.
Search results include an annotation like `"2 of 10 tools:"` when the result set is smaller than the full catalog, so the LLM knows there are more tools to discover with different queries.
You can cap result count with `default_limit`. The LLM can also override the limit per call. This is useful for large catalogs where you want to keep search results focused:
```python
Search(default_limit=5) # return at most 5 results per search
```
If your tools use [tags](/servers/tools#tags), Search also accepts a `tags` parameter so the LLM can narrow results to specific categories before searching.
### GetSchemas
`GetSchemas` returns parameter details for specific tools by name. At its default `"detailed"` level, it renders compact markdown with parameter names, types, and required markers. At `"full"`, it returns the complete JSON schema — useful when tools have deeply nested parameters that the compact format doesn't capture.
### GetTags
`GetTags` lets the LLM browse tools by category using [tag](/servers/tools#tags) metadata. At brief detail, the LLM sees tag names with counts. At full detail, it sees tools listed under each tag:
```
- math (3 tools)
- text (2 tools)
- untagged (1 tool)
```
`GetTags` isn't included in the defaults — add it when browsing by category would help the LLM orient itself in a large catalog. The LLM can browse tags first, then pass specific tags into Search to narrow results.
### ListTools
`ListTools` dumps the entire catalog at whatever detail level the LLM requests. It supports the same three detail levels as `Search` and `GetSchemas`, defaulting to `"brief"`.
`ListTools` isn't included in the defaults — for large catalogs, search-based discovery is more token-efficient. But for smaller catalogs (under ~20 tools), letting the LLM see everything upfront can be faster than multiple search round-trips:
```python
from fastmcp.experimental.transforms.code_mode import CodeMode, ListTools, GetSchemas
code_mode = CodeMode(
discovery_tools=[ListTools(), GetSchemas()],
)
```
## Discovery Patterns
The right discovery configuration depends on your server — how many tools you have and how complex their parameters are. It may be tempting to minimize round-trips by collapsing everything into fewer steps, but for the complex servers that benefit most from CodeMode, our experience is that staged discovery leads to better results. Flooding the LLM with detailed schemas for tools it doesn't end up using can hurt more than the extra round-trip costs. Each pattern below is a complete, copyable configuration.
### Three-Stage
The default. The LLM searches for candidates, inspects schemas for the ones it wants, then writes code. Best for **large or complex tool sets** where you want to minimize context usage — the LLM only pays for schemas it actually needs.
```python
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
mcp = FastMCP("Server", transforms=[CodeMode()])
```
If your tools use [tags](/servers/tools#tags), add `GetTags` so the LLM can browse by category before searching — giving it four stages of progressive disclosure:
```python
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
from fastmcp.experimental.transforms.code_mode import GetTags, Search, GetSchemas
code_mode = CodeMode(
discovery_tools=[GetTags(), Search(), GetSchemas()],
)
mcp = FastMCP("Server", transforms=[code_mode])
```
### Two-Stage
Search returns parameter schemas inline, so the LLM can go straight from search to execute. Best for **smaller catalogs** where the extra tokens per search result are a reasonable price for one fewer round-trip.
```python
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
from fastmcp.experimental.transforms.code_mode import Search, GetSchemas
code_mode = CodeMode(
discovery_tools=[Search(default_detail="detailed"), GetSchemas()],
)
mcp = FastMCP("Server", transforms=[code_mode])
```
`GetSchemas` is still available as a fallback — the LLM can call it with `detail="full"` if it encounters a tool with complex nested parameters where the compact markdown isn't enough.
### Single-Stage
Skip discovery entirely and bake tool instructions into the execute tool's description. Best for **very simple servers** where the LLM already knows what tools are available — maybe there are only a few, or they're described in the system prompt.
```python
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
code_mode = CodeMode(
discovery_tools=[],
execute_description=(
"Available tools:\n"
"- add(x: int, y: int) -> int: Add two numbers\n"
"- multiply(x: int, y: int) -> int: Multiply two numbers\n\n"
"Write Python using `await call_tool(name, params)` and `return` the result."
),
)
mcp = FastMCP("Server", transforms=[code_mode])
```
## Custom Discovery Tools
Discovery tools are composable — you can mix the built-ins with your own. Each discovery tool is a callable that receives catalog access and returns a `Tool`. The catalog accessor is a function (not the catalog itself) because the catalog is request-scoped — different users may see different tools based on auth.
Here's a minimal example:
```python
from fastmcp.experimental.transforms.code_mode import CodeMode
from fastmcp.experimental.transforms.code_mode import GetToolCatalog, GetSchemas
from fastmcp.server.context import Context
from fastmcp.tools.tool import Tool
def list_all_tools(get_catalog: GetToolCatalog) -> Tool:
async def list_tools(ctx: Context) -> str:
"""List all available tool names."""
tools = await get_catalog(ctx)
return ", ".join(t.name for t in tools)
return Tool.from_function(fn=list_tools, name="list_tools")
code_mode = CodeMode(discovery_tools=[list_all_tools, GetSchemas()])
```
The LLM sees the docstring of each discovery tool's inner function as its description — that's how it learns what each tool does and when to use it. Write docstrings that explain what the tool returns and when the LLM should call it.
Discovery tools and the execute tool can also have custom names:
```python
from fastmcp.experimental.transforms.code_mode import Search, GetSchemas
code_mode = CodeMode(
discovery_tools=[
Search(name="find_tools"),
GetSchemas(name="describe"),
],
execute_tool_name="run_workflow",
)
mcp = FastMCP("Server", transforms=[code_mode])
```
## Sandbox Configuration
### Resource Limits
The default `MontySandboxProvider` can enforce execution limits — timeouts, memory caps, recursion depth, and more. Without limits, LLM-generated scripts can run indefinitely.
```python
from fastmcp.experimental.transforms.code_mode import CodeMode
from fastmcp.experimental.transforms.code_mode import MontySandboxProvider
sandbox = MontySandboxProvider(
limits={"max_duration_secs": 10, "max_memory": 50_000_000},
)
mcp = FastMCP("Server", transforms=[CodeMode(sandbox_provider=sandbox)])
```
All keys are optional — omit any to leave that dimension uncapped:
| Key | Type | Description |
|---|---|---|
| `max_duration_secs` | `float` | Maximum wall-clock execution time |
| `max_memory` | `int` | Memory ceiling in bytes |
| `max_allocations` | `int` | Cap on total object allocations |
| `max_recursion_depth` | `int` | Maximum recursion depth |
| `gc_interval` | `int` | Garbage collection frequency |
### Custom Sandbox Providers
You can replace the default sandbox with any object implementing the `SandboxProvider` protocol:
```python
from collections.abc import Callable
from typing import Any
from fastmcp.experimental.transforms.code_mode import CodeMode
from fastmcp.experimental.transforms.code_mode import SandboxProvider
class RemoteSandboxProvider:
async def run(
self,
code: str,
*,
inputs: dict[str, Any] | None = None,
external_functions: dict[str, Callable[..., Any]] | None = None,
) -> Any:
# Send code to your remote sandbox runtime
...
mcp = FastMCP(
"Server",
transforms=[CodeMode(sandbox_provider=RemoteSandboxProvider())],
)
```
The `external_functions` dict contains async callables injected into the sandbox scope — `execute` uses this to provide `call_tool`.

View file

@ -116,7 +116,7 @@ result = await client.call_tool(
## Message Format
Rendered prompts return a messages array following the standard MCP format. Each message includes:
- `role`: The message role (typically "user", "assistant", or "system")
- `role`: The message role ("user" or "assistant")
- `content`: The message text content
Multi-message prompts are supported - the array will contain all messages in order.

View file

@ -0,0 +1,173 @@
---
title: Tool Search
sidebarTitle: Tool Search
description: Replace large tool catalogs with on-demand search
icon: magnifying-glass
tag: NEW
---
import { VersionBadge } from '/snippets/version-badge.mdx'
<VersionBadge version="3.1.0" />
When a server exposes hundreds or thousands of tools, sending the full catalog to an LLM wastes tokens and degrades tool selection accuracy. Search transforms solve this by replacing the tool listing with a search interface — the LLM discovers tools on demand instead of receiving everything upfront.
## How It Works
When you add a search transform, `list_tools()` returns just two synthetic tools instead of the full catalog:
- **`search_tools`** finds tools matching a query and returns their full definitions
- **`call_tool`** executes a discovered tool by name
The original tools are still callable. They're hidden from the listing but remain fully functional — the search transform controls *discovery*, not *access*.
Both synthetic tools search across tool names, descriptions, parameter names, and parameter descriptions. A search for `"email"` would match a tool named `send_email`, a tool with "email" in its description, or a tool with an `email_address` parameter.
Search results are returned in the same JSON format as `list_tools`, including the full input schema, so the LLM can construct valid calls immediately without a second round-trip.
## Search Strategies
FastMCP provides two search transforms. They share the same interface — two synthetic tools, same configuration options — but differ in how they match queries to tools.
### Regex Search
`RegexSearchTransform` matches tools against a regex pattern using case-insensitive `re.search`. It has zero overhead and no index to build, making it a good default when the LLM knows roughly what it's looking for.
```python
from fastmcp import FastMCP
from fastmcp.server.transforms.search import RegexSearchTransform
mcp = FastMCP("My Server", transforms=[RegexSearchTransform()])
@mcp.tool
def search_database(query: str, limit: int = 10) -> list[dict]:
"""Search the database for records matching the query."""
...
@mcp.tool
def delete_record(record_id: str) -> bool:
"""Delete a record from the database by its ID."""
...
@mcp.tool
def send_email(to: str, subject: str, body: str) -> bool:
"""Send an email to the given recipient."""
...
```
The LLM's `search_tools` call takes a `pattern` parameter — a regex string:
```python
# Exact substring match
result = await client.call_tool("search_tools", {"pattern": "database"})
# Returns: search_database, delete_record
# Regex pattern
result = await client.call_tool("search_tools", {"pattern": "send.*email|notify"})
# Returns: send_email
```
Results are returned in catalog order. If the pattern is invalid regex, the search returns an empty list rather than raising an error.
### BM25 Search
`BM25SearchTransform` ranks tools by relevance using the [BM25 Okapi](https://en.wikipedia.org/wiki/Okapi_BM25) algorithm. It's better for natural language queries because it scores each tool based on term frequency and document rarity, returning results ranked by relevance rather than filtering by match/no-match.
```python
from fastmcp import FastMCP
from fastmcp.server.transforms.search import BM25SearchTransform
mcp = FastMCP("My Server", transforms=[BM25SearchTransform()])
# ... define tools ...
```
The LLM's `search_tools` call takes a `query` parameter — natural language:
```python
result = await client.call_tool("search_tools", {
"query": "tools for deleting things from the database"
})
# Returns: delete_record ranked first, search_database second
```
BM25 builds an in-memory index from the searchable text of all tools. The index is created lazily on the first search and automatically rebuilt whenever the tool catalog changes — for example, when tools are added, removed, or have their descriptions updated. The staleness check is based on a hash of all searchable text, so description changes are detected even when tool names stay the same.
### Which to Choose
Use **regex** when your LLM is good at constructing targeted patterns and you want deterministic, predictable results. Regex is also simpler to debug — you can see exactly what pattern was sent.
Use **BM25** when your LLM tends to describe what it needs in natural language, or when your tool catalog has nuanced descriptions where relevance ranking adds value. BM25 handles partial matches and synonyms better because it scores on individual terms rather than requiring a single pattern to match.
## Configuration
Both search transforms accept the same configuration options.
### Limiting Results
By default, search returns at most 5 tools. Adjust `max_results` based on your catalog size and how much context you want the LLM to receive per search:
```python
mcp.add_transform(RegexSearchTransform(max_results=10))
mcp.add_transform(BM25SearchTransform(max_results=3))
```
With regex, results stop as soon as the limit is reached (first N matches in catalog order). With BM25, all tools are scored and the top N by relevance are returned.
### Pinning Tools
Some tools should always be visible regardless of search. Use `always_visible` to pin them in the listing alongside the synthetic tools:
```python
mcp.add_transform(RegexSearchTransform(
always_visible=["help", "status"],
))
# list_tools returns: help, status, search_tools, call_tool
```
Pinned tools appear directly in `list_tools` so the LLM can call them without searching. They're excluded from search results to avoid duplication.
### Custom Tool Names
The default names `search_tools` and `call_tool` can be changed to avoid conflicts with real tools:
```python
mcp.add_transform(RegexSearchTransform(
search_tool_name="find_tools",
call_tool_name="run_tool",
))
```
## The `call_tool` Proxy
The `call_tool` proxy forwards calls to the real tool. When a client calls `call_tool(name="search_database", arguments={...})`, the proxy resolves `search_database` through the server's normal tool pipeline — including transforms and middleware — and executes it.
The proxy rejects attempts to call the synthetic tools themselves. `call_tool(name="call_tool")` raises an error rather than recursing.
<Note>
Tools discovered through search can also be called directly via `client.call_tool("search_database", {...})` without going through the proxy. The proxy exists for LLMs that only know about the tools returned by `list_tools` and need a way to invoke discovered tools through a tool they can see.
</Note>
## Auth and Visibility
Search results respect the full authorization pipeline. Tools filtered by middleware, visibility transforms, or component-level auth checks won't appear in search results.
The search tool queries `list_tools()` through the complete pipeline at search time, so the same filtering that controls what a client sees in the listing also controls what they can discover through search.
```python
from fastmcp.server.transforms import Visibility
from fastmcp.server.transforms.search import RegexSearchTransform
mcp = FastMCP("My Server")
# ... define tools ...
# Disable admin tools globally
mcp.add_transform(Visibility(False, tags={"admin"}))
# Add search — admin tools won't appear in results
mcp.add_transform(RegexSearchTransform())
```
Session-level visibility changes (via `ctx.disable_components()`) are also reflected immediately in search results.

View file

@ -29,8 +29,10 @@ FastMCP provides several transforms for common use cases:
- **[Namespace](/servers/transforms/namespace)** - Prefix component names to prevent conflicts when composing servers
- **[Tool Transformation](/servers/transforms/tool-transformation)** - Rename tools, modify descriptions, reshape arguments
- **[Enabled](/servers/visibility)** - Control which components are visible at runtime
- **[Tool Search](/servers/transforms/tool-search)** - Replace large tool catalogs with on-demand search
- **[Resources as Tools](/servers/transforms/resources-as-tools)** - Expose resources to tool-only clients
- **[Prompts as Tools](/servers/transforms/prompts-as-tools)** - Expose prompts to tool-only clients
- **[Code Mode (Experimental)](/servers/transforms/code-mode)** - Replace many tools with programmable `search` + `execute`
## Server vs Provider Transforms
@ -79,14 +81,12 @@ Server transforms apply to all components from all providers. They run after pro
from fastmcp import FastMCP
from fastmcp.server.transforms import Namespace
mcp = FastMCP("Server")
mcp = FastMCP("Server", transforms=[Namespace("v1")])
@mcp.tool
def greet(name: str) -> str:
return f"Hello, {name}!"
mcp.add_transform(Namespace("v1"))
# All tools become v1_toolname
```

View file

@ -60,7 +60,7 @@ VersionFilter(version_gte="2.0", version_lt="3.0")
```
<Note>
**Unversioned components are exempt from version filtering.** A `VersionFilter` only affects versioned components - unversioned components always pass through regardless of the filter's constraints. This ensures that adding version filtering to a server with mixed versioned and unversioned tools doesn't accidentally hide the unversioned ones. To prevent confusion, FastMCP forbids mixing versioned and unversioned components with the same name.
**Unversioned components are exempt from version filtering by default.** Set `include_unversioned=False` to exclude them. Including them by default ensures that adding version filtering to a server with mixed versioned and unversioned components doesn't accidentally hide the unversioned ones. To prevent confusion, FastMCP forbids mixing versioned and unversioned components with the same name.
</Note>
### Filtering Mounted Servers
@ -138,7 +138,7 @@ def calculate(x: int, y: int, z: int = 0) -> int:
The error message explains the conflict: "Cannot add versioned tool 'calculate' (version='2.0'): an unversioned tool with this name already exists. Either version all components or none."
This restriction exists because unversioned components always pass through version filters. If you could mix versioned and unversioned components, you'd have no way to filter out the unversioned one using `VersionFilter`. By enforcing consistency at registration, FastMCP ensures version filtering behaves predictably.
This restriction helps keep version filtering behavior predictable.
Resources and prompts follow the same pattern.

View file

@ -190,9 +190,9 @@ async with client:
"expertise": "python programming"
})
# Typically returns messages with role="system"
system_message = result.messages[0]
print(f"System prompt: {system_message.content}")
# Access the returned messages
message = result.messages[0]
print(f"Prompt: {message.content}")
```
### Conversation Templates

View file

@ -719,6 +719,134 @@ Both parameters are required for production. Without an explicit signing key, ke
For more details on the token architecture and key management, see [OAuth Proxy Key and Storage Management](/v2/servers/auth/oauth-proxy#key-and-storage-management).
## Reverse Proxy (nginx)
In production, you'll typically run your FastMCP server behind a reverse proxy like nginx. A reverse proxy provides TLS termination, domain-based routing, static file serving, and an additional layer of security between the internet and your application.
### Running FastMCP as a Linux Service
Before configuring nginx, you need your FastMCP server running as a background service. A systemd unit file ensures your server starts automatically and restarts on failure.
Create a file at `/etc/systemd/system/fastmcp.service`:
```ini
[Unit]
Description=FastMCP Server
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/fastmcp
ExecStart=/opt/fastmcp/.venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=5
Environment="PATH=/opt/fastmcp/.venv/bin"
[Install]
WantedBy=multi-user.target
```
Enable and start the service:
```bash
sudo systemctl daemon-reload
sudo systemctl enable fastmcp
sudo systemctl start fastmcp
```
This assumes your ASGI application is in `/opt/fastmcp/app.py` with a virtual environment at `/opt/fastmcp/.venv`. Adjust paths to match your deployment layout.
### nginx Configuration
FastMCP's Streamable HTTP transport uses Server-Sent Events (SSE) for streaming responses. This requires specific nginx settings to prevent buffering from breaking the event stream.
Create a site configuration at `/etc/nginx/sites-available/fastmcp`:
```nginx
server {
listen 80;
server_name mcp.example.com;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE (Server-Sent Events) streaming
proxy_buffering off;
proxy_cache off;
# Allow long-lived connections for streaming responses
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
```
Enable the site and reload nginx:
```bash
sudo ln -s /etc/nginx/sites-available/fastmcp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Your FastMCP server is now accessible at `https://mcp.example.com/mcp`.
<Warning>
**SSE buffering is the most common issue.** If clients connect but never receive streaming responses (progress updates, tool results), verify that `proxy_buffering off` is set. Without it, nginx buffers the entire SSE stream and delivers it only when the connection closes, which breaks real-time communication.
</Warning>
### Key Considerations
When deploying FastMCP behind a reverse proxy, keep these points in mind:
- **Disable buffering**: SSE requires `proxy_buffering off` so events reach clients immediately. This is the single most important setting.
- **Increase timeouts**: The default nginx `proxy_read_timeout` is 60 seconds. Long-running MCP tools will cause the connection to drop. Set timeouts to at least 300 seconds, or higher if your tools run longer. For tools that may exceed any timeout, use [SSE Polling](#sse-polling-for-long-running-operations) to gracefully handle proxy disconnections.
- **Use HTTP/1.1**: Set `proxy_http_version 1.1` and `proxy_set_header Connection ''` to enable keep-alive connections between nginx and your server. Clearing the `Connection` header prevents clients from sending `Connection: close` to your upstream, which would break SSE streams. Both settings are required for proper SSE support.
- **Forward headers**: Pass `X-Forwarded-For` and `X-Forwarded-Proto` so your FastMCP server can determine the real client IP and protocol. This is important for logging and for OAuth redirect URLs.
- **TLS termination**: Let nginx handle TLS certificates (e.g., via Let's Encrypt with Certbot). Your FastMCP server can then run on plain HTTP internally.
### Mounting Under a Path Prefix
If you want your MCP server available at a subpath like `https://example.com/api/mcp` instead of at the root domain, adjust the nginx `location` block:
```nginx
location /api/ {
proxy_pass http://127.0.0.1:8000/;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Required for SSE streaming
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
```
Note the trailing `/` on both `location /api/` and `proxy_pass http://127.0.0.1:8000/` — this ensures nginx strips the `/api` prefix before forwarding to your server. If you're using OAuth authentication with a mount prefix, see [Mounting Authenticated Servers](#mounting-authenticated-servers) for additional configuration.
## Testing Your Deployment
Once your server is deployed, you'll need to verify it's accessible and functioning correctly. For comprehensive testing strategies including connectivity tests, client testing, and authentication testing, see the [Testing Your Server](/v2/development/tests) guide.

View file

@ -254,15 +254,7 @@ notice_resource = TextResource(
)
mcp.add_resource(notice_resource)
# 3. Using a custom key different from the URI
special_resource = TextResource(
uri="resource://common-notice",
name="Special Notice",
text="This is a special notice with a custom storage key.",
)
mcp.add_resource(special_resource, key="resource://custom-key")
# 4. Exposing a directory listing
# 3. Exposing a directory listing
data_dir_path = Path("./app_data").resolve()
if data_dir_path.is_dir():
data_listing_resource = DirectoryResource(
@ -286,24 +278,6 @@ if data_dir_path.is_dir():
Use these when the content is static or sourced directly from a file/URL, bypassing the need for a dedicated Python function.
#### Custom Resource Keys
<VersionBadge version="2.2.0" />
When adding resources directly with `mcp.add_resource()`, you can optionally provide a custom storage key:
```python
# Creating a resource with standard URI as the key
resource = TextResource(uri="resource://data")
mcp.add_resource(resource) # Will be stored and accessed using "resource://data"
# Creating a resource with a custom key
special_resource = TextResource(uri="resource://special-data")
mcp.add_resource(special_resource, key="internal://data-v2") # Will be stored and accessed using "internal://data-v2"
```
Note that this parameter is only available when using `add_resource()` directly and not through the `@resource` decorator, as URIs are provided explicitly when using the decorator.
### Notifications
<VersionBadge version="2.9.1" />

View file

@ -0,0 +1,102 @@
"""Chart MCP App — interactive data visualizations with Prefab.
Demonstrates `fastmcp[apps]` with Prefab chart components:
- `BarChart` and `LineChart` for categorical and trend data
- Multiple series, stacking, and curve styles
- Layout composition with `Column`, `Heading`, and `Muted`
- Custom text fallback via `ToolResult`
Usage:
uv run python chart_server.py # HTTP (port 8000)
uv run python chart_server.py --stdio # stdio for MCP clients
"""
from __future__ import annotations
from prefab_ui.app import PrefabApp
from prefab_ui.components import (
BarChart,
ChartSeries,
Column,
Heading,
LineChart,
Muted,
)
from fastmcp import FastMCP
mcp = FastMCP("Sales Dashboard")
MONTHLY_SALES = [
{"month": "Jan", "online": 4200, "retail": 2400},
{"month": "Feb", "online": 3800, "retail": 2100},
{"month": "Mar", "online": 5100, "retail": 2800},
{"month": "Apr", "online": 4600, "retail": 3200},
{"month": "May", "online": 5800, "retail": 3100},
{"month": "Jun", "online": 6200, "retail": 3500},
]
@mcp.tool(app=True)
def sales_overview(stacked: bool = False) -> PrefabApp:
"""View monthly sales broken down by channel.
Args:
stacked: Stack bars to show total revenue per month.
"""
total = sum(row["online"] + row["retail"] for row in MONTHLY_SALES)
with Column(gap=6, css_class="p-6") as view:
with Column(gap=1):
Heading("Monthly Sales")
Muted(f"${total:,} total revenue")
BarChart(
data=MONTHLY_SALES,
series=[
ChartSeries(data_key="online", label="Online"),
ChartSeries(data_key="retail", label="Retail"),
],
x_axis="month",
stacked=stacked,
show_legend=True,
)
return PrefabApp(
title="Sales Dashboard",
view=view,
)
@mcp.tool(app=True)
def sales_trend(curve: str = "linear") -> PrefabApp:
"""View sales trends over time as a line chart.
Args:
curve: Line style "linear", "smooth", or "step".
"""
with Column(gap=6, css_class="p-6") as view:
with Column(gap=1):
Heading("Sales Trend")
Muted("Online vs. retail over 6 months")
LineChart(
data=MONTHLY_SALES,
series=[
ChartSeries(data_key="online", label="Online"),
ChartSeries(data_key="retail", label="Retail"),
],
x_axis="month",
curve=curve,
show_dots=True,
show_legend=True,
)
return PrefabApp(
title="Sales Trend",
view=view,
)
if __name__ == "__main__":
mcp.run()

View file

@ -0,0 +1,165 @@
"""DataTable MCP App — interactive, sortable data views with Prefab.
Demonstrates `fastmcp[apps]` with Prefab UI components:
- `app=True` for automatic renderer wiring
- `PrefabApp` with `DataTable` for rich tabular views
- Searchable, sortable, paginated tables
- Layout composition with `Column`, `Heading`, `Text`, and `Badge`
Usage:
uv run python datatable_server.py # HTTP (port 8000)
uv run python datatable_server.py --stdio # stdio for MCP clients
"""
from __future__ import annotations
from prefab_ui.app import PrefabApp
from prefab_ui.components import (
Badge,
Column,
DataTable,
DataTableColumn,
Heading,
Muted,
Row,
)
from fastmcp import FastMCP
mcp = FastMCP("Team Directory")
EMPLOYEES = [
{
"name": "Alice Chen",
"role": "Engineering",
"level": "Senior",
"location": "San Francisco",
"status": "active",
},
{
"name": "Bob Martinez",
"role": "Design",
"level": "Lead",
"location": "New York",
"status": "active",
},
{
"name": "Carol Johnson",
"role": "Engineering",
"level": "Staff",
"location": "London",
"status": "active",
},
{
"name": "David Kim",
"role": "Product",
"level": "Senior",
"location": "San Francisco",
"status": "away",
},
{
"name": "Eva Müller",
"role": "Engineering",
"level": "Mid",
"location": "Berlin",
"status": "active",
},
{
"name": "Frank Okafor",
"role": "Data Science",
"level": "Senior",
"location": "Lagos",
"status": "active",
},
{
"name": "Grace Liu",
"role": "Engineering",
"level": "Junior",
"location": "Singapore",
"status": "active",
},
{
"name": "Hassan Ali",
"role": "Design",
"level": "Senior",
"location": "Dubai",
"status": "away",
},
{
"name": "Iris Tanaka",
"role": "Product",
"level": "Lead",
"location": "Tokyo",
"status": "active",
},
{
"name": "James Wright",
"role": "Engineering",
"level": "Senior",
"location": "London",
"status": "inactive",
},
{
"name": "Karen Petrov",
"role": "Data Science",
"level": "Lead",
"location": "Berlin",
"status": "active",
},
{
"name": "Liam O'Brien",
"role": "Engineering",
"level": "Mid",
"location": "Dublin",
"status": "active",
},
]
@mcp.tool(app=True)
def list_team(department: str | None = None) -> PrefabApp:
"""Browse the team directory with sorting and search.
Args:
department: Filter by department (e.g. "Engineering", "Design").
Leave empty to show everyone.
"""
if department:
rows = [e for e in EMPLOYEES if e["role"].lower() == department.lower()]
else:
rows = EMPLOYEES
active = sum(1 for e in rows if e["status"] == "active")
with Column(gap=6, css_class="p-6") as view:
with Column(gap=1):
Heading("Team Directory")
with Row(gap=2):
Muted(f"{len(rows)} members")
Muted(f"{active} active", css_class="text-success")
if department:
Badge(department, variant="outline")
DataTable(
columns=[
DataTableColumn(key="name", header="Name", sortable=True),
DataTableColumn(key="role", header="Department", sortable=True),
DataTableColumn(key="level", header="Level", sortable=True),
DataTableColumn(key="location", header="Location", sortable=True),
DataTableColumn(key="status", header="Status", sortable=True),
],
rows=rows,
searchable=True,
paginated=True,
page_size=10,
)
return PrefabApp(
title="Team Directory",
view=view,
state={"total": len(rows), "active": active},
)
if __name__ == "__main__":
mcp.run()

View file

@ -0,0 +1,489 @@
"""Patterns showcase — every Prefab pattern from the docs in one server.
A runnable collection of the patterns from https://gofastmcp.com/apps/patterns.
Each tool demonstrates a different Prefab UI pattern: charts, tables, forms,
status displays, conditional content, tabs, and accordions.
Usage:
uv run python patterns_server.py # HTTP (port 8000)
uv run python patterns_server.py --stdio # stdio for MCP clients
"""
from __future__ import annotations
from prefab_ui.actions import ShowToast
from prefab_ui.actions.mcp import CallTool
from prefab_ui.app import PrefabApp
from prefab_ui.components import (
Accordion,
AccordionItem,
Alert,
AreaChart,
Badge,
BarChart,
Button,
Card,
CardContent,
ChartSeries,
Column,
DataTable,
DataTableColumn,
ForEach,
Form,
Grid,
Heading,
If,
Input,
Muted,
PieChart,
Progress,
Row,
Select,
Separator,
Switch,
Tab,
Tabs,
Text,
Textarea,
)
from fastmcp import FastMCP
mcp = FastMCP("Patterns Showcase")
# ---------------------------------------------------------------------------
# Data
# ---------------------------------------------------------------------------
QUARTERLY_DATA = [
{"quarter": "Q1", "revenue": 42000, "costs": 28000},
{"quarter": "Q2", "revenue": 51000, "costs": 31000},
{"quarter": "Q3", "revenue": 47000, "costs": 29000},
{"quarter": "Q4", "revenue": 63000, "costs": 35000},
]
DAILY_USAGE = [
{"date": f"Feb {d}", "requests": v}
for d, v in zip(
range(1, 11),
[1200, 1350, 980, 1500, 1420, 1680, 1550, 1700, 1450, 1600],
)
]
TICKETS = [
{"category": "Bug", "count": 23},
{"category": "Feature", "count": 15},
{"category": "Docs", "count": 8},
{"category": "Infra", "count": 12},
]
EMPLOYEES = [
{
"name": "Alice Chen",
"department": "Engineering",
"role": "Staff Engineer",
"location": "San Francisco",
},
{
"name": "Bob Martinez",
"department": "Design",
"role": "Lead Designer",
"location": "New York",
},
{
"name": "Carol Johnson",
"department": "Engineering",
"role": "Senior Engineer",
"location": "London",
},
{
"name": "David Kim",
"department": "Product",
"role": "Product Manager",
"location": "San Francisco",
},
{
"name": "Eva Müller",
"department": "Engineering",
"role": "Engineer",
"location": "Berlin",
},
{
"name": "Frank Okafor",
"department": "Data Science",
"role": "Senior Analyst",
"location": "Lagos",
},
{
"name": "Grace Liu",
"department": "Engineering",
"role": "Junior Engineer",
"location": "Singapore",
},
{
"name": "Hassan Ali",
"department": "Design",
"role": "Senior Designer",
"location": "Dubai",
},
]
SERVICES = [
{
"name": "API Gateway",
"status": "healthy",
"ok": True,
"latency_ms": 12,
"uptime_pct": 99.9,
},
{
"name": "Database",
"status": "healthy",
"ok": True,
"latency_ms": 3,
"uptime_pct": 99.99,
},
{
"name": "Cache",
"status": "degraded",
"ok": False,
"latency_ms": 45,
"uptime_pct": 98.2,
},
{
"name": "Queue",
"status": "healthy",
"ok": True,
"latency_ms": 8,
"uptime_pct": 99.8,
},
]
ENDPOINTS = [
{
"path": "/api/users",
"status": 200,
"healthy": True,
"avg_ms": 45,
"p99_ms": 120,
"uptime_pct": 99.9,
},
{
"path": "/api/orders",
"status": 200,
"healthy": True,
"avg_ms": 82,
"p99_ms": 250,
"uptime_pct": 99.7,
},
{
"path": "/api/search",
"status": 200,
"healthy": True,
"avg_ms": 150,
"p99_ms": 500,
"uptime_pct": 99.5,
},
{
"path": "/api/webhooks",
"status": 503,
"healthy": False,
"avg_ms": 2000,
"p99_ms": 5000,
"uptime_pct": 95.1,
},
]
PROJECT = {
"name": "FastMCP v3",
"description": "Next generation MCP framework with Apps support.",
"status": "Active",
"created_at": "2025-01-15",
"members": [
{"name": "Alice Chen", "role": "Lead"},
{"name": "Bob Martinez", "role": "Design"},
{"name": "Carol Johnson", "role": "Backend"},
],
"activity": [
{
"timestamp": "2 hours ago",
"message": "Merged PR #342: Add Prefab UI integration",
},
{
"timestamp": "5 hours ago",
"message": "Opened issue #345: CORS convenience API",
},
{"timestamp": "1 day ago", "message": "Released v3.0.1"},
],
}
# In-memory contact store for the form demo
_contacts: list[dict] = [
{"name": "Zaphod Beeblebrox", "email": "zaphod@galaxy.gov", "category": "Partner"},
]
# ---------------------------------------------------------------------------
# Charts
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def quarterly_revenue(year: int = 2025) -> PrefabApp:
"""Show quarterly revenue as a bar chart."""
with Column(gap=4, css_class="p-6") as view:
Heading(f"{year} Revenue vs Costs")
BarChart(
data=QUARTERLY_DATA,
series=[
ChartSeries(data_key="revenue", label="Revenue"),
ChartSeries(data_key="costs", label="Costs"),
],
x_axis="quarter",
show_legend=True,
)
return PrefabApp(view=view)
@mcp.tool(app=True)
def usage_trend() -> PrefabApp:
"""Show API usage over time as an area chart."""
with Column(gap=4, css_class="p-6") as view:
Heading("API Usage (10 Days)")
AreaChart(
data=DAILY_USAGE,
series=[ChartSeries(data_key="requests", label="Requests")],
x_axis="date",
curve="smooth",
height=250,
)
return PrefabApp(view=view)
@mcp.tool(app=True)
def ticket_breakdown() -> PrefabApp:
"""Show open tickets by category as a donut chart."""
with Column(gap=4, css_class="p-6") as view:
Heading("Open Tickets")
PieChart(
data=TICKETS,
data_key="count",
name_key="category",
show_legend=True,
inner_radius=60,
)
return PrefabApp(view=view)
# ---------------------------------------------------------------------------
# Data Tables
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def employee_directory() -> PrefabApp:
"""Show a searchable, sortable employee directory."""
with Column(gap=4, css_class="p-6") as view:
Heading("Employee Directory")
DataTable(
columns=[
DataTableColumn(key="name", header="Name", sortable=True),
DataTableColumn(key="department", header="Department", sortable=True),
DataTableColumn(key="role", header="Role"),
DataTableColumn(key="location", header="Office", sortable=True),
],
rows=EMPLOYEES,
searchable=True,
paginated=True,
page_size=15,
)
return PrefabApp(view=view)
# ---------------------------------------------------------------------------
# Forms
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def contact_form() -> PrefabApp:
"""Show a form to create a new contact, with a live contact list below."""
with Column(gap=6, css_class="p-6") as view:
Heading("Contacts")
with ForEach("contacts"):
with Row(gap=2, align="center"):
Text("{{ name }}", css_class="font-medium")
Muted("{{ email }}")
Badge("{{ category }}")
Separator()
Heading("Add Contact", level=3)
with Form(
on_submit=CallTool(
"save_contact",
result_key="contacts",
on_success=ShowToast("Contact saved!", variant="success"),
on_error=ShowToast("{{ $error }}", variant="error"),
)
):
Input(name="name", label="Full Name", required=True)
Input(name="email", label="Email", input_type="email", required=True)
Select(
name="category",
label="Category",
options=["Customer", "Vendor", "Partner", "Other"],
)
Textarea(name="notes", label="Notes", placeholder="Optional notes...")
Button("Save Contact")
return PrefabApp(view=view, state={"contacts": list(_contacts)})
@mcp.tool
def save_contact(
name: str,
email: str,
category: str = "Other",
notes: str = "",
) -> list[dict]:
"""Save a new contact and return the updated list."""
contact = {"name": name, "email": email, "category": category, "notes": notes}
_contacts.append(contact)
return list(_contacts)
# ---------------------------------------------------------------------------
# Status Displays
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def system_status() -> PrefabApp:
"""Show current system health."""
all_ok = all(s["ok"] for s in SERVICES)
with Column(gap=4, css_class="p-6") as view:
with Row(gap=2, align="center"):
Heading("System Status")
Badge(
"All Healthy" if all_ok else "Degraded",
variant="success" if all_ok else "destructive",
)
Separator()
with Grid(columns=2, gap=4):
for svc in SERVICES:
with Card():
with CardContent():
with Row(gap=2, align="center"):
Text(svc["name"], css_class="font-medium")
Badge(
svc["status"],
variant="success" if svc["ok"] else "destructive",
)
Muted(f"Response: {svc['latency_ms']}ms")
Progress(value=svc["uptime_pct"])
return PrefabApp(view=view)
# ---------------------------------------------------------------------------
# Conditional Content
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def feature_flags() -> PrefabApp:
"""Toggle feature flags with live preview."""
with Column(gap=4, css_class="p-6") as view:
Heading("Feature Flags")
Switch(name="dark_mode", label="Dark Mode")
Switch(name="beta_features", label="Beta Features")
Separator()
with If("{{ dark_mode }}"):
Alert(title="Dark mode enabled", description="UI will use dark theme.")
with If("{{ beta_features }}"):
Alert(
title="Beta features active",
description="Experimental features are now visible.",
variant="warning",
)
return PrefabApp(view=view, state={"dark_mode": False, "beta_features": False})
# ---------------------------------------------------------------------------
# Tabs
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def project_overview() -> PrefabApp:
"""Show project details organized in tabs."""
with Column(gap=4, css_class="p-6") as view:
Heading(PROJECT["name"])
with Tabs():
with Tab("Overview"):
Text(PROJECT["description"])
with Row(gap=4):
Badge(PROJECT["status"])
Muted(f"Created: {PROJECT['created_at']}")
with Tab("Members"):
DataTable(
columns=[
DataTableColumn(key="name", header="Name", sortable=True),
DataTableColumn(key="role", header="Role"),
],
rows=PROJECT["members"],
)
with Tab("Activity"):
with ForEach("activity"):
with Row(gap=2):
Muted("{{ timestamp }}")
Text("{{ message }}")
return PrefabApp(view=view, state={"activity": PROJECT["activity"]})
# ---------------------------------------------------------------------------
# Accordion
# ---------------------------------------------------------------------------
@mcp.tool(app=True)
def api_health() -> PrefabApp:
"""Show health details for each API endpoint."""
with Column(gap=4, css_class="p-6") as view:
Heading("API Health")
with Accordion(multiple=True):
for ep in ENDPOINTS:
with AccordionItem(ep["path"]):
with Row(gap=4):
Badge(
f"{ep['status']}",
variant="success" if ep["healthy"] else "destructive",
)
Text(f"Avg: {ep['avg_ms']}ms")
Text(f"P99: {ep['p99_ms']}ms")
Progress(value=ep["uptime_pct"])
return PrefabApp(view=view)
if __name__ == "__main__":
mcp.run()

View file

@ -0,0 +1,67 @@
# PropelAuth OAuth Example
Demonstrates FastMCP server protection with PropelAuth OAuth.
## Setup
### 1. Configure MCP Authentication in PropelAuth
**Create a PropelAuth Account**:
- Go to [PropelAuth Dashboard](https://www.propelauth.com)
- Navigate to the **MCP** section and click **Enable MCP**
**Configure Allowed MCP Clients**:
- Under **MCP > Allowed MCP Clients**, add redirect URIs for each MCP client you want to allow
- PropelAuth provides templates for popular clients like Claude, Cursor, and ChatGPT
**Configure Scopes**:
- Under **MCP > Scopes**, define the permissions available to MCP clients (e.g., `read:user_data`)
**Generate Introspection Credentials**:
- Go to **MCP > Request Validation** and click **Create Credentials**
- Note the **Client ID** and **Client Secret**
**Note Your Auth URL**:
- Find your Auth URL in the **Backend Integration** section (e.g., `https://auth.yourdomain.com`)
Create a `.env` file:
```bash
# Required PropelAuth credentials
PROPELAUTH_AUTH_URL=https://auth.yourdomain.com
PROPELAUTH_INTROSPECTION_CLIENT_ID=your-client-id
PROPELAUTH_INTROSPECTION_CLIENT_SECRET=your-client-secret
BASE_URL=http://localhost:8000/
# Optional: additional scopes tokens must include (comma-separated)
# PROPELAUTH_REQUIRED_SCOPES=read:user_data
```
### 2. Run the Example
Start the server:
```bash
# From this directory
uv run python server.py
```
The server will start on `http://localhost:8000/mcp` with PropelAuth OAuth authentication enabled.
Test with client:
```bash
uv run python client.py
```
The `client.py` will:
1. Attempt to connect to the server
2. Detect that OAuth authentication is required
3. Open a browser for PropelAuth authentication
4. Complete the OAuth flow and connect to the server
5. Demonstrate calling authenticated tools (echo and whoami)

View file

@ -0,0 +1,43 @@
"""OAuth client example for connecting to PropelAuth-protected FastMCP servers.
This example demonstrates how to connect to a PropelAuth OAuth-protected FastMCP server.
To run:
python client.py
"""
import asyncio
from fastmcp.client import Client
SERVER_URL = "http://127.0.0.1:8000/mcp"
async def main():
try:
async with Client(SERVER_URL, auth="oauth") as client:
assert await client.ping()
print("✅ Successfully authenticated with PropelAuth!")
tools = await client.list_tools()
print(f"🔧 Available tools ({len(tools)}):")
for tool in tools:
print(f" - {tool.name}: {tool.description}")
# Test calling a tool
result = await client.call_tool(
"echo", {"message": "Hello from PropelAuth!"}
)
print(f"🎯 Echo result: {result}")
# Test calling whoami tool
whoami = await client.call_tool("whoami", {})
print(f"👤 Who am I: {whoami}")
except Exception as e:
print(f"❌ Authentication failed: {e}")
raise
if __name__ == "__main__":
asyncio.run(main())

View file

@ -0,0 +1,54 @@
"""PropelAuth OAuth server example for FastMCP.
This example demonstrates how to protect a FastMCP server with PropelAuth OAuth.
Required environment variables:
- PROPELAUTH_AUTH_URL: Your PropelAuth Auth URL (from Backend Integration page)
- PROPELAUTH_INTROSPECTION_CLIENT_ID: Introspection Client ID (from MCP > Request Validation)
- PROPELAUTH_INTROSPECTION_CLIENT_SECRET: Introspection Client Secret (from MCP > Request Validation)
Optional:
- PROPELAUTH_REQUIRED_SCOPES: Comma-separated scopes tokens must include
- BASE_URL: Public URL where the FastMCP server is exposed (defaults to `http://localhost:8000/`)
To run:
python server.py
"""
import os
from dotenv import load_dotenv
from fastmcp import FastMCP
from fastmcp.server.auth.providers.propelauth import PropelAuthProvider
from fastmcp.server.dependencies import get_access_token
load_dotenv()
auth = PropelAuthProvider(
auth_url=os.environ["PROPELAUTH_AUTH_URL"],
introspection_client_id=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_ID"],
introspection_client_secret=os.environ["PROPELAUTH_INTROSPECTION_CLIENT_SECRET"],
base_url=os.getenv("BASE_URL", "http://localhost:8000/"),
)
mcp = FastMCP("PropelAuth OAuth Example Server", auth=auth)
@mcp.tool
def echo(message: str) -> str:
"""Echo the provided message."""
return message
@mcp.tool
def whoami() -> dict:
"""Return the authenticated user's ID."""
token = get_access_token()
if token is None:
return {"error": "Not authenticated"}
return {"user_id": token.claims.get("sub")}
if __name__ == "__main__":
mcp.run(transport="http", port=8000)

View file

@ -0,0 +1,37 @@
# Code Mode
CodeMode collapses an entire tool catalog into two meta-tools: `search` (keyword-based discovery) and `execute` (run Python scripts that chain tool calls in a sandbox). Instead of burning context tokens on every intermediate result, the LLM writes a script that runs server-side and returns only the final answer.
## Run
```bash
uv run python server.py # in one terminal
uv run python client.py # in another
```
## Example Output
```
══════════════════ CodeMode Transform ══════════════════
┌────────────── list_tools() ──────────────┐
│ Tool Description │
│ search Search for available tools ... │
│ execute Chain `await call_tool(...)` ... │
└── 8 backend tools collapsed into 2 ──────┘
┌──── search(query="math arithmetic") ─────┐
│ # Tool Description │
│ 1 add Add two numbers together. │
│ 2 multiply Multiply two numbers. │
│ 3 fibonacci Generate the first n ... │
└── 3 results ─────────────────────────────┘
┌────────────── execute ───────────────────┐
│ a = await call_tool("add", {"a": 3 ... │
│ b = await call_tool("multiply", ... │
│ return b │
└── result: 14.0 ──────────────────────────┘
```
The key insight: with standard MCP, each `call_tool` is a round-trip through the LLM. With CodeMode, the LLM writes one script and all the tool calls happen server-side. Intermediate data never touches the context window.

View file

@ -0,0 +1,142 @@
"""Example: Client using CodeMode to discover and chain tools.
CodeMode exposes just two tools: `search` (keyword query) and `execute`
(run Python code with `call_tool` available). This client demonstrates
both: searching for tools, then chaining multiple calls in a single
execute block one round-trip instead of many.
Run with:
uv run python examples/code_mode/client.py
"""
import asyncio
import json
from typing import Any
from rich.console import Console
from rich.panel import Panel
from rich.syntax import Syntax
from rich.table import Table
from fastmcp.client import Client
console = Console()
def _get_result(result) -> Any:
"""Extract the value from a CallToolResult (structured or text)."""
if result.structured_content is not None:
data = result.structured_content
if isinstance(data, dict) and set(data) == {"result"}:
return data["result"]
return data
return result.content[0].text
def _format_params(tool: dict) -> str:
"""Format inputSchema properties as a compact signature."""
schema = tool.get("inputSchema", {})
props = schema.get("properties", {})
if not props:
return "()"
parts = []
for name, info in props.items():
typ = info.get("type", "")
parts.append(f"{name}: {typ}" if typ else name)
return f"({', '.join(parts)})"
def _tool_table(
tools: list[dict], *, ranked: bool = False, show_params: bool = False
) -> Table:
table = Table(show_header=True, show_edge=False, pad_edge=False, expand=True)
if ranked:
table.add_column("#", style="dim", width=3, justify="right")
table.add_column("Tool", style="cyan", no_wrap=True)
if show_params:
table.add_column("Parameters", style="dim", no_wrap=True)
table.add_column("Description", style="dim")
for i, tool in enumerate(tools, 1):
row = [tool["name"]]
if show_params:
row.append(_format_params(tool))
row.append(tool.get("description", ""))
if ranked:
row.insert(0, str(i))
table.add_row(*row)
return table
async def main():
async with Client("examples/code_mode/server.py") as client:
console.print()
console.rule("[bold]CodeMode[/bold]")
console.print()
# Step 1: list_tools only returns two synthetic meta-tools
console.print(
"The server has 8 tools. CodeMode replaces them with "
"two synthetic tools — [bold]search[/bold] and [bold]execute[/bold]:"
)
console.print()
tools = await client.list_tools()
visible = [{"name": t.name, "description": t.description} for t in tools]
console.print(
Panel(
_tool_table(visible),
title="[bold]list_tools()[/bold]",
title_align="left",
border_style="blue",
)
)
console.print()
# Step 2: search discovers available tools
console.print("The LLM calls [bold]search[/bold] to discover available tools:")
console.print()
result = await client.call_tool("search", {"query": "add multiply numbers"})
found = _get_result(result)
if isinstance(found, str):
found = json.loads(found)
console.print(
Panel(
_tool_table(found, ranked=True, show_params=True),
title='[bold]search[/bold] [dim]query="add multiply numbers"[/dim]',
title_align="left",
border_style="green",
)
)
console.print()
# Step 3: execute chains tool calls in one round-trip
console.print(
"Now the LLM writes a Python script that chains "
"the tools it found. All of it runs server-side in a "
"sandbox — [bold]one round-trip[/bold], intermediate "
"data never hits the context window:"
)
console.print()
code = """\
a = await call_tool("add", {"a": 3, "b": 4})
b = await call_tool("multiply", {"x": a["result"], "y": 2})
fib = await call_tool("fibonacci", {"n": b["result"]})
return {"sum": a["result"], "product": b["result"], "fibonacci": fib["result"]}
"""
result = await client.call_tool("execute", {"code": code})
console.print(
Panel(
Syntax(code.strip(), "python", theme="monokai"),
title="[bold]execute[/bold]",
title_align="left",
border_style="yellow",
)
)
console.print()
# Final result
console.print(f" Result: [bold green]{_get_result(result)}[/bold green]")
console.print()
if __name__ == "__main__":
asyncio.run(main())

View file

@ -0,0 +1,84 @@
"""Example: CodeMode transform — search and execute tools via code.
CodeMode replaces the entire tool catalog with two meta-tools: `search`
(keyword-based tool discovery) and `execute` (run Python code that chains
tool calls in a sandbox). This dramatically reduces round-trips and
context window usage when an LLM needs to orchestrate many tools.
Requires pydantic-monty for the sandbox:
pip install "fastmcp[code-mode]"
Run with:
uv run python examples/code_mode/server.py
"""
from fastmcp import FastMCP
from fastmcp.experimental.transforms.code_mode import CodeMode
mcp = FastMCP("CodeMode Demo")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
@mcp.tool
def multiply(x: float, y: float) -> float:
"""Multiply two numbers."""
return x * y
@mcp.tool
def fibonacci(n: int) -> list[int]:
"""Generate the first n Fibonacci numbers."""
if n <= 0:
return []
seq = [0, 1]
while len(seq) < n:
seq.append(seq[-1] + seq[-2])
return seq[:n]
@mcp.tool
def reverse_string(text: str) -> str:
"""Reverse a string."""
return text[::-1]
@mcp.tool
def word_count(text: str) -> int:
"""Count the number of words in a text."""
return len(text.split())
@mcp.tool
def to_uppercase(text: str) -> str:
"""Convert text to uppercase."""
return text.upper()
@mcp.tool
def list_files(directory: str) -> list[str]:
"""List files in a directory."""
import os
return os.listdir(directory)
@mcp.tool
def read_file(path: str) -> str:
"""Read the contents of a file."""
with open(path) as f:
return f.read()
# CodeMode collapses all 8 tools into just `search` + `execute`.
# The LLM discovers tools via keyword search, then writes Python
# scripts that chain multiple tool calls in a single round-trip.
mcp.add_transform(CodeMode())
if __name__ == "__main__":
mcp.run()

Some files were not shown because too many files have changed in this diff Show more