strava-openapi-mcp
Provides tools for interacting with the Strava REST API, enabling agents to read athlete profiles, list and fetch activities, retrieve activity streams and stats, and update activity details, with OAuth authentication and token refresh.
Click on "Install 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., "@strava-openapi-mcplist my last 5 runs with distance and pace"
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.
strava-openapi-mcp
Local Python MCP server acting as a generic proxy between an MCP client—especially OpenCode—and the Strava REST API. Tools are not implemented endpoint by endpoint: they are generated at startup from Strava’s official Swagger 2.0 specification.
The repository contains a copy of the specification and its referenced schema documents. Startup therefore does not require Internet access to build the tool list. The update-spec command refreshes the user copy after validation.
Architecture
openapi.py loads and validates Swagger, resolves local references, and normalizes operations. tools.py transforms each operation into an MCP tool with a generated JSON Schema. client.py builds URLs, parameters, JSON bodies, and multipart forms without knowing Strava endpoints individually. auth.py handles the local OAuth flow and token refresh. server.py exposes everything over MCP stdio, while cli.py provides maintenance commands.
Strava’s currently published specification is Swagger 2.0, with info.version 3.0.0. The bundle is intentionally treated as replaceable data: if a new endpoint appears in the specification, it is discovered automatically.
Related MCP server: MCP OpenAPI Connector
Prerequisites and local installation
Python 3.12+ and uv are recommended.
git clone https://github.com/Arbodgad/strava-openapi-mcp.git
cd strava-openapi-mcp
uv sync
uv run strava-mcp list-toolsStart the MCP server with:
uv run strava-mcpThe server remains active on the MCP stdin/stdout transport. Application logs are sent to stderr. No diagnostic log must be written to stdout during stdio transport.
Create a Strava application
Open
https://www.strava.com/settings/api.Create an application and note its Client ID and Client Secret.
Strava accepts
localhostand127.0.0.1as callback domains. The default callback ishttp://127.0.0.1:8765/callback.
Credentials can be provided through the environment:
export STRAVA_CLIENT_ID="..."
export STRAVA_CLIENT_SECRET="..."Or in ~/.config/strava-mcp/credentials.json with 0600 permissions:
{
"client_id": "...",
"client_secret": "..."
}Environment variables take precedence. The secret is never displayed or written to logs.
OAuth
Run once:
strava-mcp authThe browser opens the Strava authorization page. The local callback exchanges the authorization code for access_token, refresh_token, expires_at, and the granted scopes. Tokens are stored in ~/.config/strava-mcp/tokens.json with 0600 permissions. The server automatically refreshes expired access tokens and persists a rotating refresh token when Strava returns one.
By default, all scopes declared by the specification are requested. To request a subset:
export STRAVA_OAUTH_SCOPES="activity:read,activity:write"Official descriptions are analyzed to infer explicit scopes. Read endpoints accepting either activity:read or activity:read_all are represented as alternatives. A conditional scope—such as activity:read_all for a private activity—is shown to the LLM, and the original Strava error remains visible.
Configuration
Supported variables:
Variable | Default |
| none, or |
| none, or |
|
|
|
|
|
|
|
|
|
|
|
|
| all declared Strava scopes |
|
|
The aliases STRAVA_MCP_ALLOW_WRITE and STRAVA_MCP_ALLOW_DELETE are also accepted. strava-mcp show-config displays only a non-secret configuration view.
The recommended values are STRAVA_ALLOW_WRITE=true and STRAVA_ALLOW_DELETE=false. POST, PUT, and PATCH methods are not blocked by default. DELETE methods are generated when the specification contains them, but filtered from the MCP tool list while STRAVA_ALLOW_DELETE=false.
First startup
export STRAVA_CLIENT_ID="..."
export STRAVA_CLIENT_SECRET="..."
strava-mcp auth
strava-mcp list-tools
strava-mcpThe user specification copy takes precedence. If it does not exist, the bundled official specification is used without downloading anything at startup.
Update the specification
strava-mcp update-specThe command downloads STRAVA_OPENAPI_URL, validates the Swagger document, and then downloads referenced JSON documents. The existing copy is replaced only after the entire download and validation process succeeds. The reported version and number of referenced schemas are displayed.
To force a different path:
STRAVA_OPENAPI_PATH="$HOME/.config/strava-mcp/openapi.json" strava-mcp update-specDirect installation with uvx from Git
The pyproject.toml declares the executable and all dependencies. No manual Python installation or clone is required:
uvx --from git+https://github.com/Arbodgad/strava-openapi-mcp strava-mcp auth
uvx --from git+https://github.com/Arbodgad/strava-openapi-mcp strava-mcpTo immediately use a new commit despite the uv cache:
uvx --refresh --from git+https://github.com/Arbodgad/strava-openapi-mcp strava-mcpOpenCode configuration
Add the server to the OpenCode configuration:
{
"mcp": {
"strava": {
"type": "local",
"command": [
"uvx",
"--from",
"git+https://github.com/Arbodgad/strava-openapi-mcp",
"strava-mcp"
],
"enabled": true
}
}
}Export the variables in the environment that launches OpenCode, or use credentials.json, instead of committing secrets to this file. Run strava-mcp auth once for the same local account before starting OpenCode.
Generated tools and examples
Names are derived from operationId, normalized to snake case, with an HTTP method prefix added only when necessary to avoid ambiguity. For example, with the current specification:
Endpoint | Current generated tool |
|
|
|
|
|
|
|
|
|
|
|
|
The UpdatableActivity body parameters are flattened into the PUT tool. The agent can therefore make conceptually equivalent calls:
put_update_activity_by_id(id=123456789, name="Long Z2 run")
put_update_activity_by_id(id=123456789, description="Easy aerobic endurance session, good sensations.")Other examples of natural-language requests:
“List my latest running activities”: use
get_logged_in_athlete_activities, then filter the returned results.“Read the details of activity 123”: use
get_activity_by_id(id=123).“Get the distance and heartrate streams for 123”: use
get_activity_streams(id=123, keys=["distance", "heartrate"], key_by_type=true).“Get my statistics”: obtain the authenticated athlete, then use
get_stats(id=...).
Pagination is fully controlled by the parameters in the specification (page, per_page, before, after, page_size, after_cursor, and so on). The server never automatically starts a long sequence of page requests.
Writes and dangerous operations
MCP descriptions include This operation modifies Strava data for POST/PUT/PATCH and WARNING for DELETE. If STRAVA_ALLOW_WRITE=false, write tools return an explicit error. If STRAVA_ALLOW_DELETE=false, DELETE tools are absent from list_tools and direct calls are rejected.
HTTP errors preserve the status, endpoint, Strava message, and available rate-limit headers, for example:
HTTP 401 Unauthorized
Endpoint: PUT /activities/{id}
Message: Invalid or expired tokenA 204 response becomes the minimal object { "status": "success", "http_status": 204 }. JSON responses retain Strava field names.
CLI commands
strava-mcp # MCP stdio server
strava-mcp auth # Browser OAuth + localhost callback
strava-mcp update-spec # Validated update of the local copy
strava-mcp show-config # Non-secret configuration
strava-mcp list-tools # Method, endpoint, tool, and summary
strava-mcp list-tools --schemas # Also display each inputSchema JSONlist-tools --schemas is useful for diagnosing an MCP client that rejects a
schema. JSON Schema keywords such as required are displayed at the relevant
schema level; a Strava property named required remains under properties.
Tests and development
uv run pytest
uv run ruff check .Tests use mocked HTTP transports and do not contact Strava. Integration tests against Strava are intentionally not run automatically.
Troubleshooting
No Strava authorization found: runstrava-mcp authwith the correct credentials.OAuth scope missing: runstrava-mcp authagain with the scope requested inSTRAVA_OAUTH_SCOPES.Spec update aborted: the previous local copy remains intact; check the network or remove a customSTRAVA_OPENAPI_PATH.No DELETE tools: this is the default behavior; set
STRAVA_ALLOW_DELETE=trueand restart.MCP error related to stdout: do not add
printcalls to server code; logs must use logging configured for stderr.OAuth port already in use: set
STRAVA_CALLBACK_PORTto an available port and, if necessary, register the localhost domain in the Strava application.
Security
The client secret, access token, and refresh token are never included in logs, MCP descriptions, or error messages. Local credential and token files are ignored by Git and written with 0600 permissions. Never commit .env, credentials.json, or tokens.json.
Maintenance
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
- -licenseNot gradedqualityNot gradedmaintenanceDynamically generates MCP tools from Swagger/OpenAPI specifications by extracting swagger.json files at runtime. Enables natural language interaction with any REST API that has Swagger documentation.
- AlicenseNot gradedqualityDmaintenanceEnables Claude Desktop and other MCP clients to interact with any OAuth2-authenticated OpenAPI-based API through automatic tool generation from OpenAPI specifications, with built-in token management and authentication handling.83MIT
- AlicenseAqualityCmaintenanceParses Swagger 2.0 and OpenAPI 3.x specifications, exposing API endpoints, schemas, and authentication through MCP tools with local caching to reduce token usage.11161MIT
- FlicenseNot gradedqualityBmaintenanceTransforms OpenAPI specs into governed MCP applications with a local-first studio, OAuth, simulation, and Docker deployment.
Related MCP Connectors
MCP server for AI access to Swagger by SmartBear.
Generate a typed SDK, CLI, and MCP server from any OpenAPI or GraphQL spec, and keep them current.
NOAA and ECMWF weather forecast MCP for discovery, validation, and GribStream OAuth queries.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Arbodgad/strava-openapi-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server