get_activity_segments
Retrieves segment efforts for a specific Strava activity by providing the activity ID, enabling analysis of performance across route sections.
Instructions
Get the segments of a specific activity.
Args: ctx: The MCP request context activity_id: The ID of the activity
Returns: List of segment efforts for the activity
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| activity_id | Yes |
Implementation Reference
- strava_mcp/server.py:149-177 (handler)The primary MCP tool handler for 'get_activity_segments'. It is registered via @mcp.tool() decorator and executes the tool logic by calling the service layer.@mcp.tool() async def get_activity_segments( ctx: Context, activity_id: int, ) -> list[dict]: """Get the segments of a specific activity. Args: ctx: The MCP request context activity_id: The ID of the activity Returns: List of segment efforts for the activity """ try: # Safely access service from context if not ctx.request_context.lifespan_context: raise ValueError("Lifespan context not available") # Cast service to StravaService to satisfy type checker service = cast(StravaService, ctx.request_context.lifespan_context.get("service")) if not service: raise ValueError("Service not available in context") segments = await service.get_activity_segments(activity_id) return [segment.model_dump() for segment in segments] except Exception as e: logger.error(f"Error in get_activity_segments tool: {str(e)}") raise
- strava_mcp/models.py:78-98 (schema)Pydantic model defining the structure and validation for SegmentEffort objects, which are returned by the tool after model_dump().class SegmentEffort(BaseModel): """Represents a Strava segment effort.""" id: int = Field(..., description="The unique identifier of the segment effort") activity_id: int = Field(..., description="The ID of the associated activity") segment_id: int = Field(..., description="The ID of the associated segment") name: str = Field(..., description="The name of the segment") elapsed_time: int = Field(..., description="The elapsed time in seconds") moving_time: int = Field(..., description="The moving time in seconds") start_date: datetime = Field(..., description="Start date and time in UTC") start_date_local: datetime = Field(..., description="Start date and time in athlete's timezone") distance: float = Field(..., description="The effort's distance in meters") average_watts: float | None = Field(None, description="Average wattage") device_watts: bool | None = Field(None, description="Whether power data comes from a power meter") average_heartrate: float | None = Field(None, description="Average heartrate") max_heartrate: float | None = Field(None, description="Maximum heartrate") pr_rank: int | None = Field(None, description="Personal record rank (1-3), 0 if not a PR") achievements: list[dict] | None = Field(None, description="List of achievements") athlete: dict = Field(..., description="The athlete who performed the effort") segment: Segment = Field(..., description="The segment")
- strava_mcp/service.py:84-100 (helper)Service layer wrapper that delegates the get_activity_segments call to the underlying StravaAPI instance.async def get_activity_segments(self, activity_id: int) -> list[SegmentEffort]: """Get segments from a specific activity. Args: activity_id: The ID of the activity Returns: List of segment efforts for the activity """ try: logger.info(f"Getting segments for activity {activity_id}") segments = await self.api.get_activity_segments(activity_id) logger.info(f"Retrieved {len(segments)} segments") return segments except Exception as e: logger.error(f"Error getting segments for activity {activity_id}: {str(e)}") raise
- strava_mcp/api.py:208-239 (helper)Core implementation in the API client that fetches the detailed activity, processes raw segment efforts by adding required fields and calculating missing data, then validates into SegmentEffort models.async def get_activity_segments(self, activity_id: int) -> list[SegmentEffort]: """Get segments from a specific activity. Args: activity_id: The ID of the activity Returns: List of segment efforts for the activity """ activity = await self.get_activity(activity_id, include_all_efforts=True) if not activity.segment_efforts: return [] # Add missing required fields before validation segment_efforts = [] for effort in activity.segment_efforts: # Add activity_id which is required by the model effort["activity_id"] = activity_id # Add segment_id which is required by the model effort["segment_id"] = effort["segment"]["id"] # Add total_elevation_gain to the segment if it's missing if "total_elevation_gain" not in effort["segment"]: # Calculate from elevation high and low or set to 0 elev_high = effort["segment"].get("elevation_high", 0) elev_low = effort["segment"].get("elevation_low", 0) effort["segment"]["total_elevation_gain"] = max(0, elev_high - elev_low) segment_efforts.append(SegmentEffort.model_validate(effort)) return segment_efforts