From fe391611d515ef2d065ea579d7ef785ee7e2db89 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 20 Jan 2026 00:00:23 -0500 Subject: [PATCH 1/5] Prepare docs for v3.0 beta release - Streamline upgrade guide: organize by breaking changes, behavior changes, and deprecations - Add v3.0.0b1 entry to updates page - Link upgrade guide from installation page - Move upgrade guide higher in navigation for beta visibility --- docs/development/upgrade-guide.mdx | 544 +++++--------------------- docs/docs.json | 2 +- docs/getting-started/installation.mdx | 9 +- docs/updates.mdx | 20 + 4 files changed, 133 insertions(+), 442 deletions(-) diff --git a/docs/development/upgrade-guide.mdx b/docs/development/upgrade-guide.mdx index 0fcf5ab47c..883b3065d6 100644 --- a/docs/development/upgrade-guide.mdx +++ b/docs/development/upgrade-guide.mdx @@ -3,548 +3,214 @@ title: Upgrade Guide sidebarTitle: Upgrade Guide description: Migration instructions for upgrading between FastMCP versions icon: up -tag: NEW --- -This guide provides migration instructions for breaking changes and major updates when upgrading between FastMCP versions. - -## FastMCP Metadata Namespace Change - -### Metadata Namespace Renamed - -The FastMCP metadata namespace has been renamed from `_fastmcp` to `fastmcp` (underscore prefix removed). All metadata is now always included in component responses. - -**What changed:** -- Metadata namespace: `meta._fastmcp` → `meta.fastmcp` -- The `include_fastmcp_meta` setting and parameter have been removed -- Component version is now included in metadata when available (`meta.fastmcp.version`) - -**Migration steps:** - -1. **Update metadata access patterns:** - - ```python Before - tags = tool.meta.get("_fastmcp", {}).get("tags", []) - ``` - - ```python After - tags = tool.meta.get("fastmcp", {}).get("tags", []) - ``` - - -2. **Remove `include_fastmcp_meta` parameter:** - - ```python Before - mcp = FastMCP(include_fastmcp_meta=False) - ``` - - ```python After - # Parameter removed - metadata is always included - mcp = FastMCP() - ``` - - -3. **Remove `include_fastmcp_meta` from component serialization:** - - ```python Before - mcp_tool = tool.to_mcp_tool(include_fastmcp_meta=True) - ``` - - ```python After - mcp_tool = tool.to_mcp_tool() - ``` - - -4. **Access component version from metadata:** - - ```python Before - # Version was not available in metadata - ``` - - ```python After - version = tool.meta.get("fastmcp", {}).get("version") - if version: - print(f"Tool version: {version}") - ``` - - -**Why this changed:** The underscore prefix was removed to make the namespace more discoverable and consistent with standard naming conventions. Making metadata always included simplifies the API and ensures consistent behavior across all FastMCP servers. +This guide covers breaking changes and migration steps when upgrading FastMCP. ## v3.0.0 -### WSTransport Removed +Most servers need only one change: update your import from `from mcp.server.fastmcp import FastMCP` to `from fastmcp import FastMCP`. The sections below cover less common breaking changes. -The deprecated `WSTransport` client transport has been removed. Use `StreamableHttpTransport` instead. +### Breaking Changes -### Decorators Return Functions +#### WSTransport Removed - -**Breaking Change:** Decorators now return your original function instead of a component object. Code that treats the decorated function as a `FunctionTool`, `FunctionResource`, or `FunctionPrompt` will break. - +Use `StreamableHttpTransport` instead. -Decorators (`@tool`, `@resource`, `@prompt`) now return the original function instead of transforming it into a component object: +#### Auth Provider Environment Variables Removed - -```python Before -@mcp.tool -def greet(name: str) -> str: - return f"Hello, {name}!" - -isinstance(greet, FunctionTool) # True -greet.name # "greet" -``` - -```python After -@mcp.tool -def greet(name: str) -> str: - return f"Hello, {name}!" - -isinstance(greet, FunctionTool) # False - it's your function now -greet("World") # "Hello, World!" - still callable -``` - - -**Why this changed:** Functions staying as functions means they're directly callable for testing, work naturally with instance methods, and match how Flask/FastAPI decorators behave. - -**For v2 compatibility:** +Auth providers no longer auto-load configuration. Read them explicitly: ```python -import fastmcp -fastmcp.settings.decorator_mode = "object" -``` - -Or set the environment variable `FASTMCP_DECORATOR_MODE=object`. - -### Provider Architecture - -FastMCP v3 introduces a unified provider architecture for sourcing components. All tools, resources, and prompts now flow through providers: - -- **LocalProvider** stores decorator-registered components (`@mcp.tool`, etc.) -- **FastMCPProvider** wraps another FastMCP server for composition -- **ProxyProvider** connects to remote MCP servers -- **Transforms** modify components as they flow through using a middleware `call_next` pattern - -See [Providers](/servers/providers/overview) and [Transforms](/servers/providers/transforms) for documentation. - -### Tool Transformation API - -`FastMCP.add_tool_transformation()` and the `tool_transformations` constructor parameter are deprecated. Use `add_transform()` with `ToolTransform` instead: - - -```python Before -mcp = FastMCP("server", tool_transformations={ - "verbose_name": ToolTransformConfig(name="short") -}) -mcp.add_tool_transformation("verbose_name", ToolTransformConfig(name="short")) -``` - -```python After -from fastmcp.server.transforms import ToolTransform -from fastmcp.tools.tool_transform import ToolTransformConfig - -mcp = FastMCP("server") -mcp.add_transform(ToolTransform({ - "verbose_name": ToolTransformConfig(name="short") -})) -``` - - -`remove_tool_transformation()` is deprecated with no replacement - transforms are immutable once added. Use `server.disable(names={...}, components=["tool"])` to hide tools dynamically. - -### FastMCP.as_proxy() Deprecated - -The `FastMCP.as_proxy()` classmethod is deprecated. Use the `create_proxy()` function instead ([#2829](https://github.com/jlowin/fastmcp/pull/2829)): - - -```python Before -proxy = FastMCP.as_proxy("http://example.com/mcp") -``` - -```python After -from fastmcp.server import create_proxy - -proxy = create_proxy("http://example.com/mcp") -``` - - -`as_proxy()` continues to work but forwards to `create_proxy()`. - -### Mount Namespace Parameter - -The `prefix` parameter for `mount()` has been renamed to `namespace`: - - -```python Before -main.mount(subserver, prefix="api") -``` +import os -```python After -main.mount(subserver, namespace="api") +auth = GitHubProvider( + client_id=os.environ["GITHUB_CLIENT_ID"], + client_secret=os.environ["GITHUB_CLIENT_SECRET"], +) ``` - -### Component Enable/Disable +#### Component enable()/disable() Moved to Server -The `enable()`/`disable()` methods have moved from component objects to the server and provider level: +These methods moved from component objects to the server: - -```python Before +```python +# Before tool = await server.get_tool("my_tool") tool.disable() -tool.enable() -``` -```python After +# After server.disable(names={"my_tool"}, components=["tool"]) -server.enable(names={"my_tool"}, components=["tool"]) -``` - - -Components describe capabilities; servers and providers control availability. This ensures enabled state works correctly even when components pass through transforming providers. - -**Override semantics:** - -Multiple `enable()`/`disable()` calls are additive. Later calls override earlier ones for matching components: - -```python -server.disable(tags={"internal"}) # Hide all internal -server.enable(names={"safe_tool"}) # Show safe_tool (overrides the disable) -# Result: safe_tool is visible, other internal tools are hidden ``` -**Allowlist mode:** +#### Listing Methods Return Lists -Use `only=True` to restrict access to specific components: +`get_tools()`, `get_resources()`, `get_prompts()`, and `get_resource_templates()` now return lists instead of dicts: ```python -# Show ONLY tools with "public" tag -server.enable(tags={"public"}, only=True) -``` - -**`FastMCP(include_tags=..., exclude_tags=...)` deprecated:** - -These init parameters emit deprecation warnings. Use the new methods instead: - - -```python Before -mcp = FastMCP("server", exclude_tags={"internal"}) -``` - -```python After -mcp = FastMCP("server") -mcp.disable(tags={"internal"}) -``` - - -**No automatic notifications:** - -Component `enable()`/`disable()` in v2 sent `ToolListChangedNotification` automatically. The new server-level methods don't - they're treated as startup configuration. To notify clients of enabled state changes at runtime, send notifications explicitly: - -```python -import mcp.types - -@server.tool -async def hide_admin_tools(ctx: Context): - ctx.fastmcp.disable(tags={"admin"}) - await ctx.send_notification(mcp.types.ToolListChangedNotification()) -``` - -### Component Lookup Method Parameter Names - -The server lookup methods now use semantic parameter names instead of generic `key`: - -- `FastMCP.get_tool(name=...)` (was `key`) -- `FastMCP.get_resource(uri=...)` (was `key`) -- `FastMCP.get_resource_template(uri=...)` (was `key`) -- `FastMCP.get_prompt(name=...)` (was `key`) - -If you were passing arguments positionally, no change is needed. If you were using keyword arguments: - - -```python Before -tool = await mcp.get_tool(key="my_tool") -``` - -```python After -tool = await mcp.get_tool(name="my_tool") -``` - - -### Component Listing Methods Return Lists - -The `get_tools()`, `get_resources()`, `get_prompts()`, and `get_resource_templates()` methods now return lists instead of dicts: - - -```python Before +# Before tools = await server.get_tools() -if "my_tool" in tools: - tool = tools["my_tool"] -``` +tool = tools["my_tool"] -```python After +# After tools = await server.get_tools() tool = next((t for t in tools if t.name == "my_tool"), None) ``` - - -The dict key was redundant since components already have `.name` or `.uri` attributes. Use list comprehensions or `next()` for lookups. -### Prompt Return Types +#### Prompts Use Message Class -Prompt functions now use `Message` instead of `mcp.types.PromptMessage`. The `Message` class provides auto-serialization and a simpler API: +Use `Message` instead of `mcp.types.PromptMessage`: - -```python Before +```python +# Before from mcp.types import PromptMessage, TextContent @mcp.prompt def my_prompt() -> PromptMessage: - return PromptMessage( - role="user", - content=TextContent(type="text", text="Hello") - ) -``` + return PromptMessage(role="user", content=TextContent(type="text", text="Hello")) -```python After +# After from fastmcp.prompts import Message @mcp.prompt def my_prompt() -> Message: - return Message("Hello") # role defaults to "user" + return Message("Hello") ``` - - -**Key changes:** - -- Use `Message(content, role="user")` instead of `PromptMessage(role=..., content=TextContent(...))` -- `Message` auto-serializes dicts, lists, and Pydantic models to JSON -- `PromptResult` now accepts `str | list[Message]` (no single `Message`) -- Returning `mcp.types.PromptMessage` directly is no longer supported - -See [Prompts documentation](/servers/prompts#return-values) for full details. - -### Tool Serializer Deprecated - -The `tool_serializer` parameter on `FastMCP` is deprecated. Return `ToolResult` from your tools for explicit control over serialization. See [Custom Serialization](/servers/tools#custom-serialization) for examples. -### Auth Provider Automatic Environment Variable Loading Removed +#### Context State Methods Are Async -Auth providers no longer automatically read configuration from environment variables. You can still use environment variables, but you must read them yourself: +`ctx.set_state()` and `ctx.get_state()` are now async. State persists across the session: - -```python Before -# Relied on FASTMCP_SERVER_AUTH_GITHUB_CLIENT_ID, etc. -auth = GitHubProvider() -``` - -```python After -import os +```python +# Before +ctx.set_state("key", "value") +value = ctx.get_state("key") -auth = GitHubProvider( - client_id=os.environ["GITHUB_CLIENT_ID"], - client_secret=os.environ["GITHUB_CLIENT_SECRET"], - base_url=os.environ["GITHUB_BASE_URL"], -) +# After +await ctx.set_state("key", "value") +value = await ctx.get_state("key") ``` - -This applies to all auth providers: `GitHubProvider`, `GoogleProvider`, `AzureProvider`, `Auth0Provider`, `AWSProvider`, `WorkOSProvider`, `DescopeProvider`, `DiscordProvider`, `ScalekitProvider`, `SupabaseProvider`, `OCIProvider`, `JWTVerifier`, and `IntrospectionVerifier`. +#### Server Banner Environment Variable Renamed -The `FastMCPSettings` class has also been simplified - it no longer includes auth-related settings that were previously loaded from environment variables. +`FASTMCP_SHOW_CLI_BANNER` is now `FASTMCP_SHOW_SERVER_BANNER`. -### Server Banner Environment Variable Renamed +#### Metadata Namespace Renamed -The environment variable for controlling the server banner has been renamed: +The FastMCP metadata namespace changed from `_fastmcp` to `fastmcp`. This only affects code that reads component metadata from FastMCP servers: -- **Before:** `FASTMCP_SHOW_CLI_BANNER` -- **After:** `FASTMCP_SHOW_SERVER_BANNER` +```python +# Before +tags = tool.meta.get("_fastmcp", {}).get("tags", []) -This change reflects that the setting now applies to all server startup methods, not just the CLI. The banner is now suppressed when running `python server.py` directly, not just when using `fastmcp run`. +# After +tags = tool.meta.get("fastmcp", {}).get("tags", []) +``` -### Context State Methods Are Async +### Behavior Changes - -**Breaking Change:** `ctx.set_state()` and `ctx.get_state()` are now async methods. Synchronous calls will fail. - +#### Decorators Return Functions -Context state has changed from request-scoped to session-scoped, persisting across multiple tool calls within the same MCP session. The methods are now async because they interact with a pluggable storage backend. +Decorators now return your original function instead of a component object. This means functions stay callable for testing: - -```python Before +```python @mcp.tool -def my_tool(ctx: Context) -> str: - ctx.set_state("key", "value") - value = ctx.get_state("key") - return value -``` +def greet(name: str) -> str: + return f"Hello, {name}!" -```python After -@mcp.tool -async def my_tool(ctx: Context) -> str: - await ctx.set_state("key", "value") - value = await ctx.get_state("key") - return value +greet("World") # Works! Returns "Hello, World!" ``` - -**What changed:** -- State now persists across requests within a session (not just within a single request) -- Different clients have isolated state (keyed by session ID) -- State expires after 1 day to prevent unbounded memory growth -- New method: `await ctx.delete_state(key)` +If you relied on the old behavior (treating `greet` as a `FunctionTool`), set `FASTMCP_DECORATOR_MODE=object` for v2 compatibility. -**Custom storage backends:** +### Deprecated Features -By default, state uses an in-memory store. For distributed deployments, provide a custom backend: +These still work but emit warnings. Update when convenient. + +#### mount() prefix → namespace ```python -from key_value.aio.stores.redis import RedisStore +# Deprecated +main.mount(subserver, prefix="api") -mcp = FastMCP("server", session_state_store=RedisStore(...)) +# New +main.mount(subserver, namespace="api") ``` -See [Session State](/servers/context#session-state) for full documentation. - -## v2.14.0 - -### OpenAPI Parser Promotion - -The experimental OpenAPI parser is now the standard implementation. The legacy parser has been removed. - -**If you were using the legacy parser:** No code changes required. The new parser is a drop-in replacement with improved architecture. +#### include_tags/exclude_tags → enable()/disable() -**If you were using the experimental parser:** Update your imports from the experimental module to the standard location: - - -```python Before -from fastmcp.experimental.server.openapi import FastMCPOpenAPI, RouteMap, MCPType -``` +```python +# Deprecated +mcp = FastMCP("server", exclude_tags={"internal"}) -```python After -from fastmcp.server.openapi import FastMCPOpenAPI, RouteMap, MCPType +# New +mcp = FastMCP("server") +mcp.disable(tags={"internal"}) ``` - -The experimental imports will continue working temporarily but will show deprecation warnings. The `FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER` environment variable is no longer needed and can be removed. +#### tool_serializer → ToolResult -### Deprecated Features Removed +Return `ToolResult` from your tools for explicit serialization control instead of using the `tool_serializer` parameter. -The following deprecated features have been removed in v2.14.0: +#### add_tool_transformation() → add_transform() -**BearerAuthProvider** (deprecated in v2.11): - -```python Before -from fastmcp.server.auth.providers.bearer import BearerAuthProvider -``` +```python +# Deprecated +mcp.add_tool_transformation("name", config) -```python After -from fastmcp.server.auth.providers.jwt import JWTVerifier +# New +from fastmcp.server.transforms import ToolTransform +mcp.add_transform(ToolTransform({"name": config})) ``` - -**Context.get_http_request()** (deprecated in v2.2.11): - -```python Before -request = context.get_http_request() -``` +#### FastMCP.as_proxy() → create_proxy() -```python After -from fastmcp.server.dependencies import get_http_request -request = get_http_request() -``` - +```python +# Deprecated +proxy = FastMCP.as_proxy("http://example.com/mcp") -**Top-level Image import** (deprecated in v2.8.1): - -```python Before -from fastmcp import Image +# New +from fastmcp.server import create_proxy +proxy = create_proxy("http://example.com/mcp") ``` -```python After -from fastmcp.utilities.types import Image -``` - +## v2.14.0 -**FastMCP dependencies parameter** (deprecated in v2.11.4): - -```python Before -mcp = FastMCP("server", dependencies=["requests", "pandas"]) -``` +### OpenAPI Parser Promotion -```json After -{ - "environment": { - "dependencies": ["requests", "pandas"] - } -} -``` - +The experimental OpenAPI parser is now standard. Update imports: -**Legacy resource prefix format**: The `resource_prefix_format` parameter and "protocol" format have been removed. Only the "path" format is supported (this was already the default). +```python +# Before +from fastmcp.experimental.server.openapi import FastMCPOpenAPI -**FastMCPProxy client parameter**: - -```python Before -proxy = FastMCPProxy(client=my_client) +# After +from fastmcp.server.openapi import FastMCPOpenAPI ``` -```python After -proxy = FastMCPProxy(client_factory=lambda: my_client) -``` - - -**output_schema=False**: - -```python Before -@mcp.tool(output_schema=False) -def my_tool() -> str: - return "result" -``` +### Removed Deprecated Features -```python After -@mcp.tool(output_schema=None) -def my_tool() -> str: - return "result" -``` - +- `BearerAuthProvider` → use `JWTVerifier` +- `Context.get_http_request()` → use `get_http_request()` from dependencies +- `from fastmcp import Image` → use `from fastmcp.utilities.types import Image` +- `FastMCP(dependencies=[...])` → use `fastmcp.json` configuration +- `FastMCPProxy(client=...)` → use `client_factory=lambda: ...` +- `output_schema=False` → use `output_schema=None` ## v2.13.0 ### OAuth Token Key Management -The OAuth proxy now issues its own JWT tokens to clients instead of forwarding upstream provider tokens. This improves security by maintaining proper token audience boundaries. - -**What changed:** - -The OAuth proxy now implements a token factory pattern - it receives tokens from your OAuth provider (GitHub, Google, etc.), encrypts and stores them, then issues its own FastMCP JWT tokens to clients. This requires cryptographic keys for JWT signing and token encryption. - -**Default behavior (development):** - -By default, FastMCP automatically manages keys based on your platform: -- **Mac/Windows**: Keys are auto-managed via system keyring, surviving server restarts with zero configuration. Suitable **only** for development and local testing. -- **Linux**: Keys are ephemeral (random salt at startup, regenerated on each restart). - -This works fine for development and testing where re-authentication after restart is acceptable. - -**For production:** - -Production deployments must provide explicit keys and use persistent storage. Add these three things: +The OAuth proxy now issues its own JWT tokens. For production, provide explicit keys: ```python auth = GitHubProvider( client_id=os.environ["GITHUB_CLIENT_ID"], client_secret=os.environ["GITHUB_CLIENT_SECRET"], base_url="https://your-server.com", - - # Explicit keys (required for production) jwt_signing_key=os.environ["JWT_SIGNING_KEY"], - - # Persistent network storage (required for production) - client_storage=RedisStore(host="redis.example.com", port=6379) + client_storage=RedisStore(host="redis.example.com"), ) ``` -**More information:** -- [OAuth Token Security](/deployment/http#oauth-token-security) - Complete production setup guide -- [Key and Storage Management](/servers/auth/oauth-proxy#key-and-storage-management) - Detailed explanation of defaults and production requirements -- [OAuth Proxy Parameters](/servers/auth/oauth-proxy#configuration-parameters) - Parameter documentation +See [OAuth Token Security](/deployment/http#oauth-token-security) for details. diff --git a/docs/docs.json b/docs/docs.json index ff58e4a570..f436b1a69c 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -90,6 +90,7 @@ "pages": [ "getting-started/welcome", "getting-started/installation", + "development/upgrade-guide", "getting-started/quickstart", "updates" ] @@ -275,7 +276,6 @@ "development/contributing", "development/tests", "development/releases", - "development/upgrade-guide", "changelog", "patterns/contrib" ] diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 32e8ca951a..3be07b87bf 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -70,10 +70,15 @@ pip install "cyclopts>=5.0.0a1" Alternatively, wait for the stable v5 release. See [this issue](https://github.com/BrianPugh/cyclopts/issues/672) for details. -## Upgrading from the Official MCP SDK +## Upgrading -Upgrading from the official MCP SDK's FastMCP 1.0 to FastMCP 3.0 is generally straightforward. The core server API is highly compatible, and in many cases, changing your import statement from `from mcp.server.fastmcp import FastMCP` to `from fastmcp import FastMCP` will be sufficient. +### From FastMCP 2.x + +See the [Upgrade Guide](/development/upgrade-guide) for a complete list of breaking changes and migration steps. +### From the Official MCP SDK + +Upgrading from the official MCP SDK's FastMCP 1.0 to FastMCP 3.0 is generally straightforward. The core server API is highly compatible, and in many cases, changing your import statement from `from mcp.server.fastmcp import FastMCP` to `from fastmcp import FastMCP` will be sufficient. ```python {5} # Before diff --git a/docs/updates.mdx b/docs/updates.mdx index b5feab8364..b048d86403 100644 --- a/docs/updates.mdx +++ b/docs/updates.mdx @@ -5,6 +5,26 @@ icon: "sparkles" tag: NEW --- + + +FastMCP 3.0 rebuilds the framework around three primitives: components, providers, and transforms. Providers source components dynamically—from decorators, filesystems, OpenAPI specs, remote servers, or anywhere else. Transforms modify components as they flow to clients. The features that required specialized subsystems in v2 now compose naturally from these building blocks. + +🔌 **Provider Architecture** unifies how components are sourced with `FileSystemProvider`, `SkillsProvider`, `OpenAPIProvider`, and `ProxyProvider`. + +🔄 **Transforms** add middleware for components—namespace, rename, filter by version, control visibility. + +📋 **Component Versioning** lets you register multiple versions of the same tool with automatic highest-version selection. + +💾 **Session-Scoped State** persists across requests, with per-session visibility control. + +⚡ **DX Improvements** include `--reload` for development, automatic threadpool dispatch, tool timeouts, pagination, and OpenTelemetry tracing. + + + Date: Tue, 20 Jan 2026 00:07:52 -0500 Subject: [PATCH 2/5] Show how to pin to specific beta version --- docs/getting-started/installation.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 3be07b87bf..a33043896e 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -27,6 +27,12 @@ Alternatively, you can install it directly with `pip` or `uv pip`: ``` +To pin to a specific beta version: + +```bash +pip install fastmcp==3.0.0b1 +``` + ### Optional Dependencies FastMCP provides optional extras for specific features. For example, to install the background tasks extra: From fbf37e2530e5ef3570fb9a84c38ba61e8d7dd155 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 20 Jan 2026 00:08:59 -0500 Subject: [PATCH 3/5] Use explicit version pins instead of --pre flag --- docs/getting-started/installation.mdx | 25 ++++++++----------------- docs/servers/tasks.mdx | 2 +- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index a33043896e..cf5bc16f60 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -7,30 +7,21 @@ icon: arrow-down-to-line We recommend using [uv](https://docs.astral.sh/uv/getting-started/installation/) to install and manage FastMCP. -FastMCP 3.0 is currently in beta. You must explicitly opt in to pre-release versions using the flags shown below. +FastMCP 3.0 is currently in beta. Install by specifying the version explicitly. -If you plan to use FastMCP in your project, you can add it as a dependency with: - ```bash -uv add fastmcp --prerelease=allow +pip install fastmcp==3.0.0b1 ``` -Alternatively, you can install it directly with `pip` or `uv pip`: - - ```bash uv - uv pip install fastmcp --prerelease=allow - ``` - - ```bash pip - pip install fastmcp --pre - ``` - + +Avoid using `pip install --pre` as it enables prereleases for all dependencies, which may install incompatible versions of packages like httpx. + -To pin to a specific beta version: +If you plan to use FastMCP in a uv-managed project, you can add it as a dependency with: ```bash -pip install fastmcp==3.0.0b1 +uv add fastmcp --prerelease=allow ``` ### Optional Dependencies @@ -38,7 +29,7 @@ pip install fastmcp==3.0.0b1 FastMCP provides optional extras for specific features. For example, to install the background tasks extra: ```bash -pip install "fastmcp[tasks]" --pre +pip install "fastmcp[tasks]==3.0.0b1" ``` See [Background Tasks](/servers/tasks) for details on the task system. diff --git a/docs/servers/tasks.mdx b/docs/servers/tasks.mdx index f5130bbc64..585781a04e 100644 --- a/docs/servers/tasks.mdx +++ b/docs/servers/tasks.mdx @@ -43,7 +43,7 @@ MCP background tasks are different: they're **protocol-native**. This means MCP Background tasks require the `tasks` extra: ```bash -pip install "fastmcp[tasks]" --pre +pip install "fastmcp[tasks]==3.0.0b1" # or with uv uv add "fastmcp[tasks]" --prerelease=allow ``` From a42f6391370c38a85662d2372bf281540cda10a9 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 20 Jan 2026 00:11:48 -0500 Subject: [PATCH 4/5] Update redirects --- docs/docs.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/docs.json b/docs/docs.json index f436b1a69c..cc5c6dff8a 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -822,6 +822,14 @@ ] }, "redirects": [ + { + "destination": "/v2/clients/messages", + "source": "/clients/messages" + }, + { + "destination": "/v2/patterns/decorating-methods", + "source": "/patterns/decorating-methods" + }, { "destination": "/servers/providers/proxy", "source": "/patterns/proxy" From ce7cefeb315f9b281359bc6149b68acee52d2380 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 20 Jan 2026 00:12:33 -0500 Subject: [PATCH 5/5] Note include_fastmcp_meta parameter removal in metadata section --- docs/development/upgrade-guide.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/upgrade-guide.mdx b/docs/development/upgrade-guide.mdx index 883b3065d6..247e03a2bf 100644 --- a/docs/development/upgrade-guide.mdx +++ b/docs/development/upgrade-guide.mdx @@ -97,7 +97,7 @@ value = await ctx.get_state("key") #### Metadata Namespace Renamed -The FastMCP metadata namespace changed from `_fastmcp` to `fastmcp`. This only affects code that reads component metadata from FastMCP servers: +The FastMCP metadata namespace changed from `_fastmcp` to `fastmcp`, and metadata is now always included. The `include_fastmcp_meta` parameter has been removed from `FastMCP()` and `to_mcp_tool()`—remove any usage of this parameter. ```python # Before