Strava数据管道与MCP服务器

一个本地Strava数据管道和MCP服务器,将Strava活动同步到SQLite数据库并通过模型上下文协议向Claude提供查询功能。

  • by benniblau
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 benniblau/strava-mcp

使用说明

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

  1. 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.

  2. 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:

  1. Go to strava.com/settings/api and create an app
  2. 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
    
  3. 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
    
  4. Copy access_token, refresh_token, and expires_at into .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 flag
  • get_activity_details — full detail for one activity: laps, metric splits, zone distribution, segment efforts
  • get_segment_efforts — your history on any segment (progression over time)
  • get_power_analysis — power stats with FTP estimate
  • get_training_trends — weekly or monthly aggregates for any metric
  • get_gear_stats — distance logged per bike or shoe
  • get_routes — your saved routes
  • execute_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.