Initial commit: Modularized Strava MCP Server with UV and Hatchling

This commit is contained in:
2026-05-09 01:06:04 +02:00
commit ed43e1928e
21 changed files with 2688 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
from mcp.server.fastmcp import FastMCP
from strava_mcp_server.strava_client import StravaClient
def register(mcp: FastMCP, strava: StravaClient) -> None:
@mcp.tool()
async def list_athlete_clubs():
"""
List clubs that the authenticated athlete belongs to.
Returns club name, sport type, member count, and city.
"""
try:
clubs = await strava.get_athlete_clubs()
return [
{
"id": c.get("id"),
"name": c.get("name"),
"sport_type": c.get("sport_type"),
"city": c.get("city"),
"country": c.get("country"),
"member_count": c.get("member_count"),
"private": c.get("private", False),
}
for c in clubs
]
except Exception as e:
return f"Error fetching clubs: {str(e)}"
@mcp.tool()
async def get_club(club_id: int):
"""
Get detailed information about a specific Strava club.
:param club_id: The numeric ID of the club.
"""
try:
return await strava.get_club(club_id)
except Exception as e:
return f"Error fetching club: {str(e)}"
@mcp.tool()
async def get_club_activities(club_id: int, limit: int = 30):
"""
List recent activities uploaded by members of a specific club.
:param club_id: The numeric ID of the club.
:param limit: Number of activities to return (default 30).
"""
try:
activities = await strava.get_club_activities(club_id, per_page=limit)
return [
{
"name": a.get("name"),
"sport_type": a.get("sport_type") or a.get("type"),
"distance": f"{a.get('distance', 0) / 1000:.2f} km",
"moving_time": f"{a.get('moving_time', 0) / 60:.1f} min",
"total_elevation_gain": f"{a.get('total_elevation_gain', 0):.0f} m",
"athlete": f"{a.get('athlete', {}).get('firstname')} {a.get('athlete', {}).get('lastname')}",
}
for a in activities
]
except Exception as e:
return f"Error fetching club activities: {str(e)}"
@mcp.tool()
async def get_club_members(club_id: int, limit: int = 30):
"""
List members of a specific Strava club.
:param club_id: The numeric ID of the club.
:param limit: Number of members to return (default 30).
"""
try:
members = await strava.get_club_members(club_id, per_page=limit)
return [
{
"id": m.get("id"),
"name": f"{m.get('firstname')} {m.get('lastname')}",
"city": m.get("city"),
"country": m.get("country"),
}
for m in members
]
except Exception as e:
return f"Error fetching club members: {str(e)}"