使用说明
strava-mcp-server
An MCP (Model Context Protocol) server that connects AI agents to the Strava API v3. Built with TypeScript, communicates over stdio.
This lets any MCP-compatible client (Claude Desktop, OpenCode, etc.) fetch your Strava activities, stream data, routes, stats, and more through natural language.
Tools
| Tool | Description |
|---|---|
list_activities |
List recent activities with distance, time, elevation, speed, and heart rate |
get_activity |
Full activity detail including splits, laps, segment efforts, gear, and calories |
get_activity_streams |
Raw time-series data (heart rate, altitude, cadence, power, speed, GPS) |
get_activity_zones |
Heart rate and power zone distribution |
get_route |
Decoded GPS route as coordinate array or GeoJSON |
get_athlete |
Authenticated athlete's profile |
get_athlete_stats |
All-time and recent ride/run/swim totals |
Prerequisites
- Node.js 20+
- A Strava API application (create one here)
- An access token (and optionally refresh token credentials)
Getting Strava tokens
- Create an app at https://www.strava.com/settings/api
- Note your Client ID and Client Secret
- Authorize your app to get an access token and refresh token. The quickest way:
https://www.strava.com/oauth/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=http://localhost&scope=read_all,activity:read_all,profile:read_all
- After authorizing, grab the
codeparameter from the redirect URL and exchange it:
curl -X POST https://www.strava.com/oauth/token \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d code=AUTHORIZATION_CODE \
-d grant_type=authorization_code
This returns access_token, refresh_token, and expires_at.
Setup
git clone https://github.com/JohanBellander/StravaMCP.git
cd StravaMCP
npm install
npm run build
Environment variables
| Variable | Required | Description |
|---|---|---|
STRAVA_ACCESS_TOKEN |
Yes* | Bearer token for Strava API requests |
STRAVA_CLIENT_ID |
No | OAuth2 client ID (enables auto-refresh) |
STRAVA_CLIENT_SECRET |
No | OAuth2 client secret (enables auto-refresh) |
STRAVA_REFRESH_TOKEN |
No | OAuth2 refresh token (enables auto-refresh) |
*If you provide all three OAuth credentials (CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN), the access token will be refreshed automatically when it expires. You can omit STRAVA_ACCESS_TOKEN entirely in that case.
Usage
With OpenCode
Add to your opencode.json:
{
"mcp": {
"strava": {
"type": "local",
"command": ["node", "/path/to/StravaMCP/dist/index.js"],
"environment": {
"STRAVA_ACCESS_TOKEN": "{env:STRAVA_ACCESS_TOKEN}",
"STRAVA_CLIENT_ID": "{env:STRAVA_CLIENT_ID}",
"STRAVA_CLIENT_SECRET": "{env:STRAVA_CLIENT_SECRET}",
"STRAVA_REFRESH_TOKEN": "{env:STRAVA_REFRESH_TOKEN}"
}
}
}
}
With Claude Desktop
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"strava": {
"command": "node",
"args": ["/path/to/StravaMCP/dist/index.js"],
"env": {
"STRAVA_ACCESS_TOKEN": "your-token-here",
"STRAVA_CLIENT_ID": "your-client-id",
"STRAVA_CLIENT_SECRET": "your-client-secret",
"STRAVA_REFRESH_TOKEN": "your-refresh-token"
}
}
}
}
Direct
export STRAVA_ACCESS_TOKEN=your-token-here
node dist/index.js
Tool details
list_activities
List the authenticated athlete's activities.
Parameters:
page(number, default: 1) — Page numberper_page(number, default: 30, max: 200) — Activities per pageafter(number) — Epoch timestamp, only activities after this timebefore(number) — Epoch timestamp, only activities before this time
Returns: Activity summaries with id, name, type, sport_type, start_date, distance (km), moving_time (h:m:s), elapsed_time, elevation gain (m), average/max speed (km/h), average/max heart rate, suffer score.
get_activity
Get full details for a single activity.
Parameters:
id(number, required) — Activity ID
Returns: Everything from list_activities plus splits (metric), laps, segment efforts (name, time, distance, PR rank), gear, calories, description, perceived exertion.
get_activity_streams
Get raw time-series stream data for an activity.
Parameters:
id(number, required) — Activity IDstream_types(string array, default:["time", "distance", "heartrate", "altitude", "cadence", "watts", "velocity_smooth", "latlng"])
Returns: Stream data keyed by type, each with a data array and resolution.
get_activity_zones
Get heart rate and power zone distribution.
Parameters:
id(number, required) — Activity ID
Returns: Zone distributions with time-in-zone breakdowns.
get_route
Get the GPS route for an activity as decoded coordinates.
Parameters:
id(number, required) — Activity IDformat("summary"or"geojson", default:"summary")
Returns:
summary: Array of{lat, lng}coordinates decoded from the summary polylinegeojson: GeoJSON FeatureCollection with a LineString geometry (full-resolution polyline)
get_athlete
Get the authenticated athlete's profile. No parameters.
Returns: id, name, city, state, country, sex, weight, FTP, date_preference, measurement_preference.
get_athlete_stats
Get all-time and recent activity statistics.
Parameters:
id(number, required) — The athlete's Strava ID
Returns: Recent, year-to-date, and all-time totals for rides, runs, and swims (count, distance, moving time, elevation gain). Also includes biggest ride distance and biggest climb elevation.
Rate limits
Strava enforces 100 requests per 15 minutes and 1,000 requests per day. The server tracks usage via the X-RateLimit-Limit and X-RateLimit-Usage response headers and includes warnings in tool responses when usage exceeds 80% of either limit. If you hit the limit, you'll get a clear error message with the current usage and limits.
Project structure
src/
index.ts # MCP server setup, tool registration, stdio transport
strava-client.ts # HTTP client, OAuth2 token refresh, rate limit tracking
tools/
list-activities.ts
get-activity.ts
get-activity-streams.ts
get-activity-zones.ts
get-route.ts
get-athlete.ts
get-athlete-stats.ts
utils/
polyline.ts # Google encoded polyline decoder
formatting.ts # Unit conversions and time formatting
Development
npm run dev # Watch mode — recompiles on changes
npm run build # One-time build
npm start # Run the server
License
MIT