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

Aprende a construir un servidor de Model Context Protocol (MCP) desde cero. Este tutorial práctico te muestra cómo crear herramientas para que asistentes de IA como Claude accedan a APIs externas.

Canonical URL: https://a2a-mcp.org/blog/how-to-build-mcp-server-es

Language: es

Published: 2026-04-06

Updated: 2026-04-06

## 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](https://docs.astral.sh/uv/getting-started/installation/) (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:

```bash
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:

```bash
touch weather.py
```

Pega este código completo y listo para ejecutar en `weather.py`:

```python
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

1. Abre Claude Desktop.
2. 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`

Añade esta entrada exacta (reemplaza `/ABSOLUTE/PATH/TO/weather-mcp-server` con la ruta real de tu carpeta):

```json
{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/weather-mcp-server",
        "run",
        "weather.py"
      ]
    }
  }
}
```

3. Cierra completamente Claude Desktop (Cmd+Q en macOS o cierra desde la bandeja del sistema en Windows) y reinícialo.
4. 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 --version` para verificar la instalación.

- **Tiempo de espera agotado o respuesta lenta**:
  - Aumenta el tiempo de espera en `make_nws_request` si es necesario.
  - El NWS tiene límites de velocidad – evita saturarlo en producción.

- **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()` y `mcp.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 `npx` o 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!
