PTENES
MODULE 3.1

🏗️ MCP Server Structure

Understand the complete anatomy of an MCP Server—from imports to tool registration and the lifecycle of a request.

6
Topics
25
Minutes
Intermediate
Level
Theoretical
Type
1

📋 Anatomy of a Server

An MCP Server in Python with FastMCP is surprisingly simple. In just ~10 lines of code, you have a complete, functional server, ready to receive requests from any compatible MCP client. The structure follows a clear pattern: imports, creating the server instance, functions decorated with @mcp.tool() and the entry point. Each part has a specific and essential role in how the server works.

💎 Core Concept

An MCP Server built with FastMCP has four fundamental components: Import — brings the FastMCP framework into your code; Instance — creates the server object with an identifying name; Tools — Python functions decorated with @mcp.tool() that the model can call; and Entry point — the block if __name__ == "__main__" that starts the server. With just these four pieces, you have a functional MCP server in ~10 lines of code.

💡 Practical Tip

The minimum structure of an MCP Server is: (1) from fastmcp import FastMCP — (2) mcp = FastMCP("meu-server") — (3) a function decorated with @mcp.tool() — (4) mcp.run() in the main block. Memorize this sequence: import → instantiate → decorate → run. Every MCP Server follows this pattern, from the simplest to the most complex.

2

🔧 Initialization and Setup

It all starts with two lines of code: the FastMCP import and the creation of the server instance. These two lines establish the foundation on which everything else is built. The name you give the server matters—it’s how the MCP client identifies and displays the server to the user. Choose descriptive, consistent names.

💎 Core Concept

Starting an MCP Server takes two steps: from fastmcp import FastMCP — imports the framework's main class — and mcp = FastMCP("nome-do-server") — creates the server instance with an identifying name. The name passed as an argument is what appears in the client (such as Claude Desktop) so the user knows which server is available. This name should be unique and descriptive of the server's purpose.

📊 Data and Research

FastMCP is the official framework recommended by Anthropic for creating MCP Servers in Python. It abstracts away all the complexity of the MCP protocol (JSON-RPC, stdio/SSE transport, capability negotiation) behind a simple decorator-based API. With FastMCP, what once required hundreds of lines of low-level code now takes fewer than 10 lines. It’s the fastest and recommended way to create an MCP Server.

❌ Avoid
  • •Generic names: “server,” “mcp,” “test”
  • •Names with spaces or special characters
  • •Names that don’t describe the server’s function
  • •Reuse the same name across different servers
✅ Do
  • •Descriptive names: “weather-server,” “db-query”
  • •Use kebab-case for consistency
  • •Include the domain: "github-issues", "slack-bot"
  • •Unique names that prevent conflicts
3

📝 Registering Tools

The heart of an MCP Server is its tools—Python functions the AI model can call. FastMCP uses the decorator @mcp.tool() to turn any regular Python function into an MCP tool the client can access. The function’s parameters become the tool’s parameters, the type hints define the schema, and the docstring becomes the description the model reads to decide when to use the tool.

💎 Core Concept

The decorator @mcp.tool() is the bridge between Python and the MCP protocol. When you decorate a function with it, three things happen automatically: (1) The function name becomes the tool name; (2) Parameter type hints are converted into JSON Schema for validation; (3) The function’s docstring becomes the description the model uses to understand the tool’s purpose. No need to write a single line of configuration.

💡 Practical Tip

Think of the decorator @mcp.tool() as a publication badge: when you add the decorator to a function, you're saying "this function is available for the AI to use." Without the decorator, the function is just internal Python code. With it, the function becomes a server capability visible to any connected MCP client. Each decorated function is automatically registered in the server's tool list.

📋 How Tool Registration Works
Step 1

You write a regular Python function with type hints and a docstring—as you would in any Python project.

Step 2

Add the decorator @mcp.tool() above the function—FastMCP detects and registers the tool automatically.

Step 3

FastMCP extracts the name, parameters (via type hints), and description (via docstring), then generates the JSON Schema automatically.

Step 4

When the client connects, the server sends the list of available tools — and the model knows exactly how to call them.

4

🔄 Lifecycle

An MCP Server isn’t a program that runs and exits — it’s a process that stays active, waiting for connections and continuously processing requests. Understanding the server’s full lifecycle is essential for debugging issues, optimizing performance, and building robust servers that work reliably in production.

💎 Core Concept

The lifecycle of an MCP Server follows a well-defined sequence: the server starts when the client executes it; registers its capabilities (tools, resources, prompts); waits for connections via stdio or SSE; receives requests from the client (tool calls); executes the logic of the tool call; returns the result to the client; and returns to wait the next request. This cycle repeats until the client closes the connection.

📋 Complete Server Lifecycle
1. Initialization

The client (e.g., Claude Desktop) runs the configured command. The Python process starts, and FastMCP loads all decorated tools.

2. Capability Registration

The server sends the client a list of all available tools, resources, and prompts, along with their schemas and descriptions.

3. Wait for Connections

The server loops, waiting for messages from the client over the configured transport (stdio for local processes, SSE for remote ones).

4. Receives Request

When the model decides to use a tool, the client sends a JSON-RPC message with the tool name and arguments.

5. Execute the Tool

FastMCP locates the corresponding function, validates the parameters against the schema, and runs the Python function.

6. Returns and Waits

The result is serialized and sent back to the client. The server returns to a waiting state, ready for the next request.

5

📁 File Structure

An MCP Server can be as simple as a single Python file or as organized as a complete project with tests, documentation, and separate modules. The choice depends on the complexity of what you’re building. A minimal project is enough for learning and prototyping. For production, an organized structure makes all the difference in maintainability.

💎 Core Concept

Minimal project — two files are enough: pyproject.toml (metadata and dependencies) and server.py (server code). That's all you need for a functional MCP Server. Complete project — for more robust servers, organize with: directory src/ for source code, tests/ for tests, README.md for documentation, and potentially multiple modules to separate responsibilities.

❌ Avoid
  • •Put everything in one giant file
  • •Don't use pyproject.toml to manage dependencies
  • •Mixing business logic with server setup
  • •Ignore tests from the start of the project
✅ Do
  • •Start small (2 files) and grow as needed
  • •Use uv + pyproject.toml for dependency management
  • •Separate tools into modules as the server grows
  • •Keep a README with setup instructions
6

⚙️ Essential Settings

The file pyproject.toml is the configuration hub for your Python project. It defines dependencies (such as FastMCP), project metadata, and optionally entry points that make execution easier. The uv is the recommended project manager—it handles the virtual environment, dependencies, and execution quickly and reliably.

💎 Core Concept

O pyproject.toml defines: the project name, the required Python version, the dependencies (including fastmcp), and optionally entry points with [project.scripts]. O uv manages everything: automatically creates the virtual environment, installs dependencies quickly, and lets you run the server with uv run server.py. Together, pyproject.toml and uv eliminate the complexity of configuring a Python environment.

💡 Practical Tip

Use uv init nome-do-projeto to create pyproject.toml automatically, and uv add fastmcp to add the dependency. uv will create the virtual environment, resolve dependencies, and update pyproject.toml — all in a single command. You never need to run pip install manually or manage virtualenvs by hand.

🚨 Alert

Make sure the uv is installed on your machine before you begin. Claude Desktop runs the server using the command uv run, so if uv isn’t available in PATH, the server simply won’t start — and the error may be silent. Check with uv --version before proceeding. If it isn’t installed, use curl -LsSf https://astral.sh/uv/install.sh | sh.

📝 Module Summary

  • ✓ An MCP Server with FastMCP has 4 parts: imports, an instance, decorated tools, and an entry point — ~10 lines of code.
  • ✓ Initialization uses from fastmcp import FastMCP e mcp = FastMCP("nome") — the name identifies the server in the client.
  • ✓ The decorator @mcp.tool() turns Python functions into MCP tools, automatically extracting the name, parameters, and description.
  • ✓ The lifecycle follows: start → register capabilities → wait → receive → execute → return → wait.
  • ✓ Minimal project: pyproject.toml + server.py. Complete project: src/, tests/, README, and separate modules.
  • ✓ uv manages the virtual environment, dependencies, and execution — use uv init e uv add fastmcp to get started.

Next Module: 3.2 — Hello World MCP