Strava MCP Server
A Model Context Protocol (MCP) server that connects Claude to your Strava account. Ask Claude in natural language to analyze your training, predict race times, compute training loads, or generate a full periodized training plan.
Features
- 13 tools across 5 categories: auth, activities, analysis, prediction, planning
- OAuth2 flow with automatic local callback server — no manual code copying
- VDOT-based training paces (Jack Daniels' Running Formula)
- CTL/ATL/TSB training load metrics (Chronic/Acute Training Load, Training Stress Balance)
- Race time predictions via Riegel formula
- Full periodized training plans (Base → Build → Peak → Taper) with race-specific logic
Requirements
- Node.js ≥ 18
- A Strava account
- Claude Desktop (or any MCP-compatible client)
Setup
1. Create a Strava API application
Go to strava.com/settings/api and create an application.
- Authorization Callback Domain:
localhost
Note your Client ID and Client Secret.
2. Configure environment variables
cp .env.example .env
Edit .env:
STRAVA_CLIENT_ID=your_client_id
STRAVA_CLIENT_SECRET=your_client_secret
STRAVA_REDIRECT_URI=http://localhost:8080/callback
TOKENS_FILE_PATH=./tokens.json
3. Build
npm install
npm run build
4. Configure Claude Desktop
Edit %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"strava": {
"command": "node",
"args": ["C:/path/to/McpStrava/dist/index.js"],
"env": {
"STRAVA_CLIENT_ID": "your_client_id",
"STRAVA_CLIENT_SECRET": "your_client_secret",
"TOKENS_FILE_PATH": "C:/path/to/McpStrava/tokens.json"
}
}
}
}
You can use either
.envor theenvblock in the Claude Desktop config — both work.
5. Authenticate
Restart Claude Desktop, then in a conversation:
- Call
strava_get_auth_url— Claude will return a URL - Open the URL in your browser and authorize the app on Strava
- The page will show "✓ Authentification réussie !" and tokens are saved automatically
Available Tools
Authentication
| Tool | Description |
|---|---|
strava_get_auth_url | Generates the OAuth2 URL and starts the local callback server |
strava_exchange_token | Manual fallback: exchange an auth code for tokens |
strava_auth_status | Check if tokens are valid and when they expire |
Activities
| Tool | Description |
|---|---|
strava_get_activities | List recent activities (Run, Ride, Walk, All) with distance, pace, HR |
strava_get_activity_detail | Full detail for one activity: splits per km, laps, calories |
strava_athlete_stats | Global Strava stats: this week, this year, all-time |
Analysis
| Tool | Description |
|---|---|
strava_analyze_training | Weekly volume breakdown + consistency score |
strava_training_load | CTL (fitness) / ATL (fatigue) / TSB (freshness) via TRIMP |
strava_pace_zones | Distribution across 6 pace zones, 80/20 rule check |
Prediction
| Tool | Description |
|---|---|
strava_predict_race_time | Predict finish times via Riegel formula from a reference effort |
strava_vdot | Compute VDOT score + 5 training pace zones from any race performance |
Training Planning
| Tool | Description |
|---|---|
strava_generate_training_plan | Full periodized plan from today to race day (Base/Build/Peak/Taper) |
strava_weekly_workout | Generate just next week's sessions for a given phase |
Training Plan Details
Phases
| Phase | Focus | Intensity |
|---|---|---|
| Base | Aerobic foundation | Easy runs, long run, strides |
| Build | Lactate threshold | Tempo, easy medium, long run |
| Peak | VO2max + race-specific | Intervals, tempo, long run |
| Taper | Freshness | Reduced volume, maintenance quality |
How volume is calculated
- Starting volume — blend of your 4-week average km and CTL-derived weekly km estimate (robust to injury breaks)
- Peak volume — 1.4× current, with race-specific minimums (5K: 40km, 10K: 50km, Half: 60km, Marathon: 80km)
- Weekly progression — capped at +10% per week to prevent injury
- Recovery weeks — automatic every 4th week within each phase (volume × 0.8)
Race-specific logic
- Marathon (Build & Peak): Long runs include a marathon-pace section (~45% of the run at race pace)
- Taper depth: 5K tapers to 80% of peak volume, Marathon to 40% — shorter races need less recovery
- Intervals: 6 × 1000m for 5K/10K, 5 × 1000m for Half/Marathon
VDOT & pace zones
Based on Jack Daniels' Running Formula. Zones computed as a fraction of VDOT:
| Zone | % of VDOT | Use |
|---|---|---|
| Easy | 65% | Daily runs, long run |
| Marathon | 80% | Marathon-pace sections |
| Threshold | 86% | Tempo runs |
| Interval | 98% | VO2max intervals |
| Repetition | 105% | Speed work / strides |
Generating plans for friends (manual mode)
strava_generate_training_plan supports a manual mode that bypasses Strava entirely. Pass current_weekly_km and goal_time together and no Strava account is needed — useful for generating plans for friends from your own Claude Desktop.
Required parameters
| Parameter | Description | Example |
|---|---|---|
target_race | Race distance | "Marathon" |
race_date | Race date (YYYY-MM-DD) | "2026-10-18" |
goal_time | Target finish time | "3:45:00" |
current_weekly_km | Current weekly mileage | 55 |
Example prompts
Génère un plan marathon pour mon ami, il court 55km par semaine et vise 3h45, la course est le 18 octobre 2026
Mon amie veut courir un semi-marathon en 1h50 le 2026-09-14, elle fait environ 40km par semaine
When both current_weekly_km and goal_time are provided, the tool skips all Strava API calls. The resume in the response will include source_volume: "Fourni manuellement" to confirm which mode was used.
Mode comparison
| Strava mode | Manual mode | |
|---|---|---|
| Strava account needed | Yes | No |
| Volume calibration | 4-week avg + CTL | Value you provide |
| VDOT estimation | From recent activities or goal_time | From goal_time (required) |
| Use case | Your own training | Friends / athletes without Strava |
Development
# Watch mode (no build step needed)
npm run dev
# Build TypeScript
npm run build
# Run built server
npm start
# Clean build artifacts
npm run clean
Project structure
src/
├── index.ts # MCP server entry point
├── config.ts # Env vars, Strava constants, race distances
├── types.ts # Shared TypeScript interfaces
├── auth/
│ ├── oauth.ts # OAuth2 URL builder, token exchange
│ ├── tokenStore.ts # Load/save tokens.json, expiry check
│ ├── callbackServer.ts # Local HTTP server for OAuth redirect
│ └── authTools.ts # MCP auth tools
├── strava/
│ ├── client.ts # Axios instance with auto token refresh
│ ├── activities.ts # Strava activities API
│ ├── athlete.ts # Strava athlete/stats API
│ └── activityTools.ts # MCP activity tools
├── analytics/
│ ├── metrics.ts # Weekly stats, pace zones, consistency score
│ ├── trainingLoad.ts # TRIMP, CTL/ATL/TSB computation
│ └── analysisTools.ts # MCP analysis tools
├── prediction/
│ ├── riegel.ts # Riegel race time prediction formula
│ ├── vdot.ts # VDOT computation, training paces, race equivalents
│ └── predictionTools.ts # MCP prediction tools
└── planning/
├── workouts.ts # Workout templates and distance bounds
├── plan.ts # Plan generation, phase allocation, VDOT estimation
└── planTools.ts # MCP planning tools
Tokens
tokens.json stores your Strava access and refresh tokens. It is in .gitignore — never commit it. Tokens are refreshed automatically when they expire (Strava access tokens last 6 hours).
Example prompts
Strava mode (your own account)
Analyse mes 8 dernières semaines d'entraînement
Quelle serait mon heure sur un marathon si je cours un 10K en 45min ?
Génère-moi un plan d'entraînement pour un semi-marathon le 2026-09-20
Calcule ma charge d'entraînement actuelle et dis-moi si je suis en forme pour une course ce week-end
Montre-moi la répartition de mes allures sur les 4 dernières semaines
Manual mode (friends / no Strava)
Génère un plan marathon pour mon ami, il court 55km par semaine et vise 3h45, la course est le 18 octobre 2026
Mon amie veut courir un semi-marathon en 1h50 le 14 septembre 2026, elle fait 40km par semaine
License
MIT