--- title: Upgrade Guide sidebarTitle: Upgrade Guide description: Migration instructions for upgrading between FastMCP versions icon: up --- This guide covers breaking changes and migration steps when upgrading FastMCP. ## v3.0.0 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. ### Breaking Changes #### WSTransport Removed Use `StreamableHttpTransport` instead. #### Auth Provider Environment Variables Removed Auth providers no longer auto-load configuration. Read them explicitly: ```python import os auth = GitHubProvider( client_id=os.environ["GITHUB_CLIENT_ID"], client_secret=os.environ["GITHUB_CLIENT_SECRET"], ) ``` #### Component enable()/disable() Moved to Server These methods moved from component objects to the server: ```python # Before tool = await server.get_tool("my_tool") tool.disable() # After server.disable(names={"my_tool"}, components=["tool"]) ``` #### Listing Methods Return Lists `get_tools()`, `get_resources()`, `get_prompts()`, and `get_resource_templates()` now return lists instead of dicts: ```python # Before tools = await server.get_tools() tool = tools["my_tool"] # After tools = await server.get_tools() tool = next((t for t in tools if t.name == "my_tool"), None) ``` #### Prompts Use Message Class Use `Message` instead of `mcp.types.PromptMessage`: ```python # Before from mcp.types import PromptMessage, TextContent @mcp.prompt def my_prompt() -> PromptMessage: return PromptMessage(role="user", content=TextContent(type="text", text="Hello")) # After from fastmcp.prompts import Message @mcp.prompt def my_prompt() -> Message: return Message("Hello") ``` #### Context State Methods Are Async `ctx.set_state()` and `ctx.get_state()` are now async. State persists across the session: ```python # Before ctx.set_state("key", "value") value = ctx.get_state("key") # After await ctx.set_state("key", "value") value = await ctx.get_state("key") ``` #### Server Banner Environment Variable Renamed `FASTMCP_SHOW_CLI_BANNER` is now `FASTMCP_SHOW_SERVER_BANNER`. #### Metadata Namespace Renamed 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 tags = tool.meta.get("_fastmcp", {}).get("tags", []) # After tags = tool.meta.get("fastmcp", {}).get("tags", []) ``` ### Behavior Changes #### Decorators Return Functions Decorators now return your original function instead of a component object. This means functions stay callable for testing: ```python @mcp.tool def greet(name: str) -> str: return f"Hello, {name}!" greet("World") # Works! Returns "Hello, World!" ``` If you relied on the old behavior (treating `greet` as a `FunctionTool`), set `FASTMCP_DECORATOR_MODE=object` for v2 compatibility. ### Deprecated Features These still work but emit warnings. Update when convenient. #### mount() prefix → namespace ```python # Deprecated main.mount(subserver, prefix="api") # New main.mount(subserver, namespace="api") ``` #### include_tags/exclude_tags → enable()/disable() ```python # Deprecated mcp = FastMCP("server", exclude_tags={"internal"}) # New mcp = FastMCP("server") mcp.disable(tags={"internal"}) ``` #### tool_serializer → ToolResult Return `ToolResult` from your tools for explicit serialization control instead of using the `tool_serializer` parameter. #### add_tool_transformation() → add_transform() ```python # Deprecated mcp.add_tool_transformation("name", config) # New from fastmcp.server.transforms import ToolTransform mcp.add_transform(ToolTransform({"name": config})) ``` #### FastMCP.as_proxy() → create_proxy() ```python # Deprecated proxy = FastMCP.as_proxy("http://example.com/mcp") # New from fastmcp.server import create_proxy proxy = create_proxy("http://example.com/mcp") ``` ## v3.0.0b2 (from v3.0.0b1) ### Breaking Changes #### Tool `timeout` Parameter Removed The `timeout` parameter on `@mcp.tool()` has been removed. Use Docket's `Timeout` dependency instead: ```python # Before (v3.0.0b1) @mcp.tool(timeout=30.0) async def fetch_data(url: str) -> dict: ... # After (v3.0.0b2) from datetime import timedelta from docket import Timeout @mcp.tool async def fetch_data( url: str, timeout: Timeout = Timeout(timedelta(seconds=30)), ) -> dict: ... ``` Benefits of the new approach: - **Unified execution**: Timeouts work identically for foreground and background tasks - **Additional capabilities**: Access to `Retry`, `ExponentialRetry`, `ConcurrencyLimit` - **Auto-routing**: Components with Docket dependencies automatically route through Docket Note: This is only breaking from beta 1 → beta 2. The `timeout` parameter didn't exist before beta 1. ## v2.14.0 ### OpenAPI Parser Promotion The experimental OpenAPI parser is now standard. Update imports: ```python # Before from fastmcp.experimental.server.openapi import FastMCPOpenAPI # After from fastmcp.server.openapi import FastMCPOpenAPI ``` ### Removed Deprecated Features - `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. 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", jwt_signing_key=os.environ["JWT_SIGNING_KEY"], client_storage=RedisStore(host="redis.example.com"), ) ``` See [OAuth Token Security](/deployment/http#oauth-token-security) for details.