使用说明
strava-mcp
A local Strava data pipeline and MCP server. Syncs your Strava activities to a SQLite database and exposes everything to Claude via the Model Context Protocol.
What it does
-
strava_downloader.py— fetches your athlete profile, activities (with laps, splits, segment efforts, and HR/power zones), gear, routes, and starred segments from the Strava API and stores them locally in SQLite. Run it as a cron job for incremental daily syncs. -
mcp_server.py— an HTTP streamable MCP server (with bearer token auth) that gives Claude tools to query your Strava data conversationally.
Setup
1. Install dependencies
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
2. Configure credentials
Copy .env.example to .env and fill in your Strava credentials:
cp .env.example .env
You need a Strava API application and an OAuth2 refresh token:
- Go to strava.com/settings/api and create an app
- Authorize your app to get an authorization code:
https://www.strava.com/oauth/authorize?client_id=YOUR_CLIENT_ID &redirect_uri=http://localhost&response_type=code &scope=activity:read_all,profile:read_all - Exchange the code for tokens:
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 - Copy
access_token,refresh_token, andexpires_atinto.env
For the MCP server, generate a bearer token:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
Add it as STRAVA_MCP_AUTH_TOKEN in .env.
3. Sync your data
# First run — last 30 days (fast, to verify everything works)
.venv/bin/python strava_downloader.py --days 30
# Full historical sync (2+ years, respects Strava rate limits automatically)
.venv/bin/python strava_downloader.py
# Fetch laps/zones only for activities that are missing them (cheap catch-up)
.venv/bin/python strava_downloader.py --backfill-detail
# Re-fetch laps/zones for EVERY activity (one API request each — slow)
.venv/bin/python strava_downloader.py --full
The downloader automatically refreshes expired OAuth2 tokens and saves them back to .env.
4. Start the MCP server
.venv/bin/python mcp_server.py
This starts an HTTP server on port 8080 (default). Connect your MCP client with:
{
"mcpServers": {
"strava": {
"url": "http://localhost:8080/mcp/",
"headers": {
"Authorization": "Bearer YOUR_STRAVA_MCP_AUTH_TOKEN"
}
}
}
}
Both /mcp and /mcp/ are accepted — the server rewrites the bare path internally
instead of issuing a redirect, so clients that don't follow redirects (or that drop
the Authorization header when they do) work either way.
For stdio transport (Claude Desktop local):
.venv/bin/python mcp_server.py --transport stdio
Cron job (incremental sync)
Add to your crontab for a daily sync at 6 AM:
0 6 * * * cd /path/to/strava-mcp && .venv/bin/python strava_downloader.py >> /var/log/strava-sync.log 2>&1
Each incremental run picks up from the most recent activity already in the database.
What Claude can query
Resources (snapshot data):
- Athlete profile with lifetime totals
- All activities (with pace, speed, and unit conversions pre-computed)
- Aggregate stats by sport type
- Monthly training trends
- Recent activities (last 30 days)
- Gear / equipment list
Tools (parameterized queries):
query_activities— filter by sport, date range, distance, HR, power, commute flagget_activity_details— full detail for one activity: laps, metric splits, zone distribution, segment effortsget_segment_efforts— your history on any segment (progression over time)get_power_analysis— power stats with FTP estimateget_training_trends— weekly or monthly aggregates for any metricget_gear_stats— distance logged per bike or shoeget_routes— your saved routesexecute_sql— custom SELECT queries against any table
Database schema
SQLite database at ./strava_activities.db (configurable via STRAVA_DB_PATH).
| Table | Contents |
|---|---|
athletes |
Athlete profile + YTD/all-time totals |
activities |
All activities — summary + detail fields |
activity_laps |
Lap splits per activity |
activity_splits_metric |
1 km metric splits per activity |
segment_efforts |
Segment efforts within activities |
segments |
Segment master data |
starred_segments |
Your starred segments |
gear |
Bikes and shoes |
routes |
Saved routes |
activity_zones |
HR/power zone distribution per activity |
activity_summary (view) |
Activities with km, pace, speed pre-computed |
monthly_stats (view) |
Aggregated by month + sport type |
Rate limits
Strava enforces 100 requests per 15 minutes and 1000 per day. The downloader:
- Sleeps 0.6s between activity detail fetches
- Automatically waits for the next 15-minute window on a 429 response
- Retries 5xx errors up to 3 times with back-off
Production deployment (Linux)
sudo useradd --system --shell /usr/sbin/nologin strava-mcp
sudo mkdir -p /opt/strava-mcp
# Copy files, set up venv, create .env
sudo cp deploy/strava-mcp.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now strava-mcp
See deploy/strava-mcp.service for the full systemd unit.