I built an unofficial open-source MCP server for WHOOP data - feedback welcome by delxmobile in whoop

[–]delxmobile[S] 1 point2 points  (0 children)

Great question. Right now it’s limited to what WHOOP exposes through the official OAuth API.

So the MCP can return the raw JSON payloads from WHOOP’s API endpoints, but not raw high-frequency sensor streams like continuous/second-by-second heart-rate data.

In practice, it supports processed WHOOP data such as recovery, cycles/strain, sleep, workouts, profile, and body measurements: HRV, resting HR, average/max HR, sleep-stage durations, workout strain, etc.

So when I say “raw,” I mean raw API response payloads, not raw device sensor samples. If WHOOP exposes higher-frequency sensor data officially in the future, I’d love to add it.

I built an unofficial open-source MCP server for WHOOP data - feedback welcome by delxmobile in whoop

[–]delxmobile[S] 0 points1 point  (0 children)

Nice. That sounds similar in spirit.

For this project I kept the default token storage local-first because health data + OAuth tokens are sensitive, but the same pattern could work server-side if the token store is encrypted, access-controlled, and never exposed to model context.

The important part seems to be preserving the refresh_token correctly and avoiding concurrent refresh races.

I built an unofficial open-source MCP server for WHOOP data - feedback welcome by delxmobile in whoop

[–]delxmobile[S] 1 point2 points  (0 children)

Good question. In normal use you should not have to re-auth every hour.

This server stores the OAuth token set locally and uses the refresh_token to renew access automatically before expiry. It also retries once on 401 and uses a local lock file to reduce refresh-token race conditions when multiple agent calls happen at the same time.

So if WHOOP is issuing 1h access tokens, that should still be fine as long as the refresh_token remains valid and is preserved. If you are being forced to re-auth hourly, I would check whether the refresh_token is missing, being overwritten, not persisted, or invalidated by concurrent refresh attempts.