--- title: The FastMCP Server sidebarTitle: FastMCP Server description: Learn about the core FastMCP server class and how to run it. icon: server --- import { VersionBadge } from "/snippets/version-badge.mdx" The central piece of a FastMCP application is the `FastMCP` server class. This class acts as the main container for your application's tools, resources, and prompts, and manages communication with MCP clients. ## Creating a Server Instantiating a server is straightforward. You typically provide a name for your server, which helps identify it in client applications or logs. ```python from fastmcp import FastMCP # Create a basic server instance mcp = FastMCP(name="MyAssistantServer") # You can also add instructions for how to interact with the server mcp_with_instructions = FastMCP( name="HelpfulAssistant", instructions="This server provides data analysis tools. Call get_average() to analyze numerical data." ) ``` The `FastMCP` constructor accepts several arguments: * `name`: (Optional) A human-readable name for your server. Defaults to "FastMCP". * `instructions`: (Optional) Description of how to interact with this server. These instructions help clients understand the server's purpose and available functionality. * `lifespan`: (Optional) An async context manager function for server startup and shutdown logic. * `tags`: (Optional) A set of strings to tag the server itself. * `**settings`: Keyword arguments corresponding to additional `ServerSettings` configuration ## Components FastMCP servers expose several types of components to the client: ### Tools Tools are functions that the client can call to perform actions or access external systems. ```python @mcp.tool() def multiply(a: float, b: float) -> float: """Multiplies two numbers together.""" return a * b ``` See [Tools](/servers/tools) for detailed documentation. ### Resources Resources expose data sources that the client can read. ```python @mcp.resource("data://config") def get_config() -> dict: """Provides the application configuration.""" return {"theme": "dark", "version": "1.0"} ``` See [Resources & Templates](/servers/resources) for detailed documentation. ### Resource Templates Resource templates are parameterized resources that allow the client to request specific data. ```python @mcp.resource("users://{user_id}/profile") def get_user_profile(user_id: int) -> dict: """Retrieves a user's profile by ID.""" # The {user_id} in the URI is extracted and passed to this function return {"id": user_id, "name": f"User {user_id}", "status": "active"} ``` See [Resources & Templates](/servers/resources) for detailed documentation. ### Prompts Prompts are reusable message templates for guiding the LLM. ```python @mcp.prompt() def analyze_data(data_points: list[float]) -> str: """Creates a prompt asking for analysis of numerical data.""" formatted_data = ", ".join(str(point) for point in data_points) return f"Please analyze these data points: {formatted_data}" ``` See [Prompts](/servers/prompts) for detailed documentation. ## Running the Server FastMCP servers need a transport mechanism to communicate with clients. In the MCP protocol, servers typically run as separate processes that clients connect to. ### The `__main__` Block Pattern The standard way to make your server executable is to include a `run()` call inside an `if __name__ == "__main__":` block: ```python # my_server.py from fastmcp import FastMCP mcp = FastMCP(name="MyServer") @mcp.tool() def greet(name: str) -> str: """Greet a user by name.""" return f"Hello, {name}!" if __name__ == "__main__": # This code only runs when the file is executed directly # Basic run with default settings (stdio transport) mcp.run() # Or with specific transport and parameters # mcp.run(transport="sse", host="127.0.0.1", port=9000) ``` This pattern is important because: 1. **Client Compatibility**: Standard MCP clients (like Claude Desktop) expect to execute your server file directly with `python my_server.py` 2. **Process Isolation**: Each server runs in its own process, allowing clients to manage multiple servers independently 3. **Import Safety**: The main block prevents the server from running when the file is imported by other code While this pattern is technically optional when using FastMCP's CLI, it's considered a best practice for maximum compatibility with all MCP clients. ### Transport Options FastMCP supports two transport mechanisms: #### STDIO Transport (Default) The standard input/output (STDIO) transport is the default and most widely compatible option: ```python # Run with stdio (default) mcp.run() # or explicitly: mcp.run(transport="stdio") ``` With STDIO: - The client starts a new server process for each session - Communication happens through standard input/output streams - The server process terminates when the client disconnects - This is ideal for integrations with tools like Claude Desktop, where each conversation gets its own server instance #### SSE Transport (Server-Sent Events) For long-running servers that serve multiple clients, FastMCP supports SSE: ```python # Run with SSE on default host/port (0.0.0.0:8000) mcp.run(transport="sse") ``` With SSE: - The server runs as a persistent web server - Multiple clients can connect simultaneously - The server stays running until explicitly terminated - This is ideal for remote access to services You can configure transport parameters directly when running the server: ```python # Configure with specific parameters mcp.run( transport="sse", host="127.0.0.1", # Override default host port=8888, # Override default port log_level="debug" # Set logging level ) # You can also run asynchronously with the same parameters import asyncio asyncio.run( mcp.run_sse_async( host="127.0.0.1", port=8888, log_level="debug" ) ) ``` Transport parameters passed to `run()` or `run_sse_async()` override any settings defined when creating the FastMCP instance. The most common parameters for SSE transport are: - `host`: Host to bind to (default: "0.0.0.0") - `port`: Port to bind to (default: 8000) - `log_level`: Logging level (default: "INFO") #### Advanced Transport Configuration Under the hood, FastMCP's `run()` method accepts arbitrary keyword arguments (`**transport_kwargs`) that are passed to the transport-specific run methods: ```python # For SSE transport, kwargs are passed to run_sse_async() mcp.run(transport="sse", **transport_kwargs) # For stdio transport, kwargs are passed to run_stdio_async() mcp.run(transport="stdio", **transport_kwargs) ``` This means that any future transport-specific options will be automatically available through the same interface without requiring changes to your code. ### Using the FastMCP CLI The FastMCP CLI provides a convenient way to run servers: ```bash # Run a server (defaults to stdio transport) fastmcp run my_server.py:mcp # Explicitly specify a transport fastmcp run my_server.py:mcp --transport sse # Configure SSE transport with host and port fastmcp run my_server.py:mcp --transport sse --host 127.0.0.1 --port 8888 # With log level fastmcp run my_server.py:mcp --transport sse --log-level DEBUG ``` The CLI can dynamically find and run FastMCP server objects in your files, but including the `if __name__ == "__main__":` block ensures compatibility with all clients. ## Composing Servers FastMCP supports composing multiple servers together using `import_server` (static copy) and `mount` (live link). This allows you to organize large applications into modular components or reuse existing servers. See the [Server Composition](/patterns/composition) guide for full details, best practices, and examples. ```python # Example: Importing a subserver from fastmcp import FastMCP import asyncio main = FastMCP(name="Main") sub = FastMCP(name="Sub") @sub.tool() def hello(): return "hi" # Mount directly main.mount("sub", sub) ``` ## Proxying Servers FastMCP can act as a proxy for any MCP server (local or remote) using `FastMCP.from_client`, letting you bridge transports or add a frontend to existing servers. For example, you can expose a remote SSE server locally via stdio, or vice versa. See the [Proxying Servers](/patterns/proxy) guide for details and advanced usage. ```python from fastmcp import FastMCP, Client backend = Client("http://example.com/mcp/sse") proxy = FastMCP.from_client(backend, name="ProxyServer") # Now use the proxy like any FastMCP server ``` ## Server Configuration Server behavior, like transport settings (host, port for SSE) and how duplicate components are handled, can be configured via `ServerSettings`. These settings can be passed during `FastMCP` initialization, set via environment variables (prefixed with `FASTMCP_SERVER_`), or loaded from a `.env` file. ```python from fastmcp import FastMCP # Configure during initialization mcp = FastMCP( name="ConfiguredServer", port=8080, # Directly maps to ServerSettings on_duplicate_tools="error" # Set duplicate handling ) # Settings are accessible via mcp.settings print(mcp.settings.port) # Output: 8080 print(mcp.settings.on_duplicate_tools) # Output: "error" ``` ### Key Configuration Options - **`host`**: Host address for SSE transport (default: "0.0.0.0") - **`port`**: Port number for SSE transport (default: 8000) - **`log_level`**: Logging level (default: "INFO") - **`on_duplicate_tools`**: How to handle duplicate tool registrations - **`on_duplicate_resources`**: How to handle duplicate resource registrations - **`on_duplicate_prompts`**: How to handle duplicate prompt registrations All of these can be configured directly as parameters when creating the `FastMCP` instance. ### Custom Tool Serialization By default, FastMCP serializes tool return values to JSON when they need to be converted to text. You can customize this behavior by providing a `tool_serializer` function when creating your server: ```python import yaml from fastmcp import FastMCP # Define a custom serializer that formats dictionaries as YAML def yaml_serializer(data): return yaml.dump(data, sort_keys=False) # Create a server with the custom serializer mcp = FastMCP(name="MyServer", tool_serializer=yaml_serializer) @mcp.tool() def get_config(): """Returns configuration in YAML format.""" return {"api_key": "abc123", "debug": True, "rate_limit": 100} ``` The serializer function takes any data object and returns a string representation. This is applied to **all non-string return values** from your tools. Tools that already return strings bypass the serializer. This customization is useful when you want to: - Format data in a specific way (like YAML or custom formats) - Control specific serialization options (like indentation or sorting) - Add metadata or transform data before sending it to clients If the serializer function raises an exception, the tool will fall back to the default JSON serialization to avoid breaking the server. ## Authentication FastMCP inherits support for OAuth 2.0 authentication from the MCP protocol, allowing servers to protect their tools and resources behind authentication. ### OAuth 2.0 Support The `mcp.server.auth` module implements an OAuth 2.0 server interface that servers can use by providing an implementation of the `OAuthServerProvider` protocol. ```python from fastmcp import FastMCP from mcp.server.auth.settings import ( RevocationOptions, ClientRegistrationOptions, AuthSettings, ) # Create a server with authentication mcp = FastMCP( name="SecureApp", auth_provider=MyOAuthServerProvider(), auth=AuthSettings( issuer_url="https://myapp.com", revocation_options=RevocationOptions( enabled=True, ), client_registration_options=ClientRegistrationOptions( enabled=True, valid_scopes=["myscope", "myotherscope"], default_scopes=["myscope"], ), required_scopes=["myscope"], ), ) ```