Crea tu propio servidor MCP con Python
Construye un servidor MCP con Python FastMCP — @mcp.tool() y @mcp.resource(), manejo de errores, conexión a Claude Desktop y testing local.
🔄 En la lección 4 aprendiste las tres primitivas: Tools, Resources y Prompts. Ahora vas a implementarlas tú mismo.
¿Cuándo necesitas un servidor propio?
Hay 8,600+ servidores MCP disponibles. Pero necesitas uno propio cuando:
- Tu sistema interno (wiki corporativa, ticketing, BD privada) no tiene servidor público
- Tienes lógica de negocio específica que no cubre ningún servidor existente
- Quieres combinar varias APIs en una sola interfaz para la IA
Con FastMCP (SDK de Python), empiezas con 30 líneas de código.
Configurar FastMCP
# Instalar FastMCP
pip install fastmcp
# Verificar
python -c "import mcp; print('OK')"
Tu primer servidor: lista de tareas
Empecemos con algo que funcione inmediatamente.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("todo-server")
# Lista de tareas en memoria
tareas = []
@mcp.tool()
def agregar_tarea(texto: str) -> str:
"""Agregar una nueva tarea a la lista"""
tareas.append({"texto": texto, "completada": False})
return f"Tarea agregada: {texto}"
@mcp.tool()
def listar_tareas() -> str:
"""Mostrar todas las tareas"""
if not tareas:
return "No hay tareas"
return "\n".join(
f"{'✅' if t['completada'] else '⬜'} {t['texto']}"
for t in tareas
)
@mcp.tool()
def completar_tarea(indice: int) -> str:
"""Marcar una tarea como completada"""
if 0 <= indice < len(tareas):
tareas[indice]["completada"] = True
return f"Completada: {tareas[indice]['texto']}"
return "Índice no válido"
if __name__ == "__main__":
mcp.run()
Eso es todo. Tres herramientas (agregar, listar, completar) en un servidor MCP funcional.
✅ Quick Check: ¿Por qué
agregar_tarease define como @mcp.tool() y no como @mcp.resource()? (Porque agregar una tarea modifica el estado — tiene efectos secundarios. Los resources son solo lectura.)
Agregar un Resource
Añadamos datos de solo lectura al servidor:
@mcp.resource("todo://resumen")
def resumen_tareas() -> str:
"""Resumen de la lista de tareas"""
total = len(tareas)
completadas = sum(1 for t in tareas if t["completada"])
return f"Total: {total} | Completadas: {completadas} | Pendientes: {total - completadas}"
Los resources se identifican por URI. todo://resumen expone estadísticas que la IA puede consultar como contexto.
Ejemplo práctico: servidor de clima
Un servidor que se conecta a una API externa:
import httpx
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather-server")
@mcp.tool()
def obtener_clima(ciudad: str) -> str:
"""Obtener el clima actual de una ciudad"""
url = f"https://api.ejemplo.com/clima?ciudad={ciudad}"
respuesta = httpx.get(url)
datos = respuesta.json()
return f"{ciudad}: {datos['temp']}°C, {datos['condicion']}"
@mcp.tool()
def pronostico(ciudad: str, dias: int = 3) -> str:
"""Obtener el pronóstico de los próximos días"""
url = f"https://api.ejemplo.com/pronostico?ciudad={ciudad}&dias={dias}"
respuesta = httpx.get(url)
return respuesta.json()
FastMCP lee los type hints (ciudad: str, dias: int = 3) y los docstrings para generar automáticamente el schema del tool.
Manejo de errores
En producción, el manejo de errores no es opcional:
@mcp.tool()
def consultar_bd(sql: str) -> str:
"""Ejecutar una consulta SQL (solo lectura)"""
palabras_prohibidas = ["DROP", "DELETE", "INSERT", "UPDATE"]
if any(p in sql.upper() for p in palabras_prohibidas):
return "Error: solo se permiten consultas SELECT"
try:
resultado = db.execute(sql)
return str(resultado.fetchall())
except Exception as e:
return f"Error en la consulta: {str(e)}"
Filtramos keywords peligrosos en el SQL para forzar el modo solo lectura, incluso si la IA intenta escribir.
Conectar a Claude Desktop
Añade tu servidor al archivo de configuración:
{
"mcpServers": {
"tareas": {
"command": "python",
"args": ["/Users/tu-usuario/proyectos/todo_server.py"],
"env": {}
}
}
}
Si empaquetaste el servidor, puedes usar uvx:
{
"mcpServers": {
"tareas": {
"command": "uvx",
"args": ["todo-server"],
"env": {}
}
}
}
Reinicia Claude Desktop y verifica que aparezcan las herramientas.
Testing local
Antes de conectar a Claude Desktop, prueba tu servidor en local:
# Abre el MCP Inspector en tu navegador
fastmcp dev todo_server.py
El Inspector te permite llamar a cada herramienta manualmente, ver los parámetros y resultados. Muy útil para depurar antes de integrar.
✅ Quick Check: ¿Para qué sirve el comando
fastmcp dev? (Abre el MCP Inspector en tu navegador, donde puedes probar cada herramienta de tu servidor sin necesidad de Claude Desktop. Es la herramienta de desarrollo principal.)
Puntos clave
- FastMCP (Python) permite crear servidores MCP en ~30 líneas de código
@mcp.tool()para acciones con efectos secundarios,@mcp.resource()para datos de solo lectura- Type hints y docstrings generan automáticamente el schema de herramientas
- Manejo de errores es obligatorio — filtra SQL peligroso, captura excepciones
claude_desktop_config.jsonpara conectar,fastmcp devpara probar
Siguiente lección
Ya sabes crear un servidor. En la lección 6 aprenderás a combinar múltiples servidores con Claude Code — incluyendo Tool Search para optimizar tokens y el patrón de loop agéntico en la práctica.
Comprobación de Conocimientos
Primero completa el quiz de arriba
¡Lección completada!