Crear tu propio servidor MCP en Python (tutorial paso a paso)

Construir un servidor MCP propio toma menos de 50 líneas en Python. Aquí un ejemplo real: exponer una API interna de inventario como tool para Claude.

Prerrequisitos

  • Python 3.10+ y uv.
  • SDK oficial: uv add mcp.

Estructura mínima

mi_servidor/
  pyproject.toml
  src/
    __init__.py
    server.py

server.py — 40 líneas

from mcp.server.fastmcp import FastMCP
import httpx

mcp = FastMCP("inventario-empresa")

API_BASE = "https://api.miempresa.cl/v1"
TOKEN = "..."

@mcp.tool()
async def buscar_producto(nombre: str) -> dict:
    """Busca un producto en el inventario por nombre."""
    async with httpx.AsyncClient() as c:
        r = await c.get(f"{API_BASE}/productos", params={"q": nombre},
                        headers={"Authorization": f"Bearer {TOKEN}"})
        return r.json()

@mcp.tool()
async def stock(sku: str) -> dict:
    """Devuelve el stock actual por SKU."""
    async with httpx.AsyncClient() as c:
        r = await c.get(f"{API_BASE}/stock/{sku}",
                        headers={"Authorization": f"Bearer {TOKEN}"})
        return r.json()

if __name__ == "__main__":
    mcp.run()

Configurarlo en Claude Desktop

{
  "mcpServers": {
    "inventario": {
      "command": "uv",
      "args": ["--directory", "/ruta/mi_servidor", "run", "server.py"]
    }
  }
}

Probar

Reinicia Claude Desktop y pregunta: “¿Hay stock de SKU-123?”. Claude llamará automáticamente a stock("SKU-123").

Buenas prácticas

  • Validación: usa Pydantic para los inputs.
  • Errores: lanza McpError; el cliente los muestra al usuario.
  • Logs: usa logging, no print (rompe stdio).
  • Tests: el SDK incluye mcp.client para tests in-process.
  • Distribuir: publica en PyPI o un registry privado; instalable con uvx tu-paquete.

Recursos