内容
# Strava MCP Server
A Model Context Protocol (MCP) server that exposes 20 Strava API tools to Claude. Built with [FastMCP](https://github.com/jlowin/fastmcp).
## Tools
### Athlete
| Tool | Description |
|------|-------------|
| `get_athlete` | Profile: id, name, city, sex, premium status |
| `get_athlete_stats(athlete_id)` | Training totals (recent / YTD / all-time) by sport |
| `get_athlete_zones` | Heart rate and power training zones |
| `get_athlete_shoes` | Gear list with cumulative distance |
### Activities
| Tool | Description |
|------|-------------|
| `list_activities` | Paginated feed with optional date range and sport type filter |
| `get_activity(activity_id)` | Full activity detail: splits, laps, segment efforts |
| `get_activity_laps(activity_id)` | Lap / interval breakdown |
| `get_activity_streams(activity_id)` | Time-series sensor data (HR, power, GPS, cadence, …) |
| `get_activity_zones(activity_id)` | Zone distribution _(requires Strava Summit)_ |
| `update_activity(activity_id)` | Update name, description, trainer, commute, or gear _(requires `activity:write` scope)_ |
### Segments
| Tool | Description |
|------|-------------|
| `get_segment(segment_id)` | Segment details and community stats |
| `list_segment_efforts(segment_id)` | Your efforts on a segment, filterable by date |
| `list_starred_segments` | Your starred segments |
| `get_segment_leaderboard(segment_id)` | Leaderboard with gender / age / weight / date filters |
| `explore_segments(bounds)` | Discover segments within a geographic bounding box |
### Routes
| Tool | Description |
|------|-------------|
| `list_routes` | Your saved routes |
| `get_route(route_id)` | Route detail with segment list |
| `export_route_gpx(route_id)` | Export route as GPX XML |
| `export_route_tcx(route_id)` | Export route as TCX XML |
### Clubs
| Tool | Description |
|------|-------------|
| `list_athlete_clubs` | Clubs you're a member of |
## Setup
### 1. Install dependencies
```bash
cd Strava
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
```
### 2. Create a Strava API application
1. Go to [strava.com/settings/api](https://www.strava.com/settings/api) and create an app.
2. Note your **Client ID** and **Client Secret**.
3. Authorize once to get an access token and refresh token. The easiest way is the [Strava OAuth Playground](https://developers.strava.com/playground/) — request scopes `activity:read_all,profile:read_all`.
### 3. Configure `.env`
```bash
cp .env.example .env # or create from scratch
```
```env
STRAVA_CLIENT_ID=your_client_id
STRAVA_CLIENT_SECRET=your_client_secret
STRAVA_ACCESS_TOKEN=your_initial_access_token
STRAVA_REFRESH_TOKEN=your_refresh_token
```
> **Token rotation note:** Strava rotates the refresh token on every refresh. The server updates both tokens in memory automatically, but does **not** write back to `.env`. If you restart the server more than 6 hours after the last run, the token in `.env` may be stale — re-authorize to get a fresh pair.
### 4. Connect to Claude
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"strava": {
"command": "/path/to/Strava/.venv/bin/fastmcp",
"args": ["run", "/path/to/Strava/strava_server.py"]
}
}
}
```
Then restart Claude Desktop.
## Caveats
- **`get_activity_zones` requires Strava Summit.** Non-subscribers receive a clear 403 error.
- **`get_athlete_shoes` requires `profile:read_all` scope.** Without it the shoes array will be empty.
- **`list_activities` sport type filter is client-side.** The Strava API doesn't support server-side sport type filtering, so `count` may be less than `per_page` after filtering.
- **`get_activity_streams`** only returns streams the device actually recorded — missing stream types are silently omitted by Strava.
- **`update_activity` requires `activity:write` scope.** The default read-only token won't work. Re-authorize via the Strava OAuth flow with `activity:read_all,activity:write` scopes to get a token that can write.
## Enum reference
| Parameter | Tool | Allowed values |
|-----------|------|----------------|
| `gender` | `get_segment_leaderboard` | `"M"`, `"F"` |
| `date_range` | `get_segment_leaderboard` | `"this_year"`, `"this_month"`, `"this_week"`, `"today"` |
| `activity_type` | `explore_segments` | `"riding"`, `"running"` |
| `keys` | `get_activity_streams` | `time`, `distance`, `latlng`, `altitude`, `velocity_smooth`, `heartrate`, `cadence`, `watts`, `temp`, `moving`, `grade_smooth` |