Skip to main content
Glama

whoop-mcp

A small Model Context Protocol server that gives Claude read access to your WHOOP health data — recovery, sleep, strain, and workouts — through the official WHOOP API v2.

Ask Claude things like "Did I sleep well?", "Am I recovered enough to train hard today?", or "What's my resting heart rate trend this week?" and it will pull live data from your WHOOP.

Note on "current heart rate": WHOOP's API exposes completed summaries (last night's sleep, today's recovery, per-workout HR), not a live real-time pulse. daily_summary gives the freshest snapshot available — the latest recovery score, resting heart rate, HRV, and today's accumulated strain.

Tools

Tool

What it returns

daily_summary

One-call snapshot: latest recovery (score, HRV, resting HR), last night's sleep, today's strain. Start here.

get_recovery

Recovery records for the last N days (default 7).

get_sleep

Sleep records with stage breakdown for the last N days.

get_strain

Daily strain / cycle data (day strain, avg & max HR).

get_workouts

Workout activities for the last N days (default 14).

get_profile

Name, email, user id.

get_body_measurement

Height, weight, max heart rate.

Related MCP server: Whoop MCP Server

Setup

1. Create a WHOOP developer app

  1. Go to the WHOOP Developer Dashboard and sign in with your WHOOP account.

  2. Create an app. Copy the Client ID and Client Secret.

  3. Add a Redirect URI of exactly http://localhost:8080/callback.

  4. Make sure these scopes are enabled: read:recovery, read:cycles, read:sleep, read:workout, read:profile, read:body_measurement, and offline.

2. Configure credentials

cp .env.example .env
# edit .env and paste in your Client ID + Secret

3. Authorize once

uv run whoop-authorize

This opens your browser, you approve access, and tokens are saved to ~/.whoop-mcp/tokens.json (readable only by you). The server refreshes them automatically from then on — you won't need to log in again.

4. Register the server with Claude

claude mcp add whoop -- uv --directory /Users/adam/dev/whoop-mcp run whoop-mcp

Restart Claude, then ask: "How's my WHOOP recovery today?"

Using it from the Claude apps (remote connector)

The stdio setup above only works in Claude Code, which can launch the server as a local subprocess. To use WHOOP from claude.ai, the desktop app, and mobile, run the server remotely over HTTP and add it as a custom connector.

The same code serves an HTTP transport via the whoop-mcp-http entrypoint. The MCP endpoint lives at /mcp behind a minimal single-user OAuth 2.1 layer (see oauth.py) — claude.ai custom connectors force an OAuth handshake and won't connect to a no-auth server. When you add the connector, Claude bounces you to a login page; enter your WHOOP_MCP_SHARED_SECRET and it's authorized. Tokens are stateless HMAC-signed blobs, so nothing is stored and auth survives restarts.

Deploy (Render free tier — no monthly cost)

  1. Create a free Upstash Redis database (upstash.com) and copy its REST URL and REST token. This is where the rotating WHOOP token is persisted, so it survives restarts without a paid disk.

  2. Push this repo to GitHub and create a Render Blueprint from render.yaml (uses the free web plan).

  3. Set the secret env vars in the Render dashboard (all marked sync: false):

    • UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN — from step 1.

    • WHOOP_CLIENT_ID, WHOOP_CLIENT_SECRET — from the WHOOP dashboard.

    • WHOOP_REFRESH_TOKEN — the refresh_token field from your local ~/.whoop-mcp/tokens.json after uv run whoop-authorize.

  4. Render generates WHOOP_MCP_SHARED_SECRET for you — copy it from the dashboard.

Why Redis? WHOOP rotates refresh tokens on every use, so the rotated token must outlive restarts. The free Render web tier has no persistent disk, so the server stores the token blob in Upstash instead (see the token-backend section of auth.py). Locally, with no Redis env vars set, it falls back to a 0600 file in ~/.whoop-mcp/.

Cold starts: free web services sleep after ~15 min idle, so the first query after a lull takes ~30-60s and may need one retry. To keep it warm, ping /healthz every ~10 min from a free scheduler like cron-job.org.

Prefer a persistent disk instead? On a paid Starter plan you can drop the Upstash vars, add a disk: mounted at /data, and set WHOOP_MCP_HOME=/data.

Add the connector

In claude.ai → Settings → Connectors → Add custom connector, paste:

https://<your-app>.onrender.com/mcp

Claude opens a login page — enter your WHOOP_MCP_SHARED_SECRET to authorize. Once connected there it syncs to the desktop and mobile apps too.

Run the HTTP server locally to test first:

WHOOP_MCP_SHARED_SECRET=$(uuidgen) PORT=8080 uv run whoop-mcp-http
# health check: curl localhost:8080/healthz  ->  ok

How auth works

WHOOP uses OAuth 2.0 with rotating refresh tokens — each refresh returns a new refresh token and invalidates the old one. auth.py persists the new token after every refresh, so the connection stays alive indefinitely without re-authorizing. No secrets are stored in your Claude config; everything lives in ~/.whoop-mcp/.

Available Tools

7 tools
daily_summaryA

Get an at-a-glance snapshot of how the user is doing RIGHT NOW.

Combines the latest recovery score (HRV, resting heart rate), last night's sleep, and today's accumulated strain into one view. Use this first when the user asks "how am I doing", "am I recovered", "did I sleep well", "what time did I wake up / go to bed", or anything about their current physical state. last_sleep includes local bedtime and wake time.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full responsibility. It discloses that the tool combines the latest recovery score, last night's sleep, and today's accumulated strain, and mentions that last_sleep includes local bedtime and wake time. However, it does not specify data freshness, caching behavior, or whether values are real-time or from the last sync. This is adequate but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief but complete: two sentences cover purpose, contents, and usage context. Front-loaded with the core benefit, then details. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, the description provides a good overview of what is returned (recovery, sleep, strain). It could describe the output format or data types, but the description is suitable for the tool's simplicity. Omitting details like range or units is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the description adds value by explaining what the snapshot includes (recovery, sleep, strain) and that it reflects the current state. Schema coverage is 100%, so a baseline of 3 is adjusted upward for the added context above the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool provides a 'snapshot of how the user is doing RIGHT NOW' combining recovery, sleep, and strain. It distinguishes itself from sibling tools by being a composite view, unlike individual metric tools like get_recovery or get_sleep.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent to use this first when the user asks about current state, listing specific queries like 'how am I doing', 'am I recovered', 'did I sleep well'. Implicitly guides away from using separate sibling tools until a more detailed view is needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_body_measurementA

Get the user's body measurements: height, weight, and max heart rate.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided; description only lists returned values without behavioral traits like data freshness or authentication needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no fluff, efficiently conveys purpose and content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, description adequately covers what the tool returns. Minor gaps like units or data source are acceptable for this simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, and schema coverage is 100%. Description adds meaning by specifying the content of the measurement (height, weight, max heart rate).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Get the user's body measurements' with specific items (height, weight, max heart rate). It distinguishes from sibling tools like get_profile or daily_summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. Lacks context for invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_profileA

Get the user's basic WHOOP profile (name, email, user id).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It only states the output fields but fails to disclose potential behavioral aspects such as authentication requirements, rate limits, or error handling. A simple read operation is implied, but no side effects or restrictions are mentioned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no superfluous words. Every word is meaningful and earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and a simple profile retrieval, the description adequately conveys what the tool returns. However, the absence of an output schema means the description could better clarify the structure, though the listed fields suffice for basic understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters (0 params), so schema coverage is effectively 100%. The description adds no meaning beyond the input schema, which is vacuous. According to rubric, high coverage yields baseline 3. The description does not contradict the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves basic profile data (name, email, user id). The verb 'Get' and resource 'basic WHOOP profile' are specific. It distinguishes from sibling tools that retrieve other types of data (e.g., get_sleep, get_recovery).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives. While it is implied that this tool is for basic profile info, there is no guidance on when not to use it or mention of alternative tools for related purposes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recoveryA

Get recovery records (score, HRV, resting heart rate) for the last N days.

Recovery reflects how ready the body is for strain. days defaults to 7.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It only states that the tool retrieves data for the last N days with a default of 7, but does not disclose any side effects, permissions, or limitations beyond the obvious read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, with the first sentence delivering the core purpose and data, and the second providing context and default. Every sentence adds value, and there is no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one parameter and no output schema, the description covers the essential information: what data is retrieved, the meaning of the parameter, and the default. Minor omissions like valid range for days are acceptable for this complexity level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema defines one parameter 'days' with a default of 7, but no schema-level description (0% coverage). The description clarifies the parameter's purpose ('for the last N days') and its default, adding meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'get', the resource 'recovery records', and specifies the data included (score, HRV, resting heart rate). It distinguishes from siblings like get_sleep and get_strain by focusing on recovery readiness.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains recovery's role as a readiness measure, implying use for assessing strain preparation. However, it does not explicitly state when to prefer this tool over alternatives or provide exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sleepA

Get sleep records for the last N days: performance %, stages, duration, and the local bedtime + wake time for each night.

Use this (or daily_summary for just last night) to answer "what time did I wake up / go to bed", "how long was I awake", or sleep-stage questions. days defaults to 7.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, but description implies read-only operation via 'Get'. Lists returned fields but does not explicitly state lack of side effects or other behavioral details. Adequate for a simple retrieval tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, then usage guidance. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Provides enough detail for basic use: what is returned, default parameter. Lacks exact output format but fields are listed. With no output schema and simple params, this is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single parameter 'days' explained with default value 7. Description adds meaning beyond schema (which has no parameter descriptions).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states 'Get sleep records' and specifies scope 'for the last N days'. Distinguishes from sibling daily_summary by noting it covers multiple days vs just last night.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells when to use (for sleep time/quality questions) and mentions alternative (daily_summary for single night). Provides default for days parameter.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_strainB

Get daily strain / cycle data (day strain, avg & max heart rate) for N days.

days defaults to 7. Strain is WHOOP's 0-21 cardiovascular load score.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden for behavioral disclosure. It explains that strain is WHOOP's 0-21 cardiovascular load score and mentions the data includes avg & max heart rate. However, it does not disclose whether the operation is read-only, any rate limits, or constraints on the days parameter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise: two sentences plus a clarifying line. Front-loaded with the tool's action and key data, every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, no output schema), the description covers the basic functionality. However, it lacks details on return format, pagination, or how 'daily strain' is defined relative to the current day. Compared to siblings, it provides enough context for a simple query but not full completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must explain the parameter. It states 'days defaults to 7' and relates it to fetching N days of data, which gives the semantic meaning. However, it does not specify allowed range, units, or whether negative values are allowed, leaving some ambiguity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets daily strain and cycle data, including strain score and heart rate metrics. It uses a specific verb and resource, making the purpose clear. However, it does not differentiate from sibling tools, but the data type (strain) is distinct enough that confusion is unlikely.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives like daily_summary or get_workouts. It does not mention any prerequisites, typical use cases, or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_workoutsA

Get workout activities (sport, strain, avg/max HR, zones) for the last N days.

days defaults to 14. Each workout includes its local start and end time.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description adds value by stating that each workout includes local start and end times, and that the tool returns activity fields like HR zones. It implies a read operation with no destructive effects. While it could mention output format or pagination, it provides sufficient behavioral context for a simple query.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences, front-loaded with the primary purpose, and no extraneous information. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one optional parameter, no output schema), the description covers the core functionality: resource, time scope, and returned fields. It could mention the output format (e.g., array of objects) or sorting, but the provided details are sufficient for an agent to understand usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains that 'days' defines the lookback period and notes the default value of 14, adding meaning beyond the schema's type and default declaration. Could specify constraints (e.g., max value), but the current text is adequate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Get'), the resource ('workout activities'), and specifies the fields included (sport, strain, avg/max HR, zones). It also defines the default time scope ('last N days'), making the tool's purpose specific and distinct from sibling tools which target different health domains.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool (retrieve detailed workout history for a recent period), but does not explicitly state when not to use it or directly compare with alternatives like daily_summary. However, the distinct resource type makes usage obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 7 tool updatesv0.1.0
    • First observeddaily_summary
    • First observedget_body_measurement
    • First observedget_profile
    • First observedget_recovery
    • First observedget_sleep
    • First observedget_strain
    • First observedget_workouts

TDQS

A3.9/5.0
Disambiguation4/5

Each tool targets a distinct data category: profile, body measurements, recovery, sleep, strain, workouts, and a summary snapshot. The daily_summary tool could be confused with the historical get_recovery/get_sleep/get_strain tools, but descriptions clarify (current state vs historical). Overall clear.

Naming Consistency4/5

Six tools follow the consistent 'get_' prefix pattern, while 'daily_summary' deviates. All use snake_case, so the deviation is minor. The naming is generally clear and predictable.

Tool Count5/5

With 7 tools, the server covers the main WHOOP data categories without being overwhelming. Each tool serves a distinct purpose, and the count feels appropriate for a health/fitness API.

Completeness4/5

The server provides read access to core WHOOP metrics: recovery, sleep, strain, workouts, body measurements, profile, and a daily summary. Missing update functionality or fine-grained heart rate data, but for querying it covers the essential domain adequately.

Maintenance

ActivityStale
ResponsivenessNo issues

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

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Gives Claude access to your WHOOP health data including recovery, sleep, workouts, cycles, body measurements, and profile via the WHOOP Developer API.
    7
    14
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Connects your Whoop health data to Claude, enabling natural language queries about recovery, sleep, strain, and workouts.
    163
    MIT

Latest Blog Posts

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/ab75173/whoop-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server