zurich-opendata-mcp について
zurich-opendata-mcpは、研究者、住民、公共部門の利用者向けに、チューリッヒ市のオープンデータを提供します。データセット、環境・交通のリアルタイム情報、地理データ、市政記録など複数のデータ源をMCPツールとリソースにまとめています。
主な機能
- 01オープンデータセットの検索と照会
- 02天気・大気・水質のリアルタイム情報
- 03駐車場と歩行者数のリアルタイム情報
- 04地理レイヤーとGeoJSON地物
- 05議会、市政決議、観光データ
活用シーン
- 01チューリッヒの学校関連データを検索
- 02天気、大気質、駐車状況を確認
- 03学校や遊び場の地理データを取得
- 04議会記録や市政決議を検索
MCP 対応
MCPサーバーは、データセットのメタデータ、駐車情報、地理データ、観光カテゴリなどの市データ用ツールとリソースを対応クライアントに公開します。既定のstdioに加え、Streamable HTTPでも提供できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
26掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| params | any | はい |
詳細
🇨🇭 スイス公共データ MCP ポートフォリオの一部です
🏙️ チューリッヒ オープンデータ MCP サーバー
🌐 英語 | ドイツ語
スイスのチューリッヒ市のオープンデータに AI を活用してアクセスできる MCP(Model Context Protocol)サーバーです。
Claude、ChatGPT、その他の MCP 対応 AI アシスタントから、チューリッヒ市の 900 件以上のデータセット、地理データ、議会議事録、市議会決議、観光データ、リンクトデータ、環境・モビリティに関するリアルタイム情報を直接検索できます。23 個のツール(非推奨エイリアス 3 個を含む)、5 個のリソース、6 個の API。
デモ
✨ 機能
CKAN オープンデータ(data.stadt-zuerich.ch)
zurich_search_datasets– 900 件以上のデータセットを対象に、Solr 構文で全文検索zurich_get_dataset– データセットの完全なメタデータとダウンロード URL を取得zurich_datastore_query– 表形式データを直接クエリ(フィルター、並べ替え)zurich_datastore_sql– DataStore への SQL クエリzurich_list_categories– 19 のテーマ別カテゴリを閲覧zurich_list_tags– タグを使ったテーマ検索
環境データのリアルタイム情報
zurich_weather_live– 🌤️ 4 つの UGZ 観測所の現在の天気(気温、湿度、気圧、降雨量)zurich_air_quality– 🌬️ WHO 基準値付きの大気質リアルタイム情報(NO₂、O₃、PM10、PM2.5)zurich_water_weather– 🌊 チューリッヒ湖のデータ(水温、水位、風)を 10 分ごとに取得
モビリティデータのリアルタイム情報
zurich_pedestrian_traffic– 🚶 バーンホフ通りの歩行者数(3 地点、1 時間ごと)zurich_vbz_passengers– 🚊 VBZ 公共交通機関の利用者数(80 万件以上のレコード、全路線・停留所)zurich_parking_live– 🅿️ 36 か所の駐車場のリアルタイム利用状況(ParkenDD)
ジオポータル(WFS 地理データ)
zurich_geo_layers– 📍 利用可能な 14 の地理データレイヤーを一覧表示zurich_geo_features– 📍 GeoJSON フィーチャーを取得(学校、地区、遊び場、気候データなど)
市議会(Paris API)
zurich_parliament_search– 🏛️ 議会議事録(質問、動議、提案)を検索zurich_parliament_members– 🏛️ 議員を検索(政党、委員会、役職)
チューリッヒ観光
zurich_tourism– 🏨 観光名所、レストラン、ホテル、イベント(Schema.org データ、4 言語)
リンクトデータ(SPARQL)
zurich_sparql– 📊 統計リンクトデータエンドポイントへの SPARQL クエリ (エンドポイントはまだ本番運用されていません。このツールはデフォルトでは登録されません。環境変数ZURICH_OPENDATA_ENABLE_SPARQL=1で有効にしてください)
Stadtratsbeschlüsse(市議会決議)
zurich_strb_search– 📜 公開された市議会決議を全文検索(タイトル、部門、期間)zurich_strb_by_department– 📜 部門の決議をすべて一覧表示(例:SSD、FD、PRD)zurich_strb_detail– 📜NNNN/YYYY番号で個別の決議を取得
(以前の名称 search_stadtratsbeschluesse、get_beschluesse_by_departement、get_stadtratsbeschluss_detail は、次回のメジャーリリースまで非推奨エイリアスとして引き続き利用できます。)
分析ツール
zurich_analyze_datasets– 包括的な分析:関連性、最新性、データ構造zurich_catalog_stats– 統計情報付きのカタログ概要zurich_find_school_data– 教育関連データセットを対象とした厳選検索
MCP リソース
zurich://dataset/{name}– データセットのメタデータzurich://category/{group_id}– カテゴリの詳細zurich://parking– 現在の駐車場データzurich://geo/{layer_id}– GeoJSON 地理データ(14 レイヤー)zurich://tourism/categories– 観光カテゴリ
🚀 インストール
前提条件
- Python 3.11+
- pip または uv
mcp[cli]2.x — 自動的にインストールされます。サーバーは 2.x API(mcp.server.mcpserver)を使用しており、mcp1.x では実行できません。
0.6.0 以降を使用してください。 リリース
0.5.1は上限を設けずにmcp[cli]>=1.28.1を指定していました。mcp2.0.0 でmcp.server.fastmcpが削除されると、新規インストールされた0.5.1はすべて 2.0.0 が選択され、インポート時にModuleNotFoundErrorが発生するようになりました。0.6.0は 2.x API で動作し、>=2.0.0,<3に固定されています。0.5.1を使用している場合はアップグレードしてください。このリリースで動作する構成はもうありません。
インストール
# Clone
git clone https://github.com/malkreide/zurich-opendata-mcp.git
cd zurich-opendata-mcp
# Install
pip install -e .
# Or with uv
uv pip install -e .
⚙️ 設定
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json(macOS)を編集します。
{
"mcpServers": {
"zurich-opendata": {
"command": "python",
"args": ["-m", "zurich_opendata_mcp.server"],
"env": {}
}
}
}
または、インストール済みのコマンドを使用します。
{
"mcpServers": {
"zurich-opendata": {
"command": "zurich-opendata-mcp"
}
}
}
Claude Code(CLI)
claude mcp add zurich-opendata -- python -m zurich_opendata_mcp.server
Cursor / VS Code
.vscode/settings.json に追加します。
{
"mcpServers": {
"zurich-opendata": {
"command": "python",
"args": ["-m", "zurich_opendata_mcp.server"]
}
}
}
💬 質問例
設定後、Claude に次のように質問できます。
オープンデータ
- 「チューリッヒの学校に関するデータセットには何がありますか?」
- 「公立学校の休暇日程を表示してください」
- 「利用可能な地理データを分析してください」
リアルタイムデータ
- 「チューリッヒの現在の気温は?」 →
zurich_weather_live - 「今日の空気質はどうですか?」 →
zurich_air_quality - 「チューリッヒ湖の水温は?」 →
zurich_water_weather - 「現在、空いている駐車スペースはいくつありますか?」 →
zurich_parking_live - 「現在、Bahnhofstrasse に何人いますか?」 →
zurich_pedestrian_traffic
地理データ
- 「チューリッヒのすべての学校施設を GeoJSON で表示してください」 →
zurich_geo_features - 「利用可能な地理データレイヤーは何ですか?」 →
zurich_geo_layers - 「チューリッヒの遊び場はどこにありますか?」
市議会
- 「学校に関するどのような議会動議が提出されましたか?」 →
zurich_parliament_search - 「SP 党に所属する市議会議員は誰ですか?」 →
zurich_parliament_members
市議会決議(Stadtratsbeschlüsse)
- 「2025 年の Volksschule に関する市議会決議を探してください」 →
zurich_strb_search - 「2025 年の SSD 決議をすべて一覧表示してください」 →
zurich_strb_by_department - 「市議会決議 1203/2025 を表示してください」 →
zurich_strb_detail
観光
- 「Zurich Tourism が推薦するレストランはどこですか?」 →
zurich_tourism
🔗 データソース
| API | エンドポイント | データ |
|---|---|---|
| CKAN | data.stadt-zuerich.ch/api/3/ | 900 件以上のオープンデータセット |
| Geoportal WFS | ogd.stadt-zuerich.ch/wfs/geoportal | 14 の地理データレイヤー(GeoJSON) |
| Paris API | gemeinderat-zuerich.ch/api | 議会の議事手続きと議員 |
| Zurich Tourism | zuerich.com/en/api/v2/data | 観光名所、レストラン、ホテル |
| SPARQL | ld.stadt-zuerich.ch/query | リンクトオープンデータ/統計 |
| ParkenDD | api.parkendd.de/Zuerich | リアルタイムの駐車場利用状況 |
📊 利用可能なデータカテゴリ
| カテゴリ | ID |
|---|---|
| 雇用 | arbeit-und-erwerb |
| 基本地図 | basiskarten |
| 建設・住宅 | bauen-und-wohnen |
| 人口 | bevolkerung |
| 教育 | bildung |
| エネルギー | energie |
| 財政 | finanzen |
| レジャー | freizeit |
| 健康 | gesundheit |
| 犯罪 | kriminalitat |
| 文化 | kultur |
| モビリティ | mobilitat |
| 政治 | politik |
| 物価 | preise |
| 社会福祉 | soziales |
| 観光 | tourismus |
| 環境 | umwelt |
| 行政 | verwaltung |
| 経済 | volkswirtschaft |
📍 利用可能な地理情報レイヤー
情報源:src/zurich_opendata_mcp/config.py の GEOPORTAL_LAYERS。
| レイヤー ID | 説明 |
|---|---|
schulanlagen | 学校施設(幼稚園、学校、学童保育) |
schulkreise | 学区の境界(ポリゴン) |
schulwege | 通学路の横断箇所と危険地点 |
stadtkreise | 市区の境界(ポリゴン) |
spielplaetze | 公共の遊び場 |
kreisbuero | 市区の行政窓口 |
sammelstelle | 廃棄物回収拠点 |
sport | スポーツ施設 |
klimadaten | 気候データ(ラスター、気温、ヒートアイランド) |
lehrpfade | 学習用トレイル |
stimmlokale | 投票所 |
sozialzentrum | 社会福祉センター |
velopruefstrecken | 学校向け自転車試験コース |
familienberatung | 家族相談の面談場所 |
🏗️ プロジェクト構成
zurich-opendata-mcp/
├── src/zurich_opendata_mcp/
│ ├── __init__.py
│ ├── app.py # Shared FastMCP instance
│ ├── server.py # Console entry + back-compat re-exports
│ ├── config.py # Endpoints, layer maps, resource IDs
│ ├── http_client.py # Shared httpx client + CKAN wrapper
│ ├── formatters.py # CKAN→model mapping + Markdown rendering
│ ├── models.py # Pydantic structured-output models
│ ├── clients/ # API clients: paris, sparql, tourism, wfs
│ └── tools/ # @mcp.tool implementations:
│ # catalog, datastore, geo, parliament,
│ # realtime, sparql, strb, tourism,
│ # resources (zurich:// URIs)
├── tests/ # respx round-trip, unit and live-marked tests
├── audits/ # Code-audit reports
├── .github/workflows/ # ci.yml + publish.yml (Trusted Publisher)
├── pyproject.toml
├── README.md / README.de.md
├── CONTRIBUTING.md / .de.md
├── SECURITY.md / .de.md
├── CHANGELOG.md
├── CLAUDE.md # Project conventions for Claude
├── LICENSE
└── claude_desktop_config.json
🧪 開発
# Install dev dependencies
pip install -e ".[dev]"
# Unit + validation tests (no network)
pytest tests/ -m "not live"
# Live integration tests (against live APIs — opt-in)
pytest tests/ -m live
# Linting
ruff check src/ tests/
🌐 HTTP トランスポート
デフォルトでは、サーバーは stdio 経由で MCP を通信します。--http を指定すると、代わりに Streamable HTTP を提供します。
zurich-opendata-mcp --http --port 8000 # binds 127.0.0.1 (default)
zurich-opendata-mcp --http --host 0.0.0.0 --port 8000
| オプション | 意味 | デフォルト |
|---|---|---|
--http | stdio の代わりに Streamable HTTP を提供します | (オフ → stdio) |
--host | バインドアドレス | 127.0.0.1 |
--port | バインドポート(1~65535) | 8000 |
MCP_ALLOWED_HOSTS | このサーバーにアクセスできるホスト名のカンマ区切りリスト。ポートを含めます(例:zurich.example.ch:8000)。それ以外の Host によるリクエストには 421 を返します。コンテナのヘルスチェックが機能するよう、ループバックは引き続き許可されます。 | (未設定) |
ループバックをデフォルトにしているのは意図的です。 0.0.0.0 にバインドすると、すべてのインターフェースで、マシンにアクセスできるすべてのユーザーにサーバーが公開されます。前段に認証はありません。
ループバック以外にバインドする場合は、必ず MCP_ALLOWED_HOSTS を設定してください。 これにより、DNS リバインディングを防ぎます。ネットワーク上のページが自身のホスト名をこのサーバーのアドレスに解決し、ブラウザーからサーバーにアクセスする攻撃です。ブラウザーから見ると、そのリクエストは同一オリジンなので、オリジンルールでは阻止できません。阻止できるのは Host チェックだけです。
ループバック以外へのバインド時に未設定のままにすると、チェックは無効のままとなり、警告がログに記録されます。これは、サーバーの前段にある何かが Host を検証する場合にのみ適切なデフォルトです。意図的に推測は行いません。0.0.0.0 では、プロセス内から到達可能な名前を特定できず、誤った推測をすると、保護対象のデプロイメントに対してすべてのリクエストへ 421 を返すことになるためです。
MCP プロトコルのバージョン
このサーバーは、同じエンドポイントで2つのプロトコル世代に対応します。接続上のクライアントからの最初のリクエストによって適用される世代が決まり、もう一方の世代からの後続の申告は拒否されます。
| 世代 | リビジョン | 対象 |
|---|---|---|
initialize ハンドシェイク | 2024-11-05 … 2025-11-25 | 現在のクライアントが使用するものです。サーバーは要求されたリビジョンで応答するか、リクエストがそれより新しいものを要求している場合は 2025-11-25 を上限として応答します。 |
| リクエストごとのエンベロープ | 2026-07-28 | 2026-07-28 の _meta エンベロープを含むリクエストによって、モダンな接続が開始されます。 |
両方のリビジョンは
tests/test_protocol_version.py で固定されています。また、このゲートでは2段階でチェックします。プロセス内の mcp.Client が、このサーバーとの間で実際にネゴシエートするリビジョンを(両世代について、ASGI もネットワークも介さず、メモリートランスポート経由で)測定し、SDK の定数を読み取って、Dependabot による mcp の更新でどちらかがひそかに変わることを防ぎます。特に重要なのは測定部分です。定数がそのままでも、ある世代が提供されなくなればテストは失敗します。
SDK の LATEST_PROTOCOL_VERSION は、ハンドシェイク世代ではなくモダン世代の別名である点に注意してください。これだけを基準に固定すると、現在のクライアントが実際にネゴシエートする世代が変更されても検出できません。
2026-07-28 時点でこのサーバーがネイティブに対応していること
このリビジョンは、SDK が到達する単なる数値ではありません。変更点のうち3つはサーバー自体に対応を求めており、このリビジョンではそのすべてに対応しています。
| 仕様の変更 | このサーバーの対応 |
|---|---|
SEP-2549 — 一覧取得メソッドにおける ttlMs / cacheScope | tools/list、resources/list、resources/templates/list、server/discover に ttlMs 300000 と cacheScope public を含めています。これらがないと、インポート時に固定されるディレクトリに対して、SDK は「すでに古く、共有不可」と応答します。resources/read には意図的にヒントを含めていません。これはディレクトリではなく、コンテンツについての保証になってしまうためです。 |
SEP-2575 — initialize を行わないため、識別情報を結果ごとに渡す | すべての結果の _meta に、名前、タイトル、バージョン、説明、websiteUrl を含む io.modelcontextprotocol/serverInfo を設定しています。version= を指定せずに構築された MCPServer は、すべての応答に空文字列を設定し、SDK が独自の値で置き換えることもありません。 |
SEP-2575 — server/discover だけが残された指示の提供場所 | サーバーは instructions を提供します。initialize を送らないステートレスな呼び出し元も、カタログ → リソース UUID → DataStore の順序と、リアルタイムの読み取り結果が有効な時間を把握できます。 |
軽微な変更 #3(tools/list の順序は決定的であることが SHOULD)には、server.py で固定されているインポート順に従うツールマネージャーの挿入順で対応しています。テストでは、ワイヤ上の順序とこの順序を比較します。
SDK 側の特性であり、このサーバーによるものではない点が1つあります。subscriptions/listen が提供されているため、ケイパビリティブロックでは listChanged と resources.subscribe が通知されます。このサーバーのディレクトリはインポート時に固定され、変更通知を出すことはありません。この点は測定したうえで現状のままにしています。ケイパビリティが示すのはメソッドが提供されていることだけであり、それは事実です。
更新ポリシー。 ゲートに失敗した場合、定数をむやみに編集しないでください。2つのリビジョン間の仕様変更履歴を読み、サーバーが引き続き正常に動作することを確認してから、定数、このセクション、README.de.md、CHANGELOG.md をまとめて更新してください。
安全性と制限
- 読み取り専用: すべてのツールは HTTP GET リクエストのみを実行します。データの書き込み、変更、削除は行いません。
- 個人データなし: API は公開された市民データセット(駐車場の稼働状況、気象観測値、議会の議事録)を返します。このサーバーでは、個人を特定できる情報(PII)を処理または保存しません。
- レート制限: CKAN Solr の検索と ParkenDD は、レート制限が文書化されていない公開 API です。
rowsとlimitパラメーターは控えめに使用してください。サーバーはリクエストごとに30秒のタイムアウトを適用し、一時的な上流エラー(接続失敗、HTTP 502/503/504)は短いバックオフの後に1回再試行します。 - データの鮮度: リアルタイムツール(駐車場、天気、空気質)は、クエリ時点での上流ソースのデータを反映します。観測データはキャッシュされません。キャッシュ対象は、年ごとの UGZ リソース ID(天気/空気質)の検索結果のみで、プロセス内に24時間保存されます。
- 利用規約: データには各ソースの利用規約が適用されます — data.stadt-zuerich.ch、ParkenDD、gemeinderat-zuerich.ch。チューリッヒ市のデータはすべて CC0(2021年以降の Open by Default)で公開されています。
- 保証なし: このサーバーはコミュニティプロジェクトであり、チューリッヒ市やいずれの API プロバイダーとも提携していません。利用可能かどうかは上流 API に依存します。
🤝 コントリビューション
コントリビューションを歓迎します。CONTRIBUTING.md(ドイツ語)をご覧ください。
🔒 セキュリティ
読み取り専用で、PII を扱わず、認証も不要です。公開データ用のエンドポイントは固定されています。セキュリティ対策の全容と、受け入れているリスクに関する判断については、 SECURITY.md(ドイツ語)をご覧ください。
📜 ライセンス
MIT License — LICENSEをご覧ください。使用されているデータはすべて、オープンライセンス(CC0 / 2021年以降の Open by Default)で公開されています。
👤 作者
Hayal Oezkan · malkreide
Model Context Protocol を利用 • 6 個の API • 23 個のツール • 5 個のリソース
インストール
uv の uvx で実行できます。クローンや手動でのインストールは不要です。MCP クライアントの設定に追加してください(Claude Desktop、Cursor、Windsurf では mcpServers を使用します。VS Code では .vscode/mcp.json のトップレベルにある servers キーを使用します)。
{
"mcpServers": {
"zurich-opendata-mcp": {
"command": "uvx",
"args": [
"zurich-opendata-mcp"
]
}
}
}
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。