list-athlete-clubs
Retrieve the clubs a Strava athlete belongs to. This tool displays membership information for the authenticated user.
Instructions
Lists the clubs the authenticated athlete is a member of.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/listAthleteClubs.ts:9-52 (handler)The execute handler implementing the tool logic: validates token, calls the Strava API helper to fetch clubs, formats them nicely, and returns text response or error.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 athlete clubs..."); const clubs = await fetchClubs(token); console.error(`Successfully fetched ${clubs?.length ?? 0} clubs.`); if (!clubs || clubs.length === 0) { return { content: [{ type: "text" as const, text: " MNo clubs found for the athlete." }] }; } const clubText = clubs.map(club => ` š„ **${club.name}** (ID: ${club.id}) - Sport: ${club.sport_type} - Members: ${club.member_count} - Location: ${club.city}, ${club.state}, ${club.country} - Private: ${club.private ? 'Yes' : 'No'} - URL: ${club.url || 'N/A'} `.trim() ).join("\n---\n"); const responseText = `**Your Strava Clubs:**\n\n${clubText}`; 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-athlete-clubs tool:", errorMessage); return { content: [{ type: "text" as const, text: `ā API Error: ${errorMessage}` }], isError: true, }; } } };
- src/server.ts:75-80 (registration)Registers the list-athlete-clubs tool on the MCP server using the imported tool object's properties.server.tool( listAthleteClubs.name, listAthleteClubs.description, {}, listAthleteClubs.execute );
- src/stravaClient.ts:702-727 (helper)The helper function that makes the actual Strava API call to /athlete/clubs, handles validation, errors, and token refresh.export async function listAthleteClubs(accessToken: string): Promise<StravaClub[]> { if (!accessToken) { throw new Error("Strava access token is required."); } try { const response = await stravaApi.get<unknown>("athlete/clubs", { headers: { Authorization: `Bearer ${accessToken}` } }); const validationResult = StravaClubsResponseSchema.safeParse(response.data); if (!validationResult.success) { console.error("Strava API validation failed (listAthleteClubs):", validationResult.error); throw new Error(`Invalid data format received from Strava API: ${validationResult.error.message}`); } return validationResult.data; } catch (error) { return await handleApiError<StravaClub[]>(error, 'listAthleteClubs', async () => { // Use new token from environment after refresh const newToken = process.env.STRAVA_ACCESS_TOKEN!; return listAthleteClubs(newToken); }); } }
- src/tools/listAthleteClubs.ts:8-8 (schema)No input schema defined for this tool (takes no parameters).inputSchema: undefined,