
Swiss Food Safety Mcp
io.github.malkreide由 GitHub 帳號 malkreide 發布v1.2.0更新於 Oct 24, 2026
BLV open data for food safety and veterinary inspections
概覽
本機 MCP 伺服器,讓助理以唯讀方式存取瑞士 BLV 開放資料,涵蓋食品召回、動物疫病監測、食品檢查、抗生素使用與農藥登記。
- 可以做什麼
- 取得 BLV 目前的食品召回與健康警告,並瀏覽或檢視 opendata.swiss 上 28 個 BLV 資料集的詳細資訊與資源連結。查詢 1991 年以來應通報的動物疫病與年度動物健康統計,以及野生鳥類禽流感監測資料。查詢各州食品檢查結果、獸用抗生素使用與屠宰場肉品檢查統計。檢索瑞士核准的農藥登記,並讀取 menuCH-Kids 兒童營養問卷計數。所有工具都是對瑞士聯邦資料來源的唯讀 HTTP GET 查詢。
- 適用情境
- 適合在對話中需要官方瑞士食品安全或獸醫資訊時使用:查看目前召回、依州查詢動物疫病通報、檢查結果、抗生素使用或已核准農藥,不必離開助理。
- 執行需求
- 透過 stdio 在本機執行;需要 Python 3.11+ 與 uv/uvx(也可用 uv tool install 或原始碼檢出)。不需要 API 金鑰或身分驗證。需要連線至瑞士聯邦主機(opendata.swiss、lindas.admin.ch、news.admin.ch)的網路。另有選用 HTTP 模式供瀏覽器用戶端使用,主機與來源透過 BLV_MCP_* 變數設定。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Swiss Food Safety Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
🇨🇭 Part of the Swiss Public Data MCP Portfolio
swiss-food-safety-mcp
[Version] [License: MIT] [Python 3.11+] [MCP] [Data Source] [No Auth Required] [CI]
🌐 English | Deutsch
MCP server connecting AI models to Swiss Federal Food Safety and Veterinary Office (BLV) open data — food recalls, animal disease surveillance, food control results, antibiotic usage, children's nutrition surveys and the pesticide register. No authentication required.
Overview
swiss-food-safety-mcp gives AI assistants like Claude direct access to official Swiss food safety and veterinary data from the Federal Food Safety and Veterinary Office (BLV / Bundesamt für Lebensmittelsicherheit und Veterinärwesen). It provides 11 tools covering food recalls, animal disease surveillance, food control results, antibiotic usage in veterinary medicine, nutrition surveys for children, and the pesticide register.
All data comes from official Swiss federal sources (opendata.swiss, lindas.admin.ch, news.admin.ch). No API keys or authentication are required.
This server follows the No-Auth-First philosophy and is part of a Swiss public sector MCP portfolio.
Anchor demo query: "Are there any current BLV food warnings relevant to Zurich school canteens — and which notifiable animal diseases are currently reported in the canton?"
Demo
[Demo: Claude using blv_get_public_warnings and blv_search_animal_diseases] → More use cases by audience →
Features
- 🚨 Public warnings & recalls — Live RSS feed of BLV product recalls and health warnings
- 🐄 Animal disease surveillance — Notifiable animal diseases since 1991 (InfoSM) via the LINDAS SPARQL cube
- 🐦 Avian influenza monitoring — Wild bird surveillance data with geodata
- 🥩 Food control results — Cantonal food inspection results and violation rates
- 💊 Antibiotic usage veterinary — ISABV data on antibiotic use in animal medicine
- 🧒 Children's nutrition survey — menuCH-Kids questionnaire tallies (answer counts, not nutrient intake)
- 🌿 Pesticide register — Swiss approved pesticide products and active ingredients
- 📊 Dataset discovery — Browse all 28 BLV datasets on opendata.swiss via CKAN API
- 🔗 Dual transport — stdio (Claude Desktop) + Streamable HTTP (cloud/Render.com)
- 🗣️ Bilingual — English-first documentation, German secondary
Prerequisites
- Python 3.11+
uvoruvx(recommended) — install uv
Installation
Using uvx (recommended — no install needed)
Using uv
From source
Quickstart
Add to claude_desktop_config.json:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Try it immediately in Claude Desktop:
"Which BLV food warnings are currently active?"
"Are there any notifiable animal diseases reported in Zurich canton this year?"
Other MCP Clients (Cursor, Windsurf, VS Code + Continue)
Cloud Deployment (Streamable HTTP)
For use via claude.ai in the browser (e.g. on managed workstations without local software):
⚠️ The HTTP transport binds to
127.0.0.1by default. Pass--host 0.0.0.0only when external exposure is intended. SetBLV_MCP_ALLOWED_ORIGINS(comma-separated, no wildcard) to permit browser clients; it defaults tohttps://claude.ai.
Render.com (recommended):
- Push/fork the repository to GitHub
- On render.com: New Web Service → connect GitHub repo
- Set the start command to:
swiss-food-safety-mcp --http --host 0.0.0.0 - In claude.ai under Settings → MCP Servers, add:
https://your-app.onrender.com/mcp
Docker:
The image is a non-root, multi-stage build; the container already binds
0.0.0.0 and includes a healthcheck. docker-compose.yml additionally caps
CPU and memory.
💡 "stdio for the developer laptop, Streamable HTTP for the browser."
🔧 Configuration — every runtime setting is overridable via
BLV_MCP_*environment variables (BLV_MCP_HTTP_HOST,BLV_MCP_HTTP_PORT,BLV_MCP_ALLOWED_ORIGINS,BLV_MCP_TIMEOUT,BLV_MCP_OTEL_ENDPOINT, …). Outbound requests are restricted to Swiss federal hosts (*.admin.ch,opendata.swiss). Optional OpenTelemetry tracing: install withpip install swiss-food-safety-mcp[otel]and setBLV_MCP_OTEL_ENDPOINT.
Available Tools
Example Queries
Architecture
Synergies with Related MCP Servers
Project Structure
Data Sources
All data is open government data (OGD) under Creative Commons with attribution requirement.
Known Limitations
- RSS feed: Limited to the most recent BLV publications; no historical archive
- Pesticide register: XML parsing may be slow for queries returning large result sets
- CKAN datasets: Opendata.swiss rate limits apply under heavy usage
- Animal disease data: Canton-level filtering depends on data completeness in the source
- Datasets are pinned, not searched: each data tool names its dataset slug and the resource that carries the data (see
DATENQUELLENinserver.py). A keyword search takes the first hit and therefore falls back silently onto something plausible — that is howblv_get_animal_health_statscame to return antibiotics data, and howblv_get_food_control_resultscame to return a code list out of a dataset whose 26 resources include 18 of them.scripts/record_fixtures.pyre-measures the pinned pairs on every run; a renamed dataset now fails loudly. - Children's nutrition is questionnaire tallies, not nutrient intake: the only menuCH-Kids dataset published on opendata.swiss carries answer counts (
Geschlecht, Sprachregion, Altersgruppe, Frage, Antwort, Anzahl). The docstring previously promised nutrient intake against dietary recommendations and offered "Energie", "Zucker", "Eisen" as filter examples — those matched nothing and returned an empty list. Adult food-consumption data exists as a separate dataset that this server does not cover. - The SPARQL-to-CSV fallback is gone. It could never work: the one CSV resource of the fallback dataset is a ZIP file declared as
format: CSV. With the endpoint corrected the fallback is also unnecessary — and a fallback that hides a broken query is worse than none.
Safety & Limits
- Read-only: All tools perform HTTP GET requests only — no data is written, modified, or deleted.
- No personal data: The APIs return aggregated public health and food safety statistics. No personally identifiable information is processed or stored by this server.
- Rate limits: opendata.swiss CKAN and lindas.admin.ch SPARQL are public APIs; use
limitand filtering parameters conservatively. The server enforces a 30-second timeout per request. - Data freshness: RSS warnings reflect the latest BLV publications at query time. Statistical datasets (animal diseases, food control, antibiotics) are updated periodically by the BLV. No caching is performed by this server.
- Terms of service: Data is subject to the ToS of each source — opendata.swiss, lindas.admin.ch, news.admin.ch. BLV data is published under Creative Commons with attribution.
- No guarantees: This server is a community project, not affiliated with the BLV or the Swiss federal administration. Availability depends on upstream APIs.
Deployment & Scaling
This server is Phase 1 — read-only (see ROADMAP.md): all
11 tools are read-only queries with no write surface.
Run it as a single instance. The Streamable HTTP transport keeps
per-session state, so horizontal scaling would require Mcp-Session-Id sticky
routing at the load balancer plus a shared session store — neither is
implemented, by design, for a server of this scope. A single Render instance
(or one container) is the supported deployment; docker-compose.yml sets
explicit CPU/memory limits for self-hosting.
Testing
54 tests — 53 offline, 1 live.
Why the fixtures are recorded rather than written
A hand-written mock encodes its author's assumption and therefore cannot refute it: production code and fixture come from the same head, the same hour, the same reading of the docs. Where both are wrong, both are wrong together — and the suite stays green.
This repo had it in pure form. Every mocked CKAN resource was named
"name": "CSV". On opendata.swiss the same field reads Food establishments 2025 or Food establishments codelist administrative measures — and that
difference alone decided whether a tool returned inspection results or a code
legend. The mocks could not express the distinction, so no test could fail on
it.
What is recorded is therefore the selection: for each tool, the pinned
dataset slug, the resource that was hit, and that file's header line. The
header is the object of the exercise — it separates data from a legend, and it
shows whether the BOM and the delimiter were handled. PROVENANCE.md names the
source, the date, the selection rule and the SHA-256 for each file.
Two of the recorded measurements are controls: an invented path under
lindas.admin.ch (POST 404, so the 404 on /sparql is real) and an invented
class in the fsvo namespace (0 instances, so the previously queried foag
class genuinely does not exist). Without them each measurement would only show
what we received. The recorder aborts if a control stops discriminating, if a
pinned resource disappears, if a header line is empty or starts with a BOM, or
if one of the findings is superseded.
MCP Protocol Version
This server speaks spec 2026-07-28 natively. It runs fastmcp 4.x, which
pins mcp 2.x, and that SDK serves two protocol eras over the same server
object:
A current client gets 2026-07-28; one that has not moved yet falls back to
the handshake and still gets every tool. Neither revision is chosen by this
server — the SDK negotiates, and the pin records which pair that negotiation is
allowed to produce.
The modern era is not just a higher number. It has no initialize handshake
and no InitializeResult: Client.initialize() raises there, and the server
metadata comes from server/discover instead. A check that still measured
initialize_result.protocolVersion would therefore be testing only the legacy
half while reporting a pass for both.
tests/test_protocol_version.py measures each era over its own path rather
than comparing constants to one another: it pins both revisions against
LATEST_MODERN_VERSION / LATEST_HANDSHAKE_VERSION, connects a real client in
each mode, asserts the structural absence of InitializeResult in the modern
one, and checks that both eras list the same tools. test_das_sdk_fuehrt_weiterhin_zwei_aeren
guards the other direction — a downgrade back to mcp 1.x would otherwise
reduce half of those assertions to an import error nobody reads.
The transport allow-list moved with the SDK: Mcp-Method, Mcp-Name and
MCP-Protocol-Version are the routing headers spec 2026-07-28 mirrors into
HTTP, and mcp.shared.inbound now reads them, so CORS lists them. Mcp-Param-*
is deliberately still absent — the spec mints those only for parameters a tool
marks with x-mcp-header, and no tool here does.
Changelog
See CHANGELOG.md
Contributing
See CONTRIBUTING.md
Security
See SECURITY.md for the security policy and how to report a vulnerability.
License
MIT License — see LICENSE
Author
Hayal Oezkan · github.com/malkreide
Credits & Related Projects
- Data: opendata.swiss / BLV – Federal Food Safety and Veterinary Office (BLV)
- Protocol: Model Context Protocol – Anthropic / Linux Foundation
- Related: zurich-opendata-mcp – MCP server for Zurich city open data
- Portfolio: Swiss Public Data MCP Portfolio
Installation
Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):
來源:README.md,提交 ad7c4b4
工具
0版本歷史
2- v1.2.0最新Sep 27, 2026
- v1.1.5Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分