# Health MCP Server
A Model Context Protocol (MCP) server for aggregating and analyzing health and fitness data from multiple sources. Currently supports **Whoop** and **Strava** with an extensible adapter architecture for future integrations (Withings, Oura, Garmin, etc.).
## Features
### Multi-Provider Support
- **Modular Architecture**: Each adapter is optional and independently configurable
- **Auto-Enable**: Adapters are automatically enabled when credentials are configured
- **Unified Auth**: Single OAuth callback server shared across all providers
### Whoop Integration
- **Sleep Analysis**: Track sleep duration, stages (deep, REM, light), efficiency, and consistency
- **Recovery Tracking**: Monitor recovery scores, HRV, resting heart rate, and SpO2
- **Strain Monitoring**: View daily strain, workout history, and heart rate zones
- **Advanced Insights**: Get personalized recommendations, trend analysis, and correlations
### Strava Integration
- **Activity Tracking**: View runs, rides, swims, and all activity types with full stats
- **Performance Metrics**: Distance, pace, speed, elevation, heart rate, power, and cadence
- **Training Zones**: Heart rate and power zone configuration and per-activity distribution
- **Athlete Stats**: All-time totals, year-to-date, and recent activity summaries
- **Gear Tracking**: Monitor distance on bikes, shoes, and other equipment
## Available Tools
### General
| Tool | Description |
|------|-------------|
| `list_adapters` | List all available adapters and their authentication status |
### Whoop Tools
#### Authentication
| Tool | Description |
|------|-------------|
| `whoop_authenticate` | Initiate OAuth2 login flow for Whoop |
| `whoop_check_auth` | Check current authentication status |
#### Profile
| Tool | Description |
|------|-------------|
| `get_user_profile` | Get user profile and body measurements |
#### Sleep
| Tool | Description |
|------|-------------|
| `get_sleep_summary` | Recent sleep with performance, stages, and needs |
| `get_sleep_history` | Sleep history over date range with trends |
#### Recovery
| Tool | Description |
|------|-------------|
| `get_recovery_score` | Latest recovery with HRV and status |
| `get_recovery_history` | Recovery trends over time |
#### Strain & Workouts
| Tool | Description |
|------|-------------|
| `get_strain_today` | Current day strain and heart rate |
| `get_strain_history` | Daily strain patterns over time |
| `get_workout_history` | Workout details with HR zones and calories |
#### Analysis & Insights
| Tool | Description |
|------|-------------|
| `get_health_overview` | Comprehensive health dashboard |
| `analyze_sleep_patterns` | Sleep timing, consistency, and recommendations |
| `analyze_recovery_factors` | Correlations affecting recovery |
| `get_weekly_report` | Week-over-week comparison with trends |
| `get_training_readiness` | Workout intensity recommendations |
### Strava Tools
#### Authentication
| Tool | Description |
|------|-------------|
| `strava_authenticate` | Initiate OAuth2 login flow for Strava |
| `strava_check_auth` | Check current Strava authentication status |
#### Profile & Stats
| Tool | Description |
|------|-------------|
| `get_strava_profile` | Athlete profile with all-time stats and gear |
#### Activities
| Tool | Description |
|------|-------------|
| `get_strava_activities` | Recent activities with distance, pace, HR, etc. |
| `get_strava_activity_detail` | Detailed activity with laps, segments, and full stats |
| `get_strava_weekly_summary` | Weekly training summary by activity type |
#### Training Zones
| Tool | Description |
|------|-------------|
| `get_strava_zones` | Your configured HR and power training zones |
| `get_strava_activity_zones` | Zone distribution for a specific activity |
## Installation
### Prerequisites
- Python 3.10 or higher
- API credentials for at least one provider (Whoop and/or Strava)
### Setup
1. **Clone the repository**
```bash
cd /path/to/health_mcp
```
2. **Create a virtual environment**
```bash
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
3. **Install dependencies**
```bash
pip install -r requirements.txt
```
4. **Configure API credentials**
Copy the example configuration:
```bash
cp config.example.yaml config.yaml
```
Edit `config.yaml` with your API credentials (configure one or both):
```yaml
# Whoop - Get credentials from https://developer.whoop.com/
whoop:
client_id: "your_client_id_here"
client_secret: "your_client_secret_here"
redirect_uri: "http://localhost:8787/callback"
# Strava - Get credentials from https://www.strava.com/settings/api
strava:
client_id: "your_client_id_here"
client_secret: "your_client_secret_here"
redirect_uri: "http://localhost:8787/callback"
```
**Alternative: Environment Variables**
```bash
# Whoop
export HEALTH_MCP_WHOOP_CLIENT_ID="your_client_id"
export HEALTH_MCP_WHOOP_CLIENT_SECRET="your_client_secret"
# Strava
export HEALTH_MCP_STRAVA_CLIENT_ID="your_client_id"
export HEALTH_MCP_STRAVA_CLIENT_SECRET="your_client_secret"
```
### Getting API Credentials
#### Whoop
1. Go to [Whoop Developer Portal](https://developer.whoop.com/)
2. Create a new application
3. Set the redirect URI to `http://localhost:8787/callback`
4. Copy your Client ID and Client Secret
#### Strava
1. Go to [Strava API Settings](https://www.strava.com/settings/api)
2. Create a new application (or use an existing one)
3. Set the "Authorization Callback Domain" to `localhost`
4. Copy your Client ID and Client Secret
## Usage with Claude Desktop
Add the following to your Claude Desktop configuration file:
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"health": {
"command": "/path/to/health_mcp/venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/path/to/health_mcp",
"env": {
"HEALTH_MCP_WHOOP_CLIENT_ID": "your_whoop_client_id",
"HEALTH_MCP_WHOOP_CLIENT_SECRET": "your_whoop_client_secret",
"HEALTH_MCP_STRAVA_CLIENT_ID": "your_strava_client_id",
"HEALTH_MCP_STRAVA_CLIENT_SECRET": "your_strava_client_secret"
}
}
}
}
```
## Usage with Cursor
Add the following to your Cursor MCP settings:
```json
{
"mcpServers": {
"health": {
"command": "/path/to/health_mcp/venv/bin/python",
"args": ["-m", "src.server"],
"cwd": "/path/to/health_mcp"
}
}
}
```
## First-Time Authentication
After setting up the MCP server, authenticate with each provider you've configured:
### Whoop
1. Ask the AI: "Authenticate with my Whoop account"
2. A browser window will open for OAuth authorization
3. Log in and authorize the application
4. The token is automatically saved
### Strava
1. Ask the AI: "Authenticate with my Strava account"
2. A browser window will open for Strava OAuth
3. Authorize the requested permissions
4. The token is automatically saved
You can check which adapters are available and authenticated by asking: "List my health adapters"
## Example Questions
### Whoop-Specific
- "How did I sleep last night?"
- "What's my recovery score today?"
- "Show me my sleep trends for the past month"
- "Am I ready for a hard workout today?"
- "What factors are affecting my recovery?"
### Strava-Specific
- "Show me my recent Strava activities"
- "What's my weekly training summary?"
- "Show me details for my last run"
- "What are my training zones?"
- "How much have I cycled this year?"
### Combined Analysis (when both are connected)
- "Compare my workout strain from Whoop with my Strava activities"
- "Show me my overall fitness status"
- "How does my training load look across all sources?"
## Project Structure
```
health_mcp/
├── src/
│ ├── __init__.py
│ ├── server.py # Main MCP server with dynamic adapter loading
│ ├── config.py # Configuration management
│ ├── auth/
│ │ ├── __init__.py
│ │ ├── oauth_server.py # Shared OAuth callback server
│ │ └── token_store.py # Token persistence
│ ├── adapters/
│ │ ├── __init__.py
│ │ ├── base.py # Abstract adapter interface
│ │ ├── whoop.py # Whoop API adapter
│ │ └── strava.py # Strava API adapter
│ └── tools/
│ ├── __init__.py
│ ├── sleep.py # Whoop sleep tools
│ ├── recovery.py # Whoop recovery tools
│ ├── strain.py # Whoop strain & workout tools
│ ├── profile.py # Whoop profile tools
│ ├── insights.py # Whoop analysis tools
│ └── strava.py # Strava-specific tools
├── config.example.yaml
├── requirements.txt
└── README.md
```
## Adapter Architecture
The server uses a modular adapter pattern:
- **Optional Adapters**: Each adapter is optional and independently enabled
- **Auto-Discovery**: Adapters are automatically enabled when credentials are present
- **Explicit Control**: Use `enabled: true/false` in config to override auto-detection
- **Unified Interface**: All adapters implement a common base class for consistency
- **Provider-Specific Tools**: Each adapter can expose unique tools for provider-specific features
### Configuration Options
```yaml
# Each adapter section supports:
provider_name:
client_id: "..."
client_secret: "..."
redirect_uri: "http://localhost:8787/callback"
enabled: true # Optional: explicitly enable/disable (auto-detected by default)
```
## Extending with New Adapters
To add a new health data provider:
1. Create a new adapter in `src/adapters/` implementing the `HealthAdapter` base class
2. Add configuration properties in `src/config.py`
3. Create provider-specific tools in `src/tools/`
4. Register the adapter and tools in `src/server.py`
Example adapter skeleton:
```python
from .base import HealthAdapter, SleepRecord, RecoveryRecord, WorkoutRecord
class NewProviderAdapter(HealthAdapter):
provider_name = "new_provider"
async def is_authenticated(self) -> bool:
# Check auth status
pass
async def authenticate(self) -> bool:
# Initiate OAuth flow
pass
async def get_workouts(self, start=None, end=None, limit=10) -> list[WorkoutRecord]:
# Implement workout data fetching
pass
# Implement other methods (return empty lists for unsupported features)
```
## Token Storage
OAuth tokens are stored securely at `~/.health_mcp/tokens.json` with restricted file permissions (600). Tokens are automatically refreshed when expired.
## Troubleshooting
### "Not authenticated" errors
Run the appropriate authenticate tool:
- Whoop: `whoop_authenticate`
- Strava: `strava_authenticate`
### "Missing configuration" errors
Ensure your `config.yaml` is set up correctly or environment variables are exported.
### OAuth callback fails
- Ensure port 8787 is available
- Check that your redirect URI matches exactly in the provider's developer portal
- For Strava, ensure the Authorization Callback Domain is set to `localhost`
### Token refresh fails
Delete `~/.health_mcp/tokens.json` and re-authenticate.
### Adapter not showing up
- Check that credentials are configured correctly
- Use `list_adapters` tool to see adapter status
- Check server logs for initialization errors
## License
MIT License
## Contributing
Contributions are welcome! Please feel free to submit pull requests for:
- New health data adapters (Withings, Oura, Garmin, Apple Health, etc.)
- Additional analysis tools
- Bug fixes and improvements