weather-learning-server
Weather MCP 学習
段階的に学べるプロジェクトで、プレーンな LLM アプリケーションから Model Context Protocol (MCP) を通じて天気機能を公開するまでの道筋を示します。
学習の段階
プレーンな LLM アプリケーション — 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 互換のローカルサーバー)
ツール呼び出しに対応したローカルのオープンソースモデル(デフォルト:
qwen2.5:7b)
OpenAI や Gemini のアカウントは不要です。
セットアップ
1. Ollama のインストールと起動
https://ollama.com からインストールし、モデルをプルします:
ollama pull qwen2.5:7bまたは、すでに持っているツール対応モデル(ollama list)を使用し、.env の LLM_MODEL にその名前を設定します。
Ollama が実行中であることを確認します(macOS では通常インストール後に自動起動します):
ollama list2. 仮想環境の作成
python3 -m venv .venv
source .venv/bin/activateWindows の場合:
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— OpenAI 互換の API URL(上記は Ollama のデフォルト。Chat Completions と Responses の両方で使用)LLM_API_KEY— クライアントライブラリで必要。Ollama は無視します(空でない値なら何でも可)LLM_MODEL—ollama listで表示されるローカルモデル名(ステージ 4B のツール呼び出しはqwen2.5:7bで良好に動作)
その他のオプション: LM Studio、vLLM、または OpenAI チャット API を話す任意のサーバー — LLM_BASE_URL と LLM_MODEL を変更するだけです。
ステージ 2A: Open-Meteo 天気クライアント
app/weather_client.py は 2 段階で Open-Meteo と通信します(LLM も MCP もなし):
ジオコーディング —
GET https://geocoding-api.open-meteo.com/v1/searchで都市名(オプションで州/地域と国)を緯度、経度、正式名称、行政地域、国、タイムゾーンに変換します。予報 —
GET https://api.open-meteo.com/v1/forecastでその座標を使用して 現在の 天気(気温、湿度、風、WMO 天気コード)を取得します。
呼び出し元は、生のプロバイダ JSON ではなく、型付けされたモデル(Location、CurrentWeather、WeatherResult)を受け取ります。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 コードの重複なし)構造化された天気ペイロード(または安全なツールエラー)を返す
このローカル学習 POC では stdio 経由で MCP を話す
公開ツール契約: 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-serverstdio を使用する場合、プロセスは stdin/stdout で MCP ホストを待機します。単独でターミナルで実行すると「ハング」しているように見えますが、それは想定内です。
stdio トランスポートの仕組み(概念)
MCP host / Inspector
├── spawns: python -m app.mcp_server
├── writes JSON-RPC MCP messages → server stdin
└── reads JSON-RPC MCP messages ← server stdoutこの POC ではポートも 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 が壊れているか古すぎる場合は、nvm(または同等のもの)で最新の Node を使用し、npx が PATH の最初にあることを確認してください。
オプション A — mcp dev による Web UI(公式 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 + プロジェクト設定による Web UI
リポジトリルートの mcp-inspector.json は、Inspector をローカルの stdio サーバーに向けます:
npx -y @modelcontextprotocol/inspector --config ./mcp-inspector.json --server weather-learning-server表示された http://localhost:6274?... URL を開き、セッションが接続されていることを確認し、オプション A と同様に Tools タブを使用します。
オプション 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 という名前のツールが 1 つ、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への明示的な呼び出し構造化された MCP ツール結果 JSON
プロセスを終了すると、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 answerif "weather" in question も、都市の正規表現も、ハードコードされた get_current_weather 呼び出しも ありません。ツールを使用するかどうかは モデル が選択します。
エージェントループ(詳細)
MCP セッション開始 —
python -m app.mcp_serverを stdio 経由で起動; クライアントを初期化ツール発見 —
list_tools; 各ツールの名前/説明をログ出力スキーマ変換 — MCP ツール → Responses の
type: "function"ツールモデルターン —
client.responses.create(..., tools=..., tool_choice="auto")出力検査 —
function_callアイテムが存在する場合:ツール名を発見済みセットに対して検証
JSON 引数をパース/検証
MCP を呼び出し; 構造化結果を保持
previous_response_idを指定してfunction_call_outputを送信
繰り返し — モデルが最終テキストメッセージを返すまで(または最大反復回数に達するまで)
最終回答を出力 し、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_callforget_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/注意事項
公式の
openaiPythonパッケージは、OpenAI互換のクライアントとして使用されます(初期はChat Completions、Stage 4BではResponses API)。リクエストは設定されたLLM_BASE_URL(デフォルトはOllama)に送信されます。天気の検索には、
httpxを介したOpen-Meteoを使用します(app/weather_client.py)。Stage 2B(
direct_weather_app.py)は、天気→LLMの流れを明示的にオーケストレーションします。MCPやツール呼び出しはありません。Stage 3では、公式の
mcp2.0.0 SDK(mcp.serverのMCPServer)をstdio経由で使用します。サードパーティのfastmcpパッケージは使用しないでください。Stage 4A(
basic_mcp_client.py)では、依然として天気ツールを明示的に呼び出します(LLMによるツール選択はありません)。Stage 4B(
mcp_agent.py)では、Responses APIを介したMCPディスカバリ後に、モデルがツールを選択できるようにします。
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