swiss-food-safety-mcp について
swiss-food-safety-mcp は、スイスの BLV が公開する食品安全・獣医データを AI アシスタントに提供する読み取り専用 MCP サーバーです。最新の警告に加え、動物疾病、検査、抗生物質、子どもの栄養、農薬のデータを扱います。
主な機能
- 01食品リコールと健康警告
- 02動物疾病・鳥インフルエンザの監視
- 03州別の食品検査結果
- 04獣医療での抗生物質使用統計
- 05子どもの栄養調査の回答数
- 06農薬登録とデータセット検索
活用シーン
- 01スイスで現在発表中の食品リコール確認
- 02州別の動物疾病報告の確認
- 03食品検査と違反データの調査
- 04認可農薬や栄養調査結果の検索
MCP 対応
MCP クライアントに、BLV データを照会する 11 個の読み取り専用ツールを公開し、stdio と Streamable HTTP のトランスポートに対応します。認証は不要です。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
🇨🇭 スイス公共データ MCP ポートフォリオの一部です
swiss-food-safety-mcp
🌐 英語 | ドイツ語
AI モデルをスイス連邦食品安全・獣医局(BLV)のオープンデータに接続する MCP サーバーです。食品のリコール、動物疾病の監視、食品検査結果、抗生物質の使用状況、子どもの栄養調査、農薬登録簿を扱います。認証は不要です。
概要
swiss-food-safety-mcp を使うと、Claude のような AI アシスタントがスイス連邦食品安全・獣医局(BLV/Bundesamt für Lebensmittelsicherheit und Veterinärwesen)の公式な食品安全・獣医データに直接アクセスできます。食品のリコール、動物疾病の監視、食品検査結果、獣医療における抗生物質の使用状況、子どもの栄養調査、農薬登録簿を扱う 11 個のツールを提供します。
すべてのデータは、スイス連邦の公式情報源(opendata.swiss、lindas.admin.ch、news.admin.ch)から取得しています。API キーも認証も必要ありません。
このサーバーは No-Auth-First の理念に従っており、スイスの公共部門向け MCP ポートフォリオの一部です。
デモ用の質問: 「チューリッヒの学校食堂に関係する BLV の現在の食品警告はありますか?また、現在、州内でどの届出対象動物疾病が報告されていますか?」
デモ
機能
- 🚨 一般向けの警告とリコール — BLV の製品リコールと健康警告を配信するライブ RSS フィード
- 🐄 動物疾病の監視 — LINDAS SPARQL キューブを通じて、1991 年以降の届出対象動物疾病(InfoSM)を提供
- 🐦 鳥インフルエンザの監視 — 地理データ付きの野鳥監視データ
- 🥩 食品検査結果 — 州の食品検査結果と違反率
- 💊 獣医療における抗生物質の使用状況 — 動物医療における抗生物質使用に関する ISABV データ
- 🧒 子どもの栄養調査 — menuCH-Kids のアンケート集計(回答数であり、栄養摂取量ではありません)
- 🌿 農薬登録簿 — スイスで承認された農薬製品と有効成分
- 📊 データセットの検索 — CKAN API を通じて opendata.swiss 上の BLV データセット全 28 件を閲覧
- 🔗 デュアルトランスポート — stdio(Claude Desktop)と Streamable HTTP(クラウド/Render.com)
- 🗣️ バイリンガル — 英語を中心としたドキュメントと、補助的なドイツ語ドキュメント
前提条件
- Python 3.11+
uvまたはuvx(推奨)— uv をインストール
インストール
uvx を使用(推奨 — インストール不要)
uvx swiss-food-safety-mcp
uv を使用
uv tool install swiss-food-safety-mcp
swiss-food-safety-mcp
ソースからインストール
git clone https://github.com/malkreide/swiss-food-safety-mcp
cd swiss-food-safety-mcp
uv sync
uv run swiss-food-safety-mcp
クイックスタート
claude_desktop_config.json に追加します:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"swiss-food-safety": {
"command": "uvx",
"args": ["swiss-food-safety-mcp"]
}
}
}
Claude Desktop ですぐに試せます:
「現在有効な BLV の食品警告はどれですか?」
「今年、チューリッヒ州で届出対象の動物疾病は報告されていますか?」
その他の MCP クライアント(Cursor、Windsurf、VS Code + Continue)
{
"mcpServers": {
"swiss-food-safety": {
"command": "uvx",
"args": ["swiss-food-safety-mcp"]
}
}
}
クラウドへのデプロイ(Streamable HTTP)
ブラウザーで claude.ai を使用する場合(ローカルソフトウェアを利用できない管理対象ワークステーションなど):
# Loopback only (default) — safe for local testing:
swiss-food-safety-mcp --http
# Server runs on 127.0.0.1:8002
# External exposure (e.g. behind the Render TLS proxy):
swiss-food-safety-mcp --http --host 0.0.0.0
⚠️ HTTP トランスポートは、デフォルトで
127.0.0.1にバインドされます。外部への公開を意図している場合に限り、--host 0.0.0.0を指定してください。ブラウザークライアントを許可するには、BLV_MCP_ALLOWED_ORIGINS(ワイルドカードなしのカンマ区切り)を設定してください。デフォルト値はhttps://claude.aiです。
Render.com(推奨):
- リポジトリを GitHub にプッシュするか、フォークします
- render.com で、New Web Service → GitHub リポジトリに接続します
- 起動コマンドを次のように設定します:
swiss-food-safety-mcp --http --host 0.0.0.0 - claude.ai の Settings → MCP Servers で、次を追加します:
https://your-app.onrender.com/mcp
Docker:
docker build -t swiss-food-safety-mcp .
docker run -p 8002:8002 swiss-food-safety-mcp
# or, with explicit CPU/memory limits:
docker compose up
イメージは非 root のマルチステージビルドで、コンテナーはすでに
0.0.0.0 にバインドされ、ヘルスチェックも含まれています。docker-compose.yml では、
CPU とメモリの上限も設定されています。
💡 「開発者のノート PC には stdio、ブラウザーには Streamable HTTP。」
🔧 設定 — 実行時の設定はすべて、
BLV_MCP_*環境変数(BLV_MCP_HTTP_HOST、BLV_MCP_HTTP_PORT、BLV_MCP_ALLOWED_ORIGINS、BLV_MCP_TIMEOUT、BLV_MCP_OTEL_ENDPOINT、…)で上書きできます。 外部へのリクエストは、スイス連邦のホスト(*.admin.ch、opendata.swiss)に制限されています。OpenTelemetry トレースは任意です。pip install swiss-food-safety-mcp[otel]でインストールし、BLV_MCP_OTEL_ENDPOINTを設定してください。
利用可能なツール
| ツール | 説明 | データソース |
|---|---|---|
blv_get_public_warnings | 現在の食品リコールと健康警告 | news.admin.ch RSS |
blv_list_datasets | BLV の全 28 件のオープンデータセットを閲覧 | opendata.swiss CKAN |
blv_get_dataset_info | データセットの詳細とリソース URL | opendata.swiss CKAN |
blv_search_animal_diseases | 1991 年以降の届出対象動物疾病 | LINDAS SPARQL (/query) |
blv_get_animal_health_stats | 年次の動物衛生統計 | opendata.swiss CSV/JSON |
blv_get_food_control_results | 州ごとの食品検査結果 | opendata.swiss CSV |
blv_get_antibiotic_usage_vet | 獣医療における抗生物質使用量(ISABV) | opendata.swiss CSV |
blv_get_avian_influenza | 野鳥の鳥インフルエンザ監視 | opendata.swiss CSV |
blv_get_nutrition_data_children | menuCH-Kids:質問票の集計結果(栄養素摂取量ではありません) | opendata.swiss CSV |
blv_search_pesticide_products | スイスで承認された農薬の登録情報 | opendata.swiss XML |
blv_get_meat_inspection_stats | 食肉処理場の検査統計 | opendata.swiss CSV/JSON |
クエリの例
| クエリ | ツール |
|---|---|
| 「現在有効な BLV の食品警告は何ですか?」 | blv_get_public_warnings |
| 「2024 年にチューリッヒ州で動物疾病は発生していますか?」 | blv_search_animal_diseases |
| 「2024 年のスイスにおける鳥インフルエンザの状況はどうなっていますか?」 | blv_get_avian_influenza |
| 「スイスの子どもたちは実際に何を食べていますか?」 | blv_get_nutrition_data_children |
| 「スイスで承認されている銅系農薬はどれですか?」 | blv_search_pesticide_products |
アーキテクチャ
┌─────────────────┐ ┌─────────────────────────────┐ ┌──────────────────────────────┐
│ Claude / AI │────▶│ Swiss Food Safety MCP │────▶│ Swiss Federal Open Data │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ │
└─────────────────┘ │ │ │ opendata.swiss (CKAN/CSV) │
│ 11 Tools · No Auth │ │ lindas.admin.ch (SPARQL) │
│ Stdio | Streamable HTTP │ │ news.admin.ch (RSS/XML) │
└─────────────────────────────┘ └──────────────────────────────┘
関連 MCP サーバーとの連携
| 組み合わせ | ユースケース |
|---|---|
swiss-food-safety-mcp + zurich-opendata-mcp | 学校の場所周辺における動物疾病リスクを地図上に表示 |
swiss-food-safety-mcp + fedlex-mcp | リコール情報を食品法(Lebensmittelgesetz)に関連付ける |
swiss-food-safety-mcp + swiss-statistics-mcp | 学区ごとの栄養データと社会経済データを組み合わせる |
swiss-food-safety-mcp + global-education-mcp | スイスの子どもの栄養を OECD の基準と比較 |
プロジェクト構成
swiss-food-safety-mcp/
├── src/
│ └── swiss_food_safety_mcp/
│ ├── __init__.py # Package metadata
│ └── server.py # All tools, resources, prompts
├── tests/
│ ├── __init__.py
│ └── test_server.py # Unit tests (no live API calls)
├── .github/
│ └── workflows/
│ └── ci.yml # Python 3.11–3.13 matrix
├── pyproject.toml # hatchling build, uv-compatible
├── CHANGELOG.md
├── CONTRIBUTING.md # Contribution guide (English)
├── CONTRIBUTING.de.md # Contribution guide (German)
├── SECURITY.md # Security policy (English)
├── SECURITY.de.md # Security policy (German)
├── LICENSE # MIT
├── README.md # This file (English)
└── README.de.md # German version
データソース
| ソース | 説明 | 形式 |
|---|---|---|
| opendata.swiss/BLV | 28 件のオープンデータセット | CSV, JSON, Parquet, SPARQL, XML |
| lindas.admin.ch/sparql | スイスのリンクトデータ SPARQL エンドポイント | RDF/SPARQL |
| news.admin.ch RSS | BLV の公的な警告およびリコール | RSS/XML |
| blv.admin.ch | BLV のウェブサイト(DE/FR/IT/EN) | HTML |
すべてのデータは、クレジット表記を条件とする Creative Commons のオープンガバメントデータ(OGD)です。
既知の制限事項
- RSS フィード: 最新の BLV 公開情報のみが対象で、過去のアーカイブはありません
- 農薬登録簿: 大量の結果を返すクエリでは、XML の解析に時間がかかる場合があります
- CKAN データセット: 大量に利用すると、opendata.swiss のレート制限が適用されます
- 動物疾病データ: 州レベルの絞り込みは、ソースのデータ完全性に依存します
- データセットは固定指定され、検索されません: 各データツールでは、データセットのスラッグとデータを含むリソースを指定しています(
server.pyのDATENQUELLENを参照)。キーワード検索では最初の結果が採用されるため、もっともらしい別の結果にひそかに切り替わることがあります。これが、blv_get_animal_health_statsが抗生物質のデータを返すようになった原因であり、また、26 個のリソースのうち 18 個がコードリストであるデータセットから、blv_get_food_control_resultsがコードリストを返すようになった原因です。scripts/record_fixtures.pyは実行のたびに固定指定された組み合わせを再測定するため、データセット名が変更されると明確にエラーになります。 - 子どもの栄養データは、栄養素摂取量ではなくアンケートの集計値です: opendata.swiss で公開されている menuCH-Kids のデータセットは、回答数(
Geschlecht, Sprachregion, Altersgruppe, Frage, Antwort, Anzahl)を含むものだけです。以前の docstring では、食事の推奨量に対する栄養素摂取量を扱うと説明し、フィルターの例として「エネルギー」「糖分」「鉄分」を提示していましたが、これらは何も一致せず、空のリストを返していました。成人の食物摂取データは別のデータセットとして存在しますが、このサーバーでは扱っていません。 - SPARQL から CSV へのフォールバックは削除されました。 これは機能するはずがありませんでした。フォールバック先のデータセットにある唯一の CSV リソースは、
format: CSVとして宣言された ZIP ファイルです。エンドポイントが修正されたため、フォールバックも不要です。壊れたクエリを隠すフォールバックは、ないよりも悪いものです。
安全性と制限
- 読み取り専用: すべてのツールは HTTP GET リクエストのみを実行し、データの書き込み、変更、削除は行いません。
- 個人データなし: API が返すのは、集計済みの公衆衛生および食品安全の統計データです。このサーバーが個人を特定できる情報を処理または保存することはありません。
- レート制限: opendata.swiss CKAN と lindas.admin.ch SPARQL は公開 API です。
limitとフィルターパラメーターは控えめに使用してください。サーバーはリクエストごとに 30 秒のタイムアウトを適用します。 - データの鮮度: RSS の警告は、クエリ実行時点で最新の BLV 公開情報を反映します。統計データセット(動物疾病、食品管理、抗生物質)は BLV によって定期的に更新されます。このサーバーではキャッシュを行いません。
- 利用規約: データには各ソースの利用規約が適用されます(opendata.swiss、lindas.admin.ch、news.admin.ch)。BLV のデータは、クレジット表記を条件とする Creative Commons のもとで公開されています。
- 保証なし: このサーバーはコミュニティプロジェクトであり、BLV またはスイス連邦行政機関とは提携していません。利用可能かどうかは、上流 API に依存します。
デプロイとスケーリング
このサーバーは フェーズ 1 — 読み取り専用 です(ROADMAP.md を参照)。11 個のツールはすべて読み取り専用のクエリで、書き込み機能はありません。
単一インスタンスとして実行してください。Streamable HTTP トランスポートはセッションごとの状態を保持するため、水平スケーリングにはロードバランサーでの Mcp-Session-Id によるスティッキールーティングと、共有セッションストアが必要になります。この規模のサーバーでは、設計上どちらも実装していません。サポート対象のデプロイ方法は Render の単一インスタンス(または単一コンテナー)です。セルフホスト用の docker-compose.yml では、CPU とメモリの制限を明示的に設定しています。
テスト
# Unit + contract tests (no network) — this is what CI runs
PYTHONPATH=src pytest tests/ -m "not live"
# All tests including live API checks
PYTHONPATH=src pytest tests/
# Re-measure which dataset and resource each tool hits
PYTHONPATH=src python scripts/record_fixtures.py
54 件のテスト — オフライン 53 件、ライブ 1 件。
フィクスチャを手書きではなく記録する理由
手書きのモックは作成者の思い込みを反映するため、その思い込みを否定できません。本番コードとフィクスチャは、同じブランチ、同じ時間、同じドキュメントの解釈から作られます。両方が間違っていれば、両方とも同じように間違い、テストスイートは成功したままです。
このリポジトリでは、それがそのままの形で起きていました。モックされた CKAN リソースはすべて "name": "CSV" という名前でした。opendata.swiss では、同じフィールドに Food establishments 2025 や Food establishments codelist administrative measures と記載されています。この違いだけで、ツールが検査結果を返すか、コード一覧を返すかが決まります。モックではこの違いを表現できなかったため、それを検出するテストもありませんでした。
そのため、記録しているのは 選択内容 です。各ツールについて、固定したデータセットのスラッグ、アクセスしたリソース、そのファイルのヘッダー行を記録しています。確認対象はヘッダーです。ヘッダーによってデータとコード一覧を区別でき、BOM と区切り文字が適切に処理されたかもわかります。PROVENANCE.md には、各ファイルのソース、日付、選択ルール、SHA-256 を記載しています。
記録した測定結果のうち 2 つは 対照 です。1 つは lindas.admin.ch 配下の架空のパス(POST で 404 となるため、/sparql の 404 が実際の結果であると確認できます)、もう 1 つは fsvo 名前空間の架空のクラス(インスタンスが 0 件となるため、以前クエリした foag クラスが実際に存在しないと確認できます)。これらがなければ、各測定でわかるのは 私たちが 受け取った内容だけです。対照による識別ができなくなった場合、固定したリソースが消えた場合、ヘッダー行が空または BOM で始まる場合、あるいは調査結果のいずれかが更新された場合、記録処理は中断します。
MCP プロトコルバージョン
このサーバーは、仕様 2026-07-28 をネイティブにサポートしています。fastmcp 4.x を実行しており、これにより mcp 2.x が固定されています。この SDK は、同じサーバーオブジェクト上で 2 つ のプロトコル世代を提供します。
| 世代 | リビジョン | クライアントからの接続方法 |
|---|---|---|
| モダン | 2026-07-28 | server/discover、_meta.io.modelcontextprotocol/* のメタデータ |
| ハンドシェイク(レガシー) | 2025-11-25 | 従来の initialize のやり取り |
現在のクライアントは 2026-07-28 を取得します。まだ移行していないクライアントはハンドシェイクにフォールバックし、引き続きすべてのツールを利用できます。どちらのリビジョンを使うかはこのサーバーが選ぶのではありません。SDK がネゴシエーションを行い、この固定指定によってネゴシエーションで生成できるペアが記録されます。
モダン世代は単に番号が大きいだけではありません。initialize ハンドシェイクも InitializeResult もありません。この世代では Client.initialize() は例外を発生させ、サーバーのメタデータは代わりに server/discover から取得します。そのため、今も initialize_result.protocolVersion を測定するチェックでは、レガシー側だけをテストしながら、両方に合格したと報告してしまいます。
tests/test_protocol_version.py は定数同士を比較するのではなく、それぞれの世代で固有の経路を通じて測定します。両方のリビジョンを LATEST_MODERN_VERSION/LATEST_HANDSHAKE_VERSION に対して固定し、それぞれのモードで実際のクライアントを接続し、モダン側に InitializeResult が構造上存在しないことをアサートし、両方の世代で同じツールが一覧表示されることを確認します。test_das_sdk_fuehrt_weiterhin_zwei_aeren は反対方向の退行を防ぎます。これがなければ、mcp 1.x へのダウングレードによって、一連のアサーションの半分が、誰も読まないインポートエラーに変わってしまいます。
トランスポートの許可リストも SDK とともに更新されました。Mcp-Method、Mcp-Name、MCP-Protocol-Version は、仕様 2026-07-28 が HTTP に引き継ぐルーティングヘッダーです。mcp.shared.inbound がこれらを読み取るようになったため、CORS のリストに含めています。Mcp-Param-* は意図的に含めていません。仕様では、ツールが x-mcp-header で指定したパラメーターに対してのみ発行されますが、ここには該当するツールがありません。
変更履歴
CHANGELOG.md を参照してください。
コントリビューション
CONTRIBUTING.md を参照してください。
セキュリティ
セキュリティポリシーと脆弱性の報告方法については、SECURITY.md を参照してください。
ライセンス
MIT ライセンス — LICENSE を参照してください。
作者
Hayal Oezkan · github.com/malkreide
クレジットと関連プロジェクト
- データ: opendata.swiss / BLV – 連邦食品安全獣医局(BLV)
- プロトコル: Model Context Protocol – Anthropic / Linux Foundation
- 関連プロジェクト: zurich-opendata-mcp – チューリッヒ市のオープンデータ向け MCP サーバー
- ポートフォリオ: Swiss Public Data MCP Portfolio
インストール
uv の uvx 経由で実行できます。クローンや手動インストールは不要です。MCP クライアントの設定に追加してください(Claude Desktop、Cursor、Windsurf では mcpServers を使用し、VS Code では .vscode/mcp.json のトップレベルに servers キーを使用してください)。
{
"mcpServers": {
"swiss-food-safety-mcp": {
"command": "uvx",
"args": [
"swiss-food-safety-mcp"
]
}
}
}
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。