关于 swiss-food-safety-mcp
swiss-food-safety-mcp 是只读 MCP 服务,为 AI 助手提供瑞士 BLV 食品安全和兽医开放数据。工具涵盖最新警告,以及动物疾病、检查、抗生素、儿童营养和农药数据集。
主要功能
- 01食品召回与健康警告
- 02动物疾病及禽流感监测
- 03各州食品检查结果
- 04兽用抗生素使用统计
- 05儿童营养问卷计数
- 06农药登记查询与数据集发现
适用场景
- 01查看瑞士当前食品召回信息
- 02按州查看动物疾病报告
- 03检查食品检查及违规数据
- 04搜索获准农药或营养调查结果
MCP 相关
向 MCP 客户端提供 11 个只读 BLV 数据查询工具,并支持 stdio 和 Streamable HTTP 传输。无需身份验证。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🇨🇭 属于 瑞士公共数据 MCP 项目组合
swiss-food-safety-mcp
🌐 English | Deutsch
将 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 上的全部 28 个 BLV 数据集
- 🔗 双传输方式 — 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,或在 GitHub 上复刻该仓库
- 在 render.com 上:新建 Web 服务 → 连接 GitHub 仓库
- 将启动命令设置为:
swiss-food-safety-mcp --http --host 0.0.0.0 - 在 claude.ai 的“设置”→“MCP 服务”下,添加:
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 和内存。
💡 “开发者笔记本使用 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 | 浏览全部 28 个 BLV 开放数据集 | 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 |
所有数据均为开放政府数据(OGD),采用 Creative Commons 许可,并要求注明出处。
已知限制
- RSS 源: 仅包含 BLV 最近发布的内容;没有历史存档
- 农药登记册: 对返回大量结果的查询,XML 解析可能较慢
- CKAN 数据集: 高负载使用时会受到 opendata.swiss 速率限制
- 动物疾病数据: 按州筛选取决于源数据的完整性
- 数据集已固定,而非通过搜索确定: 每个数据工具都会指定其数据集 slug 和承载数据的资源(参见
server.py中的DATENQUELLEN)。关键词搜索会采用第一个命中项,因此可能悄无声息地退回到某个看似合理的数据集——这就是blv_get_animal_health_stats会返回抗生素数据,以及blv_get_food_control_results会从一个包含 26 个资源(其中 18 个是代码列表)的数据集中返回代码列表的原因。scripts/record_fixtures.py每次运行都会重新测量固定的数据集与资源配对;如果数据集被重命名,现在会明确报错。 - 儿童营养数据是问卷统计,而非营养素摄入量: opendata.swiss 上唯一发布的 menuCH-Kids 数据集包含答案数量(
Geschlecht, Sprachregion, Altersgruppe, Frage, Antwort, Anzahl)。此前的文档字符串错误地承诺提供与膳食建议对照的营养素摄入量,并提供“Energie”“Zucker”“Eisen”作为筛选示例——这些条件都无法匹配,因而返回空列表。成人膳食摄入数据属于单独的数据集,本服务不涵盖。 - 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。
部署与扩展
此服务处于 Phase 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——仅这一差异,就决定了工具返回的是检查结果还是代码图例。模拟数据无法表达这种区别,因此没有测试能因此失败。
因此,我们记录的是选择结果:对每个工具,记录固定的数据集 slug、被访问的资源,以及该文件的表头行。表头正是验证的重点——它能区分数据与图例,也能显示 BOM 和分隔符是否得到正确处理。PROVENANCE.md 列出了每个文件的来源、日期、选择规则和 SHA-256 值。
记录的测量结果中有两项是对照项:在 lindas.admin.ch 下构造一条虚假路径(POST 返回 404,因此 /sparql 上的 404 确实存在),以及在 fsvo 命名空间中构造一个虚假类(实例数为 0,因此此前查询的 foag 类确实不存在)。没有这些对照项,每项测量只能说明我们收到了什么。如果对照项不再具有区分效果、固定资源消失、表头行为空或以 BOM 开头,或者某项发现已被更新,记录器就会中止。
MCP 协议版本
此服务原生支持规范 2026-07-28。它运行 fastmcp 4.x,该版本固定使用 mcp 2.x,而该 SDK 通过同一个服务对象支持两个协议时代:
| 时代 | 版本 | 客户端如何连接 |
|---|---|---|
| 现代 | 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 — 请参阅 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 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。