MCP tool

whoop_sleep

Per-night sleep records with the full stage breakdown. Naps are excluded by default so weekly averages aren't skewed by a twenty-minute nap.

What it returns

FieldMeaning
WokeThe morning you woke. A night is dated by its end, matching the WHOOP app — bedtime often falls on the previous calendar day.
BedtimeTime you fell asleep, shown separately since it may be the day before.
Time asleepIn-bed minus awake. WHOOP does not return this directly — we compute it.
REMRapid eye movement sleep.
DeepWHOOP calls this slow-wave sleep.
LightLight sleep.
AwakeTime awake while in bed.
Sleep performancePercent of the sleep WHOOP thinks you needed.
Sleep efficiencyPercent of time in bed actually asleep.
Respiratory rateBreaths per minute during sleep.

Parameters

NameTypeDescription
daysintegerLookback window in days, counted back from now. Ignored when `start` is given.
startstringStart of the range, ISO-8601 (e.g. '2026-08-01' or '2026-08-01T00:00:00Z'). Overrides `days`.
endstringEnd of the range, ISO-8601. Defaults to now.
include_napsbooleanInclude nap records alongside main sleeps. Defaults to false.

Pass either days or an explicit start/end pair. start wins if both are given.

Example

YouAm I getting enough deep sleep?
Assistant → whoop_sleep({ days: 14 })
You averaged 1h 12m of deep sleep across 14 nights, which is within the normal band for your total sleep time. The variance is the interesting part: five nights were under 50 minutes, and four of those followed days with strain above 15. Your sleep performance averaged 78%, held down mostly by time in bed rather than efficiency — efficiency was a healthy 91%.

Sample output

Tools return markdown, not JSON — it costs roughly a third of the tokens and models reason over tables more reliably than nested objects.

markdown returned to the model
## WHOOP Sleep — 2026-08-07 to 2026-08-14 (7 records)

| Woke | Bedtime | Type | Asleep | REM | Deep | Light | Awake | Performance | Efficiency | Resp. rate |
|---|---|---|---|---|---|---|---|---|---|---|
| 2026-08-12 | 23:41 | sleep | 7h 12m | 1h 48m | 1h 22m | 4h 2m | 0h 31m | 84% | 93% | 14.6 |
| 2026-08-13 | 00:18 | sleep | 6h 04m | 1h 21m | 0h 47m | 3h 56m | 0h 44m | 71% | 89% | 15.1 |

**Period average:** avg time asleep 6h 58m · avg Sleep Performance 78%

_Data by WHOOP._
Data by WHOOP

Questions this answers

  • “How much deep sleep did I get this week?”
  • “Which nights were under six hours, and what did I do the day before?”
  • “Has my sleep efficiency improved since I moved the bedroom around?”
  • “Include naps — how much total sleep am I actually getting?”

Notes and gotchas

  • Naps are excluded unless you pass include_naps: true.
  • "Deep sleep" is WHOOP's slow-wave sleep — same thing, different label.
  • A very recent night may still be unscored and come back with dashes.
  • Rows are dated by the wake morning. Dating by bedtime instead would put two nights on one calendar date whenever bedtime crosses midnight, and none on the next.

Call it directly

The endpoint is plain JSON-RPC, so you can test without any client:

curl
curl -s https://fitnesspeak.app/mcp \
  -H "Authorization: Bearer fp_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "whoop_sleep",
         "arguments": {
           "days": 7
         }
       }
     }'

Tool description the model sees

WHOOP sleep records: time asleep, REM / deep / light / awake breakdown, sleep performance and efficiency, and respiratory rate. Call this when the user asks how they slept, about sleep debt or sleep quality, or wants sleep stages for a date range. Naps are excluded unless `include_naps` is true. Each row is dated by the morning the user woke, matching the WHOOP app — the bedtime column often falls on the previous calendar day.

Descriptions say when to call a tool, not just what it does — that trigger wording is what models actually route on.

Use whoop_sleep in your assistant

14-day free trial. Card required so there's no second signup at the end; cancel before day 14 and you're charged nothing.