Skip to main content
Glama

FlashCardsMCP

by mtib
main.py7.45 kB
from typing import List from fastmcp import FastMCP import db import openai import os import numpy as np openai.api_key = os.getenv("OPENAI_API_KEY", "sk-...your-key...") mcp = FastMCP( name="FlashCardsMCP", instructions=""" This server provides a flash card management API using the Model Context Protocol (MCP) and FastMCP framework. It supports semantic project and card search using OpenAI embeddings, and allows you to create, search, and retrieve flash card projects and cards. Tools available: - get_all_projects: List all projects (id and name). - add_project: Add a new project (stores name and embedding). - search_project_by_name: Find a project by semantic name search. - get_random_card_by_project: Get a random card from a project. - add_card: Add a card to a project (stores embedding for semantic search). - get_all_cards_by_project: List all cards in a project. - search_cards_by_embedding: Semantic search for cards in a project. - get_card_by_id: Retrieve a card by its id. See README.md for more details. """ ) @mcp.tool def get_all_projects() -> List[dict]: """ List all flash card projects. Returns: List[dict]: A list of all projects, each as a dict with 'id', 'name', and 'type'. Example: >>> get_all_projects() [{'id': 1, 'name': 'Biology', 'type': 'project'}, {'id': 2, 'name': 'Math', 'type': 'project'}] """ projects = [dict(row) for row in db.get_all_projects()] for project in projects: project['type'] = 'project' return projects @mcp.tool def add_project(name: str) -> dict: """ Add a new flash card project. Args: name (str): The name of the project. An OpenAI embedding will be generated for semantic search. Returns: dict: The created project data, including 'type': 'project'. Example: >>> add_project('Physics') {'id': 3, 'name': 'Physics', 'type': 'project'} """ emb = openai.embeddings.create(input=name, model="text-embedding-ada-002") name_embedding = np.array(emb.data[0].embedding, dtype=np.float32).tobytes() project = db.add_project(name, name_embedding) project['type'] = 'project' return project @mcp.tool def search_project_by_name(name: str) -> dict: """ Find a project by semantic name search using OpenAI embeddings. Args: name (str): The project name to search for (semantic match). Returns: dict: The closest matching project data, including 'type': 'project'. Raises: ValueError: If no project is found. Example: >>> search_project_by_name('Biology') {'id': 1, 'name': 'Biology', 'type': 'project'} """ emb = openai.embeddings.create(input=name, model="text-embedding-ada-002") query_emb = np.array(emb.data[0].embedding, dtype=np.float32) pid = db.find_project_id_by_name_embedding(query_emb) if pid is None: raise ValueError("Project not found") # Fetch the project row and add type row = db.get_all_projects() project = next((dict(r) for r in row if r['id'] == pid), None) if not project: raise ValueError("Project not found") project['type'] = 'project' return project @mcp.tool def get_random_card_by_project(project_id: int) -> dict: """ Get a random flash card from a project. Args: project_id (int): The id of the project. Returns: dict: The card data (question, answer, optional hint, optional description, and 'type': 'card'). Raises: ValueError: If no cards are found in the project. """ row = db.get_random_card_by_project(project_id) if not row: raise ValueError("No cards found") card = dict(row) # Remove binary embedding before returning to avoid JSON serialization errors if 'embedding' in card: del card['embedding'] card['type'] = 'card' return card @mcp.tool def add_card(project_id: int, question: str, answer: str, hint: str = None, description: str = None) -> dict: """ Add a flash card to a project. The card's embedding is generated for semantic search. Args: project_id (int): The id of the project. question (str): The card's question. answer (str): The card's answer. hint (str, optional): An optional hint for the card. description (str, optional): An optional description/explanation. Returns: dict: The created card data, including 'type': 'card'. """ emb = openai.embeddings.create( input=question + (hint or "") + answer, model="text-embedding-ada-002" ) embedding = np.array(emb.data[0].embedding, dtype=np.float32).tobytes() card = db.add_card( project_id, question, answer, hint, description, embedding ) card['type'] = 'card' return card @mcp.tool def get_all_cards_by_project(project_id: int) -> list: """ List all cards in a project. Args: project_id (int): The id of the project. Returns: list: A list of card dicts for the project, each including 'type': 'card'. """ cards = [dict(row) for row in db.get_all_cards_by_project(project_id)] for card in cards: if 'embedding' in card: del card['embedding'] card['type'] = 'card' return cards @mcp.tool def search_cards_by_embedding(project_id: int, query: str) -> list: """ Semantic search for cards in a project using OpenAI embeddings. Args: project_id (int): The id of the project. query (str): The search query (semantic match). Returns: list: A list of the most relevant card dicts, each including 'type': 'card'. """ emb = openai.embeddings.create(input=query, model="text-embedding-ada-002") query_emb = np.array(emb.data[0].embedding, dtype=np.float32) results = db.search_cards_by_embedding(project_id, query_emb) for card in results: if 'embedding' in card: del card['embedding'] card['type'] = 'card' return results @mcp.tool def global_search_cards_by_embedding(query: str) -> list: """ Semantic search for cards in all projects using OpenAI embeddings. Args: query (str): The search query (semantic match). Returns: list: A list of the most relevant card dicts, each including 'type': 'card'. """ emb = openai.embeddings.create(input=query, model="text-embedding-ada-002") query_emb = np.array(emb.data[0].embedding, dtype=np.float32) results = db.global_search_cards_by_embedding(query_emb) for card in results: if 'embedding' in card: del card['embedding'] card['type'] = 'card' return results @mcp.tool def get_card_by_id(card_id: int) -> dict: """ Retrieve a card by its id. Args: card_id (int): The id of the card. Returns: dict: The card data, including 'type': 'card'. Raises: ValueError: If the card is not found. """ row = db.get_card_by_id(card_id) if not row: raise ValueError("Card not found") card = dict(row) if 'embedding' in card: del card['embedding'] card['type'] = 'card' return card if __name__ == "__main__": db.init_db() mcp.run(transport="stdio")

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/mtib/flash-cards-mcp'

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