get_matchup
Analyze matchup dynamics between two Hearthstone archetypes. Learn who is favored, key strategic tensions, and priority actions for each side.
Instructions
Get the theoretical matchup dynamics between two Hearthstone archetypes. Explains who is favoured, why, the key strategic tension, and what each side should prioritise.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| archetype_a | Yes | First archetype name (e.g. "aggro", "control") | |
| archetype_b | Yes | Second archetype name (e.g. "combo", "midrange") |
Implementation Reference
- src/tools/get-matchup.ts:31-72 (handler)The main handler function `getMatchup` that queries the SQLite database for a matchup between two archetypes. Checks both orderings (a vs b and b vs a) for case-insensitive matches. Returns matchup data if found, otherwise suggests available archetypes.
export function getMatchup( db: Database.Database, input: GetMatchupInputType, ): GetMatchupResult { // Check both orderings since the table stores one direction const row = db .prepare( `SELECT * FROM matchup_framework WHERE (LOWER(archetype_a) = LOWER(?) AND LOWER(archetype_b) = LOWER(?)) OR (LOWER(archetype_a) = LOWER(?) AND LOWER(archetype_b) = LOWER(?))`, ) .get(input.archetype_a, input.archetype_b, input.archetype_b, input.archetype_a) as MatchupInfo | undefined; if (row) { return { found: true, matchup: { archetype_a: row.archetype_a, archetype_b: row.archetype_b, favoured: row.favoured, reasoning: row.reasoning, key_tension: row.key_tension, archetype_a_priority: row.archetype_a_priority, archetype_b_priority: row.archetype_b_priority, }, }; } // Not found — suggest available archetypes const archetypes = db .prepare('SELECT DISTINCT archetype_a FROM matchup_framework UNION SELECT DISTINCT archetype_b FROM matchup_framework') .all() as Array<{ archetype_a: string }>; const availableNames = archetypes.map((a) => a.archetype_a); return { found: false, message: `No matchup found for "${input.archetype_a}" vs "${input.archetype_b}".`, suggestions: availableNames.length > 0 ? availableNames : undefined, }; } - src/tools/get-matchup.ts:6-11 (schema)Zod input schema `GetMatchupInput` defining two required string fields: archetype_a and archetype_b.
export const GetMatchupInput = z.object({ archetype_a: z.string().describe('First archetype name (e.g. "aggro", "control")'), archetype_b: z.string().describe('Second archetype name (e.g. "combo", "midrange")'), }); export type GetMatchupInputType = z.infer<typeof GetMatchupInput>; - src/tools/get-matchup.ts:15-27 (schema)Result type definitions: `MatchupInfo` interface for successful matchups, and `GetMatchupResult` discriminated union for found/not-found cases.
export interface MatchupInfo { archetype_a: string; archetype_b: string; favoured: string; reasoning: string; key_tension: string; archetype_a_priority: string; archetype_b_priority: string; } export type GetMatchupResult = | { found: true; matchup: MatchupInfo } | { found: false; message: string; suggestions?: string[] }; - src/server.ts:248-273 (registration)Tool registration on the MCP server using `server.tool('get_matchup', ...)` with description, input schema, and handler that calls getMatchup and formats the result.
// 8. get_matchup server.tool( 'get_matchup', 'Get the theoretical matchup dynamics between two Hearthstone archetypes. Explains who is favoured, why, the key strategic tension, and what each side should prioritise.', GetMatchupInput.shape, async (params) => { try { const result = getMatchup(db, params); return { content: [ { type: 'text' as const, text: formatGetMatchup(result) }, ], }; } catch (err) { return { content: [ { type: 'text' as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, ); - src/format.ts:323-347 (helper)Formatter function `formatGetMatchup` that converts the GetMatchupResult into a human-readable Markdown string for display.
export function formatGetMatchup(result: GetMatchupResult): string { if (!result.found) { let msg = result.message; if (result.suggestions && result.suggestions.length > 0) { msg += '\n\nAvailable archetypes:\n'; msg += result.suggestions.map((s) => `- ${s}`).join('\n'); } return msg; } const m = result.matchup; const lines: string[] = []; lines.push(`## ${m.archetype_a} vs ${m.archetype_b}`); lines.push(''); lines.push(`**Favoured:** ${m.favoured}`); lines.push(''); lines.push(`**Reasoning:** ${m.reasoning}`); lines.push(''); lines.push(`**Key Tension:** ${m.key_tension}`); lines.push(''); lines.push(`**${m.archetype_a} should prioritise:** ${m.archetype_a_priority}`); lines.push(''); lines.push(`**${m.archetype_b} should prioritise:** ${m.archetype_b_priority}`); return lines.join('\n'); }