Google Health Broker

Google Health Broker

Self-hosted multi-user Google Health OAuth broker and read-only Agent API with remote MCP support. Enables users to connect their Google account and grant agents secure access to activity, sleep, heart, HRV, SpO2, and other health metrics via revocable per-token authentication.

Category
访问服务器

README

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

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

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选