Build Your Own MCP Server with Python

Hands-on server development using Python, MCP tools, resources, structured output, APIs, databases and tests.

Practical mini-lab

Turn an existing order API into agent-safe tools

Imagine you already have a FastAPI service with GET /orders/{id} and POST /orders/{id}/refund. Instead of exposing raw HTTP to an agent, wrap the useful business actions as narrow MCP tools.

@mcp.tool()
async def get_order(order_id: str) -> dict:
    return await orders.find(order_id)

@mcp.tool()
async def request_refund(order_id: str, reason: str) -> dict:
    order = await orders.find(order_id)
    if order["status"] != "delivered":
        raise ValueError("Only delivered orders can be refunded")
    return await refunds.create(order_id, reason)
Why this is better

The agent sees business-level actions with clear parameters instead of guessing URLs, methods and payloads.

What still belongs on the server

Authorization, refund rules, audit logging and idempotency. Never trust the model to enforce them.

Trade-off: narrow tools take more design work, but they are safer, easier to test and easier for models to select correctly.

Build outcome

By the end of this module you should be able to expose a real backend capability as an MCP server without duplicating your application logic.