Lección 5 de 9 · 10 min de lectura
Model Context Protocol: servidores y clientes
Domina MCP para conectar herramientas y recursos externos a Claude. Aprende a construir servidores MCP, sus primitivas (tools, resources, prompts) y cómo integrarlos de forma segura.
Model Context Protocol: servidores y clientes
Hasta ahora hemos visto cómo Claude puede usar herramientas directamente a través del endpoint de mensajes. Pero ¿qué pasa cuando quieres compartir herramientas, recursos y prompts reutilizables entre múltiples aplicaciones y clientes? Ahí entra Model Context Protocol (MCP).
MCP es un protocolo estándar abierto que define cómo los servidores exponen capacidades (herramientas, recursos, prompts) y cómo los clientes (como aplicaciones que usan Claude) las descubren y las utilizan. En lugar de hardcodear cada herramienta en tu aplicación, MCP te permite construir servidores independientes que cualquier cliente compatible puede consumir. Es como crear un ecosistema modular de capacidades reutilizables.
En esta lección te mostraremos qué es MCP, sus componentes clave, cómo construir un servidor MCP funcional y cómo conectarlo a Claude de forma segura.
Qué es MCP y qué problema resuelve
Antes de MCP, si querías que Claude accediera a herramientas de múltiples sistemas (una base de datos, una API externa, un archivo local), tenías dos caminos:
- Integración directa en tu aplicación: Definías todas las herramientas en tu código de llamada a Claude. Funciona, pero no es escalable ni reutilizable.
- Servidores ad-hoc: Creabas backends personalizados para cada caso. Mucha duplicación de lógica.
MCP resuelve esto proporcionando un protocolo estándar y agnóstico. Un servidor MCP puede exponer herramientas, recursos y prompts de forma consistente. Cualquier cliente que implemente el protocolo (Claude, una herramienta de IA, otro sistema) puede conectarse, descubrir y usar esas capacidades.
Beneficios clave:
- Reutilización: Un servidor MCP se puede conectar a múltiples clientes.
- Separación de responsabilidades: La lógica de negocio (servidor) se aísla del cliente de IA.
- Escalabilidad: Agregar nuevas capacidades es cuestión de crear nuevos servidores.
- Seguridad: El control de acceso se centraliza en el servidor.
Las primitivas de MCP: tools, resources y prompts
Un servidor MCP expone tres tipos de capacidades:
Tools (Herramientas)
Son funciones que Claude puede invocar. Definidas por:
- Nombre: identificador único.
- Descripción: para que Claude entienda cuándo usarla.
- Esquema de entrada: parámetros JSON con validación.
- Implementación: la lógica que se ejecuta en el servidor.
Ejemplo: un tool llamado query_db que ejecuta una consulta SQL y devuelve resultados.
Resources
Son datos o contexto estático/semi-estático que el cliente puede solicitar. Piensa en ellos como "documentos" que Claude puede leer pero no modificar típicamente. Se identifican por:
- URI: un identificador único (ej:
database://users/123). - MIME type: tipo de contenido (texto, JSON, etc.).
- Contenido: los datos reales.
Ejemplo: un resource que devuelve la especificación OpenAPI de una API externa, o un archivo de configuración.
Prompts
Son plantillas de prompts reutilizables que el cliente puede invocar. Útiles para prompts complejos que múltiples aplicaciones necesitan. Se definen con:
- Nombre: identificador del prompt.
- Descripción: qué hace.
- Argumentos: parámetros que personaliza el prompt.
- Contenido template: el prompt en sí.
Ejemplo: un prompt llamado analyze_sentiment que ya tiene la estructura lista para analizar sentimiento en textos.
Arquitectura: cómo funciona MCP
MCP funciona en un modelo cliente-servidor:
- Servidor MCP: Corre en un proceso separado (puede ser local o remoto). Expone tools, resources y prompts. Implementa el protocolo MCP.
- Cliente MCP: Tu aplicación (o Claude directamente) que quiere usar esas capacidades. Descubre el servidor, negocia la conexión y solicita capabilities.
- Comunicación: Basada en JSON-RPC sobre stdio, HTTP, o WebSocket (la especificación lo define).
El flujo típico:
Cliente → Conecta al servidor MCP
↓
Servidor responde con lista de tools, resources, prompts disponibles
↓
Cliente integra esas capabilities en su contexto
↓
Cuando Claude necesita invocar una tool, el cliente la envía al servidor
↓
Servidor ejecuta la tool y devuelve el resultado
↓
Cliente pasa el resultado a Claude
Construir un servidor MCP
Vamos a ver cómo implementar un servidor MCP simple. Usaremos Python con la SDK de MCP de Anthropic (disponible en el ecosistema oficial).
Paso 1: Configurar el servidor
from mcp.server import Server
from mcp.types import Tool, TextContent, Resource
import json
server = Server("mi-servidor-mcp")
@server.list_tools()
async def list_tools():
"""Declara qué tools expone este servidor."""
return [
Tool(
name="weather",
description="Obtiene el clima actual para una ciudad",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Nombre de la ciudad"
}
},
"required": ["city"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
"""Ejecuta una tool cuando Claude la invoca."""
if name == "weather":
city = arguments.get("city")
# Aquí irían llamadas reales a una API de clima
result = f"Clima en {city}: 22°C, parcialmente nublado"
return [TextContent(type="text", text=result)]
raise ValueError(f"Tool no encontrada: {name}")
Paso 2: Exponer resources
@server.list_resources()
async def list_resources():
"""Declara qué resources están disponibles."""
return [
Resource(
uri="config://api-keys",
name="API Configuration",
mimeType="application/json"
)
]
@server.read_resource()
async def read_resource(uri: str):
"""Lee un resource específico."""
if uri == "config://api-keys":
config = {"api_endpoint": "https://api.example.com", "version": "v2"}
return json.dumps(config)
raise ValueError(f"Resource no encontrado: {uri}")
Paso 3: Iniciar el servidor
if __name__ == "__main__":
# Ejecuta el servidor escuchando en stdio
server.run()
Integrar un servidor MCP con Claude
Una vez que tienes el servidor corriendo, necesitas conectarlo a tu cliente de Claude. En una aplicación real, tu código haría algo como esto:
from anthropic import Anthropic
from mcp.client import MCPClient
client = Anthropic()
mcp_client = MCPClient()
# Conectar al servidor MCP (por stdio, HTTP, etc.)
await mcp_client.connect("localhost", 8000)
# Obtener tools disponibles del servidor MCP
tools_from_mcp = await mcp_client.list_tools()
# Usar Claude con esas tools
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools_from_mcp, # Las tools vienen del servidor MCP
messages=[{"role": "user", "content": "¿Cuál es el clima en Madrid?"}]
)
# Cuando Claude invoca una tool, la pasas al servidor MCP
while response.stop_reason == "tool_use":
for block in response.content:
if block.type == "tool_use":
tool_result = await mcp_client.call_tool(
block.name,
block.input
)
# Continuar la conversación con el resultado...
Este flujo demuestra cómo MCP actúa como intermediario entre Claude y tus servidores de backend.
Consideraciones de seguridad
Al exponer capabilities a través de MCP, la seguridad es crítica:
1. Autenticación y autorización
- Valida la identidad del cliente antes de permitir conexiones.
- Implementa control de acceso: No todos los clientes deberían acceder a todas las tools.
- Usa tokens, certificados o credenciales que se renuevan.
2. Validación de entrada
- Valida siempre los argumentos que reciben tus tools. No confíes en Claude.
- Usa esquemas JSON-Schema estrictos en la definición de tools.
- Rechaza inputs que no coincidan con el esquema.
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "delete_user":
user_id = arguments.get("user_id")
# ❌ MAL: No validas si el user_id es un entero válido
# ✅ BIEN:
if not isinstance(user_id, int) or user_id <= 0:
raise ValueError("user_id inválido")
# Continuar...
3. Rate limiting y throttling
- Limita el número de llamadas por cliente y por tiempo.
- Implementa timeouts para tools que podrían colgarse.
4. Auditoría
- Registra todas las invocaciones de tools, quién las llamó y cuándo.
- Monitorea actividad anómala.
5. Aislamiento de secretos
- Nunca expongas credenciales en las respuestas de tools.
- Si una tool necesita credenciales (API keys, passwords), mantenlas del lado del servidor.
- Usa variables de entorno o gestores de secretos.
import os
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "query_db":
# ✅ BIEN: Credenciales del lado del servidor
db_password = os.getenv("DB_PASSWORD")
# Conectar a BD...
# ❌ NUNCA: return {"password": db_password}
6. Comunicación segura
- Si MCP se comunica por HTTP/WebSocket, usa HTTPS/WSS.
- Valida certificados SSL/TLS.
Para el examen
El examen Claude Certified Developer – Foundations evalúa sobre MCP estos aspectos clave:
- Definición y propósito: Entiende que MCP es un protocolo estándar para exponer capabilities reutilizables (tools, resources, prompts).
- Primitivas: Diferencia entre tools (funciones invocables), resources (datos accesibles) y prompts (templates reutilizables).
- Arquitectura cliente-servidor: Cómo funciona la comunicación, qué hace cada parte, cómo se descubren capabilities.
- Implementación básica: Capacidad de leer y comprender código que define un servidor MCP simple (list_tools, call_tool, decoradores).
- Integración con Claude: Cómo los tools de MCP se integran en llamadas a la API de Claude, y cómo se manejan las invocaciones.
- Seguridad: Validación de entrada, autenticación, gestión de secretos, auditoría.
No esperes preguntas sobre implementación de código desde cero, pero sí deberías reconocer patrones de código y explicar cómo funcionan.
Para recordar
- MCP es un protocolo estándar que permite que servidores expongan tools, resources y prompts de forma reutilizable para múltiples clientes.
- Las tres primitivas (tools = funciones, resources = datos, prompts = templates) cubren la mayoría de casos de uso.
- La arquitectura es cliente-servidor: El cliente descubre capabilities del servidor, los integra, e invoca herramientas cuando Claude lo solicita.
- Seguridad es central: Valida siempre, autentica clientes, protege credenciales, registra actividad, y aísla secretos en el servidor.
Próxima lección: Claude Code para desarrollo y automatización