swiss-environment-mcp について
swiss-environment-mcpは、スイス連邦の大気質、水文、自然災害、BAFUデータカタログなどの環境情報をAIアシスタントに提供します。APIキーなしで、現在の観測値や公開データセットを照会できます。
主な機能
- 01NABELの大気質と基準値の確認
- 02水位・流量・水温の参照
- 03洪水・山火事警報の照会
- 04積雪と雪崩危険度の取得
- 05BAFU環境データセットの検索
- 06航空機騒音と基準値の確認
活用シーン
- 01チューリッヒのNABEL観測所の大気質を確認
- 02スイス国内の洪水警報を確認
- 03ヴァレー州の山火事危険度を確認
- 04BAFUの生物多様性データセットを検索
MCP 対応
大気質、水文、災害、積雪、狩猟統計、データカタログ、航空機騒音に関するスイス環境データのツールをMCPクライアントに公開します。stdioとStreamable HTTP/SSEに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
🇨🇭 Swiss Public Data MCP Portfolio の一部です
🌿 swiss-environment-mcp
AI モデルを BAFU のスイス環境データ(大気質、水文、自然災害、山火事の危険度、環境オープンデータ)に接続する MCP サーバーです。
概要
swiss-environment-mcp を使うと、Claude などの AI アシスタントからスイス連邦当局のリアルタイム環境データに直接アクセスできます。API キーは不要です。国立 NABEL 監視ネットワークの大気質測定値、水文観測所のデータ、自然災害に関する速報、BAFU の全データセットカタログに、標準化された単一の MCP インターフェースからアクセスできます。
このサーバーは、大気質(NABEL)、水文、自然災害、BAFU オープンデータカタログの 4 つのテーマ別クラスターをカバーしています。各クラスターには、機関の生データを整った JSON レスポンスに変換する、目的に特化したツール群が対応しています。
デモの質問: 「NABEL の Zürich-Kaserne 観測所の現在の大気質はどうですか?WHO 2021 ガイドラインに適合していますか?」 → 利用者別のユースケース →
機能
- 🌬️ 大気質モニタリング – NABEL の 16 観測所、NO₂/O₃/PM10/PM2.5/SO₂/CO、スイス LRV および WHO 2021 の基準値チェック
- 💧 水文 – スイスの観測所における水位、流量、水温
- 🚨 洪水警報 – 危険度と州で絞り込んだ有効な警報
- 🏔️ 自然災害速報 – ドイツ語/フランス語/イタリア語/英語の SLF/BAFU 速報、地域別警報
- 🔥 山火事の危険度 – 州および地域ごとの火災危険度指数
- ❄️ 積雪・雪崩(SLF) – 各 IMIS 観測所の積雪深、新雪量、雪崩危険度(EAWS)
- 🦌 狩猟統計 – 種、州、年ごとの捕獲数と狩猟による損失(連邦狩猟統計)
- 📦 BAFU オープンデータカタログ – CKAN を通じた環境データセットの検索と取得
- 🔑 認証不要 – すべてのデータソースに公開アクセスできます
- ☁️ デュアルトランスポート – Claude Desktop 向けの stdio、クラウドデプロイ向けの Streamable HTTP/SSE
前提条件
- Python 3.11+
- API キーは不要です。すべてのエンドポイントに認証なしで公開アクセスできます
インストール
# Clone the repository
git clone https://github.com/malkreide/swiss-environment-mcp.git
cd swiss-environment-mcp
# Install
pip install -e .
または uvx を使用(永続的なインストールは不要):
uvx swiss-environment-mcp
または pip を使用:
pip install swiss-environment-mcp
クイックスタート
# Start the server (stdio mode for Claude Desktop)
swiss-environment-mcp
Claude Desktop ですぐに試せます:
「NABEL の Zürich-Kaserne 観測所の現在の大気質はどうですか?」 「現在、スイスで有効な洪水警報はありますか?」 「Valais 州の山火事の危険度はどのレベルですか?」
設定
Claude Desktop
最小構成(推奨):
{
"mcpServers": {
"swiss-environment": {
"command": "uvx",
"args": ["swiss-environment-mcp"],
"env": {}
}
}
}
設定ファイルの場所:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
保存後、Claude Desktop を完全に終了して再起動してください。
クラウドへのデプロイ(ブラウザーアクセス用の SSE)
ブラウザーの claude.ai 経由(ローカルソフトウェアを利用できない管理対象ワークステーションなど)で使用する場合:
Render.com(推奨):
- リポジトリを GitHub にプッシュするか、フォークします
- render.com で「New Web Service」→ GitHub リポジトリに接続します
- Render が
render.yamlを自動的に検出します - claude.ai の Settings → MCP Servers で、
https://your-app.onrender.com/sseを追加します
Docker:
docker build -t swiss-environment-mcp .
docker run -p 8000:8000 swiss-environment-mcp
💡 「開発者のノート PC では stdio、ブラウザーでは SSE。」
利用可能なツール
すべてのツールで安定した env_ という名前の接頭辞を共有しています。これは、サーバーのツールを識別しやすくし、複数の MCP
サーバーを同時に接続した場合にも名前が衝突しにくくするために意図的に選んだ名前空間です。ツール定義(名前、説明、入力スキーマ)は
tool-snapshot.json で固定されており、変更には CHANGELOG のエントリーが必要です(CONTRIBUTING を参照)。
ツールの上限(21 個のツール、7 つのクラスター)に達しています。 各ツールは REST エンドポイントではなく、固有の
ユーザーの質問に対応しており、CRUD/エンドポイントの模倣はありません。また、基準となるクエリにはそれぞれ 1 回の呼び出しで回答できます。
ツール数は目安の ≤12 を超えています。これは、サーバーが 7 つの環境分野(大気、水、災害、積雪、狩猟、カタログ、航空機騒音)を
意図的に対象としており、それぞれに一覧/詳細のペア、または分野固有のアクションが必要なためです。さらなる統合も検討しましたが、
採用しませんでした。*_stations/*_current のペア(NABEL、hydro、snow)は、それぞれ実際に異なる目的(検索と既知の観測所のデータ取得)に
使われており、統合すると 1 つのツールのパラメーターが過剰になるためです。
これが上限です。 航空機騒音クラスターを加えたことで、サーバーのツール枠は使い切りました。これ以上のデータソースはここではなく、
別個の *-mcp サーバーに追加してください。次に追加する場合は、一覧機能の一部をツールではなく MCP リソースに移行すべきかどうかを
検討することになります。
🌬️ 大気質/NABEL(3 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_nabel_stations | 位置の種類と州を含む、NABEL の全 16 観測所を一覧表示します | NABEL / BAFU |
env_nabel_current | 観測所の現在の大気質データ(NO₂、O₃、PM10、PM2.5、SO₂、CO) | NABEL / BAFU |
env_air_limits_check | 測定値をスイスの LRV 基準値および WHO 2021 ガイドラインと比較します | 組み込み |
💧 水文学(5 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_hydro_stations | 水域で水文観測所を絞り込みます(州のフィルターは利用できません。注を参照) | LINDAS SPARQL |
env_hydro_current | 観測所の現在の水位、流量、温度 | LINDAS SPARQL |
env_hydro_history | 最新の LINDAS 値に加え、実際の時系列データを取得するためのアクセス方法 ⚠️ | LINDAS SPARQL |
env_flood_warnings | 危険度で絞り込んだ有効な洪水警報(全国対象。州のフィルターは適用されません) | LINDAS SPARQL |
env_bathing_water | 水浴場ごとの水質(E.coli、腸球菌)— 複数年の時系列データ | LINDAS SPARQL(データキューブ ubd0104) |
🏔️ 自然災害(3 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_hazard_overview | ルーター:専用のリアルタイム災害ツールと公式ポータルを案内します(ネットワーク呼び出しなし。集約 API の naturgefahren.ch は提供終了) | ローカル |
env_hazard_regions | ルーター:災害の種類(洪水/雪崩/山火事/雪)に応じて、適切なリアルタイムツールとポータルを案内します(ネットワーク呼び出しなし) | ローカル |
env_wildfire_danger | 州と地域ごとの山火事危険度指数 | waldbrandgefahr.ch |
❄️ 積雪と雪崩/SLF(3 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_snow_stations | SLF/IMIS の自動積雪観測所を一覧表示します(州別) | measurement-api.slf.ch |
env_snow_current | 観測所ごとの現在の積雪深(HS)と 24 時間の新雪量(HN_1D)、単位は cm | measurement-api.slf.ch |
env_avalanche_bulletin | 警戒地域ごとの雪崩危険度(EAWS 1–5)、季節別 | aws.slf.ch |
🦌 狩猟と野生動物(2 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_hunting_species | 連邦狩猟統計が追跡している 36 種の一覧(コード付き) | jagdstatistik.ch(組み込み) |
env_hunting_stats | 種、州、年ごとの捕獲数/狩猟による損失数/個体数(2015–2024) | jagdstatistik.ch |
📊 環境データカタログ(2 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_bafu_datasets | opendata.swiss 上の BAFU データセットを検索(CKAN API) | opendata.swiss |
env_bafu_dataset_detail | 特定のデータセットの完全なメタデータとダウンロード URL | opendata.swiss |
✈️ 航空機騒音/BAZL 騒音カダストル(3 個のツール)
| ツール | 説明 | データソース |
|---|---|---|
env_noise_aircraft_at | LV95 の地点における航空機騒音の曝露量 — 重なり合う騒音等高線を特定し、上限値を最高値とする dB の範囲を返します | api3.geo.admin.ch(BAZL) |
env_noise_aircraft_registers | 公開済みのカダストルがある飛行場、その有効期間、dB の範囲、公式図面(PDF)を確認します — 出典確認用ツールです | api3.geo.admin.ch(BAZL) |
env_noise_limits_check | 感度レベル ES I–IV ごとに、評価騒音レベルを LSV の曝露限度値(計画値/イミッション限度値/警報値)と比較します | 組み込み(SR 814.41、附属書 5) |
⚖️ 法的通知 — これら 3 つのツールのすべての応答に含まれます。 騒音 カダストルは参考情報です。建築計画に関する法的拘束力のある情報は、 管轄する州当局または FOCA(BAZL)が発行します。これらのツールは建築許可に関する 確認に代わるものではありません。
座標は LV95 で指定する必要があります(EPSG:2056、単位はメートル:E ≈ 2'480'000–2'840'000、
N ≈ 1'070'000–1'300'000)。8.54 / 47.37 のような WGS84 の度数は、
変換方法のヒントとともに即時に拒否されます。これはスイスの地理空間データを扱う際に、
LLM が最もよく犯す間違いです。swisstopo REFRAME または
swisstopo-mcp の convert_coordinates で変換してください。
等高線は面ではなく線です。 カダストルは MultiLineString
の等高線を公開しているため、identify は点がポリゴン内にあるかを判定するのではなく、
検索半径内の近接をクエリします。そのため env_noise_aircraft_at は範囲
(「地点は 61 dB の等高線と 62 dB の等高線の間にある」)を返し、
最高値を明示的な上限値として示します。補間した地点の値は返しません。検索半径は
すべての応答に記載されます。半径を広げると結果の範囲も広がります(クローテンのある地点では、
100 m なら 61–62 dB ですが、500 m では 58–75 dB になります。75 dB の滑走路等高線が
1.5 km 離れているためです)。
アンカーデモ用クエリ
「計画中の学校用地は、建築制限のある航空機騒音区域内にありますか? また、その dB レベルはいくつですか?」
サーバー間の処理フロー:住所または EGID を
swiss-housing-mcp で特定 → LV95 座標に変換 →
env_noise_aircraft_at(east=…, north=…, period="day") を実行 →
得られた level_db を env_noise_limits_check(level_db=…, sensitivity_level="II", period="day") に渡して法的区分を確認します。
swiss-housing-mcp → address / EGID → LV95 E/N
↓
env_noise_aircraft_at → 62 dB (upper bound, LBK Zürich, valid from 03.07.2015)
↓
env_noise_limits_check → immission limit ES II (60 dB) exceeded by 2 dB
使用例
| クエリ | ツール |
|---|---|
| 「今のチューリッヒ・カゼルネの空気質は?」 | env_nabel_current |
| 「45 µg/m³ の NO₂ はスイスの基準を超えていますか?」 | env_air_limits_check |
| 「チューリッヒのリマト川の現在の水位は?」 | env_hydro_current |
| 「クスナハトのシュトランドバートの水質は遊泳に安全ですか?」 | env_bathing_water |
| 「スイスで発令中の洪水警報はありますか?」 | env_flood_warnings |
| 「グラウビュンデン州の自然災害情報は?」 | env_hazard_overview |
| 「ヴァレー州の山火事の危険度は?」 | env_wildfire_danger |
| 「opendata.swiss にある BAFU の生物多様性データセットは?」 | env_bafu_datasets |
| 「建設予定の学校用地は航空機騒音区域内ですか? 騒音レベルは何 dB ですか?」 | env_noise_aircraft_at |
| 「ジュネーブ空港の騒音台帳は何年前のものですか?」 | env_noise_aircraft_registers |
| 「夜間の 62 dB は ES II 住居区域の LSV 基準を超えていますか?」 | env_noise_limits_check |
🛡️ 安全性と制限
| 項目 | 詳細 |
|---|---|
| アクセス | 読み取り専用(readOnlyHint: true)— サーバーがデータを変更または削除することはできません |
| 個人データ | 個人データはありません — すべての情報源は、集計済みの公開環境測定データです |
| レート制限 | クエリごとに上限を組み込み済み(例:水文履歴は最大 30 日、データセット検索結果は最大 50 件) |
| タイムアウト | API 呼び出しごとに 30 秒 |
| 認証 | API キーは不要 — すべての BAFU エンドポイントにパブリックアクセスできます |
| ライセンス | BAFU オープンガバメントデータ(OGD)— 出典の明記を条件に、無料で再利用できます |
| 利用規約 | 各データソースの利用規約が適用されます:BAFU / opendata.swiss、hydrodaten.admin.ch、naturgefahren.ch、waldbrandgefahr.ch |
アーキテクチャ
┌─────────────────┐ ┌───────────────────────────┐ ┌──────────────────────────┐
│ Claude / AI │────▶│ Swiss Environment MCP │────▶│ Upstreams (contacted) │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ │
└─────────────────┘ │ │ │ lindas.admin.ch (SPARQL)│
│ 21 Tools · 3 Resources │ │ measurement-api.slf.ch │
│ Stdio | SSE │ │ aws.slf.ch │
│ │ │ waldbrandgefahr.ch │
│ api_client.py │ │ jagdstatistik.ch │
│ server.py (FastMCP) │ │ api3.geo.admin.ch │
└───────────────────────────┘ │ opendata.swiss (CKAN) │
└──────────────────────────┘
アーキテクチャに関する注記 — 抽出可能な lindas/ モジュール
LINDAS SPARQL へのすべてのアクセスは、意図的に抽出可能な
src/swiss_environment_mcp/lindas/ モジュールを経由します。このモジュールは、厳密に分離された 3 つのレイヤーで構成されています。
client.py が扱うのは SPARQL と HTTP のみです(GET/POST、クライアント側のタイムアウトは 45 秒、サーバーの MALFORMED メッセージを含む QueryError、2 秒/4 秒/8 秒の再試行)。
cube.py は cube.link の語彙を扱います(必須の observationSet による二段階アクセス、schema:expires を用いたバージョン重複の排除、コードからラベルへの解決、ライセンスの照会)。ツールが呼び出すのは常に cube.py のみです。2 つ目のサーバーが LINDAS を使用し次第、このモジュールを共有の lindas-mcp として切り出す予定です(候補:wsl-envidat-mcp)。
アーキテクチャ上の決定 — 航空機騒音カダストルのライブ API
このサーバーのほかの部分は、ポートフォリオのダンプ優先標準に従っています。
航空機騒音クラスターは意図的にこれと異なり、env_noise_aircraft_at と
env_noise_aircraft_registers は呼び出しのたびに api3.geo.admin.ch に
ライブで問い合わせます。
これはサイズの問題ではありません。2026-07-28 に測定したところ、カダストル全体は 8 つのサブレイヤーにまたがる**747 個のオブジェクト(GeoJSON で約 3 MB)**であり、 問題なくミラーリングできます。判断を左右する理由はほかに 2 つあります。
- ミラーでは鮮度に関する主張が不正確になります。 カダストルは飛行場ごとに、
個別に、告知なく改訂されます(有効期間の日付は 2009~2024 年)。ダンプから読み込むと、
source_freshnessはミラーリング時点のvalidfromを報告するため、ツールはもはや 根拠のない出所情報を主張することになります。「根拠がどれほど古いか」に答えるために 3 つ目のツールが存在するクラスターにとって、これは考えられる限り最悪の障害モードです。 - 価値があるのは属性ではなく空間クエリです。 ローカルで評価する場合、各レイヤーで
26'000 個を超える頂点に対する点と線の距離計算が必要になります。そのためには、
shapely/GEOS(バイナリ依存を意図的に含めていない
pyproject.tomlに初めて導入される コンパイル済み依存関係であり、Docker イメージ、ホイールのマトリックス、セキュリティ上の 対象範囲がすべて変わります)を使うか、距離計算を独自に実装する必要があります。後者は、 LV95 がメートル単位の投影法で、ユークリッド距離が正確なため実現可能です。しかしその場合、 公式の騒音カダストルに関する情報の正確性を連邦機関ではなくこのサーバーが担うことになります。
測定結果と詳細な理由については、docs/probe-fluglaerm.md をご覧ください。
データソース
| ソース | データ | ライセンス |
|---|---|---|
| lindas.admin.ch | SPARQL 経由で取得する現在の水文データ(水位、流量、水温)と水浴水質 | BAFU Open-Use / OGD(グラフ/データセットごとに明記 — 各レスポンスにライセンスフィールドが含まれます) |
| hydrodaten.admin.ch | v0.6.0 以降、HTTP 経由ではアクセスしていません — /lhg/az/* エンドポイントは廃止され、データは LINDAS から取得します。ツールの出力にリンクとしてのみ表示され、egress 許可リストからは削除されています(SEC-021)。 | BAFU OGD |
| naturgefahren.ch | 自然災害情報(SLF/BAFU) | BAFU/SLF |
| waldbrandgefahr.ch | 森林火災危険度指数 | BAFU |
| SLF data service | 積雪深、新雪(IMIS)、雪崩情報 | SLF (WSL) CC BY 4.0 |
| jagdstatistik.ch | 連邦狩猟統計(捕獲数、狩猟による損失、個体数) | BAFU — 出典の表示が必要(明示的なライセンスは公開されていません) |
| api3.geo.admin.ch | BAZL 航空機騒音カダストル(identify、LV95) | swisstopo / BAZL — 出典表示を条件に再利用無料 |
| opendata.swiss | BAFU データカタログ(CKAN API) | OGD |
すべてのデータは公開されており、認証は不要です。
出典表示が必要です: データを使用する際は、BAFU / SLF (WSL) を出典として記載してください。
プロジェクト構成
swiss-environment-mcp/
├── src/swiss_environment_mcp/
│ ├── __init__.py # Package
│ ├── server.py # FastMCP server: 21 tools, 3 resources
│ ├── api_client.py # HTTP client + egress allow-list (SSRF guard)
│ └── logging_setup.py # structlog -> stderr
├── tests/
│ ├── test_unit.py # Mocked unit tests (no network) — CI default
│ ├── test_integration.py # Live API tests (marker: live)
│ └── test_20_scenarios.py # Live scenario coverage
├── scripts/tool_snapshot.py # Tool-definition hash snapshot (rug-pull guard)
├── docs/ # security.md, scaling.md, roadmap.md
├── .github/
│ ├── dependabot.yml # Monthly dependency/action updates
│ └── workflows/ # ci.yml, security.yml (gitleaks), live-tests.yml, publish.yml
├── Dockerfile # Multi-stage, non-root container
├── render.yaml / Procfile # Cloud deployment
├── tool-snapshot.json # Committed tool-definition snapshot
├── .env.example # Non-secret config template
└── pyproject.toml # Build configuration (hatchling)
単一モジュール構成(理由、監査 ARCH-011): 21 個のツールは
tools/パッケージではなく、 1 つのserver.pyに配置しています。これらはapi_client.pyを通じた薄く均一なラッパーで、 入力/レスポンスのパターンを共有しているため、適切にセクション分けされた単一モジュールのほうが、 ほぼ同一のファイル 4 つよりも見通しがよくなります。これは意図的に文書化された逸脱です。 ツールのロジックにばらつきが増えた場合は、分割を再検討します。
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 の更新で、どちらかが気づかないうちに変わることはありません。
ただし、この固定で測定しているのは SDK であり、このサーバーではありません。サーバーがモダンな世代にまったく応答しなくても、テストは成功したままです。サーバー側の動作は tests/test_modern_protocol.py で測定します。運用時に uvicorn が起動するものと同じ本番アプリ(build_cors_app())を通じて、両方の世代で実際のリクエストをテストし、負の対照として _meta エンベロープの欠落、ルーティングヘッダーの不一致、モダンな接続での initialize も検証します。
このサーバーにおける 2026-07-28 の意味
- セッションなし、
initializeなし — そのため、ハンドシェイク結果にserverInfoは含まれません。サーバーはserver/discoverと、すべての応答に含まれるio.modelcontextprotocol/serverInfoの_metaスタンプを通じて自身を紹介します。名前、タイトル、説明、ウェブサイト、バージョンはMCPServerコンストラクターから取得します。バージョンはパッケージメタデータから取得し、リテラルは使いません。これがない場合、サーバーはversion: ""を報告するため、ステートレスクライアントは異なるリリースを見分けられません。 - ルーティングヘッダー。
Mcp-Method、Mcp-Name、MCP-Protocol-Versionはリクエスト本文と一致する必要があり、一致しない場合はリクエストが-32020で拒否されます。そのため、これらはCORS_ALLOW_HEADERSに含まれています。これらを送信できない可能性があるブラウザーは、応答ではなく拒否を受け取ります。 - ロギングはリクエストごとのオプトイン方式です(SEP-2577)。この機能はなくなっており、予約済みの
io.modelcontextprotocol/logLevel_metaキーがなければ、サーバーは何も送信しません。logLevel: "warning"が指定されると、応答はtext/event-streamに切り替わり、ログ項目を含みます。両方の動作を測定します。 - 鮮度のヒント(SEP-2549):一覧表示メソッドには
ttlMsとcacheScopeが含まれます。CACHE_HINTSを参照してください。
SDK の LATEST_PROTOCOL_VERSION はハンドシェイク世代ではなく、モダンな世代の別名です。これだけを基準に固定すると、現在のクライアントが実際にネゴシエーションする世代が変更されても検知できません。
更新ポリシー。 ゲートに失敗した場合、定数をむやみに編集しないでください。2 つのリビジョン間の仕様変更履歴を読み、サーバーが引き続き正常に動作することを確認してから、定数、このセクション、README.de.md、CHANGELOG.md をまとめて更新してください。
- ツール定義の安定性(監査 SEC-022): ツールの名前、説明、パラメーターを変更すると
tool-snapshot.jsonが変わります。スナップショットを再生成し、CHANGELOGの項目を追加してバージョンを上げるまで、CI は失敗します。 - 更新ポリシー: Dependabot の PR を毎月確認してください。ツール定義または動作に変更があれば、バージョンを上げてください(semver)。
ライフサイクルフェーズ
このサーバーは**フェーズ 1(読み取り専用)**です。すべてのツールは読み取り専用で、認証も副作用もありません。フェーズ 2(書き込み/認証)のフェーズモデルと前提条件は docs/roadmap.md を参照してください。セキュリティアーキテクチャ(SSRF/外向き通信、シークレット管理、リーサルトライアドの評価):docs/security.md。スケーリング/セッション戦略:docs/scaling.md。
既知の制限事項
- LINDAS 経由の水文情報:
env_hydro_current、env_hydro_stations、env_flood_warningsは、BAFU LINDAS SPARQL エンドポイントに問い合わせます(型付きのリアルタイム値:水位、流量、水温、危険度)。LINDAS が保持するのは現在値のみ(観測所ごとに1件)であり、過去の時系列データではありません。docs/probe-lindas-hydro.mdを参照してください。 - 過去の水文情報/
env_hydro_history(BUG-01 解決済み):以前のhydrodaten.admin.ch/lhg/az/*REST エンドポイント(毎時 CSV、warnings.json、観測所 JSON)は廃止済み(404)です。env_flood_warningsは現在、代わりに LINDAS のdangerLevelを使用します。実際の過去の時系列データ(日別/長期平均など。例:2024年夏と長期平均の比較)は、API から無料では入手できません。BAFU Hydrological Enquiry Service([email protected])に依頼する必要があります。env_hydro_historyは最新の LINDAS 値と、この入手方法を返します。 - 洪水警報:
env_flood_warningsは LINDAS のdangerLevelを読み取ります。LINDAS には州コードがないため、州フィルターは利用できず、応答は常に全国対象です。cantonの値は応答にそのまま含まれ、適用されていないことが示されます。JSON エンベロープではmatch_type: "fuzzy"と注記で、Markdown では表の上の警告行で示されます。警報がまったくない場合に特に重要です。リクエストに州名が含まれていると、「有効な警報なし」という結果が、その州では警報がないことを意味するように誤読されるおそれがあります。 - 水位観測所/州フィルター:
env_hydro_stationsはcantonに対応しなくなりました。州コードを含んでいた唯一の情報源hydrodaten.admin.ch/lhg/az/json/mobile_stations.jsonは**廃止済み(404)**で、LINDAS にも州属性はありません。cantonを設定したリクエストには、観測所一覧の代わりに説明が返されます。water_bodyを使用するか、フィルターなしで全件(233観測所)を取得してください。 - 水浴場の水質(
env_bathing_water):LINDAS データキューブfoen/ubd01041prodを読み取ります。これは複数年の実際の時系列データがある唯一の水文キューブです(2020年以降の季節ごとのサンプル)。データは水浴シーズン終了後に年1回更新され(リアルタイム監視ではありません)、調査対象は公式に報告された水浴場のみです(人気のある水浴施設の多くは対象外です)。ライセンスはキューブではなくグラフ/データセットのレベルで宣言されます。そのため、すべての応答に明示的なライセンス項目が含まれ、宣言がない場合は「未宣言」と正直に注記します。docs/probe-lindas-hydro.md(追補 N1–N7)を参照してください。 - LINDAS に地下水データはありません:多言語キューブ検索により、2026-07-24 に確認済みです。LINDAS には地下水キューブがありません(NAQUA の地下水位は SPARQL 経由では入手できません)。
- NABEL:準リアルタイムデータのみです。このサーバー経由では過去の時系列データを取得できません。
- 自然災害(
env_hazard_overview/env_hazard_regions):以前のnaturgefahren.ch/api/v1/warnings/*REST エンドポイントは廃止済み(2026年)です。また、2026-07-26 の確認では、集約警報用の安定した、文書化された公開 JSON フィードはありませんでした(MeteoSwiss OGD/STAC、opendata.swiss、未文書化のアプリ API をすべて確認済み)。不安定なスクレイピングを行う代わりに、両ツールは現在、ネットワークに接続しない案内/ルーターツールとして、当サーバーの専用リアルタイムツール(洪水→env_flood_warnings、雪崩→env_avalanche_bulletin、山火事→env_wildfire_danger、積雪→env_snow_current)と公式ポータルを決定論的に案内します。集約された気象警報(暴風雨/雷雨/熱波)は MeteoSwiss の担当分野であり、meteoswiss-mcpに属します。docs/probe-naturgefahren-hazards.mdを参照してください。 - 山火事危険度(
env_wildfire_danger):waldbrandgefahr.chは2026年に REST API を Rails/React アプリに置き換えており、安定した JSON エンドポイントはありません。現在の危険度は、HTML に含まれる契約に基づく2段階の手順で読み取られます。ホームページのdata-react-propsから、署名付き ActiveStorage blob URL(warnMapJsonPath)と州のマッピングを取得し、その URL を取得します。この構造が変わった場合、スキーマガードにより適切に機能が縮退します。フィルターなしの結果は40地域までに制限され(危険度の高い順)、州の一覧をすべて表示するにはcantonで絞り込んでください。docs/probe-naturgefahren-waldbrand.mdを参照してください。 - 狩猟統計(
env_hunting_stats):jagdstatistik.chのバックエンドは文書化されていません(コンテンツネゴシエーションを行うウェブアプリのエンドポイント)。構造が変わった場合、スキーマガードにより適切に機能が縮退します。種/州/データ型の参照データは埋め込み済み(2026-07-19に取得)で、数値は2015~2024年分をリアルタイムで取得します。ライセンス(2026-07-19調査):データの所有者はBAFU(州当局が集計。サイト技術は Wildtier Schweiz)です。opendata.swiss ではライセンス付きデータセットとして公開されておらず、情報源にも明示的なライセンスの記載はありません。そのため、応答では BAFU の出典表示が必要です。正式なライセンス確認は引き続き BAFU からの回答待ちです。docs/probe-jagdstatistik.mdを参照してください。 - 道路および鉄道の騒音は対象外です(
ch.bafu.laerm-*、ch.bav.laermbelastung-*):2026-07-28に確認済みです。BAFU の道路騒音レイヤーch.bafu.laerm-strassenlaerm_tag/_nachtは、同じidentifyリクエストに対してHTTP 400を返します。属性クエリのないラスター専用サービス(type: wmts、tooltip: false)であるため、地点検索は技術的に不可能です。鉄道騒音は異なり、ch.bav.laermbelastung-eisenbahn_*は実際の属性(de_es、de_pointofdetermination)を含む HTTP 200 を返すため、クエリ可能ですが、意図的に接続していません。このサーバーのツール数の上限は21に達しており、鉄道騒音には独自の期間/属性モデルが必要となるためです。覚え方:航空機騒音には線があり、道路騒音にはピクセルしかありません。鉄道騒音にはデータがありますが、あえて対象外としています。docs/probe-fluglaerm.mdを参照してください。 - 航空機騒音は基準日付きの台帳であり、リアルタイムサービスではありません(
env_noise_*):validfromは01.03.2009(CDB Genève)から16.04.2024(LBK St. Gallen-Altenrhein)までで、各飛行場の改訂は個別に行われ、事前の通知はありません。そのため、source_freshnessは「リアルタイム」と表示せず、実際に一致した台帳のvalidfromを返します。対象範囲は飛行場周辺に限られ、スイスの大部分には台帳自体がありません。その場合、ツールは空の一覧ではなく、その旨を明示します。半径を小さくした場合に結果が0件でも、曖昧な状態です(台帳の対象外である場合と、最も内側の等高線内である場合のどちらもあり得ます。Kloten の滑走路では、どちらも半径100 mで同じ結果になります)。そのため、ツールは一度、より大きな半径で再検索し、no_cadastreとwide_area_onlyを区別します。 - LSV の限度値チェックでは軍用飛行場を対象外とします:騒音抑制条例の附則5は、明示的に民間飛行場に適用されます。軍用飛行場には附則8が適用されますが、確認されていないため、
env_noise_limits_checkはperiod="military"のチェックを拒否し、もっともらしく見える誤った表を適用するのではなく、正しい根拠を案内します。
責任分担表 — 水、雪、降水(区分と meteoswiss-mcp の比較)
ポートフォリオ全体で水、雪、降水のデータが重複しないよう、責任を以下のように分担しています。meteoswiss-mcp は大気中の降水と気象を担当し、swiss-environment-mcp は地表水(BAFU の領域:流量、水位、水温、水浴水質)、地上の積雪、雪崩の危険度を担当します。実際の LINDAS キューブの次元に基づき確認済みです(2026-07-24):測定項目に重複はありません。
| データ | swiss-environment-mcp(BAFU / SLF) | meteoswiss-mcp(MeteoSwiss) |
|---|---|---|
| 流量(m³/s) | ✅ env_hydro_current(LINDAS hydro/river) | ❌ |
| 水位(m a.s.l.) | ✅ env_hydro_current(LINDAS hydro/river + lake) | ❌ |
| 水温(°C) | ✅ env_hydro_current | ❌(気温を測定) |
| 水浴水質(E.coli など) | ✅ env_bathing_water(LINDAS ubd0104) | ❌ |
地上積雪深(HS) | ✅ env_snow_current(SLF IMIS) | ❌ |
24 時間新雪(HN_1D) | ✅ env_snow_current(SLF IMIS) | ❌ |
| 雪崩危険度レベル | ✅ env_avalanche_bulletin(SLF、EAWS 1–5) | ❌ |
| 現在の気象条件としての降雪 | ❌ | ✅ meteo_current / meteo_forecast(気象コード) |
| 降水量(mm):観測網、予報、気候平年値 | ❌ | ✅ meteo_current / meteo_forecast / meteo_climate_normals |
| SLF IMIS 山岳観測所の降水量 | ✅ 積雪状況の補足情報としてのみ、独立した降水量ツールはありません | (MeteoSwiss の観測網) |
| 気象警報(暴風雨、雷雨、熱波) | ❌ | ✅ meteo_warnings |
| 自然災害警報(洪水、雪崩、山火事) | ✅ env_flood_warnings、env_hazard_*、env_wildfire_danger | ❌ |
ルール:水域の中および水面上のすべて(流量、水位、水温、水浴水質)、地上の積雪、および雪崩の危険度は swiss-environment-mcp(BAFU/SLF)の担当です。大気中の降水(雨/降雪量の mm)に加え、気象、予報、警報、気候平年値は meteoswiss-mcp の担当です。SLF IMIS の降水量エンドポイント(RR_10MIN_SUM)は、MeteoSwiss との重複を避けるため、意図的にツールとして組み込んでいません。雪/雪崩ツールは稼働中です(docs/probe-slf.md を参照)。
TODO(ここでは対象外):この責任分担表を meteoswiss-mcp の README にも反映します。この変更には、そのリポジトリは含まれません。
テスト
# Unit tests (no API keys or network required)
PYTHONPATH=src pytest tests/ -m "not live"
# Integration tests (requires live BAFU APIs)
PYTHONPATH=src pytest tests/ -m "live"
# Linting
ruff check src/
コントリビューション
CONTRIBUTING.md(英語) · CONTRIBUTING.de.md(ドイツ語)を参照してください。
セキュリティ
セキュリティポリシーと対応状況:SECURITY.md(英語) · SECURITY.de.md(ドイツ語)。
セキュリティアーキテクチャの全容:docs/security.md。
変更履歴
CHANGELOG.mdを参照してください。
ライセンス
MIT License — LICENSEを参照してください。
ソースデータには BAFU の利用規約が適用されます。データを使用する際は、BAFU のクレジット表記が必要です。
作者
Hayal Oezkan · github.com/malkreide
謝辞と関連プロジェクト
- データ: BAFU / Bundesamt für Umwelt · hydrodaten.admin.ch · naturgefahren.ch · opendata.swiss
- プロトコル: Model Context Protocol – Anthropic / Linux Foundation
- 関連プロジェクト:
| サーバー | 説明 |
|---|---|
| zurich-opendata-mcp | チューリッヒ市のオープンデータ(OSTLUFT の大気質、天気、駐車場、地理データ) |
| swiss-transport-mcp | スイスの公共交通機関 – OJP 2.0 の経路検索、SIRI-SX の運行障害情報 |
| swiss-road-mobility-mcp | GBFS のシェアモビリティ、EV 充電、DATEX II の交通情報 |
| swiss-statistics-mcp | BFS STAT-TAB – 682 の統計データセット |
連携の例: 「今日のSchulhaus Leutschenbachの大気質はどうでしたか?全国のNABEL平均と比べるとどうですか?」
→ zurich-opendata-mcp(OSTLUFT、地域)+ swiss-environment-mcp(NABEL、全国)
- ポートフォリオ: Swiss Public Data MCP Portfolio
インストール
uv の uvx で実行できます。クローンや手動インストールは不要です。MCP クライアントの設定に追加してください(Claude Desktop、Cursor、Windsurf では mcpServers を使用し、VS Code では .vscode/mcp.json のトップレベルに servers キーを使用します)。
{
"mcpServers": {
"swiss-environment-mcp": {
"command": "uvx",
"args": [
"swiss-environment-mcp"
]
}
}
}
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。