by r-huijts
Provides LLM‑friendly tools to query and manipulate Strava activity, profile, segment, and route data via the Model Context Protocol.
The server acts as a bridge between the Strava API and Large Language Models, exposing Strava data as MCP tools. LLMs can invoke these tools to retrieve recent activities, athlete stats, segment information, route exports, and detailed activity streams directly in JSON format.
npm install
, and build with npm run build
.setup-auth.ts
script to generate and store access/refresh tokens in a .env
file.server.js
entry point..env
file on refresh.Q: Do I need a Strava Premium account? A: No, a free Strava account works as long as you create an API application and grant the required scopes.
Q: How are tokens managed?
A: The server refreshes the access token automatically using the stored refresh token and writes the new values back to .env
.
Q: What if I want to export routes?
A: Set the ROUTE_EXPORT_PATH
environment variable to an absolute, write‑able directory. The export‑route‑gpx
and export‑route‑tcx
tools will save files there.
Q: Can I run the server on a remote machine?
A: Yes, as long as the LLM can reach the server’s endpoint and the .env
file contains the correct credentials.
Q: Which scopes are required?
A: Basic read scopes (activity:read
, profile:read_all
) for most tools; profile:write
is needed for starring/un‑starring segments.
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-activities
Fetches the authenticated user's recent activities.
perPage
(optional):
number
get-athlete-profile
Fetches the profile information for the authenticated athlete.
get-athlete-stats
Fetches activity statistics (recent, YTD, all-time) for the authenticated athlete.
get-activity-details
Fetches detailed information about a specific activity using its ID.
activityId
(required):
number
activityId
, Strava API errors.list-athlete-clubs
Lists the clubs the authenticated athlete is a member of.
list-starred-segments
Lists the segments starred by the authenticated athlete.
get-segment
Fetches detailed information about a specific segment using its ID.
segmentId
(required):
number
segmentId
, Strava API errors.explore-segments
Searches for popular segments within a given geographical area (bounding box).
bounds
(required):
string
south_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-segment
Stars 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):
number
starred
(required):
boolean
true
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-effort
Fetches detailed information about a specific segment effort using its ID.
effortId
(required):
number
effortId
, Strava API errors.list-segment-efforts
Lists the authenticated athlete's efforts on a given segment, optionally filtered by date.
segmentId
(required):
number
startDateLocal
(optional):
string
(ISO 8601 format)endDateLocal
(optional):
string
(ISO 8601 format)perPage
(optional):
number
segmentId
, Invalid date format, Strava API errors.list-athlete-routes
Lists the routes created by the authenticated athlete.
page
(optional):
number
perPage
(optional):
number
get-route
Fetches detailed information for a specific route using its ID.
routeId
(required):
number
routeId
, Strava API errors.export-route-gpx
Exports a specific route in GPX format and saves it locally.
ROUTE_EXPORT_PATH
environment variable must be correctly configured on the server.routeId
(required):
number
ROUTE_EXPORT_PATH
, File system errors (permissions, disk space), Invalid routeId
, Strava API errors.export-route-tcx
Exports a specific route in TCX format and saves it locally.
ROUTE_EXPORT_PATH
environment variable must be correctly configured on the server.routeId
(required):
number
ROUTE_EXPORT_PATH
, File system errors (permissions, disk space), Invalid routeId
, Strava API errors.get-activity-streams
Retrieves 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 | string
types
(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):
number
points_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-laps
Retrieves the laps recorded for a specific Strava activity.
When to use:
Parameters:
id
(required):
number | string
Output 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-zones
Retrieves 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)
Please log in to share your review and rating for this MCP.
{ "mcpServers": { "strava-mcp": { "command": "node", "args": [ "/absolute/path/to/strava-mcp/dist/server.js" ], "env": { "STRAVA_CLIENT_ID": "<YOUR_CLIENT_ID>", "STRAVA_CLIENT_SECRET": "<YOUR_CLIENT_SECRET>", "STRAVA_ACCESS_TOKEN": "<YOUR_ACCESS_TOKEN>", "STRAVA_REFRESH_TOKEN": "<YOUR_REFRESH_TOKEN>", "ROUTE_EXPORT_PATH": "<ABSOLUTE_EXPORT_DIRECTORY>" } } } }
Explore related MCPs that share similar capabilities and solve comparable challenges
by lharries
Enables searching, reading, and sending personal WhatsApp messages and media through a Model Context Protocol (MCP) server, storing all data locally in SQLite and exposing controlled tools for LLMs like Claude.
by iFurySt
Provides authenticated access to XiaoHongShu (RedNote) notes, supporting keyword search, note retrieval by URL, and cookie persistence via a Model Context Protocol server.
by korotovsky
Provides a powerful Model Context Protocol interface for Slack workspaces, enabling message retrieval, search, and optional posting via Stdio or SSE transports without requiring bot permissions.
by ZubeidHendricks
Provides a standardized interface for interacting with YouTube content, enabling video retrieval, transcript access, channel and playlist management, and advanced analytics through the Model Context Protocol.
by InditexTech
Provides Microsoft Teams integration via the Model Context Protocol, enabling reading, creating, replying to messages and mentioning members.
by chigwell
Provides a full‑featured Telegram integration for MCP‑compatible clients, enabling programmatic access to chats, messages, contacts, profile management, and group administration.
by EnesCinr
Interact with Twitter to post tweets and search tweets programmatically via an MCP server.
by chaindead
Manages Telegram dialogs, messages, drafts, and read statuses via the Model Context Protocol, enabling AI assistants to query and interact with Telegram accounts.
by carterlasalle
Securely interfaces with the macOS Messages database via MCP, enabling LLMs to query, analyze, filter, and send iMessage or SMS communications with built‑in phone number validation, attachment handling, and group chat support.