Pod

Yes, this is on purpose. Pod is built for agents, so the default page is plain HTML.
Human? View the normal website.
Agent? You probably prefer /mcp/strava-mcp-ljcl/issues.md or /mcp/strava-mcp-ljcl/issues.json, or Pod over MCP.

Reported issues for strava-mcp

Pod holds 24 of 145 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to strava-mcp.

Most discussed

spike: external tile fetch through host CSP and free tile-source choice

Summary

Determine whether an MCP App can fetch external map tiles through the host's sandbox/CSP, and choose the free tile source to standardize on.

Area

mcp-app

Motivation

MCP App iframes block external connections by default. The server can declare _meta.ui.csp (connectDomains / resourceDomains), but the host (Claude) must honor those allowlisted origins through its double-iframe sandbox. This is the gating unknown for any basemap. We also need to pick between OpenFreeMap's pu

Read the thread · 2026-06-08 · closed · 2 comments

feat: add Strava webhook (push subscription) support for real-time activity events

Problem

The server can only poll. Strava's Webhook Events API can push create / update / delete events for activities and athlete deauthorizations, enabling real-time reactions (cache invalidation, notifications) without polling and reducing rate-limit pressure.

Current behaviour

No subscription handling exists: no /push_subscriptions calls in apps/server/src/stravaClient.ts, and no webhook callback route in apps/server/src/index.ts.

Proposed approach

  1. Add a public callback

Read the thread · 2026-06-07 · closed · 2 comments

epic: Training analysis — prediction, splits, taper, and the fitness chart

Tracking issue. Four features over the same analysis primitives.

Why these belong together

They share fitnessTrend.ts, hillAnalysis.ts's grade-adjusted pace, and the getBestEfforts scan pattern. One of the pairs is explicit: #267's body already points at the companion view issue.

Ordered batches

1. Companion pair — order matters

Read the thread · 2026-07-26 · closed · 1 comment

epic: Collapse the duplicated formatters

Tracking issue. Two issues filed as explicit companions — the same class of drift on either side of the server/app boundary.

Why these belong together

Each body names the other. They are the same inventory exercise done twice, and the inventory is the expensive part.

Members — either order

Read the thread · 2026-07-26 · closed · 1 comment

epic: MCP protocol surface — schemas, capabilities, end-to-end coverage

Tracking issue. Groups everything the server advertises to a host — input schemas, output schemas, capabilities, notifications — plus the one test that would catch a break in any of them.

Why these belong together

31 of 46 tools return text only, no capability beyond tools/resources/prompts is advertised, and the protocol layer is only partly tested — tools/list is exercised end-to-end but nothing else is. These issues share server.ts's registration surface, tools/outputs.ts, an

Read the thread · 2026-07-26 · closed · 1 comment

chore: collapse the server formatDuration duplicates and the utils.ts split

Context

get-activity-zones formats durations differently from every other tool because four formatDuration variants coexist server-side, one of them commented out with stale breadcrumbs. Nothing catches this class of drift: knip cannot see commented code or a genuinely-imported duplicate. A companion issue covers the same problem across the app packages (formatters into packages/data).

Evidence

Read the thread · 2026-07-25 · closed · 1 comment

refactor: move duplicated clock, date, and duration formatters into @strava-mcp/data

Context

Formatting helpers have drifted into per-app copies with incompatible output. formatClock is implemented twice; a MONTHS array plus UTC short-date helper is duplicated byte-for-byte in two a11y modules with a third near-copy; short durations render three different ways for the same idea (1h 05m, 1h5m, hours). MCP App packages cannot import each other, so packages/data is the only shared home. Issue #216 fixed a pace-rollover bug in one copy only, which is the failure mode th

Read the thread · 2026-07-25 · closed · 1 comment

Reposition strava-mcp as a supplement to the official Strava MCP connector

Summary

Strava has shipped an official MCP connector. It overlaps with our read-only tools but covers only a slice of what this server does. This epic repositions strava-mcp as a supplement to the official connector: we drop the duplicate reads and keep everything the official MCP cannot do.

Docs:

Official connector pro

Read the thread · 2026-06-22 · closed · 1 comment

Most recent

epic: Release and container plumbing — gates that gate, manifests that match

Tracking issue. Groups five open issues across the release pipeline: what gates a merge, what builds the image, and what the registry is told afterwards.

Why these belong together

Four of the five edit .github/workflows/, scripts/setup-branch-protection.sh, or the release manifests, and three of them are the same failure in different places — a step that was designed to gate something and does not.

Read the thread · 2026-08-23 · open · 0 comments

epic: Tool surface consistency — arg names, error handling, output honesty

Tracking issue. Groups four open issues that all rewrite the same tool handler bodies in apps/server/src/tools/.

Why these belong together

The overlap is literal, not thematic. Seven of the eleven tools #354 migrates destructure an id argument that #352 renames:

Tool Today #354 rewrites #352 renames
getSegment.ts execute: async ({ segmentId } catch block :75-88 segmentIdsegment_id
getActivityLaps.ts execute: async ({ id }

Read the thread · 2026-08-23 · open · 0 comments

epic: Request path round two — coalescing, immutability, cached token reads

Tracking issue. Groups three open issues that all finish the same story: one read path that caches instead of re-fetching.

Why these belong together

#355 and #357 rewrite the same five lines. fetchClient.ts:462-466 is the cache-lookup block, ending in return { data: cached as T } — #355 wraps that site in an in-flight promise map so concurrent identical GETs share one upstream call, #357 changes what that same return hands back so a consumer cannot mutate the cached object. Landed sep

Read the thread · 2026-08-23 · open · 0 comments

perf: stop get-activity-photos and get-activity-zones dumping raw JSON into text content

Summary

get-activity-photos and get-activity-zones append a pretty-printed dump of the entire raw Strava response to their text content, then also return the same data as structuredContent. Every successful call pays for both copies, and the raw one is the larger of the two.

Area

server

Motivation

structuredContent + outputSchema is the architecture invariant for tools returning data: the machine-readable copy is the structured payload, the text copy is for a human reading th

Read the thread · 2026-08-23 · open · 0 comments

chore: resolve the stale image identifier committed in server.json

Summary

Committed server.json reads "version": "2.13.2" but packages[0].identifier is still ghcr.io/ljcl/strava-mcp:2.3.0 — release-please only updates $.version, and the real tag is stamped transiently by publish-mcp.yml at publish time, so the committed file drifts ten minor versions behind.

Area

ci-release

Motivation

Anyone reading the repo (or copying the registry reference out of server.json) sees a long-stale image tag. It also makes release-PR diffs misleading — th

Read the thread · 2026-08-22 · open · 0 comments

feat: add a race-prep prompt chaining prediction and taper solving

Summary

prompts.ts ships three prompts (weekly-review, annotate-last-run, segment-hunt). The toolset's most distinctive capability — answering "am I on form for my goal race?" via get-race-prediction plus get-fitness-trend's solved taper — has no guided prompt packaging the sequence.

Area

server

Motivation

Prompts are the discoverability layer for multi-step workflows in Claude Desktop/Code hosts. The race-prep sequence needs real ordering (best efforts → Riegel prediction → fitn

Read the thread · 2026-08-22 · open · 0 comments

docs: correct get-activity-photos' output prose and drop the Output Format sections

Summary

get-activity-photos and get-activity-zones are the only two tools whose descriptions carry an Output Format: section, and both advertise a "complete raw JSON" text dump — get-activity-photos enumerating fields (Source, uploaded_at, "URLs for different sizes") that reach the text branch but are absent from its structuredContent. Their prose is also the wordiest on the surface: get-activity-photos spends 26 lines where comparable tools spend a paragraph.

Area

server

Mo

Read the thread · 2026-08-22 · open · 0 comments

chore: serve /health token status from the in-memory token cache

Summary

getTokenStatus() calls loadTokens() directly instead of reading the in-memory cachedTokens that getStravaToken maintains, so every authed /health or /auth/status poll pays a filesystem read and re-emits the "[TokenManager] Loaded tokens …" stderr line.

Area

server

Motivation

/health backs the Docker HEALTHCHECK and operator dashboards, i.e. it is polled continuously — each poll currently costs a disk read plus log noise that buries real telemetry lines in `doc

Read the thread · 2026-08-22 · open · 0 comments

fix: pin the Docker Bun base image to the packageManager version

Summary

Root package.json declares packageManager: bun@1.3.6 (the single source of truth CI's setup action consumes), while apps/server/Dockerfile hardcodes oven/bun:1.3.14 and oven/bun:1.3.14-distroless — two independent pins of the same runtime that Dependabot bumps separately.

Area

docker

Motivation

The lockfile is resolved by Bun 1.3.6 locally/in CI, but install and production execution happen on 1.3.14 inside the image; dev/test/prod can silently run different Bun ve

Read the thread · 2026-08-22 · open · 0 comments

fix: require the Docker status context branch protection already designs for

Summary

scripts/setup-branch-protection.sh requires only the check status context, while .github/workflows/docker.yml explicitly engineers its changes/build jobs around being a required check on PRs — a required Docker status was clearly intended but never added to the enforced list.

Area

ci-release

Motivation

docker.yml's changes job exists "so that a required Docker status still reports on docs-only PRs — skipped jobs count as passing for required checks". With nothing ac

Read the thread · 2026-08-22 · open · 0 comments

fix: stop the response cache handing out shared mutable references

Summary

On a hit, FetchClient's TtlLruCache returns the exact cached object (return { data: cached as T }), so any consumer that mutates fetched data in place would poison the cache for every later reader within the TTL. No current caller does (the one candidate, get-best-efforts' efforts.sort(), operates on locally-built objects) — this is a latent hazard worth closing before it becomes live.

Area

server

Motivation

The cache exists precisely because activity details/stream

Read the thread · 2026-08-22 · open · 0 comments

fix: route legacy tools' catch blocks through typed error handling

Summary

Eleven tools hand-roll catch-block formatting with fragile string matching (errorMessage.includes("Record Not Found") || includes("404")) instead of using the typed HttpError.status / RateLimitError that handleApiError already preserves, and their conventions have drifted (❌ ${msg}, bare Error: ${msg}, ❌ API Error:).

Area

server

Motivation

Beyond maintenance cost this misreports rate limits to users: in these tools a RateLimitError falls into the generic bra

Read the thread · 2026-08-22 · open · 0 comments

perf: coalesce concurrent identical GETs in fetchClient

Summary

The TTL+LRU cache dedupes sequential repeat reads only. Two concurrent identical GETs both miss and both hit Strava — including the exact view-/get-data pairs the URL-quantization work exists to dedupe, since MCP apps commonly fire both calls together on open.

Area

server

Motivation

WINDOW_QUANTUM_SECONDS quantization was built so an app's two-call pair shares one cache key; under concurrency the second call enters before the first populates the cache and pays full cost a

Read the thread · 2026-08-22 · open · 0 comments

fix: ignore .env.* variants in .gitignore

Summary

.gitignore lists only .env under its environment section, while turbo.json treats .env.local as an expected local file and .dockerignore already excludes .env.* (keeping !.env.example). A contributor-created .env.local would sit untracked and committable with real secrets inside.

Area

repo

Motivation

turbo.json:17 includes .env.local in globalDependencies, signalling it is an anticipated pattern; git add . would stage Strava OAuth client secrets into h

Read the thread · 2026-08-22 · open · 0 comments

refactor!: unify Strava id argument names across tool input schemas

Summary

The same concept — a Strava activity id — is spelled three different ways across the tool surface: get-activity-laps/get-activity-photos/get-activity-zones take id, the analysis and write tools take activityId, and all 18 app-facing view-*/get-*-data tools take activity_id. Segment, route and effort args split the same way: segmentId in get-segment, get-segment-profile, list-segment-efforts and star-segment; routeId in get-route, get-route-preview, export-route-gp

Read the thread · 2026-08-22 · open · 0 comments

fix: escape reflected input in OAuth error pages (XSS in /auth/callback)

Summary

errorPage() interpolates its message argument straight into HTML without escaping, and two call sites pass attacker-controllable text: the Strava error query parameter and caught exception messages.

Area

server

Motivation

The server is documented as publicly reachable (tunnel/reverse-proxy deployments). Anyone can craft /auth/callback?error=<img src=x onerror=...> and send the link to the athlete; the payload executes on the server's origin because the error branch

Read the thread · 2026-08-22 · open · 0 comments

The remaining reports are on the project's issue tracker.