Skip to main content
Glama
tachibanayu24

fitbit-googlehealth-mcp

fitbit-googlehealth-mcp

Fitbit の広範なヘルスデータを取得し、食事写真から食事ログを書き込める Model Context Protocol (MCP) サーバー。TypeScript 実装、Cloudflare Workers にデプロイ。Claude モバイル / Claude Desktop / Claude.ai から接続して使えます。

個人利用前提の設計で、fork してあなた自身の Fitbit アプリ + Cloudflare アカウントで独立運用できます。

何ができる

  • Fitbit データの取得(Read tool 16 個)

    • Activity(歩数・距離・カロリー・運動ログ)

    • Heart Rate(日別 + 1秒〜15分の Intraday)

    • Sleep v1.2(stage 含む)

    • Body(体重・体脂肪・BMI)

    • Nutrition(食事ログ・水分)

    • SpO2 / 呼吸数 / 皮膚温 / HRV / VO2 Max

    • デバイス情報

  • 書き込み(Write tool 8 個)

    • 食事(log_food・日本語 OK)

    • 水分・体重・体脂肪・活動・睡眠の手動ログ

    • delete_food_log で個別エントリ取り消し

  • log_meal_photo: Claude モバイルで食事写真を添付 → Claude が視覚解析して栄養を推定 → 一括で Fitbit 食事ログに記録


⚠ 2026/09 の Fitbit Web API 停止について

Fitbit は 2026 年 9 月に既存の Web API(api.fitbit.com)を完全停止し、後継の Google Health API(health.googleapis.com/v4)に移行します。

  • 既存の Fitbit OAuth トークンは 移行不可 → Google OAuth で再同意が必要

  • あわせて、Fitbit アカウント自体を 2026/05/19 までに Google Account に統合必要(未統合は 2026/07/15 にデータ削除)

  • 本実装は Provider-agnostic 設計 を採っており、停止前に Google Health API 実装(src/providers/google-health/)を追加して差し替え予定

詳細は docs/research.md を参照。


前提

  • Fitbit アカウント(Google Account と統合済みが望ましい)

  • Fitbit Personal App(dev.fitbit.com で作成、callback http://127.0.0.1:8787/fitbit/callback)

  • Cloudflare アカウント(無料プランで十分)

  • Claude.ai アカウント(Web から Custom Connector を追加、モバイルに自動同期)

  • Node.js 20+ / pnpm 9+(ローカルビルド用)


セットアップ(5 ステップ)

1. Clone + install

git clone https://github.com/tachibanayu24/fitbit-googlehealth-mcp.git
cd fitbit-googlehealth-mcp
pnpm install

2. Fitbit Personal App 作成

dev.fitbit.com/apps/newPersonal タイプのアプリを作成:

  • OAuth 2.0 Application Type: Personal

  • Callback URL: http://127.0.0.1:8787/fitbit/callback

発行された Client IDClient Secret を控える。

3. 初回認可と Cloudflare への投入

# 認可フローを開始(ブラウザが開く)
export FITBIT_CLIENT_ID=<your-client-id>
export FITBIT_CLIENT_SECRET=<your-client-secret>
pnpm run setup:fitbit

ブラウザで承認すると refresh_token が取れて、以降表示される wrangler secret put / wrangler kv key put コマンドをコピペして実行:

# wrangler.toml は .gitignore 対象。テンプレからコピーして自分の値を入れる
cp wrangler.toml.example wrangler.toml

# KV namespace(一回きり)
pnpm wrangler kv namespace create TOKENS
pnpm wrangler kv namespace create CACHE
# 返ってきた id を wrangler.toml の <your-...-id> に貼り付け

# Secret(MCP_SHARED_SECRET は URL-safe な hex を推奨)
pnpm wrangler secret put FITBIT_CLIENT_ID
pnpm wrangler secret put FITBIT_CLIENT_SECRET
openssl rand -hex 32 | pnpm wrangler secret put MCP_SHARED_SECRET

# Fitbit トークン(setup:fitbit の出力をそのままコピペ、--remote 重要)
pnpm wrangler kv key put --remote --binding=TOKENS refresh_token '<paste>'
pnpm wrangler kv key put --remote --binding=TOKENS access_token  '<paste>'
pnpm wrangler kv key put --remote --binding=TOKENS expires_at    '<paste>'
pnpm wrangler kv key put --remote --binding=TOKENS user_id       '<paste>'

4. デプロイ

pnpm deploy
# → https://fitbit-googlehealth-mcp.<your-sub>.workers.dev

5. Claude.ai に Custom Connector として登録

  1. claude.ai で Settings → Connectors → Add Custom Connector

  2. URL に https://fitbit-googlehealth-mcp.<your-sub>.workers.dev/mcp/<MCP_SHARED_SECRET> を貼る

  3. 認証方式は OAuth なし(URL に secret を埋め込んでいるため)

  4. 保存すると Claude モバイル / Desktop / Web に自動同期される

モバイルで新規会話を開き、+ → Connectors → Fitbit を ON にして完了。


ツール一覧

Read(16)

Tool

引数

概要

get_profile

プロフィール(単位系・身長・タイムゾーン)

list_devices

デバイス一覧(バッテリ、最終同期時刻)

get_daily_summary

date?

歩数・カロリー・心拍ゾーン・active minutes

get_activity_timeseries

resource, start, end

steps / distance / calories 等の時系列

get_exercise_list

beforeDate?, limit?

運動ログ履歴

get_heart_rate_range

start, end

日別心拍(resting + zones)

get_heart_rate_intraday

date, detailLevel

Intraday(1sec/1min/5min/15min)

get_sleep

date?

Sleep v1.2(stage 含む)

get_sleep_range

start, end

期間 Sleep

get_body_log

start, end

体重 + 体脂肪

get_food_log

date?

食事ログ + 水分 + 栄養サマリ

get_spo2

start, end

血中酸素飽和度

get_respiratory_rate

start, end

呼吸数

get_skin_temperature

start, end

皮膚温(nightly relative)

get_hrv

start, end

HRV(RMSSD)

get_cardio_fitness

date?

Cardio Fitness Score(VO2 Max)

Write(7)

Tool

引数

概要

log_food

foodName, calories, mealType, date?, nutritionalValues?

食事を 1 件記録(日本語 OK、PFC 保持)

log_meal_photo

mealType, items[], date?, notes?

写真解析結果を一括で記録(Claude が視覚解析 → items を渡す前提)

log_water

amountMl, date?

水分(ml)

log_weight

weightKg, date?, time?

体重

log_body_fat

fatPercent, date?, time?

体脂肪率

log_activity

activityId or activityName+manualCalories, startTime, durationMs, date?, distanceKm?

手動で運動ログ

log_sleep

startTime, durationMs, date?

手動で睡眠ログ

Delete(6)

Tool

引数

概要

delete_food_log

logId, date?

食事エントリ削除

delete_water_log

logId, date?

水分エントリ削除

delete_weight_log

logId, date?

体重エントリ削除

delete_body_fat_log

logId

体脂肪エントリ削除

delete_activity_log

logId, date?

運動ログ削除

delete_sleep_log

logId, date?

睡眠ログ削除

Meal preset(4)

作り置き用の再利用可能な栄養プロファイルを MCP サーバー側(Workers KV)に保存して、ログ時に栄養素込みで Fitbit へ投入する仕組み。Fitbit の Create Food API は栄養素を保存しない仕様なので、PFC 追跡にはこちらを使う。

Tool

引数

概要

save_meal_preset

name, calories, protein?, carbs?, fat?, fiber?, sodium?, sugar?, notes?

preset を保存(同名で上書き)

list_meal_presets

保存済み preset 一覧

log_preset

name, mealType, date?, amount?

preset を今日/指定日の食事ログに記録

delete_meal_preset

name

preset 削除(既存 log には影響なし)

date? は省略時 JST の今日 にフォールバック。Tool 総数 33(Read 16 + Write 7 + Delete 6 + Preset 4)。


使用例

写真で食事記録

🤳 モバイルで昼食の写真を添付
🧑 「これを lunch で記録して」
🤖 Claude が視覚解析 → log_meal_photo を呼ぶ

Logged 3 item(s) for Lunch on 2026-04-22:
  • 親子丼(1人前、推定 680 kcal、高信頼度)
  • 味噌汁(1杯、推定 40 kcal、中信頼度)
  • 小鉢(ほうれん草、推定 60 kcal、中信頼度)

睡眠の分析

🧑 「昨日の睡眠を見せて」
🤖 Claude が get_sleep を呼び、stage の内訳や minutesAsleep / efficiency を要約

活動トレンド

🧑 「先週の歩数どうだった?」
🤖 get_activity_timeseries(resource: "steps", start: ..., end: ...) → 週平均・目標達成率を計算


ローカル開発

# ローカルで Worker 起動(local KV、local secret)
echo 'MCP_SHARED_SECRET=dev-secret' > .dev.vars
pnpm dev

# Lint / Format / Typecheck / Test
pnpm lint
pnpm format
pnpm typecheck
pnpm test

# MCP Inspector で tool schema 確認
npx @modelcontextprotocol/inspector
# URL: http://127.0.0.1:8787/mcp/dev-secret
# CF-Connecting-IP ヘッダで 160.79.104.5 を送る設定が必要

アーキテクチャ

Claude mobile / Desktop / Web
      │ (public URL: Streamable HTTP)
      ▼
Anthropic Cloud  (outbound CIDR 160.79.104.0/21)
      │
      ▼
Cloudflare Workers  /mcp/<SECRET>
  ├─ guard middleware  (SECRET + CIDR allowlist)
  ├─ @hono/mcp  Streamable HTTP transport
  └─ McpServer
       ├─ HealthProvider interface
       │   └─ FitbitProvider
       │       ├─ OAuth refresh (Workers KV: TOKENS)
       │       └─ FitbitClient (fetch wrapper, 401/429 retry)
       └─ tools/read/*, tools/write/*
            └─ getCached → Workers KV: CACHE  (TTL 1h)
  • Provider 抽象: 2026/09 以降、GoogleHealthProvider に差し替えて継続運用

  • Cache: Read 結果を KV に 1h キャッシュ、Fitbit の 150/h/user 制限を温存

  • 画像は MCP サーバーを通らない: Claude が視覚解析して items[] を引数として渡す


セキュリティ

個人用シンプル認証 の構成です。

  • SECRET + Anthropic CIDR の 2 層防御:

    1. URL パス末尾の <MCP_SHARED_SECRET> が一致しなければ 401(constant-time 比較)

    2. CF-Connecting-IPALLOWED_CIDRS env の CIDR のいずれにも属さなければ 403

  • Anthropic outbound CIDR は公開情報 160.79.104.0/21。claude.ai 経由のリクエストだけを通す

  • MCP_SHARED_SECRET は Workers Secret に保管、コードには入れない

  • ローテーションは wrangler secret put + claude.ai の URL 更新だけで完結。Fitbit トークンに影響なし

脅威モデル: SECRET が漏れて攻撃者が Anthropic CIDR 内からアクセスできる場合のみ、あなたの Fitbit データ閲覧・偽書き込みが可能。Fitbit アカウント自体の乗っ取りは不可(refresh_token は Worker 内にのみ存在)。

複数ユーザー配布が必要なら @cloudflare/workers-oauth-provider で本格 OAuth AS 化する方針に切り替え可能(本リポはそれを選んでいない — 個人用最小構成)。


既知の制約(Fitbit API 側の仕様、本実装で対処済みのもの)

食事ログ周り

  • Search Foods 障害(2025/11〜): Fitbit 公式 API の /foods/search が不安定。本実装は意図的に foodName + calories 直書きしか使わない

  • POST /foods/log.jsonunitId を必須化(unitName は受け付けない)。本実装は foodName モードで unitId: 304 (= serving) を自動付与

  • 栄養素キー名が非対称(実測結果、2026-04):

    • protein / totalFat / totalCarbohydrate / dietaryFiber / sodium / sugars — これらのキー名で送らないと Fitbit 側で無視される

    • 旧 docs の nutritionalValues.protein 形式も、proteinGrams / totalCarbs 等も 2026-04 時点では効かない

  • Create Food(カスタム食品)は calories のみ保存:protein/carbs/fat を送っても silent drop される。本実装は create_custom_food を廃止し、栄養素を保持したい場合は MCP サーバー側プリセット(save_meal_preset + log_preset)で foodName 経路に流している

  • sugar は get_food_log の echo に含まれない — 保存されたかは視認できない

Intraday(心拍数)

  • 運動ログがある日は Fitbit が intraday の dataset を pruningすることがある(実測:運動日は朝〜夕方の dataset が欠落、運動無しの日は終日揃う)。zone summary は別パイプラインで残るので get_heart_rate_range はフォールバックに使える

  • 1sec 粒度:運動記録中以外は 1 秒粒度が保証されない

その他

  • Sleep は v1.2 のみ(v1 は deprecated)

  • Claude モバイルから Custom Connector の新規追加は不可: 必ず claude.ai(Web)から追加

  • レート制限: 150 req/h/user。LLM が連続呼び出しする場合に備えて全 read に 1h キャッシュ。429 時は Retry-After を 30s までクランプして 1 回リトライ


開発ノート

  • docs/research.md — 設計前に行った調査(Fitbit API の現状、MCP / Claude モバイルの仕様、先行実装サーベイ、出典付き)

  • docs/journal.md — 開発ログ(決定理由、ハマり、使用感)

  • scripts/diagnose-food-log.ts — Fitbit の foodLog API の挙動(栄養素キー名など)を直接確認するための reproducer。API が再び形を変えた時にパターン追加して実行すれば原因特定できるよう in-tree 保持


Contributing

Issue / Pull Request 歓迎。設計判断は docs/journal.md を参照してください。


License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tachibanayu24/fitbit-googlehealth-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server