get_activity_data
Retrieve your top applications and websites by time spent from RescueTime, showing productivity classifications to analyze daily computer usage patterns.
Instructions
Get top activities/applications by time spent.
Args: date_str: Date to query - 'today', 'yesterday', or 'YYYY-MM-DD' limit: Maximum number of activities to show (default: 10)
Shows which specific applications and websites you spent time on, ranked by duration. Includes productivity classification for each.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No | today | |
| limit | No |
Implementation Reference
- src/rescuetime_mcp/server.py:139-190 (handler)The primary handler implementing the logic for the 'get_activity_data' tool. Resolves the input date, retrieves ranked activity data from the RescueTime API via client, formats the top limited activities with productivity indicators, durations, categories, and totals.@mcp.tool() async def get_activity_data(date_str: str = "today", limit: int = 10) -> str: """Get top activities/applications by time spent. Args: date_str: Date to query - 'today', 'yesterday', or 'YYYY-MM-DD' limit: Maximum number of activities to show (default: 10) Shows which specific applications and websites you spent time on, ranked by duration. Includes productivity classification for each. """ try: client = RescueTimeClient() resolved_date = resolve_date(date_str) activities = await client.get_analytic_data( restrict_kind="activity", perspective="rank", restrict_begin=resolved_date, restrict_end=resolved_date, ) if not activities: return f"No activity data for {resolved_date}." lines = [f"Top Activities ({resolved_date}):", ""] for i, act in enumerate(activities[:limit], 1): prod_indicator = { 2: "[++]", 1: "[+ ]", 0: "[ ]", -1: "[ -]", -2: "[--]", }.get(act.productivity, "[??]") duration = format_duration(act.time_seconds) lines.append(f"{i:2}. {prod_indicator} {act.name}") lines.append(f" {duration} | {act.category or 'Uncategorized'}") # Show totals total_seconds = sum(a.time_seconds for a in activities) lines.append("") lines.append(f"Total: {format_duration(total_seconds)} across {len(activities)} activities") return "\n".join(lines) except RescueTimeAuthError as e: return f"Authentication error: {e}" except RescueTimeAPIError as e: return f"API error: {e}"
- src/rescuetime_mcp/server.py:139-139 (registration)FastMCP decorator that registers the get_activity_data function as an MCP tool, inferring schema from signature and docstring.@mcp.tool()
- src/rescuetime_mcp/server.py:36-43 (helper)Utility function used in the handler to convert human-readable date strings ('today', 'yesterday') to ISO date format for API queries.def resolve_date(date_str: str) -> str: """Resolve 'today', 'yesterday', or return as-is.""" if date_str.lower() == "today": return date.today().isoformat() elif date_str.lower() == "yesterday": return (date.today() - timedelta(days=1)).isoformat() return date_str
- src/rescuetime_mcp/client.py:96-144 (helper)RescueTimeClient method called by the handler to fetch and parse raw analytic activity data from the RescueTime API into structured AnalyticDataRow objects.async def get_analytic_data( self, restrict_kind: str = "activity", perspective: str = "rank", resolution_time: str = "day", restrict_begin: Optional[str] = None, restrict_end: Optional[str] = None, interval: Optional[str] = None, ) -> list[AnalyticDataRow]: """Get analytic data from the main data API. Args: restrict_kind: Type of data - 'activity', 'category', 'productivity', 'document' perspective: 'rank' for ranked list, 'interval' for time-based resolution_time: 'month', 'week', 'day', 'hour', 'minute' restrict_begin: Start date (YYYY-MM-DD), defaults to today restrict_end: End date (YYYY-MM-DD), defaults to today interval: For interval perspective - 'hour', 'minute' """ today = date.today().isoformat() params = { "perspective": perspective, "resolution_time": resolution_time, "restrict_kind": restrict_kind, "restrict_begin": restrict_begin or today, "restrict_end": restrict_end or today, } if interval and perspective == "interval": params["interval"] = interval data = await self._request("data", params) if not data or "rows" not in data: return [] rows = [] for row in data["rows"]: rows.append( AnalyticDataRow( rank=row[0], time_seconds=row[1], name=row[3], category=row[4] if len(row) > 4 and row[4] else None, productivity=row[5] if len(row) > 5 else 0, ) ) return rows
- src/rescuetime_mcp/models.py:38-77 (schema)Pydantic model defining the structure and validation for individual activity data rows returned by the API and used in the tool's processing.class AnalyticDataRow(BaseModel): """A single row from the Analytic Data API. The API returns arrays where: - Row 0: Rank (for ranked perspective) - Row 1: Time spent (seconds) - Row 2: Number of people (always 1 for personal) - Row 3: Activity/Category name - Row 4: Category (for activities) or blank - Row 5: Productivity score (-2 to 2) """ rank: int time_seconds: int name: str category: Optional[str] = None productivity: int # -2=very distracting, -1=distracting, 0=neutral, 1=productive, 2=very productive @property def time_hours(self) -> float: """Time in hours.""" return self.time_seconds / 3600 @property def time_minutes(self) -> float: """Time in minutes.""" return self.time_seconds / 60 @property def productivity_label(self) -> str: """Human-readable productivity label.""" labels = { 2: "Very Productive", 1: "Productive", 0: "Neutral", -1: "Distracting", -2: "Very Distracting", } return labels.get(self.productivity, "Unknown")