check_legality
Verify card legality in MTG formats. Input one card name or up to 50 to see if they are legal, banned, or restricted in Commander, Modern, Standard, Legacy, Vintage.
Instructions
Check which formats a card (or multiple cards) is legal in. Use this when a user wants to know if a card is legal, banned, or restricted in formats like Commander, Modern, Standard, Legacy, or Vintage. Accepts a single card name or an array of up to 50 card names.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| cards | Yes | Card name or array of card names (max 50) | |
| format | No | Specific format to check (e.g., "commander", "modern"). Omit for all formats. |
Implementation Reference
- src/tools/check-legality.ts:42-97 (handler)The core handler function that checks card legality. It accepts a card name (or array of names) and an optional format, queries the database for matching cards and their legalities, and returns a structured result.
export function handler(db: Database.Database, params: CheckLegalityParams): CheckLegalityResult { const cardNames = Array.isArray(params.cards) ? params.cards : [params.cards]; const resolvedFormat = params.format ? resolveFormat(params.format) : null; const results: CardLegality[] = []; for (const name of cardNames) { // Case-insensitive exact match, then LIKE fallback let card = db.prepare( 'SELECT * FROM cards WHERE LOWER(name) = LOWER(?)' ).get(name) as CardRow | undefined; if (!card) { card = db.prepare( 'SELECT * FROM cards WHERE LOWER(name) LIKE LOWER(?)' ).get(`%${name}%`) as CardRow | undefined; } if (!card) { results.push({ card_name: name, found: false, legalities: {}, message: `Card not found: "${name}"`, }); continue; } let rows: LegalityRow[]; if (resolvedFormat) { rows = db.prepare( 'SELECT * FROM legalities WHERE card_id = ? AND format = ?' ).all(card.id, resolvedFormat) as LegalityRow[]; } else { rows = db.prepare( 'SELECT * FROM legalities WHERE card_id = ?' ).all(card.id) as LegalityRow[]; } const legalities: Record<string, string> = {}; for (const row of rows) { legalities[row.format] = row.status; } results.push({ card_name: card.name, found: true, legalities, }); } return { format: resolvedFormat, results, }; } - src/tools/check-legality.ts:7-10 (schema)Zod input schema for check_legality: accepts a string or array of up to 50 card names, and an optional format parameter.
export const CheckLegalityInput = z.object({ cards: z.union([z.string(), z.array(z.string()).max(50)]).describe('Card name or array of card names (max 50)'), format: z.string().optional().describe('Specific format to check (e.g., "commander", "modern"). Omit for all formats.'), }); - src/tools/check-legality.ts:28-38 (schema)Output type definitions: CardLegality (per-card results) and CheckLegalityResult (overall format + results array).
export interface CardLegality { card_name: string; found: boolean; legalities: Record<string, string>; message?: string; } export interface CheckLegalityResult { format: string | null; results: CardLegality[]; } - src/server.ts:121-133 (registration)Tool registration in the MCP server using server.tool() with name 'check_legality', description, input schema, and handler invocation.
server.tool( 'check_legality', 'Check which formats a card (or multiple cards) is legal in. Use this when a user wants to know if a card is legal, banned, or restricted in formats like Commander, Modern, Standard, Legacy, or Vintage. Accepts a single card name or an array of up to 50 card names.', CheckLegalityInput.shape, async (params) => { try { const result = checkLegalityHandler(db, params); return { content: [{ type: 'text' as const, text: formatCheckLegality(result) }] }; } catch (err) { return { content: [{ type: 'text' as const, text: `Error checking legality: ${err instanceof Error ? err.message : String(err)}` }], isError: true }; } }, ); - src/format.ts:173-199 (helper)Formatting helper that converts the CheckLegalityResult into a human-readable text string for display.
export function formatCheckLegality(result: CheckLegalityResult): string { const lines: string[] = []; if (result.format) { lines.push(`# Format Legality Check: ${capitalize(result.format)}\n`); } else { lines.push('# Format Legality Check\n'); } for (const card of result.results) { if (!card.found) { lines.push(`**${card.card_name}**: ${card.message}`); continue; } lines.push(`**${card.card_name}**:`); const entries = Object.entries(card.legalities); if (entries.length === 0) { lines.push(' No legality data available.'); } else { const parts = entries.map(([fmt, status]) => `${capitalize(fmt)}: ${capitalize(status)}`); lines.push(` ${parts.join(' | ')}`); } } return lines.join('\n'); }