Skip to main content
Glama
zhanjinfeng

Google Health Broker

by zhanjinfeng

Google Health Broker

Self-hosted, multi-user Google Health OAuth broker and read-only Agent API. Each person connects their own Google account and receives a separate, revocable gha_ Agent Token. Generic Agents can discover the API through OpenAPI; MCP clients with static-header support can use the optional remote MCP endpoint.

The broker runs locally on Node.js or on Cloudflare Workers with D1. It encrypts Google OAuth credentials at rest, stores only hashes of Agent Tokens, refreshes Google access automatically, and does not persist health API responses.

This project uses Google Health API v4, not the legacy Fitbit Web API. It is not a medical device and must not be used for diagnosis or emergencies.

What is included

  • Self-service Google OAuth for multiple users

  • Separate, revocable Agent Tokens instead of exposing Google refresh tokens

  • Fixed read-only routes for activity, steps, distance, floors, calories, active minutes, sleep, heart, HRV, SpO2, respiratory rate, VO2 max, temperature, profile, and devices

  • OpenAPI 3.1 and /.well-known/agent.json discovery

  • Sessionless remote MCP adapter with read-only tools

  • Local encrypted JSON storage or Cloudflare D1

  • Token rotation, Google revocation, per-token rate limits, no-store responses, and OAuth CSRF protection

Related MCP server: Fitbit MCP

Quick start: local Node.js

Requires Node.js 22 or later.

npm install
cp .env.example .env
npm run keygen

Put the generated key and your Google OAuth client values in .env, then run:

npm start

Open http://localhost:8787/connect. After authorization, save the connection bundle shown once. Never commit .env, data/, or an Agent Token.

Docker is also supported:

docker compose up --build -d

The bundled JSON store supports one service process. Use the D1 deployment for a hosted, concurrent service.

Configure Google Cloud

Follow Google's Google Health setup guide:

  1. Enable Google Health API.

  2. Configure the OAuth consent screen. While the app is in Testing, add each allowed account as a test user.

  3. Request the least-privilege scopes in .env.example.

  4. Create a Web application OAuth client.

  5. Add the exact redirect URI:

http://localhost:8787/oauth/google-health/callback

For production, use your public HTTPS origin. /v1/profile also requires the optional googlehealth.profile.readonly scope.

Google OAuth projects in Testing commonly issue refresh tokens that expire after seven days. Before offering a public service, move the app to Production and complete all verification or security assessment Google requires for your scopes and audience.

Deploy to Cloudflare Workers

The committed Worker configuration is a template. Your real wrangler.toml is ignored so account and database identifiers remain local.

cp wrangler.toml.example wrangler.toml
npx wrangler d1 create google-health-broker-db

Put the returned D1 database ID in wrangler.toml, then apply the schema:

npm run worker:migrate

Upload secrets interactively. Do not put their values in wrangler.toml, shell scripts, issues, or chat:

npx wrangler secret put GOOGLE_CLIENT_ID
npx wrangler secret put GOOGLE_CLIENT_SECRET
npx wrangler secret put TOKEN_ENCRYPTION_KEY

Deploy and verify:

npm test
npm run worker:deploy
curl -fsS https://YOUR-WORKER.workers.dev/healthz

Add this exact callback URL to the Google OAuth client:

https://YOUR-WORKER.workers.dev/oauth/google-health/callback

For production, configure CONTACT_EMAIL, operator-specific privacy/terms text, a custom domain, monitoring, backups, incident response, and the required Google verification.

Connect an Agent

The one-time connection bundle contains:

{
  "type": "google-health-connection",
  "service_url": "https://health.example.com",
  "discovery_url": "https://health.example.com/.well-known/agent.json",
  "openapi_url": "https://health.example.com/openapi.json",
  "mcp_url": "https://health.example.com/mcp",
  "authorization": "Bearer gha_REDACTED"
}

An HTTP-capable Agent should fetch openapi_url, then call only documented routes with the authorization header. Each person must authorize separately and keep their own token private.

Remote MCP

POST /mcp exposes the same read-only capabilities as MCP tools. Configure the complete Authorization: Bearer gha_... header in a client that supports static MCP headers.

This adapter is intentionally described as pre-provisioned Bearer mode: it does not implement MCP OAuth 2.1 discovery or an automatic browser login flow. See docs/MCP.md.

REST API

Every /v1/* request requires:

Authorization: Bearer gha_...

Read routes:

GET /v1/connection
GET /v1/profile
GET /v1/devices
GET /v1/activity?date=YYYY-MM-DD
GET /v1/steps?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/distance?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/floors?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/calories?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/active-minutes?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/heart?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/sleep?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/hrv?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/spo2?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/breathing?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/cardio?start=YYYY-MM-DD&end=YYYY-MM-DD
GET /v1/temperature?start=YYYY-MM-DD&end=YYYY-MM-DD

Dates are Google Health civil dates. The operator maximum is at most 90 days. Google limits total-calorie and active-minute daily rollups to 14 days. Empty data can mean the connected account, permission, or device did not supply that measurement.

Credential management remains REST-only and is intentionally omitted from Agent discovery documents:

POST   /v1/token/rotate
DELETE /v1/connection

Rotation invalidates the old Agent Token immediately. Deletion removes the stored connection and attempts to revoke Google authorization.

Security and privacy

  • Google access and refresh tokens use AES-256-GCM authenticated encryption.

  • Random Agent Tokens are stored only as SHA-256 lookup hashes.

  • OAuth state is signed, expires, and is bound to an HttpOnly SameSite cookie.

  • Agent routes and upstream Google Health data types are allowlisted.

  • MCP tools are read-only and reject mismatched browser Origin headers.

  • Responses use Cache-Control: no-store and are not persisted by this application.

Read SECURITY.md and docs/THREAT_MODEL.md before operating this for other people. Encryption at rest does not make the operator or Agent client untrusted; both can observe data while processing it.

Project documents

License

MIT

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

Maintenance

Maintainers
Response time
Release cycle
1Releases (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.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A local-first MCP server that enables AI agents to read user-authorized Google Health API v4 data from Fitbit, Pixel Watch, and partners via OAuth, with tokens never leaving the machine.
    26
    810
    40
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server to read daily activity, sleep, heart rate, and body metrics from Google Health API, allowing AI assistants like Claude to access your health data. Optionally syncs health metrics to an Obsidian vault.
    5
    MIT
  • A
    license
    -
    quality
    C
    maintenance
    Self-hosted MCP server that aggregates personal health data from Google Health, Oura, and Withings into a single, provider-attributed interface with configurable source of truth preferences.
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for Withings health data — sleep, activity, heart, and body metrics.

  • Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.

  • Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.

View all MCP Connectors

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/zhanjinfeng/google-health-broker'

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