list-starred-segments
Retrieve starred segments for the authenticated user to track and analyze preferred running or cycling routes via the Strava MCP Server.
Instructions
Lists the segments starred by the authenticated athlete.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/listStarredSegments.ts:10-61 (handler)The execute handler implementing the tool's core logic: token validation, fetching athlete data and starred segments, formatting output with measurement preferences, handling errors.execute: async () => { const token = process.env.STRAVA_ACCESS_TOKEN; if (!token || token === 'YOUR_STRAVA_ACCESS_TOKEN_HERE') { console.error("Missing or placeholder STRAVA_ACCESS_TOKEN in .env"); return { content: [{ type: "text" as const, text: "❌ Configuration Error: STRAVA_ACCESS_TOKEN is missing or not set in the .env file." }], isError: true, }; } try { console.error("Fetching starred segments..."); // Need athlete measurement preference for formatting distance const athlete = await getAuthenticatedAthlete(token); // Use renamed import const segments = await fetchSegments(token); console.error(`Successfully fetched ${segments?.length ?? 0} starred segments.`); if (!segments || segments.length === 0) { return { content: [{ type: "text" as const, text: " MNo starred segments found." }] }; } const distanceFactor = athlete.measurement_preference === 'feet' ? 0.000621371 : 0.001; const distanceUnit = athlete.measurement_preference === 'feet' ? 'mi' : 'km'; // Format the segments into a text response const segmentText = segments.map(segment => { const location = [segment.city, segment.state, segment.country].filter(Boolean).join(", ") || 'N/A'; const distance = (segment.distance * distanceFactor).toFixed(2); return ` ⭐ **${segment.name}** (ID: ${segment.id}) - Activity Type: ${segment.activity_type} - Distance: ${distance} ${distanceUnit} - Avg Grade: ${segment.average_grade}% - Location: ${location} - Private: ${segment.private ? 'Yes' : 'No'} `.trim(); }).join("\n---\n"); const responseText = `**Your Starred Segments:**\n\n${segmentText}`; return { content: [{ type: "text" as const, text: responseText }] }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "An unknown error occurred"; console.error("Error in list-starred-segments tool:", errorMessage); return { content: [{ type: "text" as const, text: `❌ API Error: ${errorMessage}` }], isError: true, }; } }
- src/server.ts:80-85 (registration)Registers the 'list-starred-segments' tool on the MCP server by calling server.tool with the imported tool object's name, description, empty input schema object, and execute function.server.tool( listStarredSegments.name, listStarredSegments.description, {}, listStarredSegments.execute );
- src/tools/listStarredSegments.ts:5-9 (schema)Tool object definition specifying the name, description, and inputSchema as undefined (tool takes no parameters).export const listStarredSegments = { name: "list-starred-segments", description: "Lists the segments starred by the authenticated athlete.", // No input schema needed inputSchema: undefined,
- src/stravaClient.ts:736-763 (helper)Strava API client helper function 'listStarredSegments' that fetches starred segments from '/segments/starred' endpoint, validates response with Zod schema, handles authentication errors with token refresh.export async function listStarredSegments(accessToken: string): Promise<StravaSegment[]> { if (!accessToken) { throw new Error("Strava access token is required."); } try { // Strava API uses page/per_page but often defaults reasonably for lists like this. // Add pagination parameters if needed later. const response = await stravaApi.get<unknown>("segments/starred", { headers: { Authorization: `Bearer ${accessToken}` } }); const validationResult = StravaSegmentsResponseSchema.safeParse(response.data); if (!validationResult.success) { console.error("Strava API validation failed (listStarredSegments):", validationResult.error); throw new Error(`Invalid data format received from Strava API: ${validationResult.error.message}`); } return validationResult.data; } catch (error) { return await handleApiError<StravaSegment[]>(error, 'listStarredSegments', async () => { // Use new token from environment after refresh const newToken = process.env.STRAVA_ACCESS_TOKEN!; return listStarredSegments(newToken); }); } }