docs/servers/server.mdx
import { VersionBadge } from "/snippets/version-badge.mdx"
The FastMCP class is the central piece of every FastMCP application. It acts as the container for your tools, resources, and prompts, managing communication with MCP clients and orchestrating the entire server lifecycle.
At its simplest, a FastMCP server just needs a name. Everything else has sensible defaults.
from fastmcp import FastMCP
mcp = FastMCP("MyServer")
Instructions help clients (and the LLMs behind them) understand what your server does and how to use it effectively.
mcp = FastMCP(
"DataAnalysis",
instructions="Provides tools for analyzing numerical datasets. Start with get_summary() for an overview.",
)
FastMCP servers expose three types of components to clients, each serving a distinct role in the MCP protocol.
Tools are functions that clients invoke to perform actions or access external systems.
@mcp.tool
def multiply(a: float, b: float) -> float:
"""Multiplies two numbers together."""
return a * b
Resources expose data that clients can read — passive data sources rather than invocable functions.
@mcp.resource("data://config")
def get_config() -> dict:
return {"theme": "dark", "version": "1.0"}
Prompts are reusable message templates that guide LLM interactions.
@mcp.prompt
def analyze_data(data_points: list[float]) -> str:
formatted_data = ", ".join(str(point) for point in data_points)
return f"Please analyze these data points: {formatted_data}"
Each component type has detailed documentation: Tools, Resources (including Resource Templates), and Prompts.
Start your server by calling mcp.run(). The if __name__ guard ensures compatibility with MCP clients that launch your server as a subprocess.
from fastmcp import FastMCP
mcp = FastMCP("MyServer")
@mcp.tool
def greet(name: str) -> str:
"""Greet a user by name."""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run()
FastMCP supports several transports:
# Run with HTTP transport
mcp.run(transport="http", host="127.0.0.1", port=9000)
The server can also be run using the FastMCP CLI. For detailed information on transports and deployment, see Running Your Server.
The FastMCP constructor accepts parameters organized into four categories: identity, composition, behavior, and handlers.
These parameters control how your server presents itself to clients.
<Card> <ParamField body="name" type="str" default="FastMCP"> A human-readable name for your server, shown in client applications and logs </ParamField> <ParamField body="instructions" type="str | None"> Description of how to interact with this server. Clients surface these instructions to help LLMs understand the server's purpose and available functionality </ParamField> <ParamField body="version" type="str | None"> Version string for your server. Defaults to the FastMCP library version if not provided </ParamField> <ParamField body="website_url" type="str | None"> <VersionBadge version="2.13.0" />URL to a website with more information about your server. Displayed in client applications </ParamField>
<ParamField body="icons" type="list[Icon] | None"> <VersionBadge version="2.13.0" />List of icon representations for your server. See Icons for details </ParamField> </Card>
These parameters control what your server is built from — its components, middleware, providers, and lifecycle.
<Card> <ParamField body="tools" type="list[Tool | Callable] | None"> Tools to register on the server. An alternative to the `@mcp.tool` decorator when you need to add tools programmatically </ParamField> <ParamField body="auth" type="OAuthProvider | TokenVerifier | None"> Authentication provider for securing HTTP-based transports. See [Authentication](/servers/auth/authentication) for configuration </ParamField> <ParamField body="middleware" type="list[Middleware] | None"> [Middleware](/servers/middleware) that intercepts and transforms every MCP message flowing through the server — requests, responses, and notifications in both directions. Use for cross-cutting concerns like logging, error handling, and rate limiting </ParamField> <ParamField body="providers" type="list[Provider] | None"> [Providers](/servers/providers) that supply tools, resources, and prompts dynamically. Providers are queried at request time, so they can serve components from databases, APIs, or other external sources </ParamField> <ParamField body="transforms" type="list[Transform] | None"> <VersionBadge version="3.1.0" />Server-level transforms to apply to all components. Transforms modify how tools, resources, and prompts are presented to clients — for example, search transforms replace large catalogs with on-demand discovery </ParamField>
<ParamField body="lifespan" type="Lifespan | AsyncContextManager | None"> Server-level setup and teardown logic that runs when the server starts and stops. See [Lifespans](/servers/lifespan) for composable lifespans </ParamField> </Card>These parameters tune how the server processes requests and communicates with clients.
<Card> <ParamField body="on_duplicate" type='Literal["warn", "error", "replace", "ignore"]' default="warn"> How to handle duplicate component registrations </ParamField> <ParamField body="strict_input_validation" type="bool" default="False"> <VersionBadge version="2.13.0" />When False (default), FastMCP uses Pydantic's flexible validation that coerces compatible inputs (e.g., "10" → 10 for int parameters). When True, validates inputs against the exact JSON Schema before calling your function, rejecting type mismatches. See Input Validation Modes for details
</ParamField>
Maximum items per page for list operations (tools/list, resources/list, etc.). When None, all results are returned in a single response. See Pagination for details
</ParamField>
Default minimum log level for messages sent to MCP clients via context.log(). When set, messages below this level are suppressed. Individual clients can override this per-session using the MCP logging/setLevel request. One of "debug", "info", "notice", "warning", "error", "critical", "alert", or "emergency"
</ParamField>
These parameters provide custom handlers for MCP capabilities and persistent storage for session state.
<Card> <ParamField body="sampling_handler" type="SamplingHandler | None"> Custom handler for MCP sampling requests (server-initiated LLM calls). See [Sampling](/servers/sampling) for details </ParamField> <ParamField body="sampling_handler_behavior" type='Literal["always", "fallback"] | None' default="fallback"> When `"fallback"`, the sampling handler is used only when no tool-specific handler exists. When `"always"`, this handler is used for all sampling requests </ParamField> <ParamField body="session_state_store" type="AsyncKeyValue | None"> Persistent key-value store for session state that survives across requests. Defaults to an in-memory store. Provide a custom implementation for persistence across server restarts </ParamField> </Card>Tags let you categorize components and selectively expose them. This is useful for creating different views of your server for different environments or user types.
@mcp.tool(tags={"public", "utility"})
def public_tool() -> str:
return "This tool is public"
@mcp.tool(tags={"internal", "admin"})
def admin_tool() -> str:
return "This tool is for admins only"
The filtering logic works as follows:
only=True: Switches to allowlist mode — only components with at least one matching tag are exposeddisable after enable to exclude from an allowlist# Only expose components tagged with "public"
mcp = FastMCP()
mcp.enable(tags={"public"}, only=True)
# Hide components tagged as "internal" or "deprecated"
mcp = FastMCP()
mcp.disable(tags={"internal", "deprecated"})
# Combine both: show admin tools but hide deprecated ones
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.
When running with HTTP transport, you can add custom web routes alongside your MCP endpoint using the @custom_route decorator.
from fastmcp import FastMCP
from starlette.requests import Request
from starlette.responses import PlainTextResponse
mcp = FastMCP("MyServer")
@mcp.custom_route("/health", methods=["GET"])
async def health_check(request: Request) -> PlainTextResponse:
return PlainTextResponse("OK")
if __name__ == "__main__":
mcp.run(transport="http") # Health check at http://localhost:8000/health
Custom routes are useful for health checks, status endpoints, and simple webhooks. For more complex web applications, consider mounting your MCP server into a FastAPI or Starlette app.