Privacy-first Google Health API MCP server for health, sleep, activity and HR agents
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste into ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
An MCP server that runs locally and hands your AI agent your own Google Health API data β from Fitbit trackers, Pixel Watch and supported partner sources β through OAuth.
npx -y google-health-fitbit-mcp setup0600 permissions and are never returned by any tool (privacy).Beta status: Google Health API is available to developers but the surface is still moving. Because Google's release notes keep listing scope and data-type changes after launch, this connector remains in beta and steers testers toward safe read-only validation before any production use.
Independent, community-built connector β no affiliation with, endorsement from or support by Google, Fitbit or Alphabet. Not a medical device or medical advice; treat the data as trend context only.
Prerequisite: a Google Cloud OAuth client (type: Desktop) with the Google Health API enabled and the redirect
http://127.0.0.1:3000/callbackregistered β details in Install.
Step 1 β Install & authorize (once):
setup asks for a Client ID and Client Secret. You create these once, for free, in Google Cloud:
health-mcp), click Create, then select it.403: access_denied.β¦apps.googleusercontent.com) and the Client secret, then paste each one when setup prompts you.Redirect URI: Desktop-app clients allow the
http://127.0.0.1:3000/callbackloopback automatically β you don't register it anywhere. Just press Enter to accept the default whensetupasks. For every othersetupprompt (scope preset, privacy mode), pressing Enter picks a sensible default.
Heads-up β the 7-day rule: while the consent screen sits in Testing publishing status, Google revokes refresh tokens after 7 days. Around once a week the next request fails with
invalid_grant, which is normal and not a bug in this server. It reopens the consent flow for you (see Staying connected); approving takes a couple of seconds. Publishing the app removes the expiry entirely β check what your scopes require on the consent screen before switching.
Step 2 β Connect your app:
Settings β Developer β Edit Config, then add to claude_desktop_config.json:
Restart Claude Desktop β the tools appear under the π connectors menu.
Add the same mcpServers block to .cursor/mcp.json (per-project) or ~/.cursor/mcp.json (global), or use Settings β MCP β Add new server.
Add the same mcpServers block to ~/.codeium/windsurf/mcp_config.json.
Then reload with /reload-mcp or hermes mcp test google_health.
Step 3 β Test it. Ask your agent:
The Google Health API is the successor to the Fitbit Web API: new OAuth, new base URL (https://health.googleapis.com), a streamlined endpoint schema, standardized kebab-case data types, reconciled cross-source streams and daily/physical-time rollups.
It gives agents a clean path to explore the API, verify their setup, sign in locally and pull data β with no need to paste tokens into prompts or agent configs.
Three good opening prompts, built around tools this connector genuinely ships:
29 tools, all read-only except the two explicitly gated local-profile/auth actions noted below.
| Tool | What it does |
|---|---|
google_health_connection_status | Local config, token, scope and MCP-client readiness β no Google call |
google_health_quickstart | Personalized 3-step setup walkthrough that adapts to your current state |
google_health_data_inventory | Supported domains, scopes, data-type naming and recommended agent flow |
google_health_list_data_types | The 39 kebab-case data-type slugs with units, scopes and supported verbs |
google_health_demo | Realistic synthetic payloads so agents see the contract before real calls |
| Tool | Endpoint |
|---|---|
google_health_get_identity | /v4/users/me/identity β Google Health + legacy Fitbit identity mapping |
google_health_get_profile | /v4/users/me/profile |
google_health_get_settings | /v4/users/me/settings β units, timezone |
google_health_list_paired_devices | /v4/users/me/pairedDevices β your Fitbit trackers and Pixel Watches, and which device produces which data |
google_health_get_irn_profile | /v4/users/me/irnProfile β irregular-rhythm (AFib) notification engagement status |
google_health_list_data_points | /v4/.../dataPoints β intraday detail for any data type |
google_health_get_data_point | /v4/.../dataPoints/{id} β one specific sleep session, exercise or measurement |
google_health_reconcile_data_points | /v4/.../dataPoints:reconcile β one clean stream across sources (all-sources, google-wearables, google-sources) |
google_health_daily_rollup | /v4/.../dataPoints:dailyRollUp β civil-day aggregates |
google_health_rollup | /v4/.../dataPoints:rollUp β physical-time window aggregates |
| Tool | What it does |
|---|---|
google_health_daily_summary | Steps, distance, calories, active-zone minutes, sleep, resting HR, HRV and weight for one day, with data-quality flags |
google_health_weekly_summary | Weekly scorecard with optional prior-window comparison, load classification and bottlenecks |
google_health_wellness_context | Normalized activity/sleep context for recommendation engines |
google_health_get_auth_url Β· google_health_exchange_code (gated: requires explicit user intent) Β· google_health_revoke_access (gated + destructive: disconnects Google Health) Β· google_health_privacy_audit Β· google_health_cache_status Β· google_health_data_type_coverage Β· google_health_capabilities Β· google_health_agent_manifest Β· google_health_onboarding Β· google_health_profile_get Β· google_health_profile_update (local file only, requires explicit_user_intent=true)
MCP resources: google-health://agent-manifest, google-health://capabilities, google-health://inventory, google-health://latest/steps, google-health://profile, google-health://summary/daily, google-health://summary/weekly.
MCP prompts: google_health_daily_checkin, google_health_weekly_review, google_health_data_type_investigation.
39 data types from the official Google Health table, including steps, sleep, heart-rate, heart-rate-variability, daily-resting-heart-rate, active-zone-minutes, distance, total-calories, weight, body-fat, blood-glucose, oxygen-saturation, vo2-max, electrocardiogram, irregular-rhythm-notification, exercise, floors, swim-lengths-data, nutrition-log and hydration-log.
Naming rules agents need:
steps, daily-resting-heart-rate.sleep.interval.civil_start_time, heart_rate.sample_time.physical_time.all-sources, google-wearables, google-sources.Call google_health_list_data_types for the full catalog with units, scopes and which verbs (list/reconcile/rollup) each type supports.
~/.google-health-mcp/tokens.json, locked down to 0600 permissions.~/.google-health-mcp/config.json or the GOOGLE_HEALTH_* environment variables.GOOGLE_HEALTH_PRIVACY_MODE=structured; summary strips identifiers further, and raw is an explicit opt-in for debugging.support prints a copy-paste support bundle for GitHub issues β always redacted, never contains tokens, secrets, local paths or health measurements.support --feedback --json prints an anonymous setup-feedback bundle for beta testers (guide).coverage --live --json prints only redacted data-type status and point-count buckets β never raw Google Health payloads (guide).Set up a Google Cloud OAuth client (type: Desktop), turn on the Google Health API, and register the local redirect:
Then run:
Presets keep OAuth consent easy to reason about β request only what your use case needs:
| Preset | Grants |
|---|---|
basic | profile + settings |
activity | basic + activity/fitness + health metrics |
sleep | basic + sleep |
heart | basic + health metrics + ECG + irregular-rhythm notifications |
full | all recommended read-only scopes (default) |
nutrition-write | opt-in nutrition write scope β the only preset with any write capability; no write tool ships yet |
Advanced users can pass --scopes with an explicit space/comma-separated scope list.
Access tokens refresh silently in the background. The refresh token behind them is what expires β Google revokes it after 7 days while the consent screen is in Testing publishing status, and the next call comes back as invalid_grant. Retrying cannot fix that: the grant is gone, and only a fresh authorization brings it back.
So the server does the authorization for you. On the first call that hits a revoked grant it opens your browser at Google's consent screen; approve, and the original request finishes on its own β no command to run, nothing to diagnose. If you take longer than GOOGLE_HEALTH_REAUTH_WAIT_MS (45s by default), the call returns the URL instead and the listener stays up, so approving still works and the next request goes through.
This only runs on the local stdio transport, where the browser and the server are on the same machine. Under the HTTP transport β where the server may be remote, and its default port collides with the loopback redirect β the call fails with an explicit instruction to run auth instead. Set GOOGLE_HEALTH_AUTO_REAUTH=0 to always handle re-authorization yourself, or GOOGLE_HEALTH_AUTH_NO_BROWSER=1 on headless hosts to get the URL without a browser launch.
Claude Desktop / Cursor / Windsurf (see examples/):
Once the config changes, run /reload-mcp or hermes mcp test google_health β there's no need to restart the gateway just to read data.
The default transport is stdio. A local Streamable-HTTP transport is available for clients that need it:
| Environment variable | Purpose | Default |
|---|---|---|
GOOGLE_HEALTH_CLIENT_ID | Google Cloud OAuth client ID | β (or local config) |
GOOGLE_HEALTH_CLIENT_SECRET | OAuth client secret (prefer local config over MCP client config) | β (or local config) |
GOOGLE_HEALTH_REDIRECT_URI | Registered redirect URI | β (or local config) |
GOOGLE_HEALTH_TOKEN_PATH | Token file location | ~/.google-health-mcp/tokens.json |
GOOGLE_HEALTH_PRIVACY_MODE | summary | structured | raw | structured |
GOOGLE_HEALTH_CACHE | Optional SQLite response cache (true/sqlite) | disabled |
GOOGLE_HEALTH_CACHE_PATH | SQLite cache location | ~/.google-health-mcp/cache.sqlite |
GOOGLE_HEALTH_NO_CACHE | Bypass the in-memory HTTP cache (60s TTL, GET-only) | unset |
GOOGLE_HEALTH_MCP_TRANSPORT | stdio | http | stdio |
GOOGLE_HEALTH_MCP_HOST / GOOGLE_HEALTH_MCP_PORT | HTTP transport bind address | 127.0.0.1 / 3000 |
GOOGLE_HEALTH_AUTO_REAUTH | Reopen the consent flow automatically when the grant is revoked (0/false to disable) | enabled |
GOOGLE_HEALTH_REAUTH_WAIT_MS | How long a tool call waits for you to approve before returning the URL instead | 45000 |
GOOGLE_HEALTH_AUTH_NO_BROWSER | Never launch a browser; print/return the URL only (headless hosts) | unset |
Reliability built in: every Google call goes through retry middleware (exponential backoff + jitter, honors Retry-After, retries 408/429/5xx) and a 60-second GET-only response cache. Multi-day summaries limit request concurrency to stay under rate limits.
All commands run via npx -y google-health-fitbit-mcp <command> (installed binary: google-health-fitbit-mcp-server).
| Command | What it does | Key flags |
|---|---|---|
| (none) | Start the MCP server on stdio | --http β local Streamable-HTTP on 127.0.0.1:3000/mcp |
setup | Guided setup: writes local config + MCP client config | --scope-preset <basic|activity|sleep|heart|full|nutrition-write> Β· --scopes "<url β¦>" Β· --client <generic|claude|cursor|windsurf|hermes|openclaw> Β· --no-auth Β· --json |
auth | Browser OAuth with local callback; saves tokens with 0600 permissions | --no-open β print the auth URL instead of opening the browser |
checkup | Setup diagnosis with β/β checks and next steps (aliases: doctor, status) | --json Β· --client <name> Β· --fix β repair file permissions Β· --live β prove API reachability Β· --live-write β dry-run the write path, never POSTs |
coverage | Data-type coverage report across list/reconcile/rollup | --json Β· --live β redacted read-only checks against your real account |
support | Redacted support bundle for GitHub issues | --json Β· --feedback β anonymous setup-feedback bundle |
onboarding | Shared wellness onboarding flow as JSON | --pt-BR |
version / help | Print version / full usage |
Right now the most valuable thing you can contribute is hands-on setup feedback from real Fitbit, Pixel Watch, Android and Google Health API accounts.
If you have a real account to test with:
npx -y google-health-fitbit-mcp checkup and let us know whether the OAuth flow reads clearly.npx -y google-health-fitbit-mcp support --feedback --json and drop the anonymous bundle into a GitHub issue.npx -y google-health-fitbit-mcp coverage --live --json and post the redacted coverage report after you've reviewed it.google_health_connection_status, google_health_data_inventory and google_health_daily_summary from inside your MCP client.npm test runs typecheck, build, MCP smoke tests (stdio + HTTP), summary fixtures, privacy/cache/retry suites, CLI UX checks and metadata validation. See CONTRIBUTING.md for guidelines and SECURITY.md for the security policy.
MIT β see LICENSE.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/google-health-fitbit-mcp)<a href="https://allmcps.com/mcp/google-health-fitbit-mcp"><img src="https://allmcps.com/api/badge/google-health-fitbit-mcp?style=directory" alt="Google Health Fitbit Mcp on AllMCPs" /></a>