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
Aplicación LLM simple — chatear con un modelo local de código abierto mediante Ollama
Aplicación tradicional de API meteorológica — Cliente Open-Meteo (Etapa 2A) + orquestación directa con LLM (Etapa 2B)
Servidor MCP meteorológico — exponer el clima como herramientas MCP sobre stdio (Etapa 3)
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:7bO 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 list2. Crear un entorno virtual
python3 -m venv .venv
source .venv/bin/activateEn Windows:
python -m venv .venv
.venv\Scripts\activate3. Instalar dependencias
pip install -e ".[dev]"4. Configurar variables de entorno
cp .env.example .envLos valores por defecto en .env apuntan a Ollama local:
LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=qwen2.5:7bLLM_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 deollama list(la llamada a herramientas de la Etapa 4B funciona bien conqwen2.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):
Geocodificación —
GET https://geocoding-api.open-meteo.com/v1/searchconvierte 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.Pronóstico —
GET https://api.open-meteo.com/v1/forecastusa 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)
→ ResponseCó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 USO el script de consola:
direct-weather "San Francisco"En stderr verás los pasos de orquestación:
La aplicación recibió la ciudad
La aplicación llamó al proveedor meteorológico
La aplicación recibió el clima estructurado
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 | Etapa 2B | |
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 |
|
Versión instalada | 2.0.0 |
Clase del servidor |
|
No utilizado | paquete de terceros |
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_weatherDelegar 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 |
| string | sí | Nombre de ciudad o lugar |
| string | no | Estado / región administrativa para desambiguación |
| 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_serverO:
weather-mcp-serverCon 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 stdoutSin 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:
mcpoficial 2.0.0 (MCPServer)Paquete oficial Inspector
@modelcontextprotocol/inspectorNode.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 --versionSi 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:
La terminal imprime algo como
MCP Inspector Web is up and running at: http://localhost:6274?MCP_INSPECTOR_API_TOKEN=...El navegador abre el Inspector
El Inspector inicia/conecta al servidor stdio local (
weather-learning-server)La sesión se inicializa (aparecen nombre del servidor/instrucciones)
Abrir Tools → la lista muestra
get_current_weatherSeleccionar la herramienta → la UI muestra la cadena de documentación/descripción y los campos de entrada del esquema (
cityrequerido;state_or_region/countryopcionales)Establecer
city=San Francisco→ Run ToolEl 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-serverAbrir 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 jsonSe 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 jsonEsperado: 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 jsonEsperado: "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-MeteoImportante: 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 USO:
basic-mcp-client "San Francisco"Deberías ver:
Información de conexión / protocolo para
weather-learning-serverEl nombre, descripción y esquema de entrada de cada herramienta descubierta
Una llamada explícita a
get_current_weatherEl 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 answerNo 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)
Iniciar sesión MCP — generar
python -m app.mcp_serversobre stdio; inicializar clienteDescubrimiento de herramientas —
list_tools; registrar nombre/descripción de cada herramientaTraducción de esquemas — herramientas MCP → herramientas
type: "function"de ResponsesTurno del modelo —
client.responses.create(..., tools=..., tool_choice="auto")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_outputconprevious_response_id
Repetir hasta que el modelo devuelva un mensaje de texto final (o alcanzar iteraciones máximas)
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_callparaget_current_weather, luego una respuesta meteorológicaPregunta 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_appO 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
pytestEstructura 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
openaide 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
mcp2.0.0 (MCPServerdemcp.server) a través de stdio. No utilice el paquete de tercerosfastmcp.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.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Tools
Related MCP Servers
- Flicense-qualityDmaintenanceProvides real-time weather information for any city worldwide using the Open-Meteo API, returning current temperature, wind speed, and geographic coordinates through a containerized MCP server.
- Alicense-qualityDmaintenanceFetches current weather information for any city using the Open-Meteo API through a simple MCP tool interface.1,299MIT
- Flicense-qualityCmaintenanceEnables AI agents to retrieve live weather updates for any city via OpenWeatherMap, wrapped in MCP format.1
- FlicenseBqualityDmaintenanceProvides real-time weather information for cities worldwide using the OpenWeatherMap API, accessible through natural language queries via the MCP protocol.1
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)
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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