Cómo Construir Tu Primer Servidor MCP: Tutorial Paso a Paso

Requisitos previos
Antes de comenzar, asegúrate de tener estos elementos listos:
- Python 3.10 o superior instalado.
- Conocimientos básicos de funciones de Python y código asíncrono.
- uv (gestor de paquetes Python rápido) – instálalo con
curl -LsSf https://astral.sh/uv/install.sh | sh. - Un cliente MCP como Claude Desktop (descárgalo desde claude.ai/download y mantenlo actualizado).
- Un editor de texto o IDE.
No se requiere experiencia previa con MCP. Construiremos un servidor MCP de clima práctico que permita a la IA consultar alertas y pronósticos meteorológicos en tiempo real en EE. UU. mediante la API del Servicio Meteorológico Nacional.
Paso234 1: Configurar el entorno
Crea un directorio de proyecto limpio e inicialízalo con uv:
mkdir weather-mcp-server
cd weather-mcp-server
uv init
uv venv
source .venv/bin/activate # En Windows: .venv\Scripts\activate
uv add "mcp[cli]" httpx
Esto instala el SDK oficial de Python para MCP (FastMCP) y httpx para las llamadas a la API. Tu proyecto ahora tiene un pyproject.toml y un entorno virtual.
Resultado esperado: Una nueva carpeta .venv y las dependencias listadas en uv.lock.
Paso 2: Crear el código del servidor MCP
Crea el archivo principal:
touch weather.py
Pega este código completo y listo para ejecutar en weather.py:
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# Inicializar el servidor MCP
mcp = FastMCP("weather")
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
# Función auxiliar para llamar a la API del NWS de forma segura
async def make_nws_request(url: str) -> dict[str, Any] | None:
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
# Formatear las alertas meteorológicas de forma legible para la IA
def format_alert(feature: dict) -> str:
props = feature["properties"]
return f"""
Evento: {props.get("event", "Desconocido")}
Área: {props.get("areaDesc", "Desconocida")}
Gravedad: {props.get("severity", "Desconocida")}
Descripción: {props.get("description", "No hay descripción disponible")}
Instrucciones: {props.get("instruction", "No se proporcionaron instrucciones específicas")}
"""
# Herramienta 1: Obtener alertas meteorológicas activas para un estado de EE. UU.
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Obtiene las alertas meteorológicas actuales para un estado de EE. UU. (ej. "CA" o "TX")."""
url = f"{NWS_API_BASE}/alerts/active/area/{state.upper()}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "No se pudieron obtener las alertas o no se encontraron alertas."
if not data["features"]:
return f"No hay alertas activas para {state.upper()}."
alerts = [format_alert(f) for f in data["features"]]
return "\n---\n".join(alerts)
Herramienta 2: Obtener pronóstico de 5 días para cualquier lat/long
@mcp.tool() async def get_forecast(latitude: float, longitude: float) -> str: """Obtener pronóstico del tiempo para una latitud y longitud específicas.""" points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}" points_data = await make_nws_request(points_url) if not points_data: return "No se puede obtener datos de pronóstico para esta ubicación." forecast_url = points_data["properties"]["forecast"] forecast_data = await make_nws_request(forecast_url) if not forecast_data: return "No se puede obtener el pronóstico detallado." periods = forecast_data["properties"]["periods"][:5] forecasts = [] for period in periods: forecast = f""" {period["name"]}: Temperatura: {period["temperature"]}°{period["temperatureUnit"]} Viento: {period["windSpeed"]} {period["windDirection"]} Pronóstico: {period["detailedForecast"]} """ forecasts.append(forecast) return "\n---\n".join(forecasts)
def main(): mcp.run(transport="stdio")
if name == "main": main()
**Conceptos clave explicados:**
- Los decoradores `@mcp.tool()` convierten funciones asíncronas regulares en herramientas MCP que la IA puede descubrir y llamar.
- El servidor se ejecuta sobre **stdio** (entrada/salida estándar) – el valor por defecto para servidores MCP locales.
- Todo el registro de eventos debe ir a stderr (FastMCP maneja esto automáticamente).
## Paso就比较 3: Probar el Servidor Localmente
Ejecuta el servidor:
```bash
uv run weather.py
Salida esperada: La terminal permanece abierta y silenciosa (esto es normal para servidores stdio). Solo verás mensajes JSON-RPC cuando un cliente MCP se conecte.
Deja esta terminal en ejecución para el siguiente paso.
Paso 4: Conectar el Servidor MCP a Claude Desktop
- Abre Claude Desktop.
- Crea o edita el archivo de configuración en:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
Añade esta entrada exacta (reemplaza /ABSOLUTE/PATH/TO/weather-mcp-server con la ruta real de tu carpeta):
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/weather-mcp-server",
"run",
"weather.py"
]
}
}
}
- Cierra completamente Claude Desktop (Cmd+Q en macOS o cierra desde la bandeja del sistema en Windows) y reinícialo.
- En Claude, haz clic en "Add files, connectors, and more" → pasa el cursor sobre Connectors → deberías ver "weather" en la lista.
Paso 5: Usa Tu Servidor MCP con la IA
Prueba estos mensajes en Claude Desktop:
- "¿Qué alertas meteorológicas activas hay en Texas?"
- "Dame el pronóstico para San Francisco (usa lat 37.77, long -122.41)."
- "Verifica las alertas en California y dime si necesito prepararme para algo."
Claude descubrirá automáticamente las herramientas, pedirá tu aprobación la primera vez y devolverá resultados formateados.
Comportamiento esperado: La IA llama a tus herramientas en segundo plano y muestra respuestas en lenguaje natural.
Problemas comunes y solución de problemas
-
El servidor no aparece en Claude:
- Verifica nuevamente que el JSON sea válido (sin comas finales).
- Usa una ruta absoluta en la configuración.
- Reinicia Claude completamente.
- Revisa los registros:
~/Library/Logs/Claude/mcp*.log(macOS) o el equivalente en Windows.
-
Errores de API o sin datos:
- La API del NWS solo funciona para ubicaciones en EE. UU.
- Usa códigos de estado de dos letras (CA, TX, etc.).
- Las coordenadas deben ser latitud/longitud válidas.
-
“Comando no encontrado”:
- Asegúrate de que uv esté en tu PATH y que el entorno virtual esté activado.
- Ejecuta
uv --versionpara verificar la instalación.
-
Tiempo de espera agotado o respuesta lenta:
- Aumenta el tiempo de espera en
make_nws_requestsi es necesario. - El NWS tiene límites de velocidad – evita saturarlo en producción.
- Aumenta el tiempo de espera en
-
Problemas de permisos:
- En macOS, otorga acceso completo al disco a Claude Desktop en Configuración del Sistema → Privacidad y Seguridad.
Próximos pasos
- Añade más herramientas: Crea herramientas para bases de datos, GitHub, Slack o tus propias APIs usando el mismo patrón
@mcp.tool(). - Añade recursos y prompts: Usa
mcp.resource()ymcp.prompt()para datos tipo archivo e instrucciones reutilizables. - Implementa remotamente: Cambia al transporte HTTP/SSE y aloja en AWS Lambda, Vercel o cualquier servidor (FastMCP admite
stateless_http=True). /Lenguajes**: Prueba los SDKs oficiales de TypeScript, Go o Rust para la misma funcionalidad. - Comparte tu servidor: Publica el repositorio para que otros puedan agregarlo mediante
npxo Docker.
Ahora tienes un servidor MCP completamente funcional que cualquier cliente de IA compatible puede usar. Experimenta, amplía las herramientas y ¡empieza a crear poderosas integraciones de IA hoy mismo!
Continue Reading
More articles connected to the same themes, protocols, and tools.
Referenced Tools
Browse entries that are adjacent to the topics covered in this article.








