Skip to main content
Glama
jorgedcb

WHOOP MCP Server

by jorgedcb
README.md
# WHOOP MCP server

Connect your WHOOP data to Claude, Cursor, or any other MCP client. Ask things like
*"How did I sleep last night?"*, *"Compare my HRV on workout days vs rest days this week"*,
or *"What was my strain yesterday?"* and get answers from your own recovery, sleep,
strain and workout records.

- One tool per WHOOP API v2 read endpoint, returning the records as WHOOP sends them
- Runs with `npx`, no clone or build needed
- Tokens refresh automatically; you log in once

## Setup

You need Node 20 or newer and a WHOOP account.

### 1. Create a WHOOP app

WHOOP does not offer a shared public app, so each user registers their own. It takes two minutes.

1. Go to [developer-dashboard.whoop.com/apps/create](https://developer-dashboard.whoop.com/apps/create) and sign in with your normal WHOOP account.
2. Fill in the form. Only these fields matter:

   | Field | What to enter |
   |---|---|
   | **Name** | Anything, e.g. `My MCP server`. Only you will see it. |
   | **Logo** | Leave empty. |
   | **Contacts** | Your email address. |
   | **Privacy policy** | `https://github.com/jorgedcb/whoop/blob/main/PRIVACY.md` (it explains that all data stays on your machine) |
   | **Redirect URLs** | `http://localhost:3000/callback` exactly. The placeholder suggests https, but http on localhost is accepted. |
   | **Scopes** | Tick all six: `read:recovery`, `read:cycles`, `read:sleep`, `read:workout`, `read:profile`, `read:body_measurement`. |
   | **Webhooks** | Leave empty. |

3. Click **Create App**. The app page then shows your **Client ID** and **Client Secret**. Keep that page open for the next step.

You do not need to look for an `offline` scope. The CLI requests it during login so it can refresh tokens without asking you to sign in again.

### 2. Connect your account

```bash
npx @jorgecastilla/whoop-mcp auth
```

Paste the client ID and secret when prompted. A browser tab opens for WHOOP login and consent.
When it says "WHOOP connected", credentials and tokens are saved under `~/.config/whoop-mcp/`
with owner-only permissions. You will not need to do this again.

Check the result at any time:

```bash
npx @jorgecastilla/whoop-mcp status
```

### 3. Add the server to your MCP client

**Claude Desktop.** Open Settings, then Developer, then Edit Config, and add:

```json
{
  "mcpServers": {
    "whoop": {
      "command": "npx",
      "args": ["-y", "@jorgecastilla/whoop-mcp"]
    }
  }
}
```

Quit and reopen Claude Desktop. The tools appear under the tools icon in a new chat.

**Claude Code.**

```bash
claude mcp add --scope user whoop -- npx -y @jorgecastilla/whoop-mcp
```

**Cursor and others.** Any client that launches stdio MCP servers works with the same command and arguments.

## Tools

| Tool | WHOOP endpoint | What it returns |
|---|---|---|
| `get_recovery` | `GET /v2/recovery` | Recovery score, HRV, resting HR, SpO2, skin temperature |
| `get_sleep` | `GET /v2/activity/sleep` | Sleep stages, sleep need, performance, respiratory rate |
| `get_sleep_by_id` | `GET /v2/activity/sleep/{id}` | One sleep record |
| `get_cycles` | `GET /v2/cycle` | Daily strain, energy, heart rate per physiological cycle |
| `get_cycle_by_id` | `GET /v2/cycle/{id}` | One cycle |
| `get_sleep_for_cycle` | `GET /v2/cycle/{id}/sleep` | The sleep that closed a cycle |
| `get_recovery_for_cycle` | `GET /v2/cycle/{id}/recovery` | The recovery for a cycle |
| `get_workouts` | `GET /v2/activity/workout` | Sport, strain, heart-rate zones, distance |
| `get_workout_by_id` | `GET /v2/activity/workout/{id}` | One workout |
| `get_profile` | `GET /v2/user/profile/basic` | Name and email |
| `get_body_measurements` | `GET /v2/user/measurement/body` | Height, weight, max heart rate |

The collection tools take `limit` (max 25), `start`, `end` and `next_token` for paging.
`start` and `end` accept `YYYY-MM-DD` in your local time or a full ISO 8601 datetime.

Records are returned exactly as WHOOP sends them, minus your user id. Field names match the
[WHOOP API reference](https://developer.whoop.com/api), so their docs apply directly.

### A note on WHOOP days

WHOOP measures in *cycles*, which run from wake-up to the next wake-up rather than midnight to
midnight. A recovery is scored from the sleep that ends a cycle. When you ask for a date range,
WHOOP matches it against the activity's own window, so a range ending on day N also returns the
recovery scored on the morning of N+1.

## Configuration

Everything is optional. The defaults work after `auth`.

| Variable | Purpose | Default |
|---|---|---|
| `WHOOP_CLIENT_ID`, `WHOOP_CLIENT_SECRET` | Override the saved credentials | from `auth` |
| `WHOOP_REDIRECT_URI` | Must match the app's registered URI | `http://localhost:3000/callback` |
| `WHOOP_CONFIG_DIR` | Where credentials and tokens are stored | `~/.config/whoop-mcp` |
| `WHOOP_TOKEN_FILE` | Token file path (use an absolute path) | `<config dir>/tokens.json` |

To pass variables to the server, use your MCP client's `env` block for that server entry.
A `.env` file is not read.

## Troubleshooting

**"No WHOOP tokens found"** means `auth` has not run for the config directory the server is
using. Run `npx @jorgecastilla/whoop-mcp status` to see which directory that is.

**"redirect_uri mismatch" during auth** means the URI registered on your WHOOP app differs
from the one the CLI is using. Both must be exactly `http://localhost:3000/callback`, or set
`WHOOP_REDIRECT_URI` to whatever you registered.

**"Port 3000 is in use"** during auth: stop whatever is on that port, or register a different
localhost URI on your app and set `WHOOP_REDIRECT_URI`.

**The server does not appear in Claude Desktop.** Almost always a JSON syntax error in the
config file. Settings, then Developer shows the parse error. Also confirm you fully quit the
app, since the config is only read at launch.

**Token refresh fails.** WHOOP rotates refresh tokens and they expire after long inactivity.
Run `auth` again.

## Development

Uses [Bun](https://bun.sh) for development and tests. The published package runs on plain Node.

```bash
bun install
bun run auth            # connect an account
bun run start           # run the server over stdio
bun test                # deterministic tests against a local mock of the WHOOP API
bun run typecheck
bun run build           # compile to build/ for Node
```

To point an MCP client at your checkout instead of the npm package, use
`bun run /path/to/whoop/src/index.ts` as the command.

## License

MIT

TDQS

A3.5/5.0

Scored across 11 tools

Disambiguation4/5

The main list tools (get_recovery, get_sleep, get_cycles, get_workouts) are distinct, but the four by_id/relationship tools (get_sleep_by_id, get_cycle_by_id, get_sleep_for_cycle, get_recovery_for_cycle) have subtle boundaries, particularly the cycle-relationship pair versus the ID lookups, risking misselection.

Naming Consistency4/5

Most tools follow a consistent get_noun pattern, with get_sleep_by_id and get_workout_by_id deviating only by adding an _by_id suffix. This is a minor, readable deviation rather than a true inconsistency.

Tool Count5/5

Eleven tools are well-scoped for WHOOP's core domains (profile, recovery, sleep, cycles, workouts, body), with relationship helpers earning their place. Nothing feels excessive or thin.

Completeness4/5

Read/list coverage is strong across all main resources, including relationship helpers, but the surface is read-only, with no create/update/delete and no explicit pagination or error tools. Minor gaps agents can work around.