meteoswiss-mcp について
meteoswiss-mcpは、MeteoSwissのデータソースからスイスの気象観測、予報、気候平年値、公式警報を提供するMCPサーバーです。学校行事の計画、地域の天気確認、気候の比較などに利用できます。
主な機能
- 01気象観測所の現在値
- 02場所・座標別の予報
- 03屋外イベントの適性チェック
- 04選択した観測所の気候平年値
- 05地域別の公式気象警報
- 06州で絞り込める観測所一覧
活用シーン
- 01学校のスポーツ行事に適した日の選定
- 02近隣観測所の現在値の確認
- 03都市間の月別気候平年値の比較
- 04州や郵便番号で有効な警報を確認
MCP 対応
stdioまたはStreamable HTTP経由で、読み取り専用の気象・気候ツール6種をMCPクライアントに提供します。観測、予報、平年値、警報の取得にはMeteoSwissなどの公開データソースを利用します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
🌦️ meteoswiss-mcp
MeteoSwiss のスイスの気象・気候データを提供する MCP サーバーです。
SwissMetNet 観測ネットワーク(160 以上の観測地点、10 分間隔)、MeteoSwiss ICON-CH1/CH2-EPS 予報、1991~2020 年の気候平年値を AI モデルに接続します。swiss-public-data-mcp ポートフォリオの一部です。
🇩🇪 ドイツ語版
デモクエリ(アンカーとなる例)
How suitable is next Wednesday for the sports day at Leutschenbach school?
→ meteo_school_check(location="Zürich Oerlikon", activity="Sporttag") は、来週の各日に対して🟢/🟡/🔴の信号機形式で判定を返します。MeteoSwiss ICON モデルのデータをそのまま使用します。
swiss-environment-mcp と組み合わせる場合:
How were air quality and weather at Leutschenbach school yesterday?
→ meteo_current(station='REH') + env_nabel_current(station='ZUE') = 環境の全体像を把握できます。
→ 対象者別のユースケースはこちら →
ツール(6)
| ツール | 説明 | データソース |
|---|---|---|
meteo_stations | SwissMetNet 観測地点の一覧(州で絞り込み可能) | 埋め込みデータ |
meteo_current | 観測地点の最新の10分間隔の観測値 | BGDI STAC API |
meteo_forecast | 場所または座標の1~16日先の予報 | Open-Meteo / MeteoSwiss ICON |
meteo_school_check | 屋外の学校行事向けの🟢/🟡/🔴信号機形式の判定 | Open-Meteo / MeteoSwiss ICON |
meteo_climate_normals | 1991~2020年の月別気候平年値 | 埋め込みデータ(KLO、SMA、BER、LUG、GVE) |
meteo_warnings | 発令中の公式気象警報(暴風、雷雨、暑さ、森林火災など)— 全国、州別、または PLZ 別 | MeteoSwiss App-API + opendata.swiss |
ツールのアノテーション(MCP ヒント)
すべてのツールに明示的な MCP アノテーション が付いています。これはクライアントの承認 UI と、LLM の安全性に関する判断に関係します。
| ツール | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
meteo_stations | ✅ | ✗ | ✅ | ✗(厳選リスト) |
meteo_current | ✅ | ✗ | ✗(ライブデータ) | ✅(上流の STAC) |
meteo_forecast | ✅ | ✗ | ✗(ライブデータ) | ✅(上流の Open-Meteo) |
meteo_school_check | ✅ | ✗ | ✗(ライブデータ) | ✅(ジオコーディング + 予報) |
meteo_climate_normals | ✅ | ✗ | ✅ | ✗(埋め込みの平年値) |
meteo_warnings | ✅ | ✗ | ✗(ライブデータ) | ✅(MeteoSwiss App-API) |
読み取りルール:6つのツールはすべて readOnly + non-destructive です。サーバーは構造上、何かを書き込んだり削除したりできません。idempotentHint=False は、呼び出すタイミングによって異なる値を返すツールを示します。
MCP プロトコルのバージョン
| 項目 | 値 |
|---|---|
| テスト済みの仕様バージョン | 2024-11-05、2025-03-26、2025-06-18(mcp[cli] SDK 経由) |
| MCP SDK のバージョン | pyproject.toml → mcp[cli]>=2.0.0,<3 を参照(mcp.server.mcpserver の MCPServer API) |
| 更新ポリシー | Dependabot が mcp[cli] を監視します。仕様の更新は、CHANGELOG に「Tool Definition Changes」マーカーを付けて記録します |
→ ロードマップと更新戦略の詳細:docs/roadmap.md
クイックスタート
Claude Desktop
{
"mcpServers": {
"meteoswiss": {
"command": "uvx",
"args": ["meteoswiss-mcp"]
}
}
}
Claude Desktop(ローカル開発)
{
"mcpServers": {
"meteoswiss": {
"command": "uv",
"args": ["run", "--directory", "/path/to/meteoswiss-mcp", "meteoswiss-mcp"]
}
}
}
クラウド/Render.com(Streamable HTTP)
ENV 変数を使用して設定します(CLI フラグ --http / --port N は引き続きオーバーライドとして使用できます)。
| 変数 | デフォルト | 説明 |
|---|---|---|
MCP_TRANSPORT | stdio | stdio または streamable-http |
MCP_HOST | 127.0.0.1 | バインドアドレス — ローカルでは絶対に変更しないでください |
MCP_PORT | 8000 | ポート |
MCP_ALLOW_ANY_HOST | 未設定 | サーバーが 0.0.0.0 にバインドできるようにするには、1 に設定する必要があります(コンテナ/クラウドのみ) |
MCP_LOG_LEVEL | INFO | DEBUG / INFO / WARNING / ERROR — 構造化 JSON ログを stderr に出力します |
MCP_ALLOWED_ORIGINS | 未設定 | CORS で許可するオリジンのカンマ区切りリストです。空の場合、CORS は無効になります(同一オリジンのみ)。Mcp-Session-Id は自動的に公開されます。 |
MCP_API_KEY | 未設定 | 設定した場合、/health を除くすべてのリクエストで X-API-Key: <key> または Authorization: Bearer <key> が必要です。定時間比較を使用します。 |
MCP_STATELESS_HTTP | 0 | 1 にすると SDK のステートレスモードが有効になり、HTTP リクエストごとに新しいセッションが開かれます。スティッキーセッションなしで複数レプリカをデプロイするための前提条件です(SCALE-002/003)。 |
OTEL_EXPORTER_OTLP_ENDPOINT | 未設定 | 設定されていて、かつ pip install meteoswiss-mcp[otel] を実行した場合、ツール呼び出しごとの OpenTelemetry スパンと httpx の自動計装が、OTLP-HTTP でコレクターに送信されます。 |
OTEL_SERVICE_NAME | meteoswiss_mcp | OTel リソース内のサービス名 |
MCP_CACHE_ENABLED | 1 | 0 にすると TTL キャッシュ全体が無効になります(エンドツーエンドテストなど) |
MCP_CACHE_TTL_STAC | 300 | STAC SMN 観測データの TTL(秒)。デフォルトは 5 分です。 |
MCP_CACHE_TTL_OPEN_METEO | 600 | ICON 予報の TTL。デフォルトは 10 分です。 |
MCP_CACHE_TTL_GEOCODING | 3600 | ジオコーディング検索の TTL。デフォルトは 1 時間です。 |
MCP_CACHE_TTL_OPENDATA | 3600 | opendata.swiss カタログの TTL。デフォルトは 1 時間です。 |
MCP_CACHE_TTL_WARNINGS | 300 | 警報(MeteoSwiss App-API /構造化オーバーライド)の TTL。デフォルトは 5 分です。 |
MCP_CLIMATE_NORMALS_PATH | 未設定 | 追加の気候平年値を含む JSON ファイルへのパスです。data/climate-normals.example.json を参照してください。 |
MCP_WARNINGS_API_URL | 未設定 | デフォルトの MeteoSwiss App-API ソースのオーバーライドです。構造化された MeteoSwiss 警報 API(将来の OGD 警報 REST エンドポイントなど)の URL を指定します。ホストは送信先許可リストに登録されている必要があります。スキーマの違いに対応します(GeoJSON の features、warnings 配列、または items)。未設定の場合は、ライブの App-API を使用します。 |
MCP_CLIMATE_NORMALS_URL_TEMPLATE | 未設定 | 埋め込み値や JSON 値がない観測地点の気候平年値を実行時に検索するための URL テンプレートです。トークン:{station}(小文字)、{STATION}(大文字)、{param}(MeteoSwiss コード tre200m0/rre150m0/sre000m0)。例:https://data.geo.admin.ch/.../{station}/{param}.txt。ホストは送信先許可リストに登録されている必要があります。 |
# Local test (safe, loopback only)
MCP_TRANSPORT=streamable-http meteoswiss-mcp
# Container / Render
MCP_TRANSPORT=streamable-http MCP_HOST=0.0.0.0 MCP_ALLOW_ANY_HOST=1 meteoswiss-mcp
Docker / Render
リポジトリには、本番環境対応のマルチステージ Dockerfile(非 root ユーザー、HEALTHCHECK)と、render.yaml ブループリントが含まれています。
# Build + test locally
docker build -t meteoswiss-mcp .
docker run --rm -p 8000:8000 meteoswiss-mcp
curl http://127.0.0.1:8000/health # → {"status":"ok","service":"meteoswiss-mcp"}
Render では、「New → Blueprint」を選択し、リポジトリを指定します。デフォルト(プラン starter、フランクフルト、単一インスタンス)は render.yaml で設定されています。
重要: 複数レプリカ向けのスティッキーセッションルーティング(監査 SCALE-002/003)はまだ実装されていないため、numInstances: 1 を意図的に設定しています。
構造化ログ
すべてのツール呼び出し、上流での障害、送信先ブロックは、JSON イベントとして stderr に出力されます(stdio トランスポートに安全です)。例:
{"tool": "meteo_forecast", "days": 7, "has_coords": false, "event": "tool_invoked", "level": "info", "timestamp": "2026-05-20T07:00:00Z"}
{"tool": "meteo_forecast", "endpoint": "geocoding", "error_type": "HTTPStatusError", "event": "upstream_failed", "level": "warning", "timestamp": "..."}
{"url": "https://evil.example.com/", "method": "GET", "reason": "host not in allow-list", "event": "egress_blocked", "level": "warning", "timestamp": "..."}
HTTP モードのセキュリティ
MCP_HOSTのデフォルトを意図的に127.0.0.1に設定しています。これにより、開発用ノート PC で--httpを使用したときに、誤ってローカルサブネットに公開されることを防ぎます(監査結果 SEC-016)。- すべての送信 HTTP 呼び出し(リダイレクト後の呼び出しを含む)は、許可リストに照らして検証されます。許可されるホストは
data.geo.admin.ch、api.open-meteo.com、geocoding-api.open-meteo.com、opendata.swissです。それ以外のホストと IP リテラル(特に169.254.169.254、RFC1918)はEgressBlockedで拒否されます(SEC-004 / SEC-021)。 - CORS:デフォルトでは無効です(同一オリジンのみ)。ブラウザクライアント(例:claude.ai の Web 版)では
MCP_ALLOWED_ORIGINS=<csv>が必要です。その場合、Mcp-Session-Idヘッダーは自動的にAccess-Control-Expose-Headersに含まれます(SDK-004)。 - API キー認証:デフォルトでは無効です。本番の HTTP 環境では、必ず
MCP_API_KEY=<random>を設定してください。有効なX-API-KeyまたはAuthorization: Bearer …を含まないリクエストは 401 で拒否されます(SEC-009 / SEC-013)。コンテナーのヘルスプローブ用に/healthは認証なしでアクセスできます。
例:本番 HTTP スタック
# 32 bytes of randomness as the auth key
export MCP_API_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
MCP_TRANSPORT=streamable-http \
MCP_HOST=0.0.0.0 \
MCP_ALLOW_ANY_HOST=1 \
MCP_ALLOWED_ORIGINS=https://app.example.com \
MCP_API_KEY="$MCP_API_KEY" \
meteoswiss-mcp
クエリの例
学校計画
Which days next week are suitable for a sports day in Zürich?
→ meteo_school_check(location="Zürich", activity="Sporttag")
What will the weather be at Leutschenbach school on Friday?
→ meteo_forecast(location="Zürich Oerlikon", days=5)
Show me current readings from the nearest MeteoSwiss station to Zürich-Schwamendingen.
→ meteo_current(station="REH")
気候の比較
How much rain normally falls in June in Zürich?
→ meteo_climate_normals(station="KLO")
Is Lugano really much sunnier than Zürich? Show me the annual values.
→ meteo_climate_normals(station="LUG") + meteo_climate_normals(station="SMA")
インフラと環境
Are there currently any weather warnings for the canton of Zürich?
→ meteo_warnings(canton="ZH")
Show me a 10-day forecast for the Heerenschürli sports facility with hourly values.
→ meteo_forecast(location="Sportanlage Heerenschürli Zürich", days=10, hourly=True)
アーキテクチャ
Claude Desktop / AI agent
│
│ MCP (stdio / Streamable HTTP)
▼
meteoswiss-mcp (MCPServer)
│
├── meteo_stations ──────────────── [embedded: ~20 SMN stations]
│
├── meteo_current ───────────────── BGDI STAC API
│ data.geo.admin.ch/api/stac/v1
│ Collection: ch.meteoschweiz.ogd-smn
│
├── meteo_forecast ──────────────── Open-Meteo
├── meteo_school_check ──────────── api.open-meteo.com/v1/meteoswiss
│ (MeteoSwiss ICON-CH1/CH2-EPS, 1–2 km)
│
├── meteo_climate_normals ───────── [embedded: normals 1991–2020]
│
└── meteo_warnings ──────────────── app-prod-ws.meteoswiss-app.ch
(MeteoSwiss App-API) + opendata.swiss
データソース
| ソース | URL | ライセンス |
|---|---|---|
| BGDI STAC API(MeteoSwiss OGD) | data.geo.admin.ch/api/stac/v1 | CC BY 4.0 |
| Open-Meteo(MeteoSwiss ICON) | api.open-meteo.com/v1/meteoswiss | CC BY 4.0 |
| Open-Meteo ジオコーディング | geocoding-api.open-meteo.com | CC BY 4.0 |
| opendata.swiss CKAN | opendata.swiss/api/3/action | CC BY 4.0 |
| MeteoSwiss App-API(警報) | app-prod-ws.meteoswiss-app.ch/v1/plzDetail | CC BY 4.0 |
安全性と制限
| 項目 | 詳細 |
|---|---|
| アクセス | 読み取り専用(すべてのツールで readOnlyHint: true)— サーバーはデータを変更または削除できません |
| 個人データ | 個人データはありません。すべてのソースは集約済みで、公開されているオープンデータです |
| レート制限 | クエリごとの上限を組み込み済み:API 呼び出しあたり最大 50 件、タイムアウト 30 秒 |
| 認証 | API キーは不要です。すべてのデータソースに一般公開でアクセスできます |
| ライセンス | すべてのデータは CC BY 4.0(MeteoSwiss オープンガバメントデータ)の下で提供されます |
| 利用規約 | 各データソースの利用規約が適用されます:MeteoSwiss OGD、Open-Meteo、opendata.swiss |
既知の制限事項
| ID | ツール | 説明 |
|---|---|---|
| BUG-01 | meteo_current | STAC アセットの構造は観測所ごとに異なる場合があります。代替手段として直接リンクへのフォールバックを実装しています |
| LIM-01 | meteo_climate_normals | 埋め込み済みの観測所は 5 か所(KLO、SMA、BER、LUG、GVE)のみです。その他は opendata.swiss のリンクから利用できます |
| LIM-02 | meteo_warnings | リアルタイムの警報は MeteoSwiss App-API(plzDetail)から取得します。一般公開され認証不要ですが、仕様は公開されていません(OGD REST API ではなく、モバイルアプリのバックエンドです)。全国向けのエンドポイントはないため、全国表示では各州を代表する首都の PLZ を 1 つずつ集約します(その PLZ 以外の地域警報が見落とされる場合があります。plz / canton で対象を絞ってください)。公式の OGD 警報 REST API が提供された時点で、MCP_WARNINGS_API_URL で接続先を上書きできます。 |
| LIM-03 | meteo_current | 10 分値を UTC で表示します。現地時間への自動変換はありません |
責任分担マトリックス — 雪と降水(swiss-environment-mcpとの区分)
ポートフォリオ内で雪と降水のデータが重複しないよう、責任を次のように分担しています。meteoswiss-mcpは大気中の降水と気象を担当し、swiss-environment-mcp(SLF ドメイン)は地上の積雪と雪崩の危険度を担当します。
| データ | meteoswiss-mcp(MeteoSwiss) | swiss-environment-mcp(BAFU / SLF) |
|---|---|---|
| 降水量(mm):観測ネットワーク、予報、気候平年値 | ✅ meteo_current / meteo_forecast / meteo_climate_normals | ❌ |
| 現在の気象状況としての降雪 | ✅ meteo_current / meteo_forecast(気象コード) | ❌ |
| 気象警報(嵐、雷雨、暑さ) | ✅ meteo_warnings | ❌ |
地上積雪深(HS) | ❌ | ✅ SLF IMIS / 調査プロット ¹ |
24 時間新雪量(HN_1D) | ❌ | ✅ SLF ¹ |
| 雪崩危険度レベル | ❌ | ✅ SLF 雪崩情報 ¹ |
| 自然災害警報(洪水、雪崩、山火事) | ❌ | ✅ env_flood_warnings、env_hazard_*、env_wildfire_danger |
原則: 大気中の降水(雨/降雪を mm で表したもの)に加え、気象、予報、警報、気候平年値はmeteoswiss-mcpの担当です。地上の積雪と雪崩の危険度はswiss-environment-mcp(SLF)の担当です。SLF IMIS の降水センサーは、積雪層の状況を把握するための情報としてのみ使用し、降水ツールとして公開することはないため、MeteoSwiss のデータとは重複しません。
¹ swiss-environment-mcpの SLF/雪関連ツールは準備中です(Phase-1 の実環境プローブは 2026-07-19 に完了。該当リポジトリのdocs/probe-slf.mdを参照)。実装後に 2 つのサーバーの担当範囲が重複しないよう、区分はすでに確定しています。
ポートフォリオの相乗効果
meteoswiss-mcp
│
├── swiss-environment-mcp Combine weather + air quality (NABEL)
│ "How were weather AND air at Leutschenbach school?"
│
└── zurich-opendata-mcp School locations → weather forecast
"Which schools in Zürich have sports-day weather?"
MCP プロトコルバージョン
このサーバーは、同じエンドポイントで2 つのプロトコル時代に対応しています。接続時のクライアントの最初のリクエストによって、どちらを適用するかが決まります。もう一方の時代のバージョンが後から提示された場合は拒否されます。
| 時代 | リビジョン | 対応するクライアント |
|---|---|---|
initializeハンドシェイク | 2024-11-05 … 2025-11-25 | 現在のクライアントが使用するバージョンです。サーバーは要求されたリビジョンで応答します。リクエストでより新しいバージョンが指定された場合は、上限の2025-11-25で応答します。 |
| リクエストごとのエンベロープ | 2026-07-28 | 2026-07-28の_metaエンベロープを含むリクエストによって、モダン接続が開始されます。 |
両方のリビジョンはtests/test_protocol_version.pyで固定され、インストール済み SDK に対して検証されます。そのため、Dependabot によるmcpの更新で、どちらかのリビジョンが気付かないうちに変更されることはありません。ワイヤー上での動作も測定します。tests/test_spec_2026.pyは、main()が uvicorn に渡すものと同じ ASGI スタックを通して、両方の時代の実際のリクエストを送信します。ハンドシェイクもセッションもなしの2026-07-28ツール呼び出しと、2025-11-25を上限とするinitializeです。
非推奨の機能は使用しません。 2026-07-28では、logging、sampling、roots が非推奨になっています(SEP-2577)。サーバーはいずれも呼び出しません。処理中のステータスはnotifications/progressで送信され(どちらの時代でも、progressTokenを送るすべてのクライアントに届きます)、エラーはツールの結果そのものに記載します。テストでは、ソース内にctx.info/ctx.warningなどがないことを確認します。
SDK のLATEST_PROTOCOL_VERSIONはモダン時代の別名であり、ハンドシェイク時代の別名ではない点に注意してください。これだけを基準に固定すると、現在のクライアントが実際にネゴシエートする時代のバージョンが変更されても検出できません。
更新ポリシー。 検証に失敗した場合、定数を考えずに編集しないでください。2 つのリビジョン間の仕様変更履歴を確認し、サーバーが引き続き正しく動作することを検証したうえで、定数、このセクション、README.de.md、CHANGELOG.mdをまとめて更新してください。
テスト
# Unit tests (no network)
PYTHONPATH=src pytest tests/ -m "not live" -v
# Live tests (real APIs) — also run daily at 05:17 UTC via
# .github/workflows/live-tests.yml, so a format change upstream
# surfaces even though the unit tests stay green.
PYTHONPATH=src pytest tests/ -m live -v
# Linting — install the local gates once with `pre-commit install`
# to run these (and the CI guards) before every commit.
ruff check src/ tests/ scripts/
ruff format --check src/ tests/ scripts/
開発
git clone https://github.com/malkreide/meteoswiss-mcp
cd meteoswiss-mcp
pip install -e ".[dev]"
MCP Inspector(ローカルテスト)
PYTHONPATH=src npx @modelcontextprotocol/inspector python -m meteoswiss_mcp.server
貢献
セキュリティ
セキュリティ対策と脆弱性の報告方法については、セキュリティポリシー(ドイツ語)をご覧ください。
ライセンス
MIT ライセンスです。詳細は LICENSE をご覧ください。
ソースデータ:MeteoSwiss Open Government Data(CC BY 4.0)。 データを使用する際は、出典:MeteoSwiss と記載してください。
作者
Hayal Oezkan · github.com/malkreide
関連サーバー
インストール
uv の uvx 経由で実行できます。クローンや手動インストールは不要です。MCP クライアントの設定に追加してください(Claude Desktop、Cursor、Windsurf では mcpServers を使用し、VS Code では .vscode/mcp.json のトップレベルにある servers キーを使用します)。
{
"mcpServers": {
"meteoswiss-mcp": {
"command": "uvx",
"args": [
"meteoswiss-mcp"
]
}
}
}
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。