Skip to main content
Glama

strava-server

Two servers over one Strava client:

  • an Express HTTP server that runs the OAuth 2.0 flow and exposes the Strava v3 API as JSON endpoints;

  • an MCP server (stdio) that exposes the same data as tools for an AI agent.

Both share src/strava/* and the same token file, so you authorize once in the browser and the MCP server picks the tokens up automatically.

1. Create a Strava API application

  1. Sign in at https://www.strava.com/settings/api and create an app (a Strava subscription is required).

  2. Set Authorization Callback Domain to localhost.

  3. Copy the Client ID and Client Secret.

New apps start in single-player mode — only your own account can authorize them, which is exactly what this server needs.

Related MCP server: strava-mcp

2. Configure

Copy-Item .env.example .env
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"  # paste into SESSION_SECRET

Fill in STRAVA_CLIENT_ID and STRAVA_CLIENT_SECRET in .env.

.env and .tokens.json are gitignored — never commit them.

3. Run

npm install
npm run dev          # HTTP server, watch mode
# or
npm run build; npm start

Then open http://localhost:3000/auth/login and click Authorize. Strava redirects back to /auth/callback, the server exchanges the one-time code for a refresh token + access token, and persists them to .tokens.json (mode 600). Access tokens expire every 6 hours; the server refreshes them automatically before each request, so you only authorize once.

4. MCP server

npm run mcp          # stdio, via tsx
# or
npm run build; npm run mcp:start

VS Code picks up .vscode/mcp.json automatically — open the Chat view, switch to Agent mode and start the strava server. For other clients:

{
  "mcpServers": {
    "strava": {
      "command": "node",
      "args": ["C:/path/to/stravamcp/dist/mcp/index.js"],
      "env": {
        "STRAVA_CLIENT_ID": "...",
        "STRAVA_CLIENT_SECRET": "..."
      }
    }
  }
}

.env and the token file are resolved relative to the package directory, not the working directory, so the MCP server works no matter where the client launches it from.

Tools

Tool

Strava endpoint

strava_auth_status

Connection state, granted scopes, token expiry

strava_get_athlete_summary

Profile + totals + recent activities in one call

strava_get_athlete

GET /athlete

strava_get_athlete_stats

GET /athletes/{id}/stats

strava_get_athlete_zones

GET /athlete/zones

strava_list_activities

GET /athlete/activities (before/after accept ISO dates)

strava_get_activity

GET /activities/{id}

strava_get_activity_laps

GET /activities/{id}/laps

strava_get_activity_zones

GET /activities/{id}/zones

strava_get_activity_streams

GET /activities/{id}/streams (downsampled to max_points)

strava_get_activity_comments

GET /activities/{id}/comments

strava_get_activity_kudoers

GET /activities/{id}/kudos

strava_list_clubs / strava_get_club

GET /athlete/clubs, GET /clubs/{id}

strava_get_gear

GET /gear/{id}

strava_list_routes / strava_get_route

GET /athletes/{id}/routes, GET /routes/{id}

strava_list_starred_segments / strava_get_segment

GET /segments/starred, GET /segments/{id}

strava_get_rate_limit

Last-seen rate-limit headers

All tools are read-only and annotated as such. Responses that would blow up an agent's context are trimmed by default: segment efforts and full-resolution polylines are opt-in, and streams are evenly downsampled (200 points by default).

If a tool reports "Not connected to Strava", run the HTTP server once and complete /auth/login — the MCP server reads the same .tokens.json.

HTTP endpoints

Auth

Method

Path

Description

GET

/auth/login

Redirect to Strava's consent screen (CSRF-protected via a signed state cookie)

GET

/auth/callback

Code → token exchange

GET

/auth/status

Connection state, granted scope, token expiry

POST

/auth/logout

Deauthorize with Strava and delete the local tokens

Data

Method

Path

Strava endpoint

GET

/api/me

Aggregated profile + totals + last 10 activities (formatted in km/min)

GET

/api/athlete

GET /athlete

GET

/api/athlete/stats

GET /athletes/{id}/stats

GET

/api/athlete/zones

GET /athlete/zones

GET

/api/athlete/clubs

GET /athlete/clubs

GET

/api/athlete/routes

GET /athletes/{id}/routes

GET

/api/activities

GET /athlete/activities (page, per_page, before, after)

GET

/api/activities/:id

GET /activities/{id} (include_all_efforts=true)

GET

/api/activities/:id/laps

GET /activities/{id}/laps

GET

/api/activities/:id/zones

GET /activities/{id}/zones

GET

/api/activities/:id/comments

GET /activities/{id}/comments

GET

/api/activities/:id/kudos

GET /activities/{id}/kudos

GET

/api/activities/:id/streams

GET /activities/{id}/streams (keys=time,distance,heartrate)

GET

/api/clubs/:id

GET /clubs/{id}

GET

/api/gear/:id

GET /gear/{id}

GET

/api/routes/:id

GET /routes/{id}

GET

/api/segments/starred

GET /segments/starred

GET

/api/segments/:id

GET /segments/{id}

GET

/api/rate-limit

Last-seen X-RateLimit-* / X-ReadRateLimit-* values

Example:

curl http://localhost:3000/api/me
curl "http://localhost:3000/api/activities?per_page=50&after=1704067200"
curl "http://localhost:3000/api/activities/123456789/streams?keys=time,heartrate,watts"

Scopes

STRAVA_SCOPE defaults to read,read_all,profile:read_all,activity:read_all:

  • profile:read_all — detailed athlete representation and /athlete/zones

  • activity:read_all — "Only Me" activities, otherwise they are filtered out

  • read_all — private routes and segments

If you change the scope you must re-run /auth/login; /auth/callback reports any scope the athlete declined under missing_scope.

Rate limits

Default limits are 200 requests / 15 min and 2,000 / day. The client records the limit headers from every response; a 429 is surfaced as a JSON error with the current usage. From the MCP server, call strava_get_rate_limit before issuing a burst of requests.

Notes

  • /activities/{id}/zones and /segment_efforts require a Strava subscription.

  • Tokens are stored on disk in plain JSON. Keep the file local; for a multi-user deployment replace src/strava/token-store.ts with an encrypted, per-user store.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that enables interaction with the Strava API v3 to manage fitness activities, athlete profiles, segments, and routes. It supports retrieving detailed performance metrics, exploring geographic data, and managing club information through natural language.
    36
    ISC
  • F
    license
    -
    quality
    D
    maintenance
    MCP server to fetch Strava activities using OAuth authentication with automatic token refresh. Allows retrieving recent activities, activities by date range, activity details, and athlete stats.
  • A
    license
    -
    quality
    C
    maintenance
    MCP server that exposes Strava API v3 data (activities, segments, routes, clubs, gear, streams) as tools for any MCP client. Read-only by default, with an optional --write flag to enable mutating operations.
    18
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

  • MCP server connecting AI agents to non-custodial staking data across 130+ networks.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sivaparthi/stravamcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server