weather-learning-server
Изучение Weather MCP
Прогрессивный учебный проект, показывающий путь от простого LLM-приложения до возможностей работы с погодой, предоставляемых через Model Context Protocol (MCP).
Этапы обучения
Простое LLM-приложение — чат с локальной open-source моделью через Ollama
Традиционное приложение с погодным API — клиент Open-Meteo (Этап 2A) + прямая оркестрация LLM (Этап 2B)
Weather MCP сервер — предоставление погоды как MCP-инструментов через stdio (Этап 3)
MCP клиент / агент — явный клиент инструментов (Этап 4A) + инструменты, выбираемые моделью (Этап 4B)
В этом репозитории реализованы этапы с 1 по 4B.
Related MCP server: MCP Weather Server Demo
Требования
Python 3.12 или новее
Ollama (или любой локальный сервер, совместимый с OpenAI)
Локальная open-source модель с поддержкой вызова инструментов (по умолчанию:
qwen2.5:7b)
Учётная запись OpenAI или Gemini не требуется.
Настройка
1. Установка и запуск Ollama
Установите с https://ollama.com, затем загрузите модель:
ollama pull qwen2.5:7bИли используйте любую другую модель с возможностью вызова инструментов, которая у вас уже есть (ollama list), затем укажите LLM_MODEL в .env с её именем.
Убедитесь, что Ollama запущен (обычно это происходит автоматически на macOS после установки):
ollama list2. Создание виртуального окружения
python3 -m venv .venv
source .venv/bin/activateНа Windows:
python -m venv .venv
.venv\Scripts\activate3. Установка зависимостей
pip install -e ".[dev]"4. Настройка переменных окружения
cp .env.example .envЗначения по умолчанию в .env указывают на локальный Ollama:
LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=qwen2.5:7bLLM_BASE_URL— URL API, совместимого с OpenAI (по умолчанию указан Ollama; используется для Chat Completions и Responses)LLM_API_KEY— требуется клиентской библиотекой; Ollama игнорирует его (подойдёт любое непустое значение)LLM_MODEL— имя локальной модели изollama list(на Этапе 4B вызов инструментов хорошо работает сqwen2.5:7b)
Другие варианты: LM Studio, vLLM или любой сервер, поддерживающий chat-API OpenAI — просто измените LLM_BASE_URL и LLM_MODEL.
Этап 2A: Клиент погоды Open-Meteo
app/weather_client.py работает с Open-Meteo в два шага (без LLM, без MCP):
Геокодирование —
GET https://geocoding-api.open-meteo.com/v1/searchпреобразует название города (и необязательно штат/регион и страну) в широту, долготу, каноническое название, административный регион, страну и часовой пояс.Прогноз —
GET https://api.open-meteo.com/v1/forecastиспользует эти координаты для получения текущей погоды (температура, влажность, ветер, WMO-код погоды).
Вызывающие получают типизированные модели (Location, CurrentWeather, WeatherResult), а не сырые JSON от провайдера. Преобразование WMO-кода погоды в текст находится в одном месте (WMO_WEATHER_CODES / weather_condition_from_code).
Пример (асинхронный):
from app.weather_client import get_current_weather
result = await get_current_weather("Berlin")
print(result.location.name, result.current.temperature, result.current.condition)Этап 2B: Приложение с прямым вызовом погоды и LLM
app/direct_weather_app.py — это традиционное LLM-приложение: ваш код решает, когда вызывать погодный API, затем передаёт результат LLM для дружественного резюме.
User
→ direct_weather_app
→ Open-Meteo (application-controlled)
→ LLM (summarize only the supplied payload)
→ ResponseКак запустить
При активированном виртуальном окружении, запущенном Ollama и наличии сетевого доступа к Open-Meteo:
python -m app.direct_weather_app "San Francisco"Необязательное уточнение:
python -m app.direct_weather_app "Springfield" --state Illinois --country USИли через консольный скрипт:
direct-weather "San Francisco"В stderr вы увидите шаги оркестрации:
Приложение получило город
Приложение вызвало погодного провайдера
Приложение получило структурированные данные о погоде
Приложение отправило контекст погоды в LLM
Stdout показывает структурированный блок погоды, затем резюме LLM.
Чем отличается от простого LLM-приложения
Этап 1 | Этап 2B | |
Данные о погоде | Нет — у модели нет актуальной погоды | Сначала получены из Open-Meteo |
Кто вызывает погоду? | Никто | Код приложения (явно) |
Роль LLM | Ответ на произвольный запрос | Обобщение авторитетных данных |
MCP / инструменты | Нет | Нет |
Важный учебный момент: LLM не находит и не вызывает погодные инструменты. Приложение само оркестрирует Open-Meteo, затем просит LLM сформулировать результат. Подсказка сообщает модели, что данные авторитетны и не нужно выдумывать недостающие факты.
Этап 3: Weather MCP сервер
app/mcp_server.py предоставляет существующий weather_client как MCP инструмент. Сервер предоставляет только возможности — он не общается с LLM и не управляет диалогом.
Официальная версия SDK и используемый API
Проверено в окружении этого проекта:
Пункт | Значение |
Пакет | официальный |
Установленная версия | 2.0.0 |
Класс сервера |
|
Не используется | сторонний пакет |
from mcp.server import MCPServer
mcp = MCPServer("weather-learning-server")Обязанности сервера
Предоставлять инструменты MCP-клиентам (обнаружение инструментов)
Принимать вызов инструмента
get_current_weatherДелегировать выполнение
app.weather_client(без дублирования кода Open-Meteo)Возвращать структурированные данные о погоде (или безопасную ошибку инструмента)
Общаться по MCP через stdio для локального прототипа
Контракт предоставляемого инструмента: get_current_weather
Аргументы
Имя | Тип | Обязательный | Описание |
| string | да | Название города или места |
| string | нет | Штат / административный регион для уточнения |
| string | нет | Название страны или код ISO-3166-1 alpha-2 |
Поля структурированного результата
resolved_location, region, country, latitude, longitude, temperature, apparent_temperature (если доступно), condition, wind_speed, observation_time, timezone, units
Как запустить сервер
python -m app.mcp_serverИли:
weather-mcp-serverПри stdio процесс ожидает MCP-хоста на stdin/stdout. Если запустить его в одиночку в терминале, он будет выглядеть «зависшим» — это нормально.
Как работает stdio-транспорт (концептуально)
MCP host / Inspector
├── spawns: python -m app.mcp_server
├── writes JSON-RPC MCP messages → server stdin
└── reads JSON-RPC MCP messages ← server stdoutДля этого прототипа нет порта и HTTP
stdout является проводом протокола (не используйте
print()для обычного вывода приложения)Логи должны идти в stderr
Независимое тестирование с официальным MCP Inspector
Проверено с:
официальным
mcp2.0.0 (MCPServer)официальным пакетом Inspector
@modelcontextprotocol/inspectorNode.js 22.19+ (требуется текущей документацией Inspector)
сетевым доступом к Open-Meteo
Предварительные требования
cd weather-mcp-learning
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]" # includes mcp[cli]Проверьте Node/npx:
node --version # need 22.19.0 or newer
npx --versionЕсли ваша системная node/npx сломана или слишком старая, используйте актуальную Node через nvm (или аналог), затем убедитесь, что npx находится первым в PATH.
Вариант A — Веб-интерфейс через mcp dev (официальный помощник SDK)
Из корня проекта с активным venv (также требуется uv, потому что mcp dev запускает сервер через uv run):
mcp dev app/mcp_server.py --with-editable .Ожидается:
Терминал выведет что-то вроде
MCP Inspector Web is up and running at: http://localhost:6274?MCP_INSPECTOR_API_TOKEN=...Браузер откроет Inspector
Inspector запустится/подключится к локальному stdio-серверу (
weather-learning-server)Сессия инициализируется (появятся имя сервера/инструкции)
Откройте Tools → список покажет
get_current_weatherВыберите инструмент → UI покажет docstring/описание и поля ввода из схемы (
cityобязательно;state_or_region/countryопционально)Установите
city=San Francisco→ Run ToolПанель результатов покажет структурированный контент, например
resolved_location,region,temperature,condition,unitsи т.д.
--with-editable . устанавливает этот проект во временное окружение, которое создаёт mcp dev, чтобы работало import app....
Вариант B — Веб-интерфейс через Inspector + конфигурация проекта
mcp-inspector.json в корне репозитория указывает Inspector на локальный stdio-сервер:
npx -y @modelcontextprotocol/inspector --config ./mcp-inspector.json --server weather-learning-serverОткройте выведенный URL http://localhost:6274?..., подтвердите подключение сессии, затем используйте вкладку Tools как в Варианте A.
Вариант C — Скриптовые проверки через CLI (без браузера)
Они полезны, чтобы проверить те же протокольные шаги из терминала. Запускайте из корня проекта с активным venv и работающим Node 22.19+ npx в 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Ожидается JSON с "name": "weather-learning-server" в 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Ожидается: один инструмент с именем get_current_weather, с inputSchema.required, содержащим city, и описание текущей погоды.
# 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Ожидается: "isError": false и structuredContent с полями, такими как:
{
"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"
}
}Числовые значения погоды меняются со временем; важны имена полей и "isError": false.
Официальная документация Inspector: MCP Inspector · Документация SDK по запуску: Running your server
Этап 4A: Базовый MCP клиент (явный вызов инструмента)
app/basic_mcp_client.py — это не-LLM MCP клиент. Он запускает локальный погодный MCP сервер через stdio, обнаруживает инструменты, затем явно вызывает 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Важно: этот клиент по-прежнему вызывает погодный инструмент явно. LLM ещё не выбирал инструмент. Это будет на более позднем этапе.
Как запустить
При активированном виртуальном окружении (не нужно запускать MCP сервер вручную — этот клиент запускает его сам):
python -m app.basic_mcp_client "San Francisco"Необязательные фильтры:
python -m app.basic_mcp_client "Springfield" --state Illinois --country USИли:
basic-mcp-client "San Francisco"Вы должны увидеть:
Информацию о подключении / протоколе для
weather-learning-serverКаждый обнаруженный инструмент: имя, описание и входную схему
Явный вызов
get_current_weatherСтруктурированный JSON результат MCP инструмента
Завершение процесса очищает MCP сессию и дочерний процесс сервера.
Этап 4B: Агент OpenAI Responses (инструменты MCP, выбираемые моделью)
app/mcp_agent.py подключается к погодному MCP серверу, обнаруживает инструменты во время выполнения, передаёт эти определения модели через официальный OpenAI Responses API, выполняет любые запрошенные моделью вызовы инструментов через MCP, возвращает результаты инструментов модели и выводит итоговый ответ.
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Нет if "weather" in question, нет регулярного выражения для города и нет жёстко закодированного вызова get_current_weather. Модель решает, использовать ли инструмент.
Цикл агента (подробно)
Запуск MCP сессии — запустить
python -m app.mcp_serverчерез stdio; инициализировать клиентОбнаружение инструментов —
list_tools; залогировать имя/описание каждого инструментаПреобразование схем — MCP инструменты → инструменты типа
"function"для ResponsesХод модели —
client.responses.create(..., tools=..., tool_choice="auto")Проверка вывода — если присутствуют
function_call:проверить имя инструмента среди обнаруженного набора
разобрать/проверить JSON аргументы
вызвать MCP; сохранить структурированные результаты
отправить
function_call_outputсprevious_response_id
Повторять, пока модель не вернёт финальное текстовое сообщение (или не достигнут максимум итераций)
Вывести итоговый ответ и закрыть MCP сессию/дочерний процесс
Как запустить
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."Ожидается:
Вопрос о погоде → логи покажут
model_requested_tools/tool_callдляget_current_weather, затем ответ о погодеВопрос о внедрении зависимостей → логи покажут финальный ответ без вызовов инструментов
Смотрите stderr на строки [mcp-agent]: обнаружение, типы вывода модели, имя/аргументы/длительность/результат вызова инструмента. Ключи API никогда не логируются.
Запуск простого приложения
При активированном виртуальном окружении и запущенном Ollama:
python -m app.plain_llm_appИли с произвольным запросом:
python -m app.plain_llm_app "What is the Model Context Protocol in one sentence?"Вы также можете использовать установленный консольный скрипт:
plain-llm "Hello!"Запуск тестов
pytestСтруктура проекта
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/Примечания
Официальный пакет
openaiдля Python используется в качестве совместимого с OpenAI клиента (ранее — Chat Completions; в Stage 4B — Responses API). Запросы направляются на ваш настроенныйLLM_BASE_URL(по умолчанию Ollama).Поиск погоды выполняется через Open-Meteo с использованием
httpx(app/weather_client.py).Stage 2B (
direct_weather_app.py) явно координирует работу погоды → LLM; без MCP и без вызова инструментов.Stage 3 использует официальный SDK
mcpверсии 2.0.0 (MCPServerизmcp.server) через stdio. Не используйте сторонний пакетfastmcp.Stage 4A (
basic_mcp_client.py) по-прежнему вызывает инструмент погоды явно (без выбора инструмента LLM).Stage 4B (
mcp_agent.py) позволяет модели выбирать инструменты после обнаружения MCP через Responses API.
Available Tools
1 toolget_current_weatherGet current weatherA
Get live/current weather for a city.
This tool returns real-time current conditions from the Open-Meteo weather provider (not a forecast summary and not model-invented weather). Provide a city name; optionally add state_or_region and/or country when the city name is ambiguous. The response includes the resolved location, coordinates, temperature, condition, wind, observation time, timezone, and units.
| Name | Required | Description | Default |
|---|---|---|---|
| city | Yes | City or place name to look up (required). | |
| country | No | Optional country name or ISO-3166-1 alpha-2 code (for example 'United States' or 'US'). | |
| state_or_region | No | Optional state or first-level administrative region used to disambiguate the city (for example 'California' or 'Illinois'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| units | Yes | |
| region | No | Administrative region / state when available |
| country | Yes | Country name |
| latitude | Yes | |
| timezone | Yes | |
| condition | Yes | Human-readable weather condition |
| longitude | Yes | |
| wind_speed | No | |
| temperature | Yes | |
| observation_time | Yes | Observation timestamp from the provider |
| resolved_location | Yes | Canonical place name from geocoding |
| apparent_temperature | No | Apparent (feels-like) temperature when the provider returns it |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that data comes from Open-Meteo, that it's real-time (not forecast or invented), and lists the response fields. It does not mention rate limits or availability constraints, which would be helpful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise: two sentences. The first sentence states the core purpose, and the second adds key details in a natural flow. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema, the description doesn't need to explain return values. It also covers the important semantic clarifications (real-time, provider, disambiguation hints). For a simple 3-param weather tool, this is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description restates that city is required and that state_or_region and country help disambiguate, but does not add new format or usage details beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get live/current weather for a city' with specific verb and resource. It explicitly distinguishes itself from non-forecast and non-invented weather, and mentions the provider (Open-Meteo).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use (for current real-time conditions) and notes when to add optional parameters for disambiguation. It doesn't explicitly state when NOT to use or list alternative tools, but context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
1 tool update
v0.1.0- First observed
get_current_weather
TDQS
With only one tool, there is no risk of confusion between tools. The tool's purpose is clearly defined and distinct by default.
The single tool uses a clear verb_noun pattern (get_current_weather), but with only one tool, consistency cannot be meaningfully evaluated across a set.
A server named 'weather-learning-server' with only one weather tool feels incomplete for learning purposes. A 'learning' server typically benefits from multiple tools (e.g., forecast, history, alerts) to cover educational use cases.
The server only provides current weather data, missing obvious complementary tools like forecasts, historical data, or weather alerts. This severely limits its usefulness for weather-related learning or applications.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
OpenWeather MCP — wraps the OpenWeatherMap API (openweathermap.org)
Open-Meteo MCP — weather forecast + historical reanalysis + sister APIs
Weather, code search, currency & Solana trust scoring as MCP tools. Free, no API key needed.
Hosted MCP server for Xweather weather data: conditions, forecasts, alerts, and more.
1
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides 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.-
- AlicenseNot gradedqualityDmaintenanceFetches current weather information for any city using the Open-Meteo API through a simple MCP tool interface.2,013MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to retrieve live weather updates for any city via OpenWeatherMap, wrapped in MCP format.1-
- AlicenseAqualityBmaintenanceMCP server that provides current weather for any city using Open-Meteo APIs. It exposes a single tool 'get_weather' returning temperature, humidity, wind, and other weather data.116MIT
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