submit_reviews
Submit multiple card reviews to Anki with ratings ('wrong', 'hard', 'good', 'easy'). Streamlines the review process by processing a list of card IDs and their respective ratings efficiently.
Instructions
Submit multiple card reviews to Anki using ratings ('wrong', 'hard', 'good', 'easy').
Args:
reviews: List of review dictionaries, each with:
- card_id (int): The ID of the card reviewed.
- rating (str): 'wrong', 'hard', 'good', or 'easy'.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| reviews | Yes |
Implementation Reference
- mcp_ankiconnect/server.py:369-444 (handler)Main handler function for the 'submit_reviews' tool. Validates input reviews, maps string ratings to Anki ease values using RATING_TO_EASE config, submits batch answers to AnkiConnect, and returns success/failure summary per card.@mcp.tool() @handle_anki_connection_error # Apply decorator async def submit_reviews( reviews: List[Dict[Literal["card_id", "rating"], Union[int, Literal["wrong", "hard", "good", "easy"]]]] ) -> str: """Submit multiple card reviews to Anki using ratings ('wrong', 'hard', 'good', 'easy'). Args: reviews: List of review dictionaries, each with: - card_id (int): The ID of the card reviewed. - rating (str): 'wrong', 'hard', 'good', or 'easy'. """ if not reviews: # Return a message instead of raising ValueError, handled by decorator now return "No reviews provided to submit." answers_to_submit = [] validation_errors = [] for review in reviews: card_id = review.get("card_id") rating = str(review.get("rating", "")).lower() # Ensure lowercase string if not isinstance(card_id, int): validation_errors.append(f"Invalid card_id '{card_id}' in review: {review}. Must be an integer.") continue # Skip this invalid review ease = RATING_TO_EASE.get(rating) if ease is None: valid_ratings = list(RATING_TO_EASE.keys()) validation_errors.append(f"Invalid rating '{rating}' for card_id {card_id}. Must be one of: {valid_ratings}.") continue # Skip this invalid review answers_to_submit.append({"cardId": card_id, "ease": ease}) if validation_errors: # Report validation errors back to the LLM/user errors_str = "\n".join(validation_errors) return f"SYSTEM_ERROR: Could not submit reviews due to validation errors:\n{errors_str}" if not answers_to_submit: return "No valid reviews found to submit after validation." async with get_anki_client() as anki: logger.info(f"Submitting {len(answers_to_submit)} reviews to Anki.") # The 'answerCards' action returns a list of booleans (or similar success indicators) # It might raise an error if the entire batch fails, handled by invoke/decorator results = await anki.answer_cards(answers=answers_to_submit) # Check if the result length matches the input length if len(results) != len(answers_to_submit): logger.warning(f"Anki response length mismatch: Expected {len(answers_to_submit)}, Got {len(results)}") # Handle potential mismatch - maybe return a generic success/fail message # For now, assume results correspond to input order if length matches # Generate response messages based on results (assuming True means success) messages = [] success_count = 0 fail_count = 0 for i, review in enumerate(reviews): # Iterate original reviews to get card_id/rating card_id = review['card_id'] rating = review['rating'] # Check corresponding result if lengths match, otherwise assume failure? success = results[i] if i < len(results) else False # Default to False if mismatch if success: messages.append(f"Card {card_id}: Marked as '{rating}' successfully.") success_count += 1 else: messages.append(f"Card {card_id}: Failed to mark as '{rating}'.") fail_count += 1 summary = f"Review submission summary: {success_count} successful, {fail_count} failed." full_response = summary + "\n" + "\n".join(messages) logger.info(full_response) return full_response
- mcp_ankiconnect/server.py:372-380 (schema)Input schema definition using typing: list of dicts with 'card_id' (int) and 'rating' (one of 'wrong','hard','good','easy'). Docstring elaborates.reviews: List[Dict[Literal["card_id", "rating"], Union[int, Literal["wrong", "hard", "good", "easy"]]]] ) -> str: """Submit multiple card reviews to Anki using ratings ('wrong', 'hard', 'good', 'easy'). Args: reviews: List of review dictionaries, each with: - card_id (int): The ID of the card reviewed. - rating (str): 'wrong', 'hard', 'good', or 'easy'. """
- mcp_ankiconnect/server.py:369-369 (registration)Registers the submit_reviews function as an MCP tool using FastMCP's @mcp.tool() decorator.@mcp.tool()
- mcp_ankiconnect/config.py:25-30 (helper)Configuration mapping string ratings to AnkiConnect ease integers used in submit_reviews validation and submission.RATING_TO_EASE = { "wrong": 1, # Again "hard": 2, # Hard "good": 3, # Good "easy": 4 # Easy }
- Prompt instructions guiding LLM usage of the submit_reviews tool, defining rating semantics.7. After all cards have been reviewed, use the submit_reviews tool to submit the ratings for all cards at once. The rating should be: - "wrong" if the user got the answer completely wrong - "hard" if the user struggled but eventually got it right - "good" if the user got it right. (DEFAULT) - "easy" if the user got it immediately and confidently right, and said it was easy."""