google-health-mcp
Provides read-only access to Google Health API data, including recorded workouts, heart-rate samples, and optional TCX retrieval with GPS coordinates when enabled.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@google-health-mcpShow me my last 5 workouts with duration and calories."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Google Health MCP
Local, read-only access to recorded workouts through Google Health API v4. Node.js 22.14+ and TypeScript. Three runtime dependencies: the official MCP SDK, Zod and an XML parser.
Each user sets up their own Google Cloud project and OAuth client, then signs in with the Google account that holds their workout data.
Requirements
Node.js 22.14 or later, npm and Git.
A Google account with recorded workouts available through Google Health API.
Permission to create a Google Cloud project and configure its OAuth client.
A local desktop browser for sign-in and an MCP client that supports stdio, such as Codex.
The Google Cloud CLI (gcloud) is not required. There is no hosted service to deploy.
Related MCP server: google-health-mcp
1. Clone and build
git clone https://github.com/metacurb/google-health-mcp.git
cd google-health-mcp
npm ci
npm run buildRun the remaining terminal commands from this repository directory.
2. Create a Google Cloud project
Open Google Cloud Console and sign in.
Open the project selector, choose New project, enter a name such as
Health MCP, select the available organization/location, and click Create.Select the new project. Keep it selected throughout setup.
Open APIs & Services → Library, search for Google Health API, open it and click Enable.
These steps follow the Google Health project setup guide.
3. Configure OAuth consent and access
Open Google Auth Platform. If prompted, click Get started.
Enter an app name, a user support email and a developer contact email. Choose External for a personal Google account. Complete the required consent-screen fields and acknowledge Google's policy to create the configuration.
Under Audience, keep the publishing status as Testing for initial setup.
Under Test users → Add users, add the exact Google account email you will use for health-data sign-in, then Save. This is required even if you own the Cloud project.
See Google's consent-screen setup and test-user instructions.
For ongoing personal use, Audience → Publish app changes the OAuth app to In production. This removes the test-user allowlist and Testing's seven-day refresh-token expiry. Unverified-app warnings and a 100-user cap still apply. Personal use can qualify for a verification exception; distributing one shared OAuth app to the public has separate verification requirements. Publishing the OAuth configuration keeps this MCP local. See OAuth app states, token expiry and the personal-use exception.
4. Add the read-only scopes
Open Google Auth Platform → Data Access → Add or remove scopes. Find Google Health API and select exactly these three scopes, then click Update and Save:
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonly
https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
https://www.googleapis.com/auth/googlehealth.location.readonlyActivity access reads workouts; health-metrics access reads heart rate; location access permits optional TCX retrieval. GPS coordinates are excluded from tool output unless include_gps is true. The helper requests all three scopes and rejects incomplete or broader grants. See Google's scope configuration instructions.
5. Create a Desktop OAuth client
Open Google Auth Platform → Clients → Create client.
Choose Desktop app as the application type, enter a client name and click Create.
Download the client's JSON file. Rename it to
credentials.jsonand place it in the repository root, besidepackage.json.
This application requires a Desktop client with an installed section in its JSON file. The authentication helper checks the file type without printing its contents. Google Health's REST codelab uses a Web client; this project's local login uses the Desktop loopback flow. The helper creates its callback on a random local port, so no hosted redirect URL needs to be configured. Keep the downloaded file private; it is already in .gitignore.
6. Sign in and test API access
npm run auth
npm run smokeauth opens the system browser. Select the account with your workout data and grant all three read-only permissions. Complete sign-in within five minutes. Valid saved credentials are reused. After changing the OAuth app's publishing status, use npm run auth -- --force to obtain a fresh grant.
smoke lists up to five workouts from the past 30 days, gets the newest workout, then retrieves up to five available heart-rate samples. Use npm run smoke -- --days=90 for a wider window. It prints health data to your terminal and saves no files. Exit code 2 means there were no workouts, so the heart-rate call could not be tested. Exit code 1 means a request or authentication failed. A successful request can still report missing heart-rate data.
7. Connect an MCP client
The server starts with node dist/index.js and waits for MCP messages on stdin. It does not open a web page. The MCP client normally starts and stops this process. npm run --silent start also works; avoid plain npm start in client configuration because its script banner would enter the protocol.
For Codex, run this from the repository directory in a macOS/Linux shell:
codex mcp add google-health -- "$(node -p 'process.execPath')" "$(pwd)/dist/index.js"This records absolute paths to Node and the built server. To configure paths manually, run node -p 'process.execPath' and node -p 'require("node:path").resolve("dist/index.js")' from the repository. Copy the results into your client's stdio command and argument fields.
For example, in Codex's config.toml, replace both placeholder paths:
[mcp_servers.google-health]
command = '/absolute/path/to/node'
args = ['/absolute/path/to/google-health-mcp/dist/index.js']
tool_timeout_sec = 90On Windows, use the paths printed by Node, including node.exe. The single-quoted TOML strings accept Windows backslashes. Other MCP clients need the same executable and server argument. No credentials or token environment variables belong in the MCP configuration.
Restart the MCP connection after registration or rebuilding. Try asking: “List my workouts from last month, including hikes.” See Codex MCP configuration for client setup details.
Credential storage and privacy
Credentials are read explicitly from ~/.config/gcloud-health/application_default_credentials.json. Valid credentials for this project's client are reused. Run npm run auth when sign-in is needed; npm run auth -- --force forces a new grant. The MCP server does not open a browser itself. On POSIX systems, the directory uses mode 0700 and new credential files use 0600. Access tokens are held in memory and refreshed on demand. The application rejects grants with missing or extra scopes.
Here, ~ means the current operating-system user's home directory; the .config/gcloud-health directory is also used on Windows. There is one saved OAuth client/account per OS user. Signing in with another client replaces the credentials in that isolated directory.
Authentication uses PKCE and a temporary callback bound to 127.0.0.1. The callback stops when login ends. No gcloud command runs during authentication or MCP use. Existing gcloud configuration, default application credentials, shell startup files, GOOGLE_APPLICATION_CREDENTIALS and metadata-server credentials are not used or changed. Tool results are sent to the MCP client that requested them; that client's data-handling policy also applies.
No health write endpoints exist in this client. Health requests use GET only. The OAuth token exchange uses POST to Google's token endpoint. HTTP redirects are refused. Errors expose HTTP status and known Google error codes, never raw response bodies, OAuth URLs, client credentials or tokens. Diagnostics go to stderr.
Setup troubleshooting
Problem | Action |
Google allows only developer-approved testers | In the OAuth client's project, add the exact sign-in email under Audience → Test users, or use the personal-use publishing option above. Start a fresh login. |
| Download a Desktop OAuth client JSON file and save it as |
| Run |
| Check the three Data Access scopes above, then sign in again and grant all three. |
HTTP 403 or | Confirm Google Health API is enabled in the same project as the downloaded client, and check account/organization access restrictions. |
| Run authentication in a local desktop terminal with a working browser and complete the new sign-in within five minutes. |
No workouts returned | Check the selected Google account and date range; try |
| See the known workout-pagination limitation below. |
TCX | Retry with a larger |
Tools
Tool | Inputs | Result |
|
| Recorded summaries and next page token |
|
| Summary, both split collections and data availability |
|
| Detailed samples, a page token for each measurement, optional TCX |
Example list arguments:
{"start_date":"2026-08-01","end_date":"2026-09-01","page_size":25}Use the exact name returned by that tool as workout_name. Supported measurements are heart_rate (default), distance, steps, active_energy_burned, active_zone_minutes and altitude (elevation gain). To get multiple types, pass them in measurements. To retrieve TCX, set include_tcx: true; add include_gps: true only when you want coordinates. Default TCX output removes coordinates, vendor extensions and metadata while retaining standard measurements. Oversized TCX produces an explicit error rather than broken, truncated XML. No exports are saved.
To read the original TCX with GPS and vendor extensions preserved, use:
{
"workout_name": "<name returned by list_workouts>",
"include_tcx": true,
"include_gps": true,
"max_tcx_bytes": 10485760,
"max_points_per_series": 1
}TCX defaults to a 1 MiB limit; max_tcx_bytes can raise it to 10 MiB per call. The limit applies to both the downloaded XML and returned XML. With include_gps: true, valid TCX is returned unchanged (transformation: none), including any recorded coordinates. This cannot add GPS data that Google did not supply. No scope change or new sign-in is needed if the three required read-only scopes were already granted. GPS remains opt-in for other calls.
The source limits are defined in src/limits.ts. After changing them, run npm test and restart the MCP connection so the client loads the new schema and server. A currently running process keeps its old limits until restarted.
Data rules:
Resource names can contain Google's numeric user ID or
me. The client preserves returned names and usesusers/mefor outgoing requests. A different workout ID or conflicting numeric user ID in a response is rejected.List dates use the workout's recorded local time: inclusive start, exclusive end, at most 366 days. All activity types, including
HIKING, are included by default. An exactactivity_typesfilter runs within each API page; an empty page can still have a next page. Keep the same filters and page size when paging.Activity labels are never reclassified.
splitSummariesand defaultsplitsremain separate named collections; they can describe overlapping segments.Metrics include units and timestamps. Google integer strings remain strings to avoid precision loss. Missing metrics are
null; recorded zero stays zero.source: recordedmeans Google supplied the value, which may itself be calculated by Google. Local calculations appear underderivedMetricswith their formulas. Derived pace uses recorded active time, never elapsed time.get_workoutmarks telemetry and TCX asnot_checked; a summary metric does not prove detailed samples exist. Series results distinguishavailable,missing,unknown_more_pagesanderror.Detailed streams are selected by the workout's time window, not an activity foreign key. They may contain overlapping device sources or paused periods. Samples and interval starts use
[startTime, endTime). Interval measurements are not clipped, prorated, deduplicated or summed. A returned page is not a whole-workout total.Each selected series has its own page token. Continue with that series in
measurementsand its token inpage_tokens. Up to six series are read per call. JSON responses are capped at 4 MiB per request and TCX at the requested byte limit. Each serialized MCP result is capped at 21 MiB before its text copy (up to about 42 MiB combined), allowing room for escaped XML and measurements. A request times out after 20 seconds; only a 401 gets one token refresh and retry.
Verification
Run npm test to build and execute the tests. Google credentials and live API access are not required for these tests.
See TESTING.md for the exact live-access status. Tests use invented TypeScript fixtures and injected HTTP responses. They never load personal health exports.
Known Google limitation observed on 2026-09-07: workout listing returned a next-page token that Google rejected with HTTP 400, Invalid page token. The client reports INVALID_PAGE_TOKEN; it does not treat a failed page as complete. Use narrower date ranges and inspect nextPageToken for possible incomplete results. Heart-rate pagination passed live checks. This limitation can still prevent a complete workout history from being retrieved.
Credentials, tokens, .env files, health export formats and data directories are ignored by Git. JSON files are ignored by default except the package files and TypeScript config. Keep any manual health downloads in data/, downloads/ or exports/.
Official references
Checked on 2026-09-07:
The workout guide's simple heart-rate example uses startTime/endTime query parameters. This client follows the endpoint reference's documented filter expression instead. Exercise listing uses the explicitly documented civil-time filter. TCX uses alt=media and partialData=true, which permits available non-GPS data. The REST reference does not document an activity-type filter, so that filter is local.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Collect Apple Health data from your wearables through the Context app and query it via MCP
- SomviaOAuthapp.somvia
Private Apple Health metrics and workout detail for ChatGPT, Claude, and any MCP client.
Read wearables and lab health data — sleep, activity, workouts, timeseries, lab tests and orders.
MCP server for Withings health data — sleep, activity, heart, and body metrics.
Related MCP Servers
- AlicenseBqualityAmaintenanceA 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.261,09753MIT
- AlicenseAqualityBmaintenanceRead-only MCP server exposing daily health facts, 7/28-day baselines, and deterministic daily pulse from Google Health API data.73MIT
- AlicenseNot gradedqualityBmaintenanceAn MCP server that connects AI clients to the Google Health API, enabling natural language queries about health and fitness data such as steps, sleep, heart rate, and exercise sessions.281MIT
- AlicenseAqualityBmaintenanceAn MCP server that locally authenticates with Google Health API v4 and provides read-only access to Fitbit, Pixel Watch, and other health data for AI agents.2910316MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/metacurb/google-health-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server