# Chapter 2: Easier Server Building with `FastMCP`
In [Chapter 1: Your Control Panel - The `mcp` Command-Line Interface](01_cli___mcp__command_.md), we learned how to use the `mcp` command to run, test, and install MCP servers. We even saw a tiny example of a server file. But how do we *build* that server code without getting lost in complex details?
Imagine you want to build a simple AI assistant that can just echo back whatever you type. Writing all the code to handle connections, interpret messages according to the MCP protocol, manage capabilities – it sounds like a lot of work just for an echo!
This is where `FastMCP` comes in. It's designed to make building MCP servers much, much easier.
## What is `FastMCP`?
Think of the low-level parts of the MCP protocol like individual kitchen tools: a pot, a pan, a knife, a whisk. You *could* use them all individually to cook a meal, but you'd need to know exactly when and how to use each one.
`FastMCP` is like a fancy **kitchen multi-cooker**. It bundles many common functions together in an easy-to-use package. You provide the ingredients (your Python functions and data) and press simple buttons (special markers called **decorators** like `@tool`, `@resource`, `@prompt`), and `FastMCP` handles the complex cooking process (managing the low-level MCP details) for you.
**Key benefits of using `FastMCP`:**
***Simplicity:** Hides a lot of the complex MCP protocol details.
***Developer-Friendly:** Uses familiar Python concepts like functions and decorators.
***Less Boilerplate:** Reduces the amount of repetitive setup code you need to write.
***Built-in Features:** Includes easy ways to manage settings, automatically tell clients what your server can do (capability generation), and handle common tasks.
## Your First `FastMCP` Server: The Foundation
Let's start with the absolute minimum needed to create a `FastMCP` server.
**File: `my_simple_server.py`**
```python
# 1. Import the FastMCP class
frommcp.server.fastmcpimportFastMCP
# 2. Create an instance of the FastMCP server
# Give it a name clients might see.
# Optionally, provide general instructions.
server=FastMCP(
name="MySimpleServer",
instructions="This is a very simple example server."
)
# 3. Add the standard Python block to run the server
# when the script is executed directly.
if__name__=="__main__":
print(f"Starting {server.name}...")
# This tells FastMCP to start listening for connections
server.run()
print(f"{server.name} finished.")# Usually only seen after stopping (Ctrl+C)
```
**Explanation:**
1.**`from mcp.server.fastmcp import FastMCP`**: We import the main `FastMCP` class from the SDK.
2.**`server = FastMCP(...)`**: We create our "multi-cooker" object.
*`name="MySimpleServer"`: This is a human-readable name for your server. Clients might display this name.
*`instructions="..."`: This provides a general description or purpose for the server. Clients can use this to understand what the server does.
3.**`if __name__ == "__main__":`**: This is a standard Python pattern. The code inside this block only runs when you execute the script directly (e.g., using `python my_simple_server.py` or `mcp run my_simple_server.py`).
4.**`server.run()`**: This is the command that actually starts the server. It tells `FastMCP` to begin listening for incoming connections and handling MCP messages. By default, it uses the "stdio" transport (reading/writing from the terminal), which we discussed briefly in Chapter 1.
If you save this code as `my_simple_server.py` and run it using `mcp run my_simple_server.py` (as learned in Chapter 1), it will start! It won't *do* much yet, because we haven't added any specific capabilities, but it's a functioning MCP server.
## Adding Features with Decorators: The "Buttons"
Our multi-cooker (`FastMCP`) is running, but it doesn't have any cooking programs yet. How do we add features, like our "echo" tool? We use **decorators**.
Decorators in Python are special markers starting with `@` that you place above a function definition. They modify or enhance the function in some way. `FastMCP` uses decorators like `@server.tool()`, `@server.resource()`, and `@server.prompt()` to easily register your Python functions as capabilities that clients can use.
Let's add an "echo" tool using the `@server.tool()` decorator.
**File: `echo_server.py` (Simpler Version)**
```python
frommcp.server.fastmcpimportFastMCP
# 1. Create the server instance
server=FastMCP(name="EchoServer")
# 2. Define the tool using the @server.tool decorator
@server.tool(name="echo",description="Repeats the input message back.")
defecho(message:str)->str:
"""
This function is now registered as the 'echo' tool.
'message: str' tells FastMCP the tool expects one argument
named 'message' which should be a string.
'-> str' tells FastMCP the tool will return a string.
"""
print(f"Tool 'echo' called with message: {message}")# Server-side log
# 3. The function's logic directly implements the tool
returnf"You said: {message}"
# 4. Standard run block
if__name__=="__main__":
print(f"Starting {server.name}...")
server.run()# Start listening
print(f"{server.name} finished.")
```
**Explanation:**
1.**`server = FastMCP(...)`**: Same as before, creates our server object.
2.**`@server.tool(...)`**: This is the magic!
* We use the `@tool()` method of our `server` object as a decorator.
*`name="echo"`: We explicitly tell `FastMCP` that this tool should be called `echo` by clients. If we omitted this, it would default to the function name (`echo`).
*`description="..."`: A helpful description for clients.
3.**`def echo(message: str) -> str:`**: This is a standard Python function.
*`message: str`: This is a **type hint**. It tells `FastMCP` (and other tools) that this function expects one argument named `message`, and that argument should be a string. `FastMCP` uses this information to automatically validate input from clients and generate documentation.
*`-> str`: This type hint indicates that the function will return a string. `FastMCP` uses this to know what kind of output to expect.
* The function body contains the logic for our tool.
4.**`server.run()`**: Starts the server, which now knows about the `echo` tool thanks to the decorator.
Now, if you run `mcp run echo_server.py`, the server will start and will be capable of responding to requests for the `echo` tool! A client could send a "callTool" request with the name "echo" and an argument `{"message": "Hello!"}`, and `FastMCP` would automatically run your `echo` function and send back the result `"You said: Hello!"`.
We'll explore `@server.resource()` and `@server.prompt()` in later chapters:
## How `FastMCP` Works Under the Hood (Simplified)
It feels simple to use, but what's `FastMCP` actually doing?
1.**Initialization:** When you create `FastMCP()`, it sets up internal managers for tools, resources, and prompts (like `_tool_manager`, `_resource_manager`, `_prompt_manager`).
2.**Registration:** When Python encounters `@server.tool(...)` above your `echo` function, it calls the `server.tool()` method. This method takes your `echo` function and its details (name, description, parameter types from hints) and registers it with the internal `_tool_manager`.
3.**Running:** When you call `server.run()`, `FastMCP` starts the underlying low-level MCP server machinery. This machinery listens for incoming connections (e.g., via stdio or web protocols).
4.**Handling Requests:** When a client connects and sends an MCP message like `{"method": "callTool", "params": {"name": "echo", "arguments": {"message": "Test"}}}`:
* The low-level server receives the raw message.
*`FastMCP`'s core logic takes over. It sees it's a `callTool` request for the tool named `echo`.
* It asks its `_tool_manager` if it knows about a tool named `echo`.
* The `_tool_manager` finds the registered `echo` function.
*`FastMCP` extracts the `arguments` (`{"message": "Test"}`) from the request.
* It validates these arguments against the function's signature (`message: str`).
* It calls your actual Python `echo` function, passing `"Test"` as the `message` argument.
* Your function runs and returns `"You said: Test"`.
*`FastMCP` takes this return value, packages it into a valid MCP `callTool` response message, and sends it back to the client via the low-level machinery.
**Sequence Diagram:**
```mermaid
sequenceDiagram
participant Client
participant FastMCP_Server as FastMCP (echo_server.py)
# Converts the function's return value (e.g., "You said: Test")
# into the format MCP expects for the response.
converted_result=_convert_to_content(result)
returnconverted_result
def_setup_handlers(self)->None:
"""Set up core MCP protocol handlers."""
# This line connects the low-level 'callTool' message
# to the 'self.call_tool' method shown above.
self._mcp_server.call_tool()(self.call_tool)
# (...) other handlers for listTools, readResource etc. (...)
```
This shows how an incoming `callTool` message gets routed to the `call_tool` method, which then uses the `_tool_manager` to run your registered function.
## Conclusion
You've now seen how `FastMCP` provides a much simpler way to build MCP servers compared to handling the low-level protocol directly. Like a multi-cooker, it offers convenient "buttons" (decorators like `@server.tool()`) to add features (like tools) to your server using standard Python functions. It handles the underlying complexity of receiving requests, calling your code, and sending responses.
You learned how to:
* Create a basic `FastMCP` server instance.
* Define a Python function that performs a task.
* Use the `@server.tool()` decorator to register that function as a tool clients can call.
* Understand the basic flow of how `FastMCP` handles a tool call request using its internal managers.
While our `echo` tool was simple, `FastMCP` provides the foundation for building much more complex and powerful AI agents and tools.
In the next chapters, we'll explore the other "buttons" on our multi-cooker, starting with how to provide data and files using `@server.resource()` in [Chapter 3: FastMCP Resources (`Resource`, `ResourceManager`)](03_fastmcp_resources___resource____resourcemanager__.md).
---
Generated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)