mcp-strava
Read-only access to the user's own Strava data via the Strava API: athlete profile, stats, and heart-rate/power zones; activity summaries and full activity details including laps, zones, and per-second streams (time, distance, position, altitude, speed, heart rate, cadence, power); starred segments, segment details with personal records, and segment efforts; routes, gear with total distance, and clubs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-strava How did Sunday's long run compare with the one the week before?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-strava
A read-only Model Context Protocol server that lets an AI assistant such as Claude read your own Strava data: activities, laps, splits, zones, second-by-second streams, segments, routes, gear and totals. Compatible with Strava.
It runs on your machine, talks to Strava with your own API application, and cannot change anything in your Strava account.
You: How did Sunday's long run compare with the one the week before?
Claude: Sunday's 14.2 km took 1:16:40, a 5:24/km average, 11 seconds per km faster than the
13.8 km the previous Sunday. Your pace held steady until 11 km, then slipped by about
15 seconds per km on the last climb.(An illustrative exchange; the numbers are made up.)
Contents
Related MCP server: Strava MCP Server
Features
Read-only by design. It asks Strava only for read scopes, and apart from the OAuth token exchange every request it makes is a
GET, so no prompt can edit, delete or post anything.14 tools covering the athlete profile, totals, activities and their detail, laps, zones, streams, segments, routes, gear and clubs.
Sized for a model's context window. Activity lists come back as compact summaries with distance in metres, kilometres and miles; map polylines are removed; per-second streams are evenly downsampled (500 points by default) so every stream still lines up point for point.
Signs in once.
mcp-strava authruns the browser OAuth flow and stores the tokens. After that the server refreshes its own access token and saves the rotated refresh token Strava hands back.Errors the model can act on. Strava's own error message, missing-permission hints and rate-limit usage reach the assistant instead of a bare "tool failed".
No secrets in client config. Claude Code and Claude Desktop only need the command to run.
Tools
Tool | Returns |
| Your profile: name, location, weight, FTP, units, bikes, shoes and clubs |
| Recent (4 weeks), year-to-date and all-time ride, run and swim totals |
| Your heart-rate and power zones |
| Compact activity summaries, filtered by |
| Full detail for one activity: splits, laps, calories, device, power; optional best efforts |
| The laps of one activity |
| Time spent in each heart-rate, power or pace zone during one activity |
| Per-second time, distance, position, altitude, speed, heart rate, cadence, power and more |
| Segments you have starred |
| One segment, including your personal record on it |
| Your efforts on one segment, optionally within a date range |
| Routes you created |
| One bike or pair of shoes, with total distance |
| Clubs you belong to |
Every tool is annotated readOnlyHint: true. Units are Strava's: metres, seconds and metres per second.
Requirements
macOS or Linux. Windows is untested.
uv, which also provides Python 3.12 or newer if you do not have it.
A Strava account and an MCP client such as Claude Code or Claude Desktop.
Quick start
1. Create your own Strava API application
Open https://www.strava.com/settings/api and create an application:
Field | Value |
Application Name | Anything that does not contain the word "Strava" (Strava's brand guidelines forbid it) |
Category | Any, e.g. Performance Analysis |
Website | Any URL you own |
Authorization Callback Domain |
|
Keep the page open: the next step asks for its Client ID and Client Secret.
2. Install
uv tool install git+https://github.com/lyzetam/mcp-strava
mcp-strava --versionThis puts an mcp-strava command on your PATH. Upgrade later with uv tool upgrade mcp-strava.
3. Authorize once
mcp-strava authIt asks for the Client ID and Client Secret (the secret is not echoed), opens Strava's consent page in
your browser, and waits for the redirect on http://localhost:8723/callback. Leave every permission box
ticked; the command warns you if one was unticked. The tokens are saved to
~/.config/mcp-strava/tokens.json.
Option | Default | Purpose |
|
| Local port for the OAuth redirect |
|
| How long to wait for you to approve |
| off | Print the authorize URL instead of opening a browser |
You only run this again if you revoke access in Strava or the server tells you to.
4. Connect your MCP client
The server speaks MCP over stdin and stdout and takes no arguments. Desktop apps often start with a
minimal PATH, so give them the absolute path that command -v mcp-strava prints.
Claude Code
claude mcp add --scope user strava -- "$(command -v mcp-strava)"
claude mcp list # strava: ... - ✔ ConnectedClaude Desktop: add the server to claude_desktop_config.json (on macOS in
~/Library/Application Support/Claude/), then restart Claude Desktop:
{
"mcpServers": {
"strava": {
"command": "/Users/you/.local/bin/mcp-strava"
}
}
}Any other MCP client: register a stdio server whose command is the same absolute path.
Then ask something like "How far did I run this month?", "Compare my pace across my last five runs" or "Where did my heart rate drift on Sunday's long ride?"
Configuration
Nothing is required after mcp-strava auth. These environment variables exist for unusual setups:
Variable | Purpose |
| Where the token file lives. Default |
| App credentials, used by |
| A refresh token to start from when the token file has none |
The server re-reads the token file on every request, so re-running mcp-strava auth takes effect
without restarting your MCP client.
Privacy and security
Your data travels between Strava, this process and your MCP client, nowhere else. What the client then sends to its model is governed by that client's data policy.
The token file holds your app's client secret and your tokens. It is written atomically with mode
0600, in a directory created as0700. Treat it like a password.To cut access off completely, revoke the application at https://www.strava.com/settings/apps and delete the token file.
Strava's API Agreement only lets a user's data be shown to that user. This server is built for exactly that: one person, their own API application, their own data. Do not host it for other people.
See SECURITY.md for the security model and how to report a vulnerability, and docs/architecture.md for how the pieces fit together.
Rate limits
A new Strava API application gets 200 requests per 15 minutes and 2,000 per day overall, of which 100
per 15 minutes and 1,000 per day may be reads. The 15-minute window resets at :00, :15, :30 and :45; the
daily one at midnight UTC. When a limit is hit the assistant receives the current usage from Strava's
X-RateLimit-* headers, so it can tell you when to try again. Typical questions use one to five
requests; filtering list_activities by date keeps it that way.
Troubleshooting
Symptom | Cause and fix |
"Strava is not authorized" or "Strava rejected the refresh token" | Access was revoked or never granted. Run |
An error naming | A permission box was unticked during consent. Run |
Heart rate is missing from activities | Strava only shares health data the athlete allowed under Settings → Data Permissions on strava.com. |
"Could not reach Strava" | A network, DNS or proxy problem between your machine and |
| Pick another one: |
The browser shows "This link is from an earlier login attempt" | You reloaded an old redirect. Approve again from the URL the current |
Claude Desktop does not list the server | Use the absolute command path, restart Claude Desktop, and check |
Private activities are missing | They need the |
Development
git clone https://github.com/lyzetam/mcp-strava.git && cd mcp-strava
uv sync
uv run pytest --cov=mcp_strava # tests and coverage
uv run ruff check . && uv run ruff format --check . && uv run mypyTests never touch the network: the Strava API is faked at the HTTP boundary and every tool is called through a real MCP client session. CONTRIBUTING.md explains the workflow and how to add a tool, and CHANGELOG.md lists what changed in each release.
License and trademarks
Released under the MIT License.
Strava is a trademark of Strava, Inc. This project is independent and is not affiliated with, endorsed by or sponsored by Strava. Use of the Strava API is subject to the Strava API Agreement and brand guidelines.
Available Tools
14 toolsget_activityARead-only
Full detail for one activity: description, calories, device, gear, laps, per-km splits (splits_metric), heart rate, power, photos and achievement counts. Map polylines are removed.
Inputs: activity_id (required), include_efforts. Returns: object
get_activity_lapsARead-only
Laps of one activity, with distance, time, speed, heart rate, cadence and power per lap. Useful for interval sessions and races split by lap.
Inputs: activity_id (required). Returns: object
get_activity_streamsARead-only
Second-by-second data recorded during one activity (heart rate, power, cadence, altitude, speed in m/s, position), evenly downsampled so every stream lines up point for point. Use it for pacing, heart-rate drift, or interval analysis. Each stream reports its original_size.
Inputs: activity_id (required), keys, max_points. Returns: object
get_activity_zonesARead-only
Time spent in each heart-rate and power zone during one activity. Strava may require a subscription for this data.
Inputs: activity_id (required). Returns: object
get_athleteARead-only
Profile of the connected athlete: name, location, sex, weight, FTP, measurement preference, and their bikes, shoes and clubs.
Inputs: no named parameters. Returns: object
get_athlete_statsARead-only
Ride, run and swim totals for the connected athlete: recent (last 4 weeks), year-to-date and all-time count, distance, moving time, elapsed time and elevation gain, plus biggest ride and climb. Strava only counts activities whose visibility is Everyone.
Inputs: no named parameters. Returns: object
get_athlete_zonesARead-only
The connected athlete's heart-rate zones (bpm) and power zones (watts).
Inputs: no named parameters. Returns: object
get_gearARead-only
One bike or pair of shoes: brand, model, nickname and total distance in meters. Gear ids (b... for bikes, g... for shoes) appear as gear_id on activities and in get_athlete.
Inputs: gear_id (required). Returns: object
get_segmentARead-only
Detail for one segment: distance, average and max grade, elevation, climb category, location, effort and athlete counts, and the connected athlete's PR (athlete_segment_stats).
Inputs: segment_id (required). Returns: object
list_activitiesARead-only
The connected athlete's activities as compact summaries: sport, start time, distance (m, km, mi),
moving and elapsed time, elevation gain, speed, heart rate, power, cadence, suffer score, kudos.
Strava returns newest first, but oldest first when after is set. more_available is true when
the page came back full, so ask for the next page. Use get_activity for one activity's full detail.
Inputs: page, after, before, per_page. Returns: object
list_clubsBRead-only
Clubs the connected athlete belongs to, with sport type, location and member count.
Inputs: page, per_page. Returns: object
list_routesARead-only
Routes the connected athlete created, with distance, elevation gain, type and estimated time.
Inputs: page, per_page. Returns: object
list_segment_effortsARead-only
The connected athlete's efforts on one segment, with elapsed time, heart rate, power and the activity each came from, so you can track progress on a climb or sprint. Strava may require a subscription for this data.
Inputs: segment_id (required), per_page, end_date_local, start_date_local. Returns: object
list_starred_segmentsARead-only
Segments the connected athlete has starred, with distance, grade, elevation, location and their PR.
Inputs: page, per_page. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Each tool targets a clearly distinct resource and action: athlete summary vs stats vs zones, activity list vs detail vs laps vs zones vs streams, and segment starred list vs detail vs efforts. The descriptions reinforce the boundaries, so an agent can reliably choose the right tool.
All tools use consistent snake_case with predictable get_/list_ verb prefixes followed by the resource name. Nested concepts such as get_activity_zones and list_segment_efforts remain readable and follow the same convention.
The 14 tools are well-scoped for a Strava read/analytics server. Each tool covers a meaningful slice of the domain without excessive surface area.
The surface covers the main read workflows: athlete profile, stats, zones, activities, streams, segments, routes, gear, and clubs. Minor gaps remain, such as no get_route or get_club detail after list_routes/list_clubs, and no activity upload or write operations, but agents can still handle most exploration tasks.
Maintenance
Related MCP Connectors
Your own cycling data for your AI assistant: rides, power, climbs and routes. Read-only.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
tri-train is a training platform for triathletes that syncs activities from Strava and Garmin and exposes them to Claude through a remote MCP server. Ask Claude how your last block went, why your run pace dropped, or whether you are fresh enough for Sunday's race, and it answers from your real data: activities with laps and grade-adjusted pace, weekly load and the performance management chart (CTL/ATL/TSB), sleep, HRV and resting heart rate, and your race calendar with predictions. Claude can also act: create and adjust planned workouts with structured intervals, push them to your Garmin watch, add races and write notes. Every change is journaled and can be undone. Read and write access are separate OAuth scopes, and the server enforces them on every call. Built and hosted in Switzerland by a triathlete; data stays on our own servers (Swiss revDSG / GDPR).
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables interaction with Strava's API to access and manage activities, athlete data, routes, segments, clubs, and gear through natural language.2210 npmMIT
- AlicenseBqualityDmaintenanceIntegrates with the Strava API to allow AI assistants to access fitness data including athlete profiles, activity history, and segment statistics. It enables users to query detailed performance metrics and explore geographic segment data through natural language commands.895 npmMIT
- AlicenseNot gradedqualityCmaintenanceConnects Claude to Strava data for natural language queries about rides, stats, and activities.10 npmMIT
- AlicenseAqualityDmaintenanceConnects Claude to your Strava account so you can query your activities, stats, routes, and segments using natural language.2715 npm1MIT