Skip to main content
Glama
get_review_stats.py3.21 kB
import mcp.types as types from datetime import datetime, timedelta from typing import Optional from .utils import make_anki_request # Time range to days mapping TIME_RANGES = { "day": 0, "week": 7, "month": 30, "year": 365, "all": None } async def get_review_stats(time_range: str = "month") -> list[types.TextContent]: """ Get review statistics from Anki showing cards reviewed per day. Parameters: - time_range: Time range for statistics ("day", "week", "month", "year", "all") """ # Validate and calculate cutoff date try: cutoff_date = _get_cutoff_date(time_range) except ValueError as e: return _error_response(str(e)) # Fetch review data from Anki review_result = await make_anki_request("getNumCardsReviewedByDay") if not review_result["success"]: return _error_response(f"Failed to retrieve review statistics: {review_result['error']}") # Filter and format the results review_data = review_result["result"] filtered_data = _filter_by_date(review_data, cutoff_date) formatted_text = _format_review_data(filtered_data) return [types.TextContent(type="text", text=formatted_text)] def _get_cutoff_date(time_range: str) -> Optional[datetime.date]: """ Calculate the cutoff date based on time range. Args: time_range: The time range identifier Returns: datetime.date for filtered ranges, or None for "all" (no filtering) Raises: ValueError: If time_range is not a valid option """ if time_range not in TIME_RANGES: valid_options = ', '.join(TIME_RANGES.keys()) raise ValueError(f"Invalid time_range '{time_range}'. Valid options: {valid_options}") days = TIME_RANGES[time_range] if days is None: return None today = datetime.now().date() return today if days == 0 else today - timedelta(days=days) def _filter_by_date(review_data: list, cutoff_date: Optional[datetime.date]) -> list: """Filter review data by cutoff date.""" if cutoff_date is None: return review_data return [ (date_str, count) for date_str, count in review_data if _parse_date(date_str) >= cutoff_date ] def _format_review_data(filtered_data: list) -> str: """Format filtered review data into readable text.""" if not filtered_data: return "No reviews found for the specified time range." total_cards = sum(count for _, count in filtered_data) formatted_lines = [f" {date_str}: {count} cards" for date_str, count in filtered_data] header = f"Cards reviewed ({len(filtered_data)} days, {total_cards} total reviews):\n" return header + "\n".join(formatted_lines) def _error_response(message: str) -> list[types.TextContent]: """Create an error response.""" return [types.TextContent(type="text", text=message)] def _parse_date(date_str: str) -> datetime.date: """Parse date string from Anki format to date object.""" try: return datetime.strptime(date_str, "%Y-%m-%d").date() except ValueError: # If parsing fails, return a very old date so it gets filtered out return datetime(1900, 1, 1).date()

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/johwiebe/anki-mcp'

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