Skip to main content
Glama
Shreyamkmr

Google Health MCP — Remote

Google Health MCP — Remote

Connect Claude (or any MCP client) to your Fitbit / Pixel Watch data from anywhere. A remote, multi-user Model Context Protocol server for the Google Health API v4, with built-in OAuth 2.0 sign-in, ready to deploy to Google Cloud Run — and tuned to run inside the free tier.

CI Release License: MIT

Fork of davidmosiah/google-health-mcp (google-health-mcp-unofficial), which runs locally over stdio. This fork adds a remote transport so the server can live on the internet and be used from Claude on the web, desktop and mobile. Unofficial — not affiliated with Google or Fitbit.


What you get

  • Paste one URL into Claude — https://<your-service>.run.app/mcp. Claude discovers the login itself, sends you to Google's consent screen, and you're connected.

  • Your data, your server — it runs in your Google Cloud project with your OAuth client. Nothing goes through a third party.

  • Stateless and free to idle — no database; tokens are encrypted blobs only the server can open. Scales to zero, so a personal setup typically costs £0/month.

  • Read-only by default — sleep, steps, distance, heart rate, HRV, Active Zone Minutes, workouts, weight, nutrition and more, plus daily/weekly summaries.

  • Locked down — only the Google accounts you allow (MCP_ALLOWED_EMAILS) can sign in.

Related MCP server: Google Health MCP

How it works

sequenceDiagram
    participant C as Claude (MCP client)
    participant S as This server (Cloud Run)
    participant G as Google sign-in
    participant H as Google Health API
    C->>S: POST /mcp (no token)
    S-->>C: 401 + where to log in
    C->>S: /register, /authorize
    S->>G: redirect to consent (your OAuth client)
    G-->>S: /oauth/callback with code
    S-->>C: code → /token → encrypted access + refresh tokens
    C->>S: POST /mcp (Bearer token)
    S->>H: request with *your* Google token
    H-->>S: health data
    S-->>C: tool result

The server is both the MCP resource server and an OAuth 2.1 authorization server (MCP authorization spec 2025-06-18: protected-resource metadata, authorization-server metadata, dynamic client registration, PKCE S256, refresh tokens). Login itself is delegated to Google. Client registrations, codes and tokens are sealed with AES-256-GCM, so there is no database and any instance can serve any request.

Deploy (about 15 minutes)

You need a Google account, a Google Cloud project with billing enabled (the free tier covers personal use), and Cloud Shell or the gcloud CLI.

  1. Google Cloud Console (same project you'll deploy to):

    • Enable the Google Health API.

    • Google Auth Platform → Get started: External, add yourself under Audience → Test users.

    • Clients → Create client → Web application. Leave both URI lists empty for now; copy the Client ID and secret.

  2. Deploy from Cloud Shell:

    git clone https://github.com/Shreyamkmr/google-health-mcp-remote.git
    cd google-health-mcp-remote
    export PROJECT_ID="your-project-id"
    export GOOGLE_HEALTH_CLIENT_ID="xxxx.apps.googleusercontent.com"
    export GOOGLE_HEALTH_CLIENT_SECRET="GOCSPX-xxxx"
    export MCP_ALLOWED_EMAILS="you@gmail.com"
    ./deploy-cloudrun.sh
  3. Add the printed …/oauth/callback URL to your OAuth client's Authorized redirect URIs.

  4. In Claude: Settings → Connectors → Add custom connector → paste the printed …/mcp URL → Connect.

Step-by-step guide, configuration reference, free-tier details and troubleshooting: DEPLOY-CLOUD-RUN.md.

Other clients:

  • Claude Code: claude mcp add --transport http google-health https://<service>/mcp

  • MCP Inspector: Streamable HTTP → URL → Quick OAuth Flow

Common gotchas

Symptom

Fix

Build fails with artifactregistry.repositories.uploadArtifacts denied

New projects don't grant build permissions by default. The script now grants roles/run.builder; on older copies run it by hand (see the deploy guide).

redirect_uri_mismatch at sign-in

The callback URL on your OAuth client must match exactly (https, no trailing slash).

"Google hasn't verified this app"

Expected for a personal app — click Continue.

Logged out every 7 days

Apps in Testing get 7-day refresh tokens. Fill in Branding (the server serves /, /privacy, /terms) and Publish the app, then reconnect once.

Free-trial billing account

Upgrade to a paid account before the trial ends, or Cloud Run is stopped. Always-free allowances still apply.

Tools (remote mode)

Area

Tools

Health data

google_health_list_data_points, google_health_reconcile_data_points, google_health_daily_rollup, google_health_rollup

Summaries

google_health_daily_summary, google_health_weekly_summary, google_health_wellness_context

Account

google_health_get_profile, google_health_get_settings, google_health_get_identity, google_health_revoke_access

Discovery

google_health_list_data_types, google_health_data_inventory, google_health_data_type_coverage, google_health_capabilities, google_health_quickstart, google_health_agent_manifest, google_health_demo

Tools that only make sense for one local user (manual auth URL/code exchange, token-file status, local disk audits, local wellness-profile file) are hidden in remote mode. Resources and prompts from the original project are still served.

Try asking: "How did I sleep last night?", "Summarise my last run and whether I've recovered", "How many Active Zone Minutes have I got this week?"

Security model

  • Google access/refresh tokens are only ever held encrypted inside tokens issued to your MCP client; the server stores nothing. Health data is not stored.

  • MCP_TOKEN_SECRET (in Secret Manager) encrypts everything. Rotate with new,old; drop old to sign everyone out.

  • MCP_ALLOWED_EMAILS is checked at sign-in, on every request and on every refresh.

  • Dynamic registration accepts https redirect URIs (and http only on localhost); PKCE is required; authorization codes are single-use and expire in 5 minutes.

  • google_health_revoke_access revokes the caller's Google grant.

  • Report vulnerabilities via SECURITY.md / a private GitHub advisory.

Running locally

All original modes still work:

npm ci && npm run build
node dist/index.js                 # stdio, single user (original behaviour)
node dist/index.js --http          # local HTTP, single user, no auth
npm run start:remote               # remote mode on :8080 (needs the env vars above + MCP_TOKEN_SECRET)

For local remote mode, add http://localhost:8080/oauth/callback to your OAuth client and set MCP_PUBLIC_URL=http://localhost:8080. The original single-user documentation is kept in docs/UPSTREAM-README.md.

Development

npm ci
npm run typecheck
npm run build
npm run smoke          # stdio tools/resources/prompts smoke test
npm run test:remote    # 25-check OAuth + MCP end-to-end test against a mock Google
npm run ci             # all of the above

Remote-mode code lives in src/remote/: oauth.ts (authorization server and bearer middleware), sealed.ts (AES-256-GCM token sealing), server.ts (Express app) and request-context.ts (per-request Google token).

Credits and licence

Built on google-health-mcp by David Mosiah, which provides the Google Health client, tools, summaries and privacy modes. Remote transport, OAuth layer and Cloud Run deployment by @Shreyamkmr.

MIT — see LICENSE. Not medical advice; Google Health data is wellness context only.

Related MCP Connectors

Related MCP Servers