swiss-electricity-mcp について
swiss-electricity-mcpは、スイスの電力生産、消費予測、貯水湖の水位、電気料金を調べる分析担当者や公共機関向けです。エネルギーダッシュボード、ElComの料金データ、CKANのデータセット検索をまとめ、出典と取得情報を結果に含めます。
主な機能
- 01全国の電源構成と消費予測の検索
- 02貯水湖の水位と消費者価格指数の確認
- 03自治体・州の料金基準の取得
- 04自治体間の料金内訳の比較
- 05BFEとチューリッヒのオープンデータ検索
- 06出典・来歴・取得時刻の付与
活用シーン
- 01自治体の電気料金を年ごとに比較する
- 02地域の料金を全国・州中央値と比較する
- 03全国の発電構成と消費予測を確認する
- 04チューリッヒの時間帯別消費データを探す
MCP 対応
MCPサーバーは、BFEダッシュボード、ElComの料金データ、CKANデータセットを検索する12の読み取り専用ツールを提供します。認証不要で、stdioとStreamable HTTPに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
swiss-electricity-mcp
スイスの電力データ向け MCP サーバー — 3 つの公式データソース、12 個のツール、認証不要です。
🌍 他の言語で読む: 🇩🇪 Deutsch
Swiss Public Data MCP Portfolio の一部です。スイスの行政機関向けに連携して構成された MCP サーバーのセットです。
サンプルクエリ
「一般的な学校建築物(消費カテゴリー C3、約 150'000 kWh/a)向けの ewz 電気料金は、2019 年以降どのように推移し、スイスの中央値と比べてどうですか?」
1 回の会話で tariff_get_by_municipality(bfs_nr=261、category="C3")と tariff_get_median_swiss を呼び出し、出典情報をすべて含む年ごとの比較を返します。経営陣向けスライドにそのまま使えます。
デモ
内容
スイスの 3 つの公式データソースを 1 つの MCP サーバーに統合し、それぞれに専用のツールグループを用意しています。
| ソース | 提供データ | 出典 |
|---|---|---|
| Energiedashboard.ch(連邦エネルギー庁) | 国内の発電構成、消費予測、貯水湖の貯水率、消費者物価指数 | live_api |
| ElCom 電気料金データキューブ(LINDAS SPARQL 経由) | 自治体、カテゴリー、年ごとの料金と詳細内訳(エネルギー+送配電網利用+KEV+賦課金) | sparql |
| opendata.swiss + Stadt Zürich OGD(CKAN) | 生の時系列データ(例:15 分単位の NE5/NE7 消費量)のデータセット検索 | live_api |
認証は不要です。 すべてのエンドポイントはスイスの公開 OGD です。
ツール(12 個)
dashboard_* — Energiedashboard.ch(BFE)
dashboard_get_production_mix— 年ごとの発電構成(TWh+%):原子力、水力、PV、風力、火力。dashboard_get_consumption_forecast— 現在の消費予測+5 日間の見通し+5 年間の予測範囲。dashboard_get_storage_lakes— 貯水湖の貯水率(スイス全体または地域別:ヴァレー、ティチーノ、グラウビュンデン、中部/東部)— 冬季の電力供給を示す重要な指標です。dashboard_get_consumer_price_index— 最終消費者向け電力価格指数(2020-01-01 = 100)。
tariff_* — ElCom(LINDAS SPARQL 経由)
tariff_list_categories— H1~H8(家庭向け)および C1~C7(商業向け)。C3 ≈ 150'000 kWh/a は、学校建築物の一般的な基準です。tariff_get_by_municipality— BFS-Nr、カテゴリー、年の範囲で指定した料金。エネルギー/送配電網利用/KEV/賦課金に分けて表示します。tariff_get_median_swiss— 全国の中央値を示す基準値。tariff_get_median_canton— 州の中央値(例:チューリッヒ州)。tariff_compare_municipalities— 最大 20 の自治体を並べて比較します。
consumption_* — opendata.swiss + Stadt Zürich OGD
consumption_search_bfe_datasets— BFE 公開データセットを CKAN で検索します。consumption_search_zurich— Stadt Zürich OGD を CKAN で検索します(15 分単位の NE5/NE7 消費量を含みます)。
ステータス
electricity_check_status— 4 つすべての上流サービスの稼働状況を確認します(HTTP ステータス+レイテンシ+全体の正常性フラグ)。
インストール
PyPI から
pip install swiss-electricity-mcp
ソースから
git clone https://github.com/malkreide/swiss-electricity-mcp.git
cd swiss-electricity-mcp
pip install -e ".[dev]"
Claude Desktop で使用する
claude_desktop_config.json に追加します。
{
"mcpServers": {
"swiss-electricity": {
"command": "swiss-electricity-mcp"
}
}
}
クラウドデプロイ(Streamable HTTP)
SWISS_ELECTRICITY_TRANSPORT=streamable-http \
SWISS_ELECTRICITY_HOST=0.0.0.0 \
SWISS_ELECTRICITY_PORT=8000 \
swiss-electricity-mcp
Render.com、Railway、Fly.ioで動作します。
ホストのバインド(セキュリティ)。 HTTP モードでは、ホストのデフォルトは
127.0.0.1(ループバックのみ)です。すべてのインターフェースにバインドするには、ネットワーク境界がホストではなく コンテナになる、コンテナ内でのみSWISS_ELECTRICITY_HOST=0.0.0.0を設定してください。 開発者のマシンで0.0.0.0を設定すると、サーバーがローカルネットワークに公開されます(NeighborJack)。
Docker
マルチステージの Dockerfile が用意されています。非 root ユーザー(UID 10001)として実行され、
コンテナでの使用時に SWISS_ELECTRICITY_HOST=0.0.0.0 を明示的に設定します。
docker build -t swiss-electricity-mcp .
docker run --rm -p 8000:8000 swiss-electricity-mcp
可観測性と設定
| 環境変数 | デフォルト | 用途 |
|---|---|---|
SWISS_ELECTRICITY_TRANSPORT | stdio | stdio または streamable-http |
SWISS_ELECTRICITY_HOST | 127.0.0.1 | HTTP バインドホスト(コンテナ内のみ 0.0.0.0) |
SWISS_ELECTRICITY_PORT | 8000 | HTTP ポート |
SWISS_ELECTRICITY_LOG_LEVEL | INFO | ログレベル(DEBUG/INFO/WARNING/ERROR) |
SWISS_ELECTRICITY_CORS_ORIGINS | (空) | 許可する CORS オリジン(ブラウザクライアント用、カンマ区切り)。* は指定しないでください |
OTEL_EXPORTER_OTLP_ENDPOINT | (未設定) | 設定すると OpenTelemetry トレーシングを有効にします |
SWISS_ELECTRICITY_ENV | unknown | トレースの deployment.environment リソース属性 |
-
ロギングは stderr に構造化 JSON 形式で出力されます(stdout は stdio JSON-RPC チャネル専用です)。上流の障害はサーバー側で詳細に記録されますが、クライアント向けの応答ではマスキングされます。
-
トレーシングはオプトインです。追加パッケージをインストールし、コレクターを指定してください。
pip install "swiss-electricity-mcp[otel]" OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 swiss-electricity-mcpツール呼び出しごとに 1 つのスパン(
mcp.tool.<name>)が作成され、各上流リクエストについて httpx の子スパンも自動的に作成されます。引数の値や PII は記録されません。
アーキテクチャ
┌────────────────────────── MCP client (Claude etc.) ──────────────────────────┐
│ stdio or Streamable HTTP │
└───────────────────────────────────────┬──────────────────────────────────────┘
│ 12 read-only tools (annotated)
┌────────▼──────────┐
│ MCPServer (mcp) │ egress allow-list + HTTPS gate
│ + structlog/OTel │ per-source TTL cache + retry
└───┬────────┬───┬──┘
dashboard_* │ tariff_* │ │ │ consumption_*
▼ ▼ ▼ ▼
┌───────────────────┐ ┌───────────┐ ┌──────────────┐ ┌─────────────────────┐
│ Energiedashboard │ │ LINDAS │ │ opendata.swiss│ │ data.stadt-zuerich.ch│
│ .admin.ch (BFE) │ │ SPARQL │ │ CKAN │ │ CKAN (OGD) │
└───────────────────┘ └───────────┘ └──────────────┘ └─────────────────────┘
**ハイブリッド(ライブ API + SPARQL + CKAN ディスカバリー)**で、認証は不要です。この構成が適切である理由は 3 つあります。
- ソースごとに異なるレイテンシ特性:Energiedashboard は約 200 ms で応答するため、リアルタイム利用に最適です。LINDAS SPARQL は応答が遅く、時折 504 を返すため、タイムアウトを長めに設定し、3 回再試行します。CKAN はメタデータのみを扱うため、本質的に安全です。
- 更新頻度が異なる:ダッシュボードは日中に更新されます。ElCom の料金は年に 1 回更新されます。OGD データセットは数か月にわたって安定しています。ソースごとの TTL キャッシュ(600 s / 3600 s)は、この違いを反映しています。
swiss-energy-mcpとのドメイン分離:このサーバーは地理情報とインフラデータ(発電所、送電線)を扱います。swiss-electricity-mcpは時系列データと料金を扱います。両者は問題なく連携できます。
データの出典管理
すべてのツール応答は、以下を含む Pydantic エンベロープです。
source— 完全な帰属情報文字列(例:"データ:連邦エネルギー局(BFE)…")。provenance—live_api/sparql/cached/weekly_dump/stale_cache_fallbackのいずれか 1 つ。retrieved_at— ISO-8601 UTC タイムスタンプ。
これにより、誤った帰属が構造上起こり得ないようになっています。
回復性
- 再試行:最大 3 回再試行するため、試行回数は最大 4 回です。待機時間は指数関数的に増加し(基準値は 2 s / 4 s / 8 s)、クライアントが障害後に一斉に復帰しないよう、それぞれ 0.5~1.5 倍のジッターが加えられます。1 回の待機時間が 20 s を超えることはありません。429 または 503 とともに
Retry-Afterが送られた場合は、それが優先されます(さらに 0~25%を加算し、20 s を上限とします)。 - 時間予算:呼び出し全体に 25 s を割り当てます。すべての試行と待機を含みます。予算を超える待機が必要な場合は呼び出しを終了するため、試行回数が 4 回未満になることがあります。
- 5xx + 429:再試行します。4xx(429 を除く):恒久的なクライアントエラーとして、直ちに例外を発生させます。
- メモリ内 TTL キャッシュ:ソースごとの TTL により、上流への負荷と、エージェントの複数ステップにわたるワークフロー中の往復を削減します。
MCP のプリミティブ — ツールのみを公開する理由
このサーバーが公開するのは意図的にツールのみであり、リソースやプロンプトは公開しません。データはパラメーター指定でクエリ駆動型(自治体の BfS 番号、カテゴリー、年)であり、ツール呼び出しに自然に対応します。リソースとして公開できる、安定して列挙可能なドキュメント群はなく、同梱するために厳選したプロンプトテンプレートもありません。将来、たとえば固定の「全国の生産構成」ドキュメントが必要になった場合は、読み取り専用の dashboard_* ツールがリソースへの移行候補として最適です。
プロジェクトのフェーズ
フェーズ 1 — 読み取り専用。 12 個すべてのツールは読み取り専用(readOnlyHint=true)で、書き込み操作や破壊的な操作はありません。フェーズ移行の基準と長期計画については、docs/roadmap.md をご覧ください。セキュリティ体制(外部送信、サプライチェーン、致命的な三要素の評価)については、docs/security-posture.md に記載しています。
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 を更新しても、どちらのリビジョンも気付かれないまま変更されることはありません。ハンドシェイクの上限は定数名から読み取るのではなく、組み立てられた ASGI スタックを通した実際の initialize に基づいて測定されます。
SDK の LATEST_PROTOCOL_VERSION はハンドシェイク世代ではなく、モダンな世代の別名であることに注意してください。これだけを基準に固定すると、現在のクライアントが実際にネゴシエートする世代が変更可能なままになります。
更新ポリシー。 ゲートで失敗した場合は、定数を盲目的に編集しないでください。2 つのリビジョン間の仕様変更履歴を読み、サーバーが引き続き正しく動作することを確認してから、定数、このセクション、README.de.md、CHANGELOG.md をまとめて更新してください。仕様のバージョンアップは、明示的な mcp のマイナーまたはメジャー更新を通じてのみ採用し、その内容を CHANGELOG.md に記録したうえで、ツール定義ロック(tool-definitions.lock.json)と照合して検証します。
2026-07-28 にサーバーが標準で設定する内容
SDK があるリビジョンに到達していることと、サーバーがそのリビジョンで通信することは同じではありません。SDK がサーバーに委ねている 2 つの項目と、何も設定しない場合の動作は次のとおりです。
| 項目 | このサーバーが設定する内容 | 設定しない場合の SDK の動作 |
|---|---|---|
serverInfo — initialize の応答だけでなく、すべての結果の _meta に記録されます | name、title、version、websiteUrl | 何も補いません。バージョン未設定のサーバーは、どちらの時代のどちらのトランスポートでも、すべての呼び出し元に "version": "" を報告します。 |
キャッシュ可能なメソッド(SEP-2549)の ttlMs / cacheScope | tools/list、server/discover、prompts/list、resources/list、resources/templates/list に対し、300000 ms、スコープは public | CacheHint() のデフォルトは ttl_ms=0、scope="private" です。これは「すでに期限切れで、共有しない」というワイヤー上の形式です。そのため、すべてのクライアントが接続のたびに再度一覧を取得します。 |
2026-07-28 では、serverInfo が接続時に一度だけ行われるハンドシェイクの補足情報から、実行中のトラフィックに記録される情報へと変わりました。そのため、空のバージョンを見過ごさず、ゲートで検証する価値があります。
3 つの空のディレクトリには、意図的にヒントを付けています。MCPServer はハンドラーを無条件に登録し、server/discover はそのケイパビリティに prompts と resources を含めるため、ワイヤー上には項目が存在しますが、中身は空です。このサーバーには実行時にプロンプトやリソースを登録する方法がないため、プロセスの稼働中は空のままです。そのため、ここにあるものの中では最も安全にキャッシュできます。
どちらもコンストラクターから読み戻すのではなく、実際の応答を使って測定しています。tests/test_server_identity.py は各時代について各 ID フィールドを個別に確認し、tests/test_cache_hints.py は稼働中のクライアントセッションからヒントを読み取ります。それぞれに、素の MCPServer("kontrolle") を使ったネガティブコントロールがあります。これがなければ、SDK がいつか単独で要件を満たすようになった場合に、アサーションが「このサーバーが設定している」ことの証明として読み続けられてしまいます。
テスト
# Unit tests (mocked, fast, CI default) — tests/test_unit.py + tests/test_security.py
PYTHONPATH=src pytest -m "not live" -v
# Live tests (hits real upstreams) — tests/test_live.py
PYTHONPATH=src pytest -m live -v
単体テストでは、契約の各レイヤーをカバーしています。成功系(レスポンスの解析)、リトライ(5xx、429、4xx)、タイムアウト(ネットワークエラー → 正常に処理される UpstreamUnreachableError)、エンベロープ/帰属の不変条件に加え、セキュリティ(外向き通信の許可リスト、SPARQL のエスケープ、ツール定義のロック)も対象です。CI では Python 3.11–3.13 で ruff と pytest -m "not live" を実行します。
ポートフォリオ全体の ruff ピンを監査する
scripts/pin_audit.py は、サーバー独自のピンを保護するガードが実際に機能しているかを確認します。これはCI ゲートではありません。兄弟リポジトリがディスク上に必要なためです。ただし、ピンの規約を変更するときや、新しいサーバーを加えるときには実行する価値があります。
python scripts/pin_audit.py ../*-mcp
ブラックボックス方式で測定します。独自の rev: を持つ通常の 2 つ目の pre-commit フックを先頭に追加し、ガードを実行して終了コードを読み取り、ファイルを元に戻します。以前、ポートフォリオ内の 2 つのガードがそのフックのバージョンを ruff のピンとして報告し、その結果、誰も記述していない番号が原因で CI が失敗していました。ポジティブコントロールでは、ruff フック自体の rev を誤った値に設定します。これにより、「適切に対象を絞っている」状態と「ファイルをまったく読んでいない」状態を区別できます。これがなければ、設定を無視するガードも、問題なしと判定されてしまいます。
テストデータの取得元
tests/fixtures/ にあるフィクスチャは実際のソースから記録したもので、日付が付いています。各ファイルのソース、取得日、選択ルール、SHA-256 については、tests/fixtures/PROVENANCE.md を参照してください。
python scripts/record_fixtures.py # re-record
リクエストは本番コードによって構築されます。 スクリプトは ElComSparqlClient と EnergyDashboardClient を呼び出し、SPARQL を横で書き直すのではなく、httpx トランスポートを通じて応答を取得します。サーバーが尋ねる質問と少しでも異なる質問に答えるフィクスチャでは、間違った回答が証明されます。もっともらしく見えるため、気付かれないままです。SPARQL が 40 行もある場合、「少し異なる」は例外ではなく、よくあることです。
選択ルールは、意図的に単なる「先頭から N 件」よりも複雑になっています。
- 蓄電池の時系列データは未来まで続いています。 最後の実測日の後には、測定値が
nullの行が続きます。記録日にそのような行は 94 件ありました。これらは意図的に残しています。そうしなければ、ツールがそれらをスキップすることを示すテストができません。 - 測定値の判定基準は推測せず、ファイルごとに明示しています。 最初のバージョンでは「
date以外のフィールドがすべて null でないこと」を使っていましたが、これは誤りです。未来の行にも値、つまり 5 年間の参照曲線が含まれており、測定値だけがないためです。
検索結果を切り詰める場合も、count は実際の値を保持します。これは、ファイルに含まれていない件数を示しています。
既知の制限事項
- LINDAS SPARQL の 504 タイムアウト:LINDAS の公開エンドポイントは、高負荷時に 504 を返すことがあります。3 回の再試行ポリシーで一時的な問題に対処し、利用不能が続く場合は
UpstreamUnreachableErrorが発生します。 - PV/風力発電の過去の詳細データなし:Energiedashboard で公開されているのは、年単位の集計済み電源構成のみです。1 年未満の PV または風力発電データには、
consumption_search_bfe_datasetsを使用してください。 - FHIR またはスマートメーターデータなし:対象外です。将来的に
swiss-prosumer-mcpなどを追加する可能性があります。 - 対象年:ElCom の料金データは 2009 年からです。Energiedashboard の電源構成データは 2014 年からです。
ポートフォリオ内での連携
このサーバーは、ポートフォリオ内の他のサーバーと自然に連携します。
- +
swiss-energy-mcp— 地理/設備データ(発電所)と時系列データ、料金データを組み合わせ、エネルギーインフラを包括的に分析します。 - +
meteoswiss-mcp— 消費予測と天候を関連付けます(気温は暖房/冷房の負荷に影響します)。 - +
fedlex-mcp— 料金データを Stromversorgungsgesetz(StromVG)と組み合わせ、コンプライアンス/法的な背景を確認します。 - +
zh-education-mcp— 料金、学校数、インフラ予算を組み合わせ、Schulamt に関連する問い合わせに対応します。
データソースとライセンス
すべての上流データは、**Open Government Data Switzerland(OGD-CH)**です。
- Energiedashboard.ch © Bundesamt für Energie BFE — オープンデータ。自由に利用できます。
- ElCom / LINDAS © Eidgenössische Elektrizitätskommission ElCom — CC BY 4.0。
- opendata.swiss © Various Swiss public bodies — ほとんどが CC0/CC BY 4.0。
- Stadt Zürich OGD © Stadt Zürich — CC0。
この MCP サーバーは MIT ライセンスです(LICENSE を参照)。常に元のデータソースを明記してください。応答エンベロープには、適切な出典表記が自動的に含まれます。
貢献
CONTRIBUTING.md を参照してください。
セキュリティ
セキュリティポリシーと脆弱性の報告方法については、SECURITY.md を参照してください。
ライセンス
MIT License — LICENSE を参照してください。上流データには、上記の「データソースとライセンス」に記載されたライセンスが適用されます。
作者
Hayal Oezkan · github.com/malkreide
変更履歴
CHANGELOG.md を参照してください。
インストール
uv の uvx で実行できます。リポジトリのクローンや手動インストールは不要です。MCP クライアントの設定に追加してください(Claude Desktop、Cursor、Windsurf では mcpServers を使用します。VS Code では .vscode/mcp.json のトップレベルにある servers キーを使用します)。
{
"mcpServers": {
"swiss-electricity-mcp": {
"command": "uvx",
"args": [
"swiss-electricity-mcp"
]
}
}
}
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。