get_keyword
Look up Hearthstone keywords or mechanics to understand their effects and find all cards that use them. Filter results by player class for targeted searches.
Instructions
Look up a Hearthstone keyword or mechanic (e.g., Battlecry, Deathrattle, Discover) and see all cards that have it. Use this to explain what a keyword does or find all cards with a specific mechanic.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Keyword name (e.g. "Deathrattle", "Battlecry") | |
| player_class | No | Filter related cards by class (e.g. MAGE, WARRIOR) |
Implementation Reference
- src/tools/get-keyword.ts:57-122 (handler)The handler function 'getKeyword' which implements the tool logic, including searching for the keyword definition in the database and finding associated cards.
export function getKeyword( db: Database.Database, input: GetKeywordInputType, ): GetKeywordResult { // 1. Look up keyword in keywords table (case-insensitive) const keywordRow = db .prepare('SELECT * FROM keywords WHERE LOWER(name) = LOWER(?)') .get(input.name) as { name: string; description: string; related_keywords: string | null } | undefined; // 2. Find cards that have this keyword in their keywords JSON // The keywords JSON stores mechanics like "BATTLECRY", "TAUNT", etc. // We search case-insensitively by upper-casing the keyword and replacing spaces with underscores const mechanicName = input.name.toUpperCase().replace(/\s+/g, '_'); let cardSql = `SELECT * FROM cards WHERE keywords LIKE ? AND collectible = 1`; const cardParams: unknown[] = [`%${mechanicName}%`]; if (input.player_class) { cardSql += ' AND UPPER(player_class) = UPPER(?)'; cardParams.push(input.player_class); } cardSql += ' ORDER BY name LIMIT 25'; const cardRows = db.prepare(cardSql).all(...cardParams) as CardRow[]; const cards = cardRows.map(toCardSummary); // 3. If keyword found in table, return it with cards if (keywordRow) { return { found: true, keyword: { name: keywordRow.name, description: keywordRow.description, related_keywords: parseJson(keywordRow.related_keywords), }, cards, }; } // 4. If keyword not in table but we found cards with it, still return found if (cards.length > 0) { return { found: true, keyword: { name: input.name, description: `Cards with the ${input.name} mechanic.`, related_keywords: [], }, cards, }; } // 5. Not found — provide suggestions via LIKE match on partial name const suggestions = db .prepare('SELECT name FROM keywords WHERE LOWER(name) LIKE LOWER(?) LIMIT 5') .all(`%${input.name}%`) as Array<{ name: string }>; const suggestionNames = suggestions.map((s) => s.name); return { found: false, message: `No keyword found matching "${input.name}".`, suggestions: suggestionNames.length > 0 ? suggestionNames : undefined, }; } - src/tools/get-keyword.ts:8-14 (schema)Input schema for 'get_keyword' tool, defining the expected 'name' and optional 'player_class' parameters.
export const GetKeywordInput = z.object({ name: z.string().describe('Keyword name (e.g. "Deathrattle", "Battlecry")'), player_class: z .string() .optional() .describe('Filter related cards by class (e.g. MAGE, WARRIOR)'), }); - src/server.ts:110-135 (registration)Registration of the 'get_keyword' tool within the McpServer instance.
// 3. get_keyword server.tool( 'get_keyword', 'Look up a Hearthstone keyword or mechanic (e.g., Battlecry, Deathrattle, Discover) and see all cards that have it. Use this to explain what a keyword does or find all cards with a specific mechanic.', GetKeywordInput.shape, async (params) => { try { const result = getKeyword(db, params); return { content: [ { type: 'text' as const, text: formatGetKeyword(result) }, ], }; } catch (err) { return { content: [ { type: 'text' as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, );