get_leech_cards
Retrieve cards tagged as leeches from Anki to identify and address difficult-to-memorize items in your flashcard collection.
Instructions
Retrieve cards tagged as leeches from Anki
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| detailed | No | Whether to return detailed card information or just IDs | |
| count | No | Number of random cards to return (defaults to all) |
Implementation Reference
- src/index.ts:579-670 (handler)The primary handler for the 'get_leech_cards' tool. It processes the request parameters (detailed, count), finds leech cards using AnkiConnectClient, selects a random subset if specified, fetches detailed card information if requested, and returns a structured JSON response.private async handleGetLeechCards(request: any) { // Default to detailed = true if not specified const detailed = request.params.arguments?.detailed !== false; // Get the count parameter (optional) const count = typeof request.params.arguments?.count === "number" ? request.params.arguments.count : undefined; // Find all leech cards const allLeechCardIds = await this.ankiClient.findLeechCards(); if (allLeechCardIds.length === 0) { return { content: [ { type: "text", text: "No leech cards found in Anki.", }, ], }; } // Select random subset if count is specified const leechCardIds = count ? this.getRandomCardIds(allLeechCardIds, count) : allLeechCardIds; // Add information about total vs. returned cards const cardCountInfo = count ? `Returning ${leechCardIds.length} random cards out of ${allLeechCardIds.length} total leech cards.` : `Returning all ${leechCardIds.length} leech cards.`; if (!detailed) { // Just return the IDs if detailed=false return { content: [ { type: "text", text: JSON.stringify( { message: cardCountInfo, count: leechCardIds.length, totalLeechCards: allLeechCardIds.length, cardIds: leechCardIds, }, null, 2 ), }, ], }; } // Get detailed information for each selected leech card const cardsInfo = await this.ankiClient.getCardsInfo(leechCardIds); return { content: [ { type: "text", text: JSON.stringify( { message: cardCountInfo, count: cardsInfo.length, totalLeechCards: allLeechCardIds.length, cards: cardsInfo.map((card) => ({ id: card.id, noteId: card.noteId, deck: card.deck, modelName: card.modelName, fields: Object.entries(card.fields).reduce( (acc, [key, field]) => { acc[key] = field.value; return acc; }, {} as Record<string, string> ), tags: card.tags, front: card.front, back: card.back, statistics: card.statistics, })), }, null, 2 ), }, ], }; }
- src/index.ts:482-501 (registration)Registration of the 'get_leech_cards' tool in the MCP server's listTools handler, including name, description, and input schema definition.{ name: "get_leech_cards", description: "Retrieve cards tagged as leeches from Anki", inputSchema: { type: "object", properties: { detailed: { type: "boolean", description: "Whether to return detailed card information or just IDs", }, count: { type: "number", description: "Number of random cards to return (defaults to all)", minimum: 1, }, }, }, },
- src/index.ts:485-500 (schema)Input schema definition for the 'get_leech_cards' tool, specifying optional 'detailed' boolean and 'count' number parameters.inputSchema: { type: "object", properties: { detailed: { type: "boolean", description: "Whether to return detailed card information or just IDs", }, count: { type: "number", description: "Number of random cards to return (defaults to all)", minimum: 1, }, }, },
- src/index.ts:242-250 (helper)Helper method in AnkiConnectClient that finds leech cards by querying AnkiConnect for cards tagged 'leech' excluding those tagged with yesterday's review tag.async findLeechCards(): Promise<number[]> { // Generate yesterday's review tag to exclude const yesterdayTag = this.generateYesterdayReviewedTag(); // Construct query to find leech cards but exclude those with yesterday's review tag return this.request<number[]>("findCards", { query: `tag:leech -tag:${yesterdayTag}`, }); }
- src/index.ts:459-473 (helper)Helper method to randomly select a specified number of card IDs from a list using Fisher-Yates shuffle.private getRandomCardIds(cardIds: number[], count: number): number[] { // If count is greater than or equal to the total number of cards, return all cards if (count >= cardIds.length) { return cardIds; } // Fisher-Yates shuffle and take the first 'count' elements const shuffled = [...cardIds]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } return shuffled.slice(0, count); }