Strava
STDIOMCP server bridging Strava API for fitness data access and activity analysis
MCP server bridging Strava API for fitness data access and activity analysis
This project implements a Model Context Protocol (MCP) server in TypeScript that acts as a bridge to the Strava API. It exposes Strava data and functionalities as "tools" that Large Language Models (LLMs) can utilize through the MCP standard.
Ask your AI assistant questions like these to interact with your Strava data:
Recent Activity & Profile:
Activity Streams & Data:
Stats:
Specific Activities:
Clubs:
Segments:
Segment Efforts:
Routes:
Here's an example of a more advanced prompt to create a professional cycling coach analysis of your Strava activities:
You are Tom Verhaegen, elite cycling coach and mentor to world champion Mathieu van der Poel. Analyze my most recent Strava activity. Provide a thorough, data-driven assessment of the ride, combining both quantitative insights and textual interpretation.
Begin your report with a written summary that highlights key findings and context. Then, bring the raw numbers to life: build an interactive, visually striking dashboard using HTML, CSS, and JavaScript. Use bold, high-contrast colors and intuitive, insightful chart types that best suit each metric (e.g., heart rate, power, cadence, elevation).
Embed clear coaching feedback and personalized training recommendations directly within the visualization. These should be practical, actionable, and grounded solely in the data provided—no assumptions or fabrications.
As a bonus, sprinkle in motivational quotes and cheeky commentary from Mathieu van der Poel himself—he's been watching my rides with one eyebrow raised and a smirk of both concern and amusement.
Goal: Deliver a professional-grade performance analysis that looks and feels like it came straight from the inner circle of world-class cycling.
This prompt creates a personalized analysis of your most recent Strava activity, complete with professional coaching feedback and a custom visualization dashboard.
For successful integration with Claude, follow these steps in exact order:
Skipping steps or performing them out of order may result in environment variables not being properly read by Claude.
Clone Repository:
git clone https://github.com/r-huijts/strava-mcp.git cd strava-mcp
Install Dependencies:
npm install
Build the Project:
npm run build
Update your Claude configuration file:
{ "mcpServers": { "strava-mcp-local": { "command": "node", "args": [ "/absolute/path/to/your/strava-mcp/dist/server.js" ] // Environment variables are read from the .env file by the server } } }
Make sure to replace /absolute/path/to/your/strava-mcp/ with the actual path to your installation.
The setup-auth.ts script makes it easy to set up authentication with the Strava API. Follow these steps carefully:
localhost# In your strava-mcp directory npx tsx scripts/setup-auth.ts
Follow the prompts to complete the authentication flow (detailed instructions in the Authentication section below).
After completing all the above steps, restart Claude Desktop for the changes to take effect. This ensures that:
| Variable | Description | 
|---|---|
| STRAVA_CLIENT_ID | Your Strava Application Client ID (required) | 
| STRAVA_CLIENT_SECRET | Your Strava Application Client Secret (required) | 
| STRAVA_ACCESS_TOKEN | Your Strava API access token (generated during setup) | 
| STRAVA_REFRESH_TOKEN | Your Strava API refresh token (generated during setup) | 
| ROUTE_EXPORT_PATH | Absolute path for saving exported route files (optional) | 
This server implements automatic token refreshing. When the initial access token expires (typically after 6 hours), the server will automatically use the refresh token stored in .env to obtain a new access token and refresh token. These new tokens are then updated in both the running process and the .env file, ensuring continuous operation.
You only need to run the scripts/setup-auth.ts script once for the initial setup.
If you intend to use the export-route-gpx or export-route-tcx tools, you need to specify a directory for saving exported files.
Edit your .env file and add/update the ROUTE_EXPORT_PATH variable:
# Optional: Define an *absolute* path for saving exported route files (GPX/TCX) # Ensure this directory exists and the server process has write permissions. # Example: ROUTE_EXPORT_PATH=/Users/your_username/strava-exports ROUTE_EXPORT_PATH=
Replace the placeholder with the absolute path to your desired export directory. Ensure the directory exists and the server has permission to write to it.
The server exposes the following MCP tools:
get-recent-activitiesFetches the authenticated user's recent activities.
perPage (optional):
numberget-athlete-profileFetches the profile information for the authenticated athlete.
get-athlete-statsFetches activity statistics (recent, YTD, all-time) for the authenticated athlete.
get-activity-detailsFetches detailed information about a specific activity using its ID.
activityId (required):
numberactivityId, Strava API errors.list-athlete-clubsLists the clubs the authenticated athlete is a member of.
list-starred-segmentsLists the segments starred by the authenticated athlete.
get-segmentFetches detailed information about a specific segment using its ID.
segmentId (required):
numbersegmentId, Strava API errors.explore-segmentsSearches for popular segments within a given geographical area (bounding box).
bounds (required):
stringsouth_west_lat,south_west_lng,north_east_lat,north_east_lng.activityType (optional):
string ("running" or "riding")minCat (optional):
number (0-5)activityType: 'riding'.maxCat (optional):
number (0-5)activityType: 'riding'.bounds format, Invalid filter combination, Strava API errors.star-segmentStars or unstars a specific segment for the authenticated athlete.
When to use: When the user explicitly asks to star, favorite, unstar, or unfavorite a specific segment identified by its ID.
Parameters:
segmentId (required):
numberstarred (required):
booleantrue to star, false to unstar.Output: Success message confirming the action and the segment's new starred status.
Errors: Missing/invalid token, Invalid segmentId, Strava API errors (e.g., segment not found, rate limit).
Notes:
profile:write scope for star-ing and unstar-ing segmentsget-segment-effortFetches detailed information about a specific segment effort using its ID.
effortId (required):
numbereffortId, Strava API errors.list-segment-effortsLists the authenticated athlete's efforts on a given segment, optionally filtered by date.
segmentId (required):
numberstartDateLocal (optional):
string (ISO 8601 format)endDateLocal (optional):
string (ISO 8601 format)perPage (optional):
numbersegmentId, Invalid date format, Strava API errors.list-athlete-routesLists the routes created by the authenticated athlete.
page (optional):
numberperPage (optional):
numberget-routeFetches detailed information for a specific route using its ID.
routeId (required):
numberrouteId, Strava API errors.export-route-gpxExports a specific route in GPX format and saves it locally.
ROUTE_EXPORT_PATH environment variable must be correctly configured on the server.routeId (required):
numberROUTE_EXPORT_PATH, File system errors (permissions, disk space), Invalid routeId, Strava API errors.export-route-tcxExports a specific route in TCX format and saves it locally.
ROUTE_EXPORT_PATH environment variable must be correctly configured on the server.routeId (required):
numberROUTE_EXPORT_PATH, File system errors (permissions, disk space), Invalid routeId, Strava API errors.get-activity-streamsRetrieves detailed time-series data streams from a Strava activity, perfect for analyzing workout metrics, visualizing routes, or performing detailed activity analysis.
When to use: When you need detailed time-series data from an activity for:
Parameters:
id (required):
number | stringtypes (optional):
array['time', 'distance', 'heartrate', 'cadence', 'watts']time: Time in seconds from startdistance: Distance in meters from startlatlng: Array of [latitude, longitude] pairsaltitude: Elevation in metersvelocity_smooth: Smoothed speed in meters/secondheartrate: Heart rate in beats per minutecadence: Cadence in revolutions per minutewatts: Power output in wattstemp: Temperature in Celsiusmoving: Boolean indicating if movinggrade_smooth: Road grade as percentageresolution (optional):
string'low' (~100 points), 'medium' (~1000 points), 'high' (~10000 points)series_type (optional):
string'time' or 'distance''distance'page (optional):
numberpoints_per_page (optional):
number-1 returns ALL data points split into multiple messagesOutput Format:
Example Request:
{ "id": 12345678, "types": ["time", "heartrate", "watts", "velocity_smooth", "cadence"], "resolution": "high", "points_per_page": 100, "page": 1 }
Special Features:
Notes:
Errors:
get-activity-lapsRetrieves the laps recorded for a specific Strava activity.
When to use:
Parameters:
id (required):
number | stringOutput Format: A text summary detailing each lap, including:
Example Request:
{ "id": 1234567890 }
Example Response Snippet:
Activity Laps Summary (ID: 1234567890): Lap 1: Warmup Lap Time: 15:02 (Moving: 14:35) Distance: 5.01 km Avg Speed: 20.82 km/h Max Speed: 35.50 km/h Elevation Gain: 50.2 m Avg HR: 135.5 bpm Max HR: 150 bpm Avg Cadence: 85.0 rpm Lap 2: Interval 1 Time: 05:15 (Moving: 05:10) Distance: 2.50 km Avg Speed: 29.03 km/h Max Speed: 42.10 km/h Elevation Gain: 10.1 m Avg HR: 168.2 bpm Max HR: 175 bpm Avg Cadence: 92.1 rpm Avg Power: 280.5 W (Sensor) ...
Notes:
activity:read scope for public/followers activities, activity:read_all for private activities.Errors:
get-athlete-zonesRetrieves the authenticated athlete's configured heart rate and power zones.
**Athlete Zones:** ❤️ **Heart Rate Zones** Custom Zones: No Zone 1: 0 - 115 bpm Zone 2: 115 - 145 bpm Zone 3: 145 - 165 bpm Zone 4: 165 - 180 bpm Zone 5: 180+ bpm ⚡ **Power Zones** Zone 1: 0 - 150 W Zone 2: 151 - 210 W Zone 3: 211 - 250 W Zone 4: 251 - 300 W Zone 5: 301 - 350 W Zone 6: 351 - 420 W Zone 7: 421+ W Time Distribution: - 0-50: 0:24:58 - 50-100: 0:01:02 ... - 450-∞: 0:05:43
profile:read_all scope.profile:read_all scope - 403 error)Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details. (Assuming MIT, update if different)