SuperAPI AI Directory

fitbit-mcp

Fitbit Web API access with a local SQLite cache and trend analysis for heart rate, activity, exercises, sleep, weight, SpO2 and HRV.

Open website

About this tool

Project status (retired)

fitbit-mcp is no longer maintained (Retired), and the official recommendation is to switch to google-health-mcp. The reason is that the Fitbit Web API will be shut down on September 30, 2026, and Fitbit has also stopped accepting new app registrations, so this package cannot be set up from scratch—the step of registering a personal app can no longer be completed. Installed instances can continue to be used until the shutdown date.

google-health-mcp covers the same measurement data through the Google Health API, and adds ECG and irregular rhythm notifications. It reads historical data from Google rather than from this package's cache, so no migration is needed: just run a single backfill after installation.

Not all data can be migrated. Fitbit's activity goals and server-side lifetime totals have no equivalent in google-health-mcp; fields that Google does not provide also include heart rate zones, active minutes breakdowns, VO2 max expressed as a range rather than a single value, sleep efficiency, SpO2 high/low values, and BMI. After September 30, 2026, this package will also no longer be able to obtain this data, so back up fitbit.db before the deadline if you want to keep it.

Purpose and positioning

fitbit-mcp is an MCP server for the Fitbit Web API, with OAuth PKCE authorization, a local SQLite cache, and trend analysis features. It is designed for Claude Code and other MCP clients, syncing Fitbit data to a local database for fast, offline queries—after the first sync, no further API calls are needed.

Main capabilities

  • OAuth 2.0 PKCE: a secure authorization flow with no client secret required.
  • Local SQLite cache: sync once, query instantly.
  • Incremental sync: fetch only new data since the last sync.
  • MCP tools: sync, query (cached data types plus devices/lifetime/goals that are available only in real time), and trend analysis.
  • Real-time mode: bypass the cache and query the API directly.
  • CLI: authorization setup, sync, and JSON import from the command line.
  • Rate limit handling: activity and food log syncs sleep and retry when they encounter a 429; other data types report rate_limited, and resume on the next sync.

Requirements

  • Python 3.13+ (tested on 3.13 and 3.14 in CI)
  • A Fitbit developer account with a registered personal app

How to use

Installation

You can run it directly without installing, or do a development install from a cloned repository.

2. Register a Fitbit app

Go to dev.fitbit.com/apps to create a new app, set OAuth 2.0 Application Type to Personal, and set Redirect URL to http://localhost:8080,记录 Client ID (no client secret needed—PKCE does not use it).

3. Authorization

This step opens a browser for Fitbit login, exchanges the authorization code via PKCE, and saves the token locally. The token is stored at ~/.config/fitbit-mcp/fitbit_tokens.json with permissions 0600. The access token expires after 8 hours and is refreshed automatically; the refresh token expires after 90 days of inactivity.

4. Register with Claude Code

5. First sync (optional)

Query tools sync automatically on first use, so this step can be skipped. Run it manually to prefill the cache or sync a longer history.

MCP tool reference

Query tools sync automatically on the first query of each data type each day. Use live=True to bypass the cache entirely and fetch directly from the API.

All query tools accept the following common parameters:

  • start_date: start date, in the format YYYY-MM-DD, YYYY-MM, or 30d (relative). Default: the last 30 days.
  • end_date: end date, in the format YYYY-MM-DD. Default: today.
  • live: if true, fetch from the Fitbit API instead of the cache (bypasses automatic sync).

fitbit_get_exercises also accepts:

  • exercise_type: filter by activity name (case-insensitive substring match), such as "cycling", "walk", "run". Default: all types.

Sync tools sync data from the Fitbit API to the local SQLite cache. Query tools call them automatically on first use each day, so they only need to be called explicitly when a longer history is needed or a forced refresh is required.

  • data_types: the types to sync: all, heart_rate, activity, exercises, sleep, weight, spo2, hrv, azm, breathing_rate, skin_temperature, core_temperature, cardio_fitness, food_log. Comma-separated. Default: all.
  • days: number of days of history for the first sync (default: 30). Subsequent syncs are incremental.
  • since: optional YYYY-MM-DD. Backfill from that date, ignoring already cached content, overriding incremental resume and the days parameter.
  • until: optional YYYY-MM-DD (inclusive) end date; must be used together with since. The two refetch and upsert data for exactly the since..until window—used to repair gaps in the middle of the cache without refetching all data up to today.

Trend analysis tools perform aggregated trend analysis based on cached data.

  • data_type: analysis type: heart_rate, activity, exercises, sleep, weight, spo2, hrv, azm, breathing_rate, skin_temperature, core_temperature, cardio_fitness, food_log. Default: activity.
  • period: aggregation granularity: weekly, monthly, quarterly. Default: monthly.
  • start_date: start date. Default: the last 12 months (365 days).
  • end_date: end date. Default: today.
  • compare: compare two periods: last_30d vs previous_30d, 2026-03 vs 2026-02, 2026-Q1 vs 2025-Q4. When set, period/start_date/end_date are ignored.

Authorization scopes

The following Fitbit API scopes are requested during setup. These are the scopes required by all tools. If only a subset is needed, edit FITBIT_SCOPES in config.py before setup. After upgrading from a smaller scope set, rerun fitbit-mcp auth to reauthorize.

Environment variables

Paths can be overridden via environment variables.

Offline / cache-only mode

By default, the server syncs automatically on demand, and query tools can get the latest data without a cron job. Set FITBIT_MCP_OFFLINE=1 to run it as a pure cache reader:

  • No Fitbit credentials needed—the server never touches the token file.
  • No live API calls. Automatic sync is disabled, live=True, live-only tools (fitbit_get_devices, fitbit_get_lifetime_stats, fitbit_get_goals) and fitbit_sync return an explicit "offline mode" message instead of calling the API.
  • Query tools serve content from the local SQLite cache. Responses are marked with "offline_mode": true.

Multi-device scenario: one host runs fitbit-mcp sync via cron/systemd to write to the shared database; other hosts set FITBIT_MCP_OFFLINE=1 and point FITBIT_MCP_DB_PATH to the same cache, performing reads only. This way the Fitbit OAuth token (one-time, rotating) is held by only one host, avoiding refresh conflicts.

CI and privacy: run queries without network access and without credentials.

Keeping the cache fresh is from then on the responsibility of the sync host. Unsetting FITBIT_MCP_OFFLINE restores on-demand automatic syncing.

Rate limits

The Fitbit API allows 150 requests per hour. Activity and food log syncs sleep and automatically retry when encountering a 429; date-range data types instead mark that sync as rate_limited and continue on the next run. Note:

  • Activity and food log syncs use 1 API call per day (there is no date-range endpoint)
  • The first 30-day sync consumes about 30 per hour of quota each
  • Heart rate, sleep, weight, SpO2, HRV, AZM, breathing rate, skin temperature, core temperature, and cardiorespiratory fitness use date-range endpoints and are far more efficient
  • Use live=False (the default) to query from the cache and avoid API calls entirely

Data protection

The project includes a pre-commit hook (scripts/check-no-data.sh) to prevent accidental commits:

  • Database files (*.db, *.db-journal, *.db-wal)
  • Config/credentials (config/*.json)
  • Large files (>100KB)

Install the hook after cloning.

Importing existing data

If you already have Fitbit data in JSON format (for example, from a previous export or script), you can import it in bulk. Expected filenames: heart_rate.json, activity.json, exercises.json, sleep.json, weight.json, spo2.json, hrv.json. For the JSON format, see src/fitbit_mcp/importer.py. Import currently covers only these seven types; newer types (AZM, breathing rate, skin/core temperature, cardiorespiratory fitness, food log) are populated via sync rather than import.

Development

For development setup, test workflow, and pre-commit hooks, see CONTRIBUTING.md. Changes are recorded in CHANGELOG.md. License: GPL-3.0-or-later.

Limitations and caveats

  • The project is retired; the Fitbit Web API will be shut down on September 30, 2026, and new app registrations are not possible.
  • Some data (activity goals, lifetime totals, heart rate zones, active minutes breakdown, VO2 max range, sleep efficiency, SpO2 high/low, BMI) also has no counterpart in the alternatives.
  • Specific details such as authorization scopes, environment variable names, and CLI subcommands require reference to the official documentation and are not listed one by one in this introduction.