健康同步 MCP
# 健康同步 MCP
以繁體中文記錄飲食與運動,透過 Google Health API v4 寫入使用者的 Fitbit / Google Health 帳號。提供本機 stdio MCP,可接到 Codex;原始程式採 MIT 授權。
這是個人/自行部署版本。多人雲端服務的帳號隔離、付款與公開 OAuth 審核尚未實作。
## 快速開始
需要 Node.js 22.14 以上(建議 24)、Google Cloud 專案與已啟用的 Google Health API,以及連結 Fitbit 的 Google 帳號。
```powershell
npm ci
npm run build
```
在 Google Auth Platform 建立外部、測試模式的應用程式,把自己的帳號加入測試使用者。建立「網頁應用程式」OAuth 用戶端,設定重新導向 URI:
```text
http://127.0.0.1:8765/oauth/callback
```
匯入下載的 OAuth 用戶端 JSON,程式會加密保存到 `.data/oauth-client.encrypted.json`。這個目錄已被 Git 排除;原始下載 JSON 可自行刪除。
```powershell
node dist/cli.js import-client "C:/path/to/downloaded-oauth-client.json"
```
接著執行:
```powershell
npm run auth
```
打開終端機列出的 Google 授權網址。預設要求 `openid`(識別帳號,避免混用同步帳本)、`googlehealth.activity_and_fitness.writeonly` 及 `googlehealth.nutrition.writeonly`。可使用寫入權限讀回自己透過同一用戶端寫入的紀錄;不會預設要求完整健康歷史。
```powershell
codex mcp add google_health -- node "C:/absolute/path/google-health-write-mcp/dist/cli.js"
codex mcp get google_health
```
如果使用 `.env`,在 Node 命令前加入 `--env-file=C:/absolute/path/.env`。Codex 不一定自動重新載入新 MCP;在 MCP 設定重新啟動連線,或新開 Codex 工作階段。憑證 JSON 會相對程式目錄讀取,不依賴 Codex 工作目錄。
## 使用方式
告訴 Codex:
> 使用 google_health:先預覽今天 12:00–12:20(台灣時間)的午餐「雞肉飯」,550 kcal、蛋白質 30 g、碳水 60 g。不要猜脂肪。唯一鍵 meal:2026-10-04:lunch。
確認資料後,明確要求寫入。`dry_run` 預設為 `true`;只有 `false` 才會呼叫寫入 API。請提供真實資訊,不要直接將文件範例匯入自己的健康帳號。
工具:
| 工具 | 功能 |
|---|---|
| `health_status` | 授權、權限與加密狀態,不回傳權杖 |
| `health_log_meal` | 飲食名稱、餐別、熱量與三大營養素 |
| `health_log_workout` | 重訓/有氧場次、時間、備註與可選摘要 |
| `health_catalog` / `health_schema` | 官方可寫類型與 Discovery 欄位 |
| `health_create` | 通用新增 11 種可寫入資料類型 |
| `health_update` / `health_delete` | 更新/刪除指定資源;預設先預覽 |
| `health_list` / `health_get` | 讀回同一用戶端寫入的紀錄 |
| `health_write_status` | 查詢穩定唯一鍵的本機同步結果 |
目前官方可新增類型:`body-fat`、`exercise`、`height`、`hydration-log`、`menstrual-period`、`moods`、`nutrition-log`、`ovulation-test`、`sleep`、`symptoms`、`weight`。通用介面遵循規格,但各類型的線上實測狀態應以驗證紀錄為準。預設權限只涵蓋飲食、喝水、運動;其他類型需額外授權,不會自動要求所有健康權限。
## 同步與限制
- 每筆寫入需要穩定 `idempotency_key`。Google Sheet 可使用表格 ID、工作表名稱與不變的來源紀錄 ID 組成鍵,勿使用排序後會變動的列號。
- SQLite 帳本可避免跨程序重送;帳本以 OAuth 用戶端與 Google 帳號隔離。相同鍵不同資料會拒絕,成功記錄可重播結果。
- 網路逾時或程序中止時結果可能不明,帳本保留 `uncertain`/`started`,不會自動重送。請查詢遠端資料後處理,勿任意更換鍵重送。
- `succeeded` 才代表 Google 回傳完成。`pending` 表示操作尚未完成,程式不會把它當成功。目前官方 Discovery 未公開通用 operations.get,需以資料讀回確認。
- 匿名飲食無法直接更新。重訓組數、重量與次數保存在 `notes`,不會假造結構化逐組欄位;Fitbit App 是否顯示備註需以實際介面確認。
- 不猜測未記錄的營養、開始時間或運動時長。Google Sheets 自動讀取及每週排程尚未加入;可先將真實資料交給 Codex 寫入。
- Google OAuth 測試模式的權杖可能短期到期;若遇 `invalid_grant`,重新授權。公開商用需遵守 Google Health 驗證、資料政策與適用審核。
## 資料保護
Windows 使用 DPAPI CurrentUser,加密匯入的 OAuth 用戶端、權杖與寫入結果。`.data` 目錄應限制為自己的 Windows 帳號。Linux/macOS 需以秘密管理工具提供 `GOOGLE_HEALTH_STORAGE_KEY`,勿把金鑰與加密資料公開。服務只固定呼叫 Google 的 OAuth 與 Health HTTPS 端點。為相容舊設定仍可讀 `.data/oauth-client.json`,但建議使用加密匯入。
本機資料不會出售、拿來投放廣告或訓練模型。將健康資料送給 Codex 等第三方時,由使用者主動要求且應符合該服務的使用條款與 Google Limited Use 規則。可以在 Google 帳戶的第三方連線設定撤銷授權;停止 MCP 後可刪除本機 `.data`,不會自動刪除已寫入 Fitbit 的資料。
## 開發與規格來源
```powershell
npm run check
npm run spec:sync
```
測試使用模擬 API,不會寫入真實健康帳號。規格更新使用官方 [Discovery](https://health.googleapis.com/$discovery/rest?version=v4) 與[資料類型表](https://developers.google.com/health/data-types?hl=en)。飲食及運動欄位依據[飲食文件](https://developers.google.com/health/data-types/nutrition)與[運動文件](https://developers.google.com/health/data-types/workouts)。程式開源不會公開 OAuth Secret、使用者權杖或健康資料。
## 真實寫入驗證
OAuth 完成後,把一筆自己要求寫入的真實資料存成私有 JSON(例如 `.data/verify-input.json`)。格式為 `{"tool":"health_log_meal","arguments":{...}}`,arguments 使用工具的實際欄位,必須包含穩定的 `idempotency_key`。勿將健康資料存到 Git 追蹤的目錄。
```powershell
node scripts/verify-live.mjs .data/verify-input.json
node scripts/verify-live.mjs .data/verify-input.json --commit
```
第一個命令只產生預覽。第二個透過真正的 stdio MCP 寫入,再用 `health_get` 讀回比對;只有 Google 回傳完成且內容吻合,才輸出 `readbackConfirmed: true`。這不代替 Fitbit App 畫面的人工確認。運動類型非 `OTHER` 時,Google 可能產生顯示名稱,比對會遵守官方行為而保留其他輸入欄位檢查。
TDQS
Scored across 11 tools
Most tools target distinct actions (status, catalog, schema, list, get, create, update, delete), but health_create's generic 'create any supported type' purpose overlaps with the specialized health_log_meal and health_log_workout writers. Descriptions clarify that the log_* tools are convenience wrappers for specific domains, so misselection is possible but manageable.
All 11 tools use a strict snake_case health_<verb>_<noun> pattern (health_write_status, health_log_meal, health_create, health_delete). Naming is highly predictable and consistent across the set.
11 tools is well within the ideal 3-15 range and each tool has a clear role: CRUD operations plus discovery (catalog, schema) and operational helpers (status, write_status). No redundancy that inflates the count.
Full lifecycle coverage is present: read (health_get, health_list), create (health_create plus domain-specific log_*), update (health_update), delete (health_delete), plus introspection (catalog, schema), auth status, and idempotent write verification. No obvious dead ends for a Google Health sync server.