Skip to main content
Glama
HumairaShaista

weather-learning-server

Aprendizaje de Weather MCP

Un proyecto de aprendizaje progresivo que muestra el camino desde una aplicación LLM simple hasta capacidades meteorológicas expuestas a través del Protocolo de Contexto de Modelo (MCP).

Progresión de aprendizaje

  1. Aplicación LLM simple — chatear con un modelo local de código abierto mediante Ollama

  2. Aplicación tradicional de API meteorológica — Cliente Open-Meteo (Etapa 2A) + orquestación directa con LLM (Etapa 2B)

  3. Servidor MCP meteorológico — exponer el clima como herramientas MCP sobre stdio (Etapa 3)

  4. Cliente / agente MCP — cliente de herramientas explícito (Etapa 4A) + herramientas seleccionadas por el modelo (Etapa 4B)

Este repositorio implementa actualmente las etapas 1 a 4B.

Related MCP server: MCP Weather Server Demo

Requisitos

  • Python 3.12 o posterior

  • Ollama (o cualquier servidor local compatible con OpenAI)

  • Un modelo local de código abierto con capacidad de llamada a herramientas (por defecto: qwen2.5:7b)

No se requiere cuenta de OpenAI ni de Gemini.

Configuración

1. Instalar e iniciar Ollama

Instalar desde https://ollama.com, luego descargar un modelo:

ollama pull qwen2.5:7b

O usar cualquier modelo con capacidad de herramientas de Responses-API que ya tengas (ollama list), luego establecer LLM_MODEL en .env con ese nombre.

Confirmar que Ollama está en ejecución (normalmente automático en macOS tras la instalación):

ollama list

2. Crear un entorno virtual

python3 -m venv .venv
source .venv/bin/activate

En Windows:

python -m venv .venv
.venv\Scripts\activate

3. Instalar dependencias

pip install -e ".[dev]"

4. Configurar variables de entorno

cp .env.example .env

Los valores por defecto en .env apuntan a Ollama local:

LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=qwen2.5:7b
  • LLM_BASE_URL — URL de API compatible con OpenAI (se muestra el valor por defecto de Ollama; usado por Chat Completions y Responses)

  • LLM_API_KEY — requerida por la librería cliente; Ollama la ignora (cualquier valor no vacío funciona)

  • LLM_MODEL — nombre del modelo local de ollama list (la llamada a herramientas de la Etapa 4B funciona bien con qwen2.5:7b)

Otras opciones: LM Studio, vLLM, o cualquier servidor que hable la API de chat de OpenAI — solo cambia LLM_BASE_URL y LLM_MODEL.

Etapa 2A: Cliente meteorológico Open-Meteo

app/weather_client.py se comunica con Open-Meteo en dos pasos (sin LLM, sin MCP):

  1. GeocodificaciónGET https://geocoding-api.open-meteo.com/v1/search convierte un nombre de ciudad (más opcionalmente estado/región y país) en latitud, longitud, nombre canónico, región administrativa, país y zona horaria.

  2. PronósticoGET https://api.open-meteo.com/v1/forecast usa esas coordenadas para obtener el clima actual (temperatura, humedad, viento, código meteorológico WMO).

Los llamadores reciben modelos tipados (Location, CurrentWeather, WeatherResult), no JSON crudo del proveedor. La traducción de código meteorológico WMO a texto reside en un solo lugar (WMO_WEATHER_CODES / weather_condition_from_code).

Ejemplo (asíncrono):

from app.weather_client import get_current_weather

result = await get_current_weather("Berlin")
print(result.location.name, result.current.temperature, result.current.condition)

Etapa 2B: Aplicación directa de clima + LLM

app/direct_weather_app.py es una aplicación LLM tradicional: tu código decide cuándo llamar a la API meteorológica, luego pasa ese resultado al LLM para un resumen amigable.

User
  → direct_weather_app
      → Open-Meteo   (application-controlled)
      → LLM          (summarize only the supplied payload)
  → Response

Cómo ejecutarlo

Con el entorno virtual activado, Ollama en ejecución y acceso a red para Open-Meteo:

python -m app.direct_weather_app "San Francisco"

Desambiguación opcional:

python -m app.direct_weather_app "Springfield" --state Illinois --country US

O el script de consola:

direct-weather "San Francisco"

En stderr verás los pasos de orquestación:

  1. La aplicación recibió la ciudad

  2. La aplicación llamó al proveedor meteorológico

  3. La aplicación recibió el clima estructurado

  4. La aplicación envió el contexto meteorológico al LLM

Stdout muestra el bloque de clima estructurado, luego el resumen del LLM.

Cómo se diferencia de la aplicación LLM simple

Etapa 1 plain_llm_app

Etapa 2B direct_weather_app

Datos meteorológicos

Ninguno — el modelo no tiene clima en vivo

Obtenidos primero de Open-Meteo

¿Quién llama al clima?

Nadie

El código de la aplicación (explícito)

Rol del LLM

Responder a un prompt libre

Resumir un payload autoritario

MCP / herramientas

No

No

Punto de aprendizaje importante: el LLM no descubre ni llama a herramientas meteorológicas. La aplicación orquesta Open-Meteo, luego pide al LLM que exprese el resultado. El prompt indica al modelo que el payload es autoritario y que no invente hechos faltantes.

Etapa 3: Servidor MCP meteorológico

app/mcp_server.py expone el weather_client existente como una herramienta MCP. El servidor solo proporciona capacidades — no se comunica con un LLM ni gestiona una conversación.

Versión oficial del SDK y API utilizada

Inspeccionado en el entorno de este proyecto:

Elemento

Valor

Paquete

mcp oficial en PyPI (modelcontextprotocol/python-sdk)

Versión instalada

2.0.0

Clase del servidor

MCPServer de mcp.server

No utilizado

paquete de terceros fastmcp; ruta de importación FastMCP de la v1 anterior

from mcp.server import MCPServer

mcp = MCPServer("weather-learning-server")

Responsabilidades del servidor

  • Anunciar herramientas a los clientes MCP (descubrimiento de herramientas)

  • Aceptar una llamada a la herramienta get_current_weather

  • Delegar en app.weather_client (sin código duplicado de Open-Meteo)

  • Devolver un payload meteorológico estructurado (o un error de herramienta seguro)

  • Hablar MCP sobre stdio para este POC de aprendizaje local

Contrato de la herramienta expuesta: get_current_weather

Argumentos

Nombre

Tipo

Requerido

Descripción

city

string

Nombre de ciudad o lugar

state_or_region

string

no

Estado / región administrativa para desambiguación

country

string

no

Nombre del país o código ISO-3166-1 alfa-2

Campos del resultado estructurado

resolved_location, region, country, latitude, longitude, temperature, apparent_temperature (cuando esté disponible), condition, wind_speed, observation_time, timezone, units

Cómo iniciar el servidor

python -m app.mcp_server

O:

weather-mcp-server

Con stdio, el proceso espera a un host MCP en stdin/stdout. Ejecutarlo solo en una terminal parece "colgado" — eso es esperado.

Cómo funciona el transporte stdio (conceptualmente)

MCP host / Inspector
   ├── spawns: python -m app.mcp_server
   ├── writes JSON-RPC MCP messages → server stdin
   └── reads JSON-RPC MCP messages  ← server stdout
  • Sin puerto ni HTTP para este POC

  • stdout es el cable del protocolo (no uses print() para salida normal de la aplicación allí)

  • Los registros van a stderr

Pruebas independientes con el Inspector MCP oficial

Verificado contra:

  • mcp oficial 2.0.0 (MCPServer)

  • Paquete oficial Inspector @modelcontextprotocol/inspector

  • Node.js 22.19+ (requerido por la documentación actual del Inspector)

  • Acceso a red para Open-Meteo

Prerrequisitos

cd weather-mcp-learning
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"   # includes mcp[cli]

Confirmar Node/npx:

node --version   # need 22.19.0 or newer
npx --version

Si tu node/npx del sistema está roto o es demasiado antiguo, usa un Node actual mediante nvm (o equivalente), luego asegúrate de que npx esté primero en tu PATH.

Opción A — Interfaz web mediante mcp dev (ayudante oficial del SDK)

Desde la raíz del proyecto con el venv activo (también necesita uv porque mcp dev lanza el servidor a través de uv run):

mcp dev app/mcp_server.py --with-editable .

Esperado:

  1. La terminal imprime algo como MCP Inspector Web is up and running at: http://localhost:6274?MCP_INSPECTOR_API_TOKEN=...

  2. El navegador abre el Inspector

  3. El Inspector inicia/conecta al servidor stdio local (weather-learning-server)

  4. La sesión se inicializa (aparecen nombre del servidor/instrucciones)

  5. Abrir Tools → la lista muestra get_current_weather

  6. Seleccionar la herramienta → la UI muestra la cadena de documentación/descripción y los campos de entrada del esquema (city requerido; state_or_region / country opcionales)

  7. Establecer city = San FranciscoRun Tool

  8. El panel de resultados muestra contenido estructurado como resolved_location, region, temperature, condition, units, etc.

--with-editable . instala este proyecto en el entorno temporal que mcp dev construye para que import app... funcione.

Opción B — Interfaz web mediante Inspector + configuración del proyecto

mcp-inspector.json en la raíz del repositorio apunta al Inspector al servidor stdio local:

npx -y @modelcontextprotocol/inspector --config ./mcp-inspector.json --server weather-learning-server

Abrir la URL impresa http://localhost:6274?..., confirmar que la sesión está conectada, luego usar la pestaña Tools como en la Opción A.

Opción C — Comprobaciones CLI mediante script (sin navegador)

Son útiles para probar los mismos pasos del protocolo desde una terminal. Ejecutar desde la raíz del proyecto con el venv activo y un npx funcional de Node 22.19+ en PATH:

# 1–2. Start/connect over stdio + initialize session
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method initialize \
  --format json

Se espera JSON que incluya "name": "weather-learning-server" bajo result.serverInfo.

# 3–4. List tools; confirm description + input schema
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method tools/list \
  --format json

Esperado: una herramienta llamada get_current_weather, con inputSchema.required que contenga city, y una descripción de clima actual/en vivo.

# 5–6. Invoke with city = San Francisco; display structured result
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method tools/call \
  --tool-name get_current_weather \
  --tool-arg 'city=San Francisco' \
  --format json

Esperado: "isError": false y structuredContent con campos como:

{
  "resolved_location": "San Francisco",
  "region": "California",
  "country": "United States",
  "latitude": 37.77493,
  "longitude": -122.41942,
  "temperature": 13.8,
  "apparent_temperature": 12.1,
  "condition": "Fog",
  "wind_speed": 19.1,
  "observation_time": "2026-08-12T22:45",
  "timezone": "America/Los_Angeles",
  "units": {
    "temperature": "°C",
    "wind_speed": "km/h",
    "apparent_temperature": "°C"
  }
}

Los valores numéricos del clima cambian con el tiempo; los nombres de campo y "isError": false son lo que importa.

Documentación oficial del Inspector: MCP Inspector · Documentación de ejecución del SDK: Ejecutar tu servidor

Etapa 4A: Cliente MCP básico (llamada explícita a herramienta)

app/basic_mcp_client.py es un cliente MCP sin LLM. Lanza el servidor MCP meteorológico local sobre stdio, descubre herramientas, luego llama explícitamente a get_current_weather.

basic_mcp_client
    → list_tools
    → get_current_weather   (hardcoded by this app — not chosen by an LLM)
    → MCP server (app.mcp_server via stdio)
    → Open-Meteo

Importante: este cliente aún invoca la herramienta meteorológica explícitamente. El LLM no ha elegido aún la herramienta. Eso llegará en una etapa posterior.

Cómo ejecutarlo

Con el entorno virtual activado (no es necesario iniciar el servidor MCP tú mismo — este cliente lo genera):

python -m app.basic_mcp_client "San Francisco"

Filtros opcionales:

python -m app.basic_mcp_client "Springfield" --state Illinois --country US

O:

basic-mcp-client "San Francisco"

Deberías ver:

  1. Información de conexión / protocolo para weather-learning-server

  2. El nombre, descripción y esquema de entrada de cada herramienta descubierta

  3. Una llamada explícita a get_current_weather

  4. El resultado JSON estructurado de la herramienta MCP

Al salir del proceso se limpia la sesión MCP y el proceso hijo del servidor.

Etapa 4B: Agente OpenAI Responses (herramientas MCP seleccionadas por el modelo)

app/mcp_agent.py se conecta al servidor MCP meteorológico, descubre herramientas en tiempo de ejecución, entrega esas definiciones al modelo mediante la API oficial OpenAI Responses, ejecuta cualquier llamada a herramienta solicitada por el modelo a través de MCP, devuelve los resultados de la herramienta al modelo e imprime la respuesta final.

user question
  → mcp_agent
      → MCP list_tools          (discovery)
      → OpenAI Responses API    (question + tool schemas)
      → model may request tool(s)
      → MCP tools/call          (only discovered names)
      → Responses function_call_output
      → final natural-language answer

No hay if "weather" in question, ni expresión regular para ciudades, ni llamada hardcodeada a get_current_weather. El modelo decide si usar una herramienta.

Bucle del agente (detalle)

  1. Iniciar sesión MCP — generar python -m app.mcp_server sobre stdio; inicializar cliente

  2. Descubrimiento de herramientaslist_tools; registrar nombre/descripción de cada herramienta

  3. Traducción de esquemas — herramientas MCP → herramientas type: "function" de Responses

  4. Turno del modeloclient.responses.create(..., tools=..., tool_choice="auto")

  5. Inspeccionar salida — si existen elementos function_call:

    • validar nombre de herramienta contra el conjunto descubierto

    • analizar/validar argumentos JSON

    • llamar a MCP; preservar resultados estructurados

    • enviar function_call_output con previous_response_id

  6. Repetir hasta que el modelo devuelva un mensaje de texto final (o alcanzar iteraciones máximas)

  7. Imprimir respuesta final y cerrar la sesión MCP/proceso hijo

Cómo ejecutarlo

ollama pull qwen2.5:7b   # once, if needed
source .venv/bin/activate
python -m app.mcp_agent "What is the current weather in San Francisco?"
python -m app.mcp_agent "Explain what dependency injection is."

Esperado:

  • Pregunta sobre el clima → los registros muestran model_requested_tools / tool_call para get_current_weather, luego una respuesta meteorológica

  • Pregunta sobre inyección de dependencias → los registros muestran una respuesta final sin llamadas a herramientas

Observa stderr para líneas [mcp-agent]: descubrimiento, tipos de salida del modelo, nombre/argumentos/duración/resultado de la herramienta. Las claves API nunca se registran.

Ejecutar la aplicación simple

Con el entorno virtual activado y Ollama en ejecución:

python -m app.plain_llm_app

O con un prompt personalizado:

python -m app.plain_llm_app "What is the Model Context Protocol in one sentence?"

También puedes usar el script de consola instalado:

plain-llm "Hello!"

Ejecutar pruebas

pytest

Estructura del proyecto

weather-mcp-learning/
  README.md
  .env.example
  .gitignore
  pyproject.toml
  mcp-inspector.json
  app/
    __init__.py
    config.py
    llm_client.py
    plain_llm_app.py
    weather_client.py
    direct_weather_app.py
    mcp_server.py
    basic_mcp_client.py
    mcp_agent.py
  tests/

Notas

  • El paquete oficial openai de Python se utiliza como un cliente compatible con OpenAI (Chat Completions anteriormente; Responses API en la Etapa 4B).

  • Las búsquedas meteorológicas utilizan Open-Meteo a través de httpx (app/weather_client.py).

  • La Etapa 2B (direct_weather_app.py) orquesta explícitamente clima → LLM; no hay MCP ni llamadas a herramientas.

  • La Etapa 3 utiliza el SDK oficial mcp 2.0.0 (MCPServer de mcp.server) a través de stdio. No utilice el paquete de terceros fastmcp.

  • La Etapa 4A (basic_mcp_client.py) todavía llama a la herramienta meteorológica explícitamente (sin elección de herramienta del LLM).

  • La Etapa 4B (mcp_agent.py) permite que el modelo seleccione herramientas después del descubrimiento de MCP a través de la Responses API.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • OpenWeather MCP — wraps the OpenWeatherMap API (openweathermap.org)

  • Open-Meteo MCP — weather forecast + historical reanalysis + sister APIs

  • WeatherAPI.com MCP — wraps WeatherAPI.com (api.weatherapi.com)

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HumairaShaista/Weather-MCP-Learning'

If you have feedback or need assistance with the MCP directory API, please join our Discord server