whoopmcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| WHOOPMCP_CACHE | No | Cache responses on disk | false |
| WHOOPMCP_SCOPES | No | Space-separated scope list | all read scopes + offline |
| WHOOP_CLIENT_ID | Yes | OAuth client ID from the WHOOP dashboard | |
| WHOOPMCP_TIMEOUT | No | Per-request timeout, seconds | 30 |
| WHOOPMCP_STATE_DIR | No | Token and cache location | ~/.local/state/whoopmcp |
| WHOOP_REDIRECT_URI | Yes | Must match a registered redirect URL exactly | |
| WHOOP_CLIENT_SECRET | Yes | OAuth client secret | |
| WHOOPMCP_TOKEN_BACKEND | No | file or keyring | file |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| whoop_auth_statusA | Report whether a valid WHOOP token is held, its scopes and its expiry. Call this first when a data tool fails; it distinguishes "never logged in" from "token expired" from "scope not granted". |
| whoop_loginA | Return a URL the user must open in a browser to authorise this server. The user completes the WHOOP consent screen, is redirected to the
configured redirect URI, and then passes the |
| whoop_complete_loginA | Finish a login using the code and state from the redirect URL. Args:
code: The |
| whoop_logoutA | Delete the locally stored WHOOP token. This does not revoke the grant at WHOOP; do that from the WHOOP app under Settings if you want the authorisation itself withdrawn. |
| get_profileA | Return the user's WHOOP profile: user id, email, first and last name. |
| get_body_measurementA | Return height in metres, weight in kilograms and max heart rate in bpm. |
| list_recoveriesA | List recovery records: recovery score (%), HRV (ms) and resting heart rate (bpm). Args: start: ISO 8601 start of the range, e.g. "2026-07-01T00:00:00Z". Defaults, with end, to the last 7 days when both are omitted. end: ISO 8601 end of the range. limit: Records to return, capped at 25 per page by WHOOP. next_token: Cursor from a previous truncated response, to continue that page. |
| list_sleepsA | List sleep records: performance (%), efficiency, and stage durations in milliseconds. Args: start: ISO 8601 start of the range. Defaults, with end, to the last 7 days when both are omitted. end: ISO 8601 end of the range. limit: Records to return, capped at 25 per page by WHOOP. next_token: Cursor from a previous truncated response, to continue that page. detail: "summary" (default) omits the per-stage sleep-duration breakdown to keep the response small; "full" includes it under "stage_durations", with the units declared once in a top-level "units" key. |
| list_cyclesA | List physiological cycles: day strain (0-21), average and max heart rate, kilojoules. A cycle is WHOOP's notion of a day, bounded by sleep rather than by midnight, and is the key other records join on. Args: start: ISO 8601 start of the range. Defaults, with end, to the last 7 days when both are omitted. end: ISO 8601 end of the range. limit: Records to return, capped at 25 per page by WHOOP. next_token: Cursor from a previous truncated response, to continue that page. |
| list_workoutsA | List workouts: sport, strain, average and max heart rate, and heart-rate zone durations. Args: start: ISO 8601 start of the range. Defaults, with end, to the last 7 days when both are omitted. end: ISO 8601 end of the range. limit: Records to return, capped at 25 per page by WHOOP. next_token: Cursor from a previous truncated response, to continue that page. detail: "summary" (default) omits the per-zone heart-rate duration breakdown to keep the response small; "full" includes it under "zone_durations", with the units declared once in a top-level "units" key. |
| get_sleepA | Return a single sleep by its v2 UUID. |
| get_workoutA | Return a single workout by its v2 UUID. |
| summarize_periodA | Summarise recovery, sleep and strain over a date range. Returns mean, standard deviation, median, min and max for each
metric, along with the number of scored records behind each figure
and Args: start: ISO 8601 start of the range. end: ISO 8601 end of the range. |
| metric_trendA | Compute the direction and rate of change of one metric over a range. Args: metric: One of "recovery_score", "hrv", "resting_heart_rate", "sleep_performance", "sleep_efficiency", "strain". start: ISO 8601 start of the range. end: ISO 8601 end of the range. Returns the least-squares slope in metric units per day. A slope is a description of the window requested, not a forecast. Also returns an r² fit-quality figure for that slope -- both as the number and as a word ("strong"/"moderate"/"weak"/"negligible") -- and 7/30/90-day rolling means of the metric over calendar days. |
| correlate_metricsA | Correlate two metrics over a range, sweeping a range of day-offsets. Joins the two metrics by UTC calendar date rather than by cycle, and reports Pearson's r and Spearman's rho at every lag from -lag_days to +lag_days (inclusive), each with its own sample size. A positive lag means metric_a's date precedes metric_b's by that many days -- metric_a "leads". A lag whose surviving pairs fall below 8 is reported as refused rather than omitted. Correlation here is descriptive, not causal: WHOOP daily samples are autocorrelated (today's recovery is not independent of yesterday's), so do not read a strong r at some lag as proof that one metric drives the other, and do not treat a handful of weeks as a stable finding. Args: metric_a: First metric name, as in metric_trend. metric_b: Second metric name. start: ISO 8601 start of the range. end: ISO 8601 end of the range. lag_days: Sweep radius in days (default 3, capped at 14); the sweep covers every integer lag from -lag_days to +lag_days. Raises: ValueError: if lag_days is negative. |
| compare_periodsA | Compare every summary metric between a baseline period and a later one. Useful for "did the training block change anything" questions. Returns both periods' summaries and the delta, with sample sizes. Args: baseline_start: ISO 8601 start of the baseline period. baseline_end: ISO 8601 end of the baseline period. comparison_start: ISO 8601 start of the comparison period. comparison_end: ISO 8601 end of the comparison period. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 16 tools
Each tool targets a distinct resource or analytical operation: auth lifecycle (status, login, complete_login, logout), raw data (profile, body measurement, recoveries, sleeps, cycles, workouts, single gets), and analysis (summarize, trend, correlate, compare). Even similar-sounding tools like list_sleeps vs get_sleep are clearly differentiated by singular vs plural and description.
The naming is mostly verb_noun (get_profile, list_sleeps, summarize_period) but inconsistent: auth tools carry a whoop_ prefix (whoop_login, whoop_complete_login) while data tools do not, and metric_trend breaks the verb_noun pattern by being noun_noun. The style is readable but not uniform.
16 tools is slightly above the typical 3-15 range, but each tool earns its place by addressing a distinct need (auth, each data type, individual records, and analysis). The count is a bit heavy but not bloated, and the domain of WHOOP data access justifies the breadth.
The surface covers the core WHOOP data types (profile, body measurement, recoveries, sleeps, cycles, workouts) plus individual getters for sleep and workout, and adds useful analytical tools. Minor gaps persist: there is no get_recovery or get_cycle by ID, and no way to retrieve a single cycle or recovery directly, but these can be worked around via the list functions.