Skip to main content
Glama

Notion-Anki MCP Server

by bakhruhk
generate.py5.67 kB
import os import json import logging from typing import Dict, List, Any, Set from dotenv import load_dotenv from openai import OpenAI # Configure logging logger = logging.getLogger(__name__) load_dotenv() # Validate environment variables openai_api_key = os.getenv("OPENAI_API_KEY") if not openai_api_key: raise ValueError("OPENAI_API_KEY environment variable is required") open_client = OpenAI(api_key=openai_api_key) functions = [ { "name": "generate_anki_notes", "description": "Produce flashcards ready for AnkiConnect addNotes", "parameters": { "type": "object", "properties": { "notes": { "type": "array", "items": { "type": "object", "properties": { "deckName": {"type": "string"}, "modelName": {"type": "string"}, "fields": { "type": "object", "properties": { "Front": {"type": "string"}, "Back": {"type": "string"} }, "required": ["Front","Back"] }, "options": { "type":"object", "properties": {"allowDuplicate": {"type":"boolean"}}, "default": {"allowDuplicate": False} }, "tags": { "type":"array", "items": {"type":"string"}, "default": [] } }, "required": ["deckName","modelName","fields"] } } }, "required": ["notes"] } } ] async def generate_flashcards_gpt(page_name: str, topics: Set[str], content: Dict[str, str]) -> List[Dict[str, Any]]: """ Generates flashcards using the OpenAI Models. Takes page topics and Q&A content, returns structured Anki cards. """ if not page_name or not content: logger.warning("Empty page name or content provided to GPT") return [] logger.info(f"Generating flashcards for {page_name} with {len(content)} Q&A pairs") topics_str = ", ".join(list(topics)) if topics else "general study topics" system = { "role": "system", "content": f""" You are an expert tutor and curriculum designer specializing in {topics_str}. Your job is to take a student's raw Q&A notes (provided as a JSON dict) and: • Refine each question for clarity and focus on core concepts • Correct or enhance answers with accurate, relevant details • Keep language concise and suitable for flashcard study • Ensure questions test understanding, not just memorization Create Anki flashcards by calling the function "generate_anki_notes" with these parameters: - deckName: "{page_name}" - modelName: "Basic" (always use this note type) - fields.Front: refined, clear question - fields.Back: comprehensive but concise answer - options.allowDuplicate: false - tags: [] (empty array) Generate high-quality study cards that will help with long-term retention. """ } user = { "role": "user", "content": f"Topics covered: {topics_str}\n\nStudent's Q&A notes to convert to flashcards:\n{json.dumps(content, indent=2)}" } try: resp = open_client.chat.completions.create( model="gpt-4o-mini", messages=[system, user], functions=functions, function_call={"name": "generate_anki_notes"} ) if not resp.choices or not resp.choices[0].message.function_call: logger.error("No function call received from OpenAI") return [] except Exception as e: logger.error(f"OpenAI API error: {str(e)}") raise try: args = json.loads(resp.choices[0].message.function_call.arguments) notes = args.get("notes", []) if not notes: logger.warning("No notes generated by OpenAI") return [] # Ensure all cards have correct deck name flashcards = enforce_deck_name(notes, page_name) logger.info(f"Generated {len(flashcards)} flashcards") return flashcards except (json.JSONDecodeError, KeyError) as e: logger.error(f"Error parsing OpenAI response: {str(e)}") return [] def enforce_deck_name(cards: List[Dict[str, Any]], correct_deck: str) -> List[Dict[str, Any]]: """ Overwrite every card's deckName with the correct one. This guarantees no stray values get through and validates card structure. """ validated_cards = [] for i, card in enumerate(cards): if not isinstance(card, dict): logger.warning(f"Skipping invalid card at index {i}: not a dict") continue # Ensure required fields exist if 'fields' not in card or 'Front' not in card.get('fields', {}) or 'Back' not in card.get('fields', {}): logger.warning(f"Skipping invalid card at index {i}: missing required fields") continue # Set correct values card['deckName'] = correct_deck card['modelName'] = 'Basic' # Ensure consistent model # Ensure options and tags exist if 'options' not in card: card['options'] = {} card['options']['allowDuplicate'] = False if 'tags' not in card: card['tags'] = [] validated_cards.append(card) logger.info(f"Validated {len(validated_cards)} cards out of {len(cards)}") return validated_cards

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

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