Skip to main content
Glama

list-athlete-clubs

Retrieve the list of clubs an authenticated Strava athlete is a member of using this tool, facilitating access to membership data through the Strava MCP Server.

Instructions

Lists the clubs the authenticated athlete is a member of.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main tool handler implementation for 'list-athlete-clubs', exporting the tool object with name, description, inputSchema (undefined), and the execute function that handles token validation, fetches clubs using the imported helper, formats the output, and handles errors.
    export const listAthleteClubs = { name: "list-athlete-clubs", description: "Lists the clubs the authenticated athlete is a member of.", inputSchema: undefined, 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:74-79 (registration)
    Registration of the 'list-athlete-clubs' tool on the MCP server using the imported tool object.
    server.tool( listAthleteClubs.name, listAthleteClubs.description, {}, listAthleteClubs.execute );
  • Supporting function 'listAthleteClubs' (imported as fetchClubs) that performs the actual Strava API call to /athlete/clubs, validates the response with Zod schema, and handles API errors including 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); }); } }
  • Zod schemas (SummaryClubSchema and StravaClubsResponseSchema) defining the structure of Strava club data, used for response validation in the helper function.
    // Based on https://developers.strava.com/docs/reference/#api-models-SummaryClub const SummaryClubSchema = z.object({ id: z.number().int(), resource_state: z.number().int(), name: z.string(), profile_medium: z.string().url(), cover_photo: z.string().url().nullable(), cover_photo_small: z.string().url().nullable(), sport_type: z.string(), // cycling, running, triathlon, other activity_types: z.array(z.string()), // More specific types city: z.string(), state: z.string(), country: z.string(), private: z.boolean(), member_count: z.number().int(), featured: z.boolean(), verified: z.boolean(), url: z.string().nullable(), }); export type StravaClub = z.infer<typeof SummaryClubSchema>; const StravaClubsResponseSchema = z.array(SummaryClubSchema);

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/r-huijts/strava-mcp'

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