AI and MCP
How to Build an MCP Server: A Step-by-Step Guide (with Python Code)
Updated on:
June 9, 2026

TL;DR:
What you build: An MCP server exposes tools, resources, and prompts to AI clients like Claude over a standard protocol, so a model can call your code and data.
The fastest path: Python with FastMCP. You write normal Python functions, decorate them, and the framework handles the protocol.
The steps: set up a project with uv, define a tool, run the server, test it with the MCP Inspector, and connect it to Claude Desktop.
The shortcut for API teams: if you already have an API, you can generate an MCP server from its OpenAPI spec instead of hand-writing every tool.
Before production: move from a local stdio server to a remote HTTP server, and put authentication, rate limits, and audit in front of it with a gateway.
The Model Context Protocol (MCP) is how AI applications connect to your tools and data. Building a server is the way you expose your own functions to an AI model. This guide walks through building one in Python with FastMCP, testing it, connecting it to Claude, the faster path for teams that already have an API, and what changes when you take it to production. The code is copy-pasteable.
What you will build and what you need
By the end you will have a working MCP server that exposes a tool an AI model can call, plus a resource and a prompt, tested locally and connected to Claude Desktop.
You need:
- Python 3.10 or newer.
- uv, a fast Python package manager that handles environments and dependencies.
- An MCP client to test with, such as Claude Desktop or the MCP Inspector (covered below).
- Basic Python. You do not need to know the protocol itself, the framework handles it.
What is an MCP server? Tools, resources, and prompts
An MCP server is a small program that exposes capabilities to an AI client over a standard interface (JSON-RPC, carried over stdio or streamable HTTP). It can expose three kinds of capability:
- Tools: Functions the model can call to take an action or fetch live data, like "create a ticket" or "look up an order." This is what most servers are built for.
- Resources: Read-only data the model can load for context, like a file or a config value.
- Prompts: Reusable prompt templates a user can invoke.
The server's job is to describe these clearly and handle the calls. The framework you use takes care of the wire protocol.
How to build an MCP server in Python, step by step
We will use FastMCP, the most popular Python framework for MCP. Its philosophy is simple: write Python, not protocol boilerplate. It turns a function's name into the tool name, its docstring into the description, and its type hints into the input schema.
Step 1: Set up the project
Create a project and add FastMCP:
uv init mcp-demo
cd mcp-demo
uv add fastmcpStep 2: Create the server and add a tool
Create a file called `server.py`. Define a FastMCP instance and decorate a function to expose it as a tool:
from fastmcp import FastMCP
mcp = FastMCP("Demo Server")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two numbers and return the result."""
return a + b
@mcp.tool
def to_fahrenheit(celsius: float) -> float:
"""Convert a Celsius temperature to Fahrenheit."""
return celsius * 9 / 5 + 32
if __name__ == "__main__":
mcp.run()That is a complete, working MCP server. FastMCP reads the type hints (`a: int`, `b: int`) to build the input schema and the docstring to describe the tool, so the model knows exactly how to call it.
Step 3: Add a resource and a prompt
Tools are the core, but a useful server often exposes a resource and a prompt too. Add these to `server.py`:
@mcp.resource("config://version")
def version() -> str:
"""Expose the server version as a resource."""
return "1.0.0"
@mcp.prompt
def summarize(text: str) -> str:
"""Build a prompt that asks the model to summarize text."""
return f"Summarize the following in three short bullet points:\n\n{text}"A resource is addressed by a URI (here `config://version`) and returns read-only data. A prompt returns a reusable template the user can invoke from the client.
Step 4: Run the server
Run it directly:
python server.pyBy default the server runs over stdio, which is how desktop clients like Claude launch and talk to local servers.
How to test and connect your MCP server
Test with the MCP Inspector
Before wiring it into a client, test it in isolation. FastMCP ships a dev command that launches the MCP Inspector, a browser-based UI for calling your tools:
fastmcp dev server.pyThis opens the Inspector (typically at http://127.0.0.1:6274), where you can list your tools, resources, and prompts and call them with test inputs. It is the fastest way to confirm the server works before involving a model.
Connect to Claude Desktop
To use the server in Claude Desktop, add it to the client's config file (`claude_desktop_config.json`):
{
"mcpServers": {
"demo": {
"command": "uv",
"args": ["run", "python", "server.py"]
}
}
}Restart Claude Desktop, and your tools appear. When you ask Claude something that matches a tool, it will request to call it, and on approval your Python function runs.
One gotcha to remember for stdio servers: never write to standard output (no stray `print()` statements). The protocol uses stdout for JSON messages, and printing to it corrupts them and breaks the server. Log to standard error instead.
The shortcut: build an MCP server from your OpenAPI spec
Writing a tool per function is fine for a handful of capabilities. But if you are an API team with dozens or hundreds of endpoints already described in an OpenAPI spec, hand-writing a tool for each one is wasted effort. You can generate the server from the spec instead.
FastMCP can do this directly:
import httpx
from fastmcp import FastMCP
spec = httpx.get("https://api.example.com/openapi.json").json()
client = httpx.AsyncClient(base_url="https://api.example.com")
mcp = FastMCP.from_openapi(openapi_spec=spec, client=client, name="My API")
if __name__ == "__main__":
mcp.run()Every endpoint in the spec becomes a tool, with schemas derived from the spec. This is the most efficient path for teams that already run APIs. At enterprise scale, DigitalAPI does this across your whole estate, generating governed MCP endpoints from your existing OpenAPI specs so you do not maintain a separate server per API by hand.
From local to production: deploy and govern your server
The server above runs locally over stdio. Production is different in two ways.
Remote MCP servers
To serve a server to remote clients and agents, you run it over streamable HTTP rather than stdio. FastMCP supports this by changing how you run it (for example, running with an HTTP transport), and you host it like any web service, on a container platform, a serverless function, or behind your existing infrastructure.
Securing and governing with a gateway
Once a server is remote and real agents can call it, it needs the same controls as any production API:
- Authentication: Scoped tokens per client or agent, typically via OAuth, not a shared secret.
- Authorization: Role-based access so a client can only reach the tools it is entitled to.
- Rate limits: Per-client quotas so an automated loop cannot overwhelm your systems.
- Audit logging: A record of which client called which tool, when, for security and compliance.
This is where an MCP gateway sits. DigitalAPI puts a governed gateway in front of your MCP servers, applying authentication, RBAC, rate limits, and audit consistently, and unifying it with the way you already govern your APIs. If you are taking MCP servers to production and need that control, book a demo and we will map it to your stack.
Common mistakes to avoid
- Writing to stdout in a stdio server: Any stray print corrupts the JSON-RPC stream. Log to stderr.
- Skipping type hints and docstrings: FastMCP builds the tool schema and description from them, so vague hints mean the model calls your tool badly.
- Doing too much in one tool: Keep each tool focused. One clear job per tool is easier for a model to use correctly.
- Shipping without auth: A local demo needs none, but a remote server that takes actions must be authenticated and rate-limited before it goes live.
- Hand-coding tools you could generate: If the capability is an existing API, generate the server from the OpenAPI spec instead.
FAQs
How do I build an MCP server?
Pick a language with an MCP SDK (Python with FastMCP is the fastest), define your capabilities as tools, run the server over stdio for local use, test it with the MCP Inspector, and connect it to a client like Claude Desktop.
What language should I use to build an MCP server?
Python and TypeScript have the most mature SDKs. Python with FastMCP is the quickest for prototyping and stdio servers; TypeScript suits teams already in the Node ecosystem. Go and other SDKs also exist.
What is FastMCP?
FastMCP is a Python framework that builds MCP servers from plain functions. It turns a function name into the tool name, the docstring into the description, and type hints into the input schema, so you write business logic instead of protocol code.
How do I test an MCP server?
Use the MCP Inspector, a browser-based tool launched with a command like `fastmcp dev server.py`. It lets you list and call your tools, resources, and prompts with test inputs before connecting a model.
How do I connect an MCP server to Claude?
Add the server to Claude Desktop's `claude_desktop_config.json` with the command and arguments to run it, then restart Claude. Your tools then appear and Claude can call them with your approval.
Can I build an MCP server from an existing API?
Yes. Frameworks like FastMCP can generate a server from an OpenAPI spec, turning each endpoint into a tool. For a large API estate, a platform like DigitalAPI generates governed MCP endpoints from your specs automatically.
How do I deploy a remote MCP server?
Run it over streamable HTTP instead of stdio and host it like any web service, on a container, a serverless function, or your existing platform. Put authentication and rate limiting in front of it before going live.
Do I need to secure my MCP server?
A local demo, no. A remote server that takes actions, yes. It needs authentication, role-based access, rate limits, and audit logging, which is what an MCP gateway provides.
%20(1).png)



.avif)
