Bag Health Mcp

io.github.malkreide由 GitHub 帳號 malkreide 發布v0.4.1更新於 Oct 24, 2026

BAG public-health open data: indicators, programmes, statistics

已驗證STDIO僅桌面位置與生活資料與分析

概覽

AI 產生的概覽

唯讀 MCP 伺服器,讓助理取得瑞士公共衛生資料:BAG 傳染病監測,以及 Obsan、Versorgungsatlas 與 Sucht Schweiz 的指標。

可以做什麼
列出並瀏覽 BAG 傳染病儀表板的疾病主題、資料系列、篩選維度與匯出檔案,查看目前資料版本與可用匯出,並可下載原始 CSV/JSON 匯出、依系列及州、年齡、性別取得時間序列監測資料,以及取得州級疫情概況。依來源、主題、地區與年份範圍搜尋 Obsan、Versorgungsatlas 與 Sucht Schweiz 的健康指標,並取得單一指標的時間序列及其切分方式(全國、依州、依年齡組、依社會地位)與信賴區間。讀取州代碼、疾病分類與資料授權條款等靜態參考資源。執行內建提示詞以產生州級公共衛生情勢簡報或疾病是否升高的檢查。
適用情境
需要瑞士公共衛生數據時適用:某州或某病原體的目前與歷史傳染病監測、污水訊號,或青少年飲酒等群體健康指標,並附來源標註。適合學校與市政公共衛生報告,而非個人醫療建議。
執行需求
透過 stdio 在本機執行,通常以 uvx 從 PyPI 套件啟動,需要 Python/uv 執行環境。無需 API 金鑰或帳號,會存取三個公開 HTTPS 資料主機。選用 HTTP 模式透過 MCP_TRANSPORT、MCP_HOST、MCP_PORT、MCP_AUTH_TOKEN、MCP_CORS_ORIGINS、MCP_ALLOWED_HOSTS 等環境變數設定。
安裝前請注意
所有工具皆為唯讀,資料是彙總的公開統計,不構成個人建議、診斷或病例評估。資料非即時(每週三更新),上游 API 標示為 beta,結構可能變動。重複使用資料須標註來源。若啟用 HTTP 傳輸,除網路隔離環境外不要綁定到 localhost 以外;對外暴露時應設定 MCP_AUTH_TOKEN 與 MCP_ALLOWED_HOSTS。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Bag Health Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

bag-health-mcp

[PyPI] [Python 3.11+] [License: MIT] [Swiss Public Data MCP Portfolio]

Part of the Swiss Public Data MCP Portfolio — connecting AI models to Swiss public data sources.

🇩🇪 Deutsche Version

MCP server for Swiss public health data. Its core is the Swiss Federal Office of Public Health (BAG) Infectious Disease Dashboard (IDD) — epidemiological surveillance for 51 pathogens (influenza, COVID-19, measles, wastewater surveillance, and more) — extended with a multi-source health-indicator layer over the Swiss Health Observatory (Obsan), the Versorgungsatlas (health-care supply atlas, with cantonal series) and Sucht Schweiz (HBSC youth survey). All read-only, public Open Government Data.


What You Can Do

"Wie ist die aktuelle Grippesituation im Kanton Zürich verglichen mit den letzten Wochen?"→ bag_health_mcp__get_canton_situation(canton="ZH")
"Gibt es aktuell einen Masernausbruch in der Schweiz?"→ bag_health_mcp__get_disease_data(series_id="measles/cases/incValue/year", canton="all")
"Wie entwickelt sich das SARS-CoV-2-Signal im Abwasser?"→ bag_health_mcp__list_series(topic="wastewater_viral_load")→ bag_health_mcp__get_disease_data(series_id="wastewater_viral_load/NA/value/date", ...)
"Welche Krankheitsdaten stellt das BAG aktuell bereit?"→ bag_health_mcp__list_diseases()
"Wie hat sich der Alkoholkonsum bei 15-Jährigen seit 2010 entwickelt?"   # 🎯 anchor query→ bag_health_mcp__search_health_indicators(source="suchtschweiz", topic="alkohol")→ bag_health_mcp__get_indicator_series(source="suchtschweiz",      indicator_id="monam/alkoholkonsum-alter-11-15", region="ZH", year_from=2010)→ More use cases by audience →

🎯 Anchor demo query — «Wie hat sich der Alkoholkonsum bei 15-Jährigen im Kanton Zürich seit 2010 entwickelt, und wie steht der Kanton im Schweizer Vergleich da?» The HBSC youth series (via Obsan) answers the Switzerland-wide trend since 2010 with 95% confidence intervals. This particular indicator is national only, so the response includes a region_note saying so (HBSC is not cantonally representative). Most other Obsan indicators are published by canton — see the note on cuts below. These are aggregated population statistics — not individual advice. See docs/tool-design-health-indicators.md.


Tools

Infectious-disease surveillance (BAG IDD):

ToolDescription
bag_health_mcp__list_diseasesList all 51 disease topics, grouped by category
bag_health_mcp__list_seriesList data series for a specific disease
bag_health_mcp__get_series_detailsGet available filter dimensions (canton, age, sex)
bag_health_mcp__get_disease_dataFetch time-series surveillance data
bag_health_mcp__get_canton_situationSituational overview for a canton (Schulamt use case)
bag_health_mcp__list_export_filesList available complete export datasets
bag_health_mcp__download_exportDownload raw CSV/JSON export
bag_health_mcp__get_data_versionCurrent data version (updated every Wednesday)

Health indicators — Obsan, Versorgungsatlas & Sucht Schweiz (multi-source):

ToolDescription
bag_health_mcp__search_health_indicatorsSearch indicators by source (obsan / versorgungsatlas / suchtschweiz), topic, region, year range
bag_health_mcp__get_indicator_seriesFetch one indicator's time series, naming which cut it is (variant: national / by canton / by age class / by social position / distribution) and which others exist. Pass region='ZH' for the cantonal cut; 95% CIs throughout

⚠️ Aggregated population statistics only. The indicator tools serve population-level aggregates (prevalences/metrics by age/sex/region) — not individual advice, diagnosis or case assessment, and no personal data. This is stated in both tool descriptions and every response (aggregate_statistics_notice), and matters especially for suchtschweiz (HBSC), which touches prevention topics in a school context. Sources: Obsan ind.obsan.admin.ch (clean JSON API); Sucht Schweiz HBSC via the Obsan mirror (national); Versorgungsatlas returns a cantonal year/value series (26 cantons + a CH national total, with 95% CIs and a canton-vs-CH ratio) from the Tarifpool. See the per-source probe notes.

Obsan publishes an indicator in several cuts, not one series. Measured over 60 catalogue entries on 2026-08-08: 50 have a cantonal cut (kg), 49 one by age class (ag), 24 one by social position (sd) — and only 3 the plain national one (g). They are different measurements with different units, so get_indicator_series names the cut it returned in variant and lists the rest in variants_available, rather than presenting one as a stand-in for another. Eight of the 60 publish no series at all; that case fails with its reason instead of returning an empty result. The census is recorded and dated in tests/fixtures/obsan_variant_census.json.

Tool annotations

All tools carry MCP tool annotations so a host can reason about them without calling. Every tool is identical here — it only ever reads from the public, allow-listed data sources (BAG IDD, Obsan, Versorgungsatlas):

AnnotationValueMeaning
readOnlyHinttrueNo tool mutates any state.
destructiveHintfalseNo destructive side effects.
idempotentHinttrueRepeating a call has no additional effect.
openWorldHinttrueTools reach an external system (the upstream data APIs).

A host may therefore treat all calls as safe, cacheable reads. The values are declared once as READ_ONLY in server.py and applied to all 10 tools.

MCP Primitives

This server uses all three MCP primitives, each for what it is best at:

Tools (10) — live, parameterised actions that call the IDD API (above).

Resources — static, read-only reference data a host can fetch and cache, no arguments or upstream call needed:

Resource URIDescription
bag://reference/cantonsCanton codes accepted by the tools (incl. FL, all)
bag://reference/disease-categoriesDisease-topic taxonomy by category
bag://reference/data-licenceSource, attribution and licence terms

Prompts — reusable, parameterised workflows a host can surface (e.g. as slash-commands):

PromptArgumentsPurpose
canton_situation_briefcantonDraft a Schulamt public-health situation brief
outbreak_checkdisease, cantonCheck whether a disease is currently elevated

Live surveillance data stays behind Tools (it is parameterised and changes weekly); fixed reference data is exposed as Resources; recommended multi-tool workflows are packaged as Prompts.


Relevance for Schools & City Administration

Schulamt / Kreisschulbehörden:

  • Monitor influenza and ARI incidence in your canton
  • Single measles case → alert for schools with low vaccination coverage
  • Pertussis tracking → protect unvaccinated infants (siblings of school children)

Stadtverwaltung / KI-Fachgruppe:

  • Public Health Reporting with structured weekly data
  • Wastewater surveillance as 1-week lead indicator before clinical cases

Synergy with portfolio:

  • bag-epl-mcp → "What treatments are listed?" (EPL medication database)
  • bag-health-mcp → "What is currently spreading?" (surveillance data)

Data Source

  • IDD API: https://api.idd.bag.admin.ch — No authentication required
  • Update cycle: Every Wednesday
  • Coverage: Switzerland + Liechtenstein (FL), 26 cantons
  • Topics: 51 pathogens, 1386 data series

Datenquellen & Lizenzen / Data sources & licences

SourceProviderLicenceAttribution required
Infectious Disease Dashboard (IDD)Federal Office of Public Health (FOPH / BAG)opendata.swiss Open Government Data — free use, source attribution required (Swiss OGD terms, CC BY-equivalent)Yes
Health indicatorsObsan — Swiss Health Observatory (ind.obsan.admin.ch)No explicit machine-readable licence; treat as Swiss OGD practice — free use, cite the per-indicator sourceYes
Health-care supply atlasVersorgungsatlas (BAG/Obsan, versorgungsatlas.ch)Same (Swiss OGD practice, cite source)Yes
HBSC youth surveySucht Schweiz — HBSC, obtained via the Obsan mirrorSame (Swiss OGD practice, cite «Sucht Schweiz — HBSC»)Yes

Required citation: Federal Office of Public Health FOPH — Infectious Disease Dashboard (IDD), open data via opendata.swiss. For the indicator tools, each response's provenance.source names the concrete upstream (e.g. «Sucht Schweiz — HBSC» via Obsan). Every tool response carries attribution in a provenance block (attribution + license fields) so downstream consumers can surface it automatically.

Architecture:                    ┌─────────────────┐    api.idd.bag.admin.ch (IDD API, no auth)  MCP Host          │  bag-health-mcp │──▶ ind.obsan.admin.ch   (Obsan JSON API)  (Claude, etc.) ──▶│  MCP SDK        │──▶ versorgungsatlas.ch  (indicator catalogue)                    │  10 Tools       │    all HTTPS, egress allow-listed, no auth                    └─────────────────┘

Installation

Claude Desktop (stdio)

json
{  "mcpServers": {    "bag-health": {      "command": "uvx",      "args": ["bag-health-mcp"]    }  }}

Cloud / HTTP

bash
pip install bag-health-mcppython -m bag_health_mcp.server --http --port 8000

Transport, host and port are set via environment variables — MCP_TRANSPORT (http/stdio), MCP_HOST, MCP_PORT — which is the recommended way for deployments (the --http flag still works for local use). The server binds to 127.0.0.1 by default so a local HTTP server is not exposed to the network. Container/cloud deployments bind all interfaces by setting MCP_HOST=0.0.0.0 explicitly — the provided Dockerfile does this.

⚠️ Security: HTTP transport exposes the server on the network. Only bind beyond 127.0.0.1 in a network-isolated environment — never directly on a public/shared network. Binding to a non-localhost host logs a warning at startup. The default stdio transport has no network surface. See docs/security-posture.md.

HTTP auth (optional): set MCP_AUTH_TOKEN to require Authorization: Bearer <token> on every HTTP request (401 otherwise). Unset = no auth (fine for stdio/local). This gates who may invoke the server; for real user identity, front it with a gateway.

CORS (browser clients): set MCP_CORS_ORIGINS to a comma-separated origin allow-list to enable cross-origin browser access. The 2026-07-28 routing headers (Mcp-Method, Mcp-Name, Mcp-Protocol-Version) pass the preflight; no session header is exposed, because the server issues none. Empty = no cross-origin (never a wildcard).

Host allow-list (DNS rebinding): set MCP_ALLOWED_HOSTS to a comma-separated list of the names this server is reachable under, including the port, e.g. bag.example.ch:8000. Requests arriving under any other Host are rejected with 421; loopback stays allowed so container health checks keep working.

Unset on a non-localhost bind, the check is left off and a warning is logged — that is the gateway-fronted deployment, where the gateway validates Host. It is not guessed: on 0.0.0.0 the reachable name is unknowable here, and a wrong guess would reject the very deployment it is meant to protect.

This is independent of MCP_AUTH_TOKEN. The token says who is asking; this says under which name the server is addressed. A rebinding attack runs in a browser that already holds the token.

For running at scale (no session affinity needed, resource limits, MCP gateway), see the deployment & scaling guide and the reference manifests in deploy/.

Logging: the server emits structured JSON logs (one object per line, with an RFC 5424 severity) to stderr — stdout is reserved for the stdio JSON-RPC transport. Set the level with MCP_LOG_LEVEL (default INFO).

Tracing (optional): install the telemetry extra and point the server at an OTLP collector to get OpenTelemetry spans per tool-call plus instrumented outbound HTTP:

bash
pip install "bag-health-mcp[telemetry]"export OTEL_EXPORTER_OTLP_ENDPOINT="http://otel-collector:4318"# optional: OTEL_SERVICE_NAME=bag-health-mcp

Tracing is a no-op unless both the extra is installed and an OTEL_* endpoint is set. Spans carry only the tool name and (on error) the exception class — never tool arguments, cantons or surveillance data.


Available Disease Topics

CategoryTopics
Respiratoryinfluenza, covid19, acute_respiratory_infection, respiratory_pathogens
Entericcampylobacteriosis, salmonellosis, ehec, listeriosis, hepatitis_a/e
STI & Bloodbornehiv, aids, syphilis, gonorrhea, hepatitis_b/c, chlamydiosis
Vaccine-preventablemeasles, pertussis, rubella, tetanus, diphtheria, ipd, meningo
Vector-bornelyme_borreliosis, tick-borne_encephalitis, dengue, malaria, zika
Wastewaterwastewater_viral_load, wastewater_sequencing

Demo

[Demo: Claude queries BAG IDD via bag-health-mcp]

Claude asking about the influenza situation in canton Zurich — single tool call, structured result, actionable German-language summary.


MCP Protocol Version

This server speaks MCP 2026-07-28 natively, and still serves every older client over the same endpoint. The client's first request on a connection decides the era; a later claim from the other era is refused.

EraRevisionWho reaches it
Per-request envelope2026-07-28A request carrying the 2026-07-28 _meta envelope. No initialize, no session — the SDK's own Client lands here by default.
initialize handshake2024-11-05 … 2025-11-25Clients that do not speak 2026-07-28 yet. The server answers with the revision asked for, or with the 2025-11-25 ceiling when the request asks for something newer.

What "natively" means here, each point asserted in tests/test_spec_2026_07_28.py:

  • No session, in either era. No response carries Mcp-Session-Id; any replica can answer any request, so a plain round-robin load balancer is enough (see deployment & scaling). For handshake clients this is a deliberate stateless_http=True.
  • No deprecated capabilities. Protocol logging (ctx.info/ctx.warning), sampling and roots are deprecated in 2026-07-28 (SEP-2577). The server uses none of them; operational logs go to stderr. The test suite turns MCPDeprecationWarning into an error, so a reintroduced call fails CI.
  • No server-to-client requests. No tool asks the client anything, so nothing depends on a back-channel 2026-07-28 no longer has.
  • Progress (server-to-client, still in the spec) arrives in both eras, on the response stream of the tool call.
  • Cache hints (ttlMs/cacheScope, SEP-2549) on the listing methods, and CORS for the routing headers Mcp-Method, Mcp-Name, Mcp-Protocol-Version.

Both revisions are pinned in tests/test_protocol_version.py and asserted against the installed SDK, so a Dependabot bump of mcp cannot move either one silently. The handshake ceiling is measured against a live initialize through the assembled ASGI stack, not read off a constant name.

Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern era, not for the handshake era — pinning against it alone would leave the handshake era free to drift.

Update policy. When the gate fails, do not edit the constant blindly: read the spec changelog between the two revisions, verify the server still behaves, then move the constant, this section, README.de.md and CHANGELOG.md together.


Safety & Limits

AspectDetails
AccessRead-only — no write operations possible
EgressCode-layer allow-list: the server only contacts three public data hosts (api.idd.bag.admin.ch, ind.obsan.admin.ch, www.versorgungsatlas.ch), HTTPS-only, enforced on every request incl. redirect hops (SSRF/SEC-004 + SEC-021). Network-layer companion policy in deploy/networkpolicy.yaml
Personal dataNone — all sources are aggregated/anonymised (BAG IDD at canton level by law; indicators are population aggregates by age/sex/region)
Rate limitsNo published IDD API rate limit; server caps responses at 104 data points per call by default (limit_weeks param)
Timeout30 s per API call
AuthenticationNo API keys required — all data publicly accessible
Data licenceopendata.swiss OGD — free use, source attribution required (CC BY-equivalent). FOPH IDD must be cited; see Data sources & licences
Terms of ServiceSubject to BAG IDD API ToS

Known Limitations

  • Beta API: IDD API is labelled v0.1 beta — schema may change without notice
  • Weekly cadence: Data is not real-time; updated Wednesdays only
  • Canton granularity: Some rare diseases have insufficient cases for canton-level data (suppressed for privacy)
  • Age groups: Available dimensions vary by disease series; use bag_health_mcp__get_series_details to check

Compliance

  • ISDS (Stadt Zürich): a draft information-security protection-needs classification (Schutzbedarfsanalyse per Grundwert + measures mapping) is in docs/isds-klassifikation.md. It is a technically-grounded draft pending ISBO/OIZ sign-off — not a binding classification.
  • Data classification (Schulamt): the data is classified ÖFFENTLICH / BUI (public OGD, no personal data, aggregated at canton level with small cells suppressed at source). Draft scheme + aggregation-risk note in docs/datenklassifikation-schulamt.md; the aggregating bag_health_mcp__get_canton_situation tool surfaces this in its response.
  • Security posture: lethal-trifecta assessment (the server is strictly read-only → not affected), secret-management decision (no secrets — public data), and network-exposure notes are in docs/security-posture.md.
  • Phase architecture: this is a Phase 1 (read-only) server; write/send capabilities are deferred behind documented prerequisites. See docs/roadmap.md.
  • Reporting vulnerabilities: see the security policy for how to report security issues privately.

Contributing

See CONTRIBUTING.md (Deutsch).

Security

See SECURITY.md (Deutsch) for the security posture and how to report a vulnerability confidentially.

License

Code: MIT (see LICENSE).

Data: BAG IDD is Open Government Data on opendata.swiss under free use with mandatory source attribution (Swiss OGD terms, CC BY-equivalent) — not public domain. Cite the Federal Office of Public Health FOPH (IDD) when reusing the data; see Data sources & licences.

Author

Hayal Oezkan · github.com/malkreide

Related Portfolio Servers

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):

json
{  "mcpServers": {    "bag-health-mcp": {      "command": "uvx",      "args": [        "bag-health-mcp"      ]    }  }}

來源:README.md,提交 02e802c

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

3
  1. v0.4.1最新Sep 27, 2026
  2. v0.4.0Sep 27, 2026
  3. v0.3.0Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分