How-to guide
How to implement the Model Context Protocol (MCP) in Python
Build an MCP server in Python step by step: define tools with the official SDK, test them, connect a client such as Claude Desktop, and keep it safe.
Short answer: install the official Python SDK (pip install mcp), create a server object, turn ordinary Python
functions into tools with a decorator (the type hints and docstring become the tool's schema and description), and
call run(). Any MCP client, such as Claude Desktop or an IDE agent, can then discover and call your tools over the
standard protocol, without custom glue code for each app.
What MCP is, in one paragraph
The Model Context Protocol is an open standard for connecting AI applications to tools and data. An MCP server exposes tools (functions the model may call), resources (data it may read) and prompts (reusable templates). An MCP client inside an AI app lists what the server offers and calls it when the model asks. Write the server once and every MCP-capable app can use it.
Step 1: a server with one tool
from mcp.server.mcpserver import MCPServer # SDK 2.x; in 1.x the class was FastMCP (mcp.server.fastmcp)
mcp = MCPServer("invoice-tools")
@mcp.tool()
def gst_amount(net: float, rate: float = 18.0) -> float:
"""GST payable on a net amount."""
return round(net * rate / 100, 2)
if __name__ == "__main__":
mcp.run() # serves over stdio, the transport desktop clients use
The decorator reads the signature: net is a required number, rate an optional one, and the docstring is the
description the model sees. Good names and docstrings matter, because they are how the model decides when to call
the tool.
Step 2: test the tool before connecting anything
The decorated function is still a normal function, so unit-test it with pytest. You can also ask the server what it exposes:
import asyncio
tools = asyncio.run(mcp.list_tools())
print([t.name for t in tools]) # ['gst_amount']
print(tools[0].input_schema["properties"].keys())
See this exact example run, with its real output, on the Model Context Protocol glossary page.
Step 3: connect a client
Desktop clients start your server as a subprocess. In Claude Desktop, for example, you add an entry to its MCP configuration file:
{ "mcpServers": { "invoice-tools": { "command": "python", "args": ["/full/path/to/server.py"] } } }
Restart the app and the tool appears. For a server other people use over the network, the SDK also offers an HTTP transport (streamable HTTP); put authentication in front of it.
Step 4: add resources and keep it safe
- Resources give read-only context (a ledger, a policy document) without letting the model change anything.
- Least privilege. Expose the smallest set of actions. A "read invoice" tool and a separate "post payment" tool are safer than one "do anything" tool.
- Human approval for writes. Anything that sends money, emails or deletes data should ask a person first.
- Treat tool output as untrusted. Text a tool returns can contain prompt-injection attempts; validate it.
- Log every call with its arguments and result, so you can audit what the agent did.
Common mistakes
- Vague tool names (
process,handle) that the model cannot choose between. - Returning huge payloads that flood the context window; return what the model needs.
- No input validation: type hints help, but check ranges and IDs yourself.
- Testing only through the chat app. Unit-test tools directly, then test the agent end to end with evals.
Where this is taught
Module 10 (Agents & MCP) of the program builds an MCP server and MCP clients that connect agents to spreadsheets, GitHub and databases, and ends with a finance-operations agent that asks for approval before any write. Related reads: What is an AI agent? · Building multi-agent systems · Function calling.