Los tres pilares que hacen que la integración de la herramienta LLM sea sorprendentemente sencilla.
Hace seis meses, pasé dos semanas creando un agente de atención al cliente «inteligente». Podía responder preguntas, consultar el estado de los pedidos e incluso procesar reembolsos. Estaba orgulloso de él.
El código de integración fue una pesadilla. Llamadas API personalizadas por todas partes. Análisis JSON que fallaba si faltaba un campo. Una función de 400 líneas solo para gestionar el enrutamiento de herramientas. Pero funcionaba, en su mayor parte.
Luego se lo mostré al equipo.
«¿Cuál es el estado del pedido 12345?», preguntó alguien.
El agente respondió con confianza con los detalles del pedido. Genial. Entonces alguien hizo una pregunta de seguimiento y el agente intentó volver a llamar a la función de búsqueda de pedidos. Excepto que esta vez, mi frágil lógica de análisis se atascó en un caso extremo. Todo se colgó. Delante de todo el mundo.
Pasé esa noche depurando y me di cuenta de que el problema no era mi lógica. Era la arquitectura. Había construido un castillo de naipes al intentar conectar un LLM a herramientas externas utilizando código personalizado. Cada nueva herramienta significaba más análisis personalizado. Cada caso extremo significaba más sentencias if.
Ese fracaso me llevó al MCP.
El Protocolo de Contexto de Modelo (MCP) es un estándar abierto que hace bien una cosa: proporciona a los LLM una forma limpia y coherente de descubrir y utilizar herramientas externas. Se acabó el análisis personalizado. Se acabaron las integraciones frágiles. Solo un protocolo que funciona.
Una vez que entendí MCP, reconstruí ese mismo agente en una tarde. Y no se ha bloqueado desde entonces.
Odio cuando la gente complica demasiado estas cosas. La mayoría de las explicaciones sobre MCP comienzan con especificaciones JSON-RPC y discusiones sobre la capa de transporte. Eso es al revés.
No es necesario comprender el funcionamiento interno del protocolo para utilizarlo, al igual que no es necesario comprender HTTP para crear una aplicación web.
Esto es lo que realmente necesitas: tres conceptos y unos 15 minutos.
Los tres pilares
MCP tiene tres pilares. Eso es todo.
Servidor: lo que expone tus herramientas. Es un script de Python que dice «estas son las funciones que puede llamar un LLM». Lo ejecutas y espera las solicitudes.
Herramienta: una función que quieres que utilice el LLM. Puede ser cualquier cosa: obtener el tiempo, consultar una base de datos, enviar un correo electrónico. La escribes como una función Python normal, añades un decorador y MCP se encarga del resto.
Cliente: lo que se conecta a tu servidor y llama a las herramientas. En producción, suele ser tu aplicación LLM. Para las pruebas, FastMCP te ofrece un cliente que funciona desde el primer momento.
El servidor expone las herramientas. El cliente llama a las herramientas. Ese es todo el modelo mental.
Todo lo demás (transportes, JSON-RPC, negociación de capacidades) son detalles de implementación. No es necesario pensar en ello hasta que se escala a producción.
Vamos a crear uno.
Paso 1: Instalar FastMCP
FastMCP es el marco de trabajo de Python que simplifica MCP. Una instalación, sin configuración.
pip install fastmcpEso es todo. No se necesitan entornos virtuales para este tutorial (aunque es recomendable tener uno en producción).
Paso 2: Crear el servidor
Crear un archivo llamado my_server.py:
from fastmcp import FastMCP
# Initialize the server with a name
mcp = FastMCP("my-first-server")
# Define a tool using the @mcp.tool decorator
@mcp.tool
def get_weather(city: str) -> dict:
"""Get the current weather for a city."""
# In production, you'd call a real weather API
# For now, we'll return mock data
weather_data = {
"new york": {"temp": 72, "condition": "sunny"},
"london": {"temp": 59, "condition": "cloudy"},
"tokyo": {"temp": 68, "condition": "rainy"},
}
city_lower = city.lower()
if city_lower in weather_data:
return {"city": city, **weather_data[city_lower]}
else:
return {"city": city, "temp": 70, "condition": "unknown"}
# Run the server
if __name__ == "__main__":
mcp.run(transport="stdio")Analicemos lo que está sucediendo:
FastMCP(«my-first-server»)crea tu servidor con un nombre@mcp.tooles el decorador que convierte cualquier función en una herramienta MCP- La cadena de documentación se convierte en la descripción de la herramienta (los LLM la utilizan para saber cuándo invocarla)
- Las sugerencias de tipo (
city: str,-> dict) indican a MCP las entradas y salidas esperadas transport=«stdio»significa que el servidor se comunica a través de la entrada/salida estándar (perfecto para pruebas locales)
Eso es todo tu servidor. 15 líneas de código real.
Paso 3: Crea un cliente para probarlo
Crea un archivo llamado test_client.py:
import asyncio
from fastmcp import Client
async def main():
# Point the client at your server file
client = Client("my_server.py")
# Connect to the server
async with client:
# List available tools
tools = await client.list_tools()
print("Available tools:")
for tool in tools:
print(f" - {tool.name}: {tool.description}")
print("\n" + "="*50 + "\n")
# Call the weather tool
result = await client.call_tool(
"get_weather",
{"city": "Tokyo"}
)
print(f"Weather result: {result}")
if __name__ == "__main__":
asyncio.run(main())Puntos clave:
Client(«my_server.py»)indica al cliente a qué servidor conectarseasync with client:gestiona automáticamente el ciclo de vida de la conexiónlist_tools()descubre qué herramientas están disponibles (esta es la detección dinámica de MCP)call_tool(«get_weather», {“city”: «Tokyo»})invoca la herramienta con parámetros
Paso 4: Ejecutarlo
Abre tu terminal y ejecuta:
python test_client.pyDeberías ver:
Available tools:
- get_weather: Get the current weather for a city.==================================================
Weather result: {'city': 'Tokyo', 'temp': 68, 'condition': 'rainy'}Eso es todo. Acabas de crear un servidor MCP y lo has invocado desde un cliente.
Paso 5: Añadir más herramientas
La potencia de MCP reside en lo fácil que es añadir capacidades. Añadamos dos herramientas más a nuestro servidor:
from fastmcp import FastMCP
from datetime import datetime
mcp = FastMCP("my-first-server")
@mcp.tool
def get_weather(city: str) -> dict:
"""Get the current weather for a city."""
weather_data = {
"new york": {"temp": 72, "condition": "sunny"},
"london": {"temp": 59, "condition": "cloudy"},
"tokyo": {"temp": 68, "condition": "rainy"},
}
city_lower = city.lower()
if city_lower in weather_data:
return {"city": city, **weather_data[city_lower]}
return {"city": city, "temp": 70, "condition": "unknown"}
@mcp.tool
def get_time(timezone: str = "UTC") -> str:
"""Get the current time in a specified timezone."""
# Simplified - in production use pytz or zoneinfo
return f"Current time ({timezone}): {datetime.now().strftime('%H:%M:%S')}"
@mcp.tool
def calculate(expression: str) -> dict:
"""Safely evaluate a mathematical expression."""
try:
# Only allow safe math operations
allowed_chars = set("0123456789+-*/.() ")
if not all(c in allowed_chars for c in expression):
return {"error": "Invalid characters in expression"}
result = eval(expression) # Safe because we validated input
return {"expression": expression, "result": result}
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
mcp.run(transport="stdio")Vuelva a ejecutar su cliente de prueba: detectará automáticamente las tres herramientas:
Available tools:
- get_weather: Get the current weather for a city.
- get_time: Get the current time in a specified timezone.
- calculate: Safely evaluate a mathematical expression.Sin cambios en la configuración. Sin lógica de enrutamiento. Usted añadió herramientas y MCP las puso a su disposición.
Próximo paso: conexión a un LLM
El cliente que hemos creado es para realizar pruebas. En producción, su marco LLM se conecta como cliente. Así es como se ve conceptualmente:
El código del servidor que escribiste no cambia. Esa es la ventaja de MCP: creas herramientas una vez y cualquier cliente compatible con MCP puede utilizarlas.
Para implementaciones de producción, también cambiarías del transporte stdio a http:
if __name__ == "__main__":
mcp.run(transport="http", host="0.0.0.0", port=8000)Esto expone su servidor MCP como un punto final HTTP al que pueden conectarse los clientes remotos.
La verdadera lección
¿Recuerda ese agente de atención al cliente que se colgó durante mi demostración?
El problema no era que no pudiera escribir código que funcionara. Podía hacerlo. El problema era que estaba resolviendo el problema equivocado. Estaba creando integraciones personalizadas cuando lo que necesitaba era un protocolo estándar.
MCP no es magia. Es fontanería. Buena fontanería.
Se encarga de las tareas aburridas (detección, enrutamiento, serialización) para que puedas centrarte en lo que importa: las herramientas en sí. Tu función meteorológica, tu consulta de base de datos, tu remitente de correo electrónico.
¿La verdadera revelación?
Las buenas abstracciones hacen desaparecer los problemas difíciles.
Ahora tienes un servidor MCP que funciona. En 15 minutos. El siguiente paso es conectarlo a tu LLM real y crear algo útil.
Yo empezaría con cualquier herramienta que desearas que tu agente tuviera la semana pasada.