{"id":"7da9e6ea-1a92-4ff3-8a75-05d06e3a1587","slug":"healthcare-opendata-mcp","kind":"mcp","name":"healthcare-opendata-mcp","summary":"Taiwan gov procurement + NHI open data as a queryable MCP server — SQLite sync, SELECT-only query guard, Twinkle-compatible query_rows (FastMCP)","owner":"trionnemesis","repoUrl":"https://github.com/trionnemesis/healthcare-opendata-mcp","license":"MIT","licenseTier":"permissive","trust":"community","stars":1,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-06-10T07:52:33.000Z","addedAt":"2026-10-21T09:05:59.093Z","logoUrl":"https://avatars.githubusercontent.com/u/19563301?u=bd862f9a0403aaeff54d690e1f09efa34a11ff4f&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["databases","cloud-infra","data-analytics"],"tags":["fastmcp","government-procurement","healthcare","opendata","taiwan"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T20:29:11.387Z","sample":false,"url":"https://conduits.dev/tools/healthcare-opendata-mcp","language":"Python","transports":["stdio"],"install":{"pypi":"hcmcp"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# healthcare-opendata-mcp 🏥\n\n> 官方開放資料 → 可查詢 MCP 介面，讓 AI agent 不必直接處理分散的政府資料來源。\n\nSelf-hosted MCP server that syncs Taiwan government procurement (PCC) and National Health Insurance (NHI) open data into a local SQLite database, then exposes it through read-only MCP tools. A SELECT-only query guard (syntax allowlist plus a read-only SQLite authorizer) keeps the Twinkle-compatible `query_rows` interface safe for agent-driven querying.\n\n[![CI](https://github.com/trionnemesis/healthcare-opendata-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/trionnemesis/healthcare-opendata-mcp/actions/workflows/ci.yml)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)\n[![FastMCP](https://img.shields.io/badge/built%20with-FastMCP-orange)](https://github.com/jlowin/fastmcp)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n\n`healthcare-opendata-mcp`（命令名稱：`hcmcp`）是一個自建、可部署的 MCP server：把政府電子採購網與健保署開放資料同步到 SQLite，再以穩定的 MCP tools 提供給 Claude 或其他 agent 查詢。\n\n專案保留 Twinkle Hub `query_rows` 的 SQL 式查詢模式，但資料來源、同步流程與儲存層都由本專案自行掌握，不依賴第三方聚合服務。\n\n[GitHub Pages 導覽](https://trionnemesis.github.io/healthcare-opendata-mcp/) · [PCC 靜態資料看板](https://trionnemesis.github.io/healthcare-opendata-mcp/dashboard/) · [GitHub repository](https://github.com/trionnemesis/healthcare-opendata-mcp)\n\n## Contents\n\n- [Why](#why)\n- [How it works](#how-it-works)\n- [Static data dashboard](#static-data-dashboard)\n- [Install](#install)\n- [What it provides](#what-it-provides)\n- [Querying](#querying)\n- [Trust & security](#trust--security)\n- [HTTP & GKE](#http--gke)\n- [Development](#development)\n- [Scope & limits](#scope--limits)\n- [Related projects](#related-projects)\n- [License](#license)\n\n## Why\n\nAI agent 要查政府資料時，真正的摩擦通常不在模型，而在資料入口：來源分散、格式不同、欄位缺漏，而且外部聚合服務的政策或可用性可能改變。\n\n| Problem | What hcmcp does |\n|---|---|\n| 政府電子採購網與健保資料各自分散 | 以 `SourceAdapter` 統一 discover → fetch → normalize → upsert 流程 |\n| 半月 XML、CSV API、標案明細頁格式不同 | 正規化成可查詢的 dataset 與 schema |\n| 標案 open data 缺少截標、開標、預算 | 以 `get_tender_detail` 按需讀取官方明細頁補足資訊 |\n| 第三方資料入口不可控 | 自行同步、儲存與提供 MCP 介面 |\n\n## How it works\n\n```mermaid\nflowchart LR\n    PCC[政府電子採購網<br/>半月 XML] --> SYNC[hcmcp-sync<br/>fetch / normalize / upsert]\n    NHI[健保署開放平台<br/>CSV API] --> SYNC\n    SYNC --> DB[(SQLite<br/>~/.hcmcp/hcmcp.db)]\n    DB --> SERVER[hcmcp<br/>唯讀 MCP server]\n    SERVER --> AGENT[Claude / Agent]\n    AGENT -->|按需補查| DETAIL[get_tender_detail]\n    DETAIL --> PCCDETAIL[政府採購網<br/>標案明細頁]\n```\n\nThe project keeps ingestion and querying separate:\n\n1. `hcmcp-sync` pulls official sources and writes the shared SQLite database.\n2. `hcmcp` opens the same database in the query path and exposes MCP tools.\n3. `list_datasets` → `get_dataset` → `query_rows` is the recommended discovery flow.\n4. `get_tender_detail` performs an on-demand lookup when a tender needs deadline, opening time, or budget details.\n\n## Static data dashboard\n\n[GitHub Pages 資料看板](https://trionnemesis.github.io/healthcare-opendata-mcp/dashboard/) 是 SQLite 的可重建、唯讀 projection。它讀取 build-time 產生的 `docs/data/current.json`，提供 PCC 摘要、搜尋、公告類型／機關／日期篩選、日期／預算／決標金額排序與固定 20 筆分頁；現有 landing page 仍保留為專案導覽。\n\n資料邊界：\n\n- 「資料集概覽」矩陣由 catalog（已啟用者）與資料庫產生，**不硬編碼資料集名單**：啟用一個新資料集後，重新 export 即會出現在頁面上，不需要改 HTML、schema 或部署閘門。停用的候選不發布 —— 它們尚未實查，列出來會讓訪客誤以為已涵蓋。\n- 矩陣中筆數顯示「—」代表該資料集**從未同步成功**（物化表尚未建立），與「同步成功但 0 筆」不同。\n- 新鮮度**逐資料集**判定，門檻由 catalog 的 `update_cadence` 推導（**2 倍更新週期**）：每日更新的資料集停更 3 天就是過期，年度更新的資料集停更 3 天完全正常。顯示「無契約」代表該資料集未登錄更新頻率，**沒有判定依據**，不等於資料是最新的；這類資料集不會把整頁狀態拉成過期。判定基準是 `last_fetched_at`（per-dataset），不是 `ingestion_runs.finished_at`（per-source）—— 一個成功的 run 底下可能有某個資料集根本沒更新到。\n- `generated_at` 是 UTC 快照產生時間；`status.source_max_date` 才是 PCC 官方資料中的最新日期。\n- 狀態明確區分 `fresh`、`stale`、`degraded`、`empty`；JSON 無法載入或格式錯誤時，頁面顯示失敗而不呈現假成功。\n- P0 只發布 allowlist 中的 PCC 欄位。NHI 僅顯示筆數與最後同步 metadata，不發布電話、地址或全院所目錄。\n- 金額缺值維持 `null`，不轉為 0。完整 projection 先量測；超過 5 MiB 時只縮限明細列，仍保留全量聚合與明確的 export strategy。\n- 部署流程會嘗試重新同步官方來源並重建快照；**同步失敗時部署上一份有效快照（last-known-good）並讓 workflow 轉紅**，不會部署空資料，也不會靜默成功。新快照必須通過驗證且非空，才准取代舊的。\n- 每日排程**尚未啟用**（`schedule:` 在 `pages.yml` 中維持註解）：runner 能否穩定完成官方同步尚未實測，且每日全量重抓 12 個月的 PCC 半月檔對政府站台是持續性負載。以 `workflow_dispatch` 跑過一次確認後即可啟用。\n- 頁面載入時會以「現在」重新檢查快照年紀 —— 若自動同步停擺，舊快照不會繼續自稱最新。\n- 完整、即時或任意條件查詢仍使用 MCP／SQLite。\n\n從已成功同步的真實 DB 重建 snapshot 與預先渲染摘要：\n\n```bash\n.venv/bin/python scripts/export_board_data.py \\\n  --db /path/to/hcmcp.db \\\n  --out docs/data/current.json \\\n  --template scripts/templates/dashboard.html \\\n  --dashboard-out docs/dashboard/index.html\n\n.venv/bin/python scripts/verify_dashboard.py --site docs\n```\n\n快照契約見 [`docs/data/schema-v1.json`](docs/data/schema-v1.json)，設計與 P0/P1/P2 邊界見 [`docs/superpowers/specs/2026-09-01-pages-dashboard-p0.md`](docs/superpowers/specs/2026-09-01-pages-dashboard-p0.md)；資料集矩陣改由 catalog 驅動的決策見 [`docs/superpowers/specs/2026-09-07-pages-catalog-driven-datasets.md`](docs/superpowers/specs/2026-09-07-pages-catalog-driven-datasets.md)，過期門檻的推導規則見 [`docs/superpowers/specs/2026-09-09-freshness-from-cadence.md`](docs/superpowers/specs/2026-09-09-freshness-from-cadence.md)，自動同步與 last-known-good 的設計見 [`docs/superpowers/specs/2026-09-10-pages-auto-sync.md`](docs/superpowers/specs/2026-09-10-pages-auto-sync.md)。\n\n## Install\n\n```bash\ngit clone https://github.com/trionnemesis/healthcare-opendata-mcp.git\ncd healthcare-opendata-mcp\n\npython3.11 -m venv .venv\n.venv/bin/python -m pip install -e .\n\n# 建立或更新預設 DB：~/.hcmcp/hcmcp.db\n.venv/bin/hcmcp-sync\n```\n\n加入 Claude Code：\n\n```bash\nclaude mcp add hcmcp -- /absolute/path/to/healthcare-opendata-mcp/.venv/bin/hcmcp\n```\n\n### Sync options\n\n```bash\n.venv/bin/hcmcp-sync --db /path/to/hcmcp.db --tender-months 12 --award-months 12\n```\n\n| Flag | Default | Purpose |\n|---|---|---|\n| `--db` | `HCMCP_DB` 或 `~/.hcmcp/hcmcp.db` | 寫入的 SQLite 路徑 |\n| `--tender-months` | `12` | 招標回溯月數（PCC 站上實際可回溯約 6 個月） |\n| `--award-months` | `12` | 決標回溯月數 |\n\n### Environment variables\n\n| Variable | Default | Used by | Purpose |\n|---|---|---|---|\n| `HCMCP_DB` | `~/.hcmcp/hcmcp.db` | sync + server | SQLite 路徑；兩個 process 必須一致 |\n| `HCMCP_TRANSPORT` | `stdio` | server | `stdio` / `http` / `sse`（僅相容既有部署） |\n| `HCMCP_HOST` | `0.0.0.0` | server（http/sse） | 監聽位址；server 無 authentication，公開網段請改綁內網位址並在前方配置存取控制 |\n| `HCMCP_PORT` | `8000` | server（http/sse） | 監聽 port |\n\n`hcmcp-sync` 與 `hcmcp` server 共用同一個預設 DB：`~/.hcmcp/hcmcp.db`。如果要改路徑，兩個 process 都必須使用相同的 `HCMCP_DB`；sync 也可以使用 `--db`：\n\n```bash\nHCMCP_DB=/path/to/hcmcp.db .venv/bin/hcmcp-sync\nHCMCP_DB=/path/to/hcmcp.db .venv/bin/hcmcp\n```\n\n否則可能出現「同步成功，但 server 查不到資料」的路徑漂移問題。server 啟動時若 DB 沒有任何資料集會直接以錯誤訊息結束，提醒先跑 `hcmcp-sync`。\n\n## What it provides\n\n### Datasets\n\n目前 CLI 預設同步兩個資料集：\n\n| Dataset | Scope | Official source | Update path |\n|---|---|---|---|\n| `pcc-tender` | 衛生福利部轄下機關的資訊勞務相關標案 | [政府電子採購網](https://web.pcc.gov.tw/) | 半月 XML；明細欄位按需 enrich |\n| `nhi-clinic` | 健保特約醫事機構－診所 | [健保署資料開放平台](https://info.nhi.gov.tw/) | CSV API，每日更新 |\n\n候選（catalog 中 `enabled=false`，**尚未同步**，待對官方端點實查後啟用）：\n\n| Dataset | Scope | Official source | Update path |\n|---|---|---|---|\n| `nhi-healthcare-facility` | 部立／地方政府醫院、健保特約診所與衛生所 | [健保署資料開放平台](https://info.nhi.gov.tw/api/iode0000s01/Dataset?rId=A21030000I-D2100G-001) | CSV API，每日更新 |\n\n### Dataset catalog\n\n要同步哪些政府開放資料，由 [`src/health_opendata_mcp/catalog.py`](src/health_opendata_mcp/catalog.py) 這份宣告式目錄決定 —— 不是散落在程式流程裡。每筆 entry 除了 resource id／URL，還攜帶**出處與驗證狀態**：更新頻率、官方說明頁、`verified_at`（何時對官方端點實查過）、`verified_note`（實查當下觀察到的事實）與 `enabled`。\n\n目錄在 import 時就會被驗證，違反即失敗（不靜默降級）：\n\n- **驗證閘門** — `enabled=true` 必須有 `verified_at` 與 `verified_note`。未實查的候選可以留在目錄裡，但只能是 `enabled=false`；目錄有能力誠實表達「還沒驗證」。\n- **官方網域白名單** — 下載與說明頁 URL 的 host 必須在 `OFFICIAL_HOSTS`。entry 是資料；不設限等於「新增一筆資料 = 新增一個對任意主機發請求的能力」。\n- **欄位一致性與 `r_id` 字元集** — `r_id` 會被插值進 query string，限制字元集才能保證它不會挾帶 `&` / `?` 改寫 URL 的其他參數。\n\n因此擴充資料範圍的流程是：\n\n```text\n1. 加一筆 CatalogEntry，enabled=False、verified_at=None\n2. 對官方端點實查，把觀察到的事實寫進 verified_note，填上 verified_at\n3. 改 enabled=True\n```\n\n目前目錄中的候選（**尚未實查，不會被同步**）：`nhi-hospital-district`（健保特約醫事機構－地區醫院）、`nhi-hospital-bed-ratio`（全民健保特約醫院之保險病床比率）。兩者的 `rId` 取自本 repository 既有測試，沒有實查日期紀錄，因此維持停用。\n\n第 2 步的實查由 [`scripts/verify_catalog_sources.py`](scripts/verify_catalog_sources.py) 執行 —— 它只輸出可觀察的事實（HTTP status、列數、欄位名、natural key 是否存在與是否唯一），並產生可貼進 `catalog.py` 的 `verified_at` / `verified_note`：\n\n```bash\n.venv/bin/python scripts/verify_catalog_sources.py --only nhi-clinic\n```\n\n```text\n[OK  ] nhi-clinic  (enabled=True)\n       url: https://info.nhi.gov.tw/api/iode0000s01/Dataset?rId=A21030000I-D21004-009\n       HTTP 200 · text/csv; charset=utf-8 · ... bytes · 24695 列 · 29 欄\n       natural key 醫事機構代碼 · 相異 24695 · 無鍵列 0\n       建議填入 catalog.py：\n           verified_at=\"2026-09-07\",\n           verified_note=\"實查 2026-09-07:HTTP 200；...\",\n```\n\n啟用一個資料集之後不需要再改別的地方：`hcmcp-sync` 會同步它，`list_datasets` 會列出它，重新 export 後 [資料看板](https://trionnemesis.github.io/healthcare-opendata-mcp/dashboard/) 的資料集矩陣也會出現它。\n\n該 script **只讀**：不會修改 `catalog.py`，也不會翻 `enabled`；啟用仍是人工 review 後的 PR 編輯。`--enabled-only` 可作為上游漂移檢查（欄位或 natural key 不再成立時離開碼非零）。若本機不便連外，可用 GitHub Actions 的 `Verify catalog sources` workflow 手動觸發（`workflow_dispatch`，未排程）。\n\n### MCP tools\n\n| Tool | Purpose |\n|---|---|\n| `list_sources` | 列出資料來源、取得策略與最後抓取時間 |\n| `list_datasets` | 列出可查詢資料集、欄位與新鮮度（`last_fetched_at` / `row_count`） |\n| `get_dataset` | 取得 dataset metadata、schema、新鮮度與可選的抽樣資料列 |\n| `query_rows` | 對單一 dataset 做 SELECT-only 篩選、排序與聚合 |\n| `search_records` | 跨資料集關鍵字搜尋 |\n| `get_record` | 以 `(dataset_id, natural_key)` 取得單筆完整資料 |\n| `get_vendor_stats` | 依得標次數與金額整理廠商排名 |\n| `get_tender_detail` | 即時取得標案明細的截標、開標、預算與採購屬性 |\n\n## Querying\n\n先看資料集與 schema，再執行查詢：\n\n```python\nlist_datasets()\nget_dataset(dataset_id=\"pcc-tender\", sample_rows=5)\n```\n\n兩者都會回 `last_fetched_at` 與 `row_count`，因此不需要額外查詢就能判斷資料是否過期。`row_count` 為 `null` 代表該資料集**從未同步成功**（物化表尚未建立），與「同步成功但 0 筆」不同 —— 缺值不會被折成 0。\n\n`query_rows` 保留 Twinkle 相容的 SQL-style 查詢介面，支援欄位選取、`WHERE`、`GROUP BY`、排序與聚合：\n\n```python\nquery_rows(\n    dataset_id=\"pcc-tender\",\n    columns=[\n        \"agency\",\n        \"COUNT(*) AS n\",\n        \"SUM(CAST(award_price AS INTEGER)) AS total\",\n    ],\n    where=\"announcement_type='決標公告' AND date >= '2025-01-01'\",\n    group_by=[\"agency\"],\n    order_by=\"total DESC\",\n    limit=50,\n)\n\n# nhi-healthcare-facility 目前為候選（catalog enabled=false），啟用後才有資料\nquery_rows(\n    dataset_id=\"nhi-healthcare-facility\",\n    columns=[\n        \"醫事機構代碼\",\n        \"醫事機構名稱\",\n        \"facility_type\",\n        \"governing_level\",\n        \"classification_source\",\n        \"is_active\",\n    ],\n    where=(\n        \"facility_type='hospital' AND governing_level='mohw' \"\n        \"AND is_active=1\"\n    ),\n    order_by=\"醫事機構名稱\",\n    limit=50,\n)\n```\n\nSQLite 使用 `LIKE`，不使用 PostgreSQL 的 `ILIKE`；金額欄位需要依資料內容使用 `CAST(... AS INTEGER)`。\n\n## Trust & security\n\n`query_rows` 接受 SQL 片段，因此實作了兩層防禦：\n\n- **語法層**：只允許單一 `SELECT`；拒絕多語句、註解、`PRAGMA`、`ATTACH`、DML、DDL 與危險 keyword，並將 limit 硬上限設為 400。\n- **執行層**：使用 SQLite read-only connection 與 authorizer allowlist，只允許讀取單一物化資料表；另有 VM 步數上限。\n\n寫入路徑（sync）另有一層 ingestion 防禦：PCC 半月 XML 一律以 `defusedxml` 解析，DTD 與 entity 在 parser 層就被拒絕（CWE-611/776，不使用可被 padding 繞過的字串前綴檢查），並保留 20M 字元的輸入上限。\n\n這是查詢執行安全邊界，不是使用者認證層。MCP server 本身沒有 authentication；HTTP/GKE 部署應放在內部網路，或在前方配置 IAP、service mesh mTLS 等存取控制。\n\n## HTTP & GKE\n\n本機或容器可使用 MCP streamable HTTP：\n\n```bash\nHCMCP_TRANSPORT=http HCMCP_PORT=8000 .venv/bin/hcmcp\n\ncurl http://localhost:8000/healthz\n# {\"status\":\"ok\"}\n\nclaude mcp add --transport http hcmcp http://<host>:8000/mcp\n```\n\n`HCMCP_TRANSPORT=sse` 僅保留給既有部署相容；新網路部署使用 `http`。預設監聽 `0.0.0.0:8000`，容器外執行時可用 `HCMCP_HOST` 收斂綁定位址。\n\nGKE 架構、Workload Identity、CronJob、GCS DB artifact 與 Kubernetes manifests 請見 [deploy/README.md](deploy/README.md)。DB 以不可變唯讀 artifact 形式從 GCS 拉進各 pod 的 emptyDir，因此 replica 可自由水平擴展；manifests 依 Pod Security Standards *restricted* 設定 `runAsNonRoot`、`allowPrivilegeEscalation: false`、`capabilities.drop: [\"ALL\"]` 與 seccomp `RuntimeDefault`。\n\n## Development\n\n```bash\n.venv/bin/python -m pip install -e \".[dev]\"\n.venv/bin/python -m pytest\n.venv/bin/python -m bandit -r src -ll        # SAST，與 CI 同門檻（Medium 以上失敗）\n.venv/bin/python -m pip_audit --skip-editable # 依賴弱點掃描\n```\n\nCI（`.github/workflows/ci.yml`）在 push 與 pull request 跑相同三項：pytest（Python 3.11 / 3.12）、bandit、pip-audit。另有 `verify-catalog.yml`，僅手動觸發（`workflow_dispatch`），用於對官方端點實查；刻意未排程，避免對官方來源產生持續性流量。\n\n主要程式分層如下：\n\n```text\nsrc/health_opendata_mcp/\n├── catalog.py     資料集目錄：要同步哪些開放資料（含出處與驗證閘門）\n├── adapters/      官方來源 adapter 與 HTTP/CSV/PCC parser\n├── domain/        query_guard 等純函式安全規則\n├── ingestion/     discover → fetch → normalize → upsert pipeline\n├── repository/    SQLite schema、物化表與唯讀 query executor\n└── mcp_server/    FastMCP tools、transport 與 QueryService\n```\n\n新增資料集是在 `catalog.py` 加一筆 `CatalogEntry`（見上方 [Dataset catalog](#dataset-catalog)），不必改 `cli.py`；`cli.py` 的 `build_adapters()` 只依目錄中 `enabled` 的 entry 組裝 adapter，某一種 adapter 沒有啟用項目時就不建立。新增**資料來源**（新的取得策略）才需要實作 `SourceAdapter` 的 `discover`、`fetch`、`normalize`。標案的資訊勞務主題篩選由 `cli.py` 的 `IT_INCLUDE` / `IT_EXCLUDE` 關鍵字決定。\n\n行為契約以 Gherkin 記錄在 `spec/features/`（ingestion、query-rows、query-tools、source-registration、headless-fallback），資料模型見 `spec/erm.dbml`。\n\n### Maintenance scripts\n\n| Script | Purpose |\n|---|---|\n| `scripts/enrich_bid_deadline.py` | 對近期、IT 類、尚未 enrich 且尚未決標的招標公告逐案補截標/開標/預算（限量 `--limit` + 節流 `--throttle`，被封鎖即停） |\n| `scripts/export_board_data.py` | 從真實 SQLite 原子匯出 versioned `current.json` 與預渲染看板摘要；超過 5 MiB 時縮限明細 |\n| `scripts/verify_dashboard.py` | 在 Pages 上傳前驗證 snapshot schema、大小、安全 DOM 路徑、連結與 artifact 邊界 |\n| `scripts/prune_local_db.py` | 清除超出目前同步範圍的舊資料（預設 dry-run，`--apply` 才寫入） |\n| `scripts/verify_catalog_sources.py` | 對 catalog 的官方端點實查，輸出 `verified_at` / `verified_note` 素材與上游漂移檢查（只讀，不改 `catalog.py`） |\n\n`enrich_bid_deadline.py` 的候選條件為：`announcement_type='招標公告'`、`date` 在區間內、`bid_deadline` 為空、標題屬 IT 類，且同 `job_number` 尚無決標公告。決標與招標是兩筆獨立 record，只看招標那筆看不出案子已結束，因此另行比對決標的 `job_number` 集合，避免已決標的舊案佔用有限的明細頁請求額度、排擠仍可投標的新案。\n\n## Scope & limits\n\n- 預設同步範圍刻意收斂為衛福部資訊勞務相關標案與健保診所，不是完整的政府採購或醫療資料目錄。\n- `catalog.py` 中 `enabled=false` 的候選資料集尚未對官方端點實查，不會被同步，也不應被視為已支援的資料範圍。\n- `get_tender_detail` 依賴政府電子採購網即時明細頁；舊案下架、網站維護或限流時，工具可能回傳錯誤，應稍後重試。\n- GitHub Pages 看板是提交時的靜態 snapshot，不等於 MCP／SQLite 即時查詢；自動同步與 last-known-good 發布屬後續 P1。\n- HTTP server 預設沒有 authentication；公開暴露前必須自行配置網路層存取控制。\n- `nhi-healthcare-facility` 目前在 catalog 中為 `enabled=false`：adapter 與分類規則已併入且有測試覆蓋，但尚未對官方端點實查，因此不會被同步。啟用方式見下方 Development。\n- 啟用後 `nhi-clinic` 與 `nhi-healthcare-facility` 會有資料重疊（例如診所），這是正常行為；兩者各自保留原有用途。\n- `nhi-healthcare-facility` 僅納入 `特約類別` 1~3 且 `權屬別名稱` 在「部立及直轄市立醫院」與「縣市立醫院」，以及 `特約類別` 4（診所／衛生所）。\n- `governing_level` 的 `mohw` 由衛福部官方名冊與 NHI exact-name mapping 決定；衛生所與其餘市／縣立醫院標為 `local_government`，私人診所等無可靠主管層級者為 `unknown`。\n- 資料依官方來源更新節奏而變動；repository 只提交經欄位 allowlist、大小門檻與驗證的 Pages snapshot，不提交 SQLite 或原始同步資料。\n\n## Related projects\n\n[g0VMCP](https://github.com/trionnemesis/g0VMCP) — 衛福部標案的生命週期與明細加值 MCP，處理招標 → 更正 → 決標狀態與深度標案情報。兩個專案刻意零耦合：本專案提供 Twinkle 相容的扁平列查詢，g0VMCP 提供深度標案資訊；PCC XML parser 以純函式方式 vendored 自 g0VMCP。\n\n[opendataCampus-MCP](https://github.com/trionnemesis/opendataCampus-MCP) — 教育資源導航 MCP，以 TWCampus 為目錄入口路由至台灣官方教育平台。與本專案同屬「官方開放資料 → 可查詢 MCP 介面」系列，但服務網域為教育資源而非採購／健保。\n\n## License\n\n[MIT](./LICENSE) — 資料依[政府資料開放授權條款](https://data.gov.tw/license)使用。\n"}