get_keyword
Retrieve the official rules text for a Magic: The Gathering keyword ability like Flying or Deathtouch. Ideal for clarifying keyword mechanics.
Instructions
Get the official rules definition for a Magic keyword ability (e.g., "Flying", "Deathtouch", "Equip"). Use this when a user asks how a keyword works or what its rules text says. Different from get_glossary — this is specifically for keyword abilities with rules text.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Keyword name to look up (case-insensitive). Examples: "Flying", "Equip", "Scry". |
Implementation Reference
- src/tools/get-keyword.ts:33-68 (handler)Core handler function that looks up a keyword by name. First tries exact (case-insensitive) match, then fuzzy LIKE match, and finally returns suggestions based on the first word of the query.
export function handler(db: Database.Database, params: GetKeywordParams): GetKeywordResult { // 1. Exact match (case-insensitive) const exact = db.prepare( 'SELECT * FROM keywords WHERE LOWER(name) = LOWER(?)' ).get(params.name) as KeywordRow | undefined; if (exact) { return { found: true, keyword: toEntry(exact), }; } // 2. Fuzzy fallback via LIKE const fuzzy = db.prepare( 'SELECT * FROM keywords WHERE LOWER(name) LIKE LOWER(?)' ).get(`%${params.name}%`) as KeywordRow | undefined; if (fuzzy) { return { found: true, keyword: toEntry(fuzzy), }; } // 3. Suggestions based on first word const suggestions = db.prepare( 'SELECT name FROM keywords WHERE LOWER(name) LIKE LOWER(?) LIMIT 5' ).all(`%${params.name.split(' ')[0]}%`) as Array<{ name: string }>; return { found: false, message: `No keyword found matching "${params.name}"`, suggestions: suggestions.length > 0 ? suggestions.map(s => s.name) : undefined, }; } - src/tools/get-keyword.ts:1-11 (schema)Input schema using Zod, output types (KeywordEntry and GetKeywordResult discriminated union), and the type alias for params.
import { z } from 'zod'; import type Database from 'better-sqlite3'; import type { KeywordRow } from '../data/db.js'; // --- Input schema --- export const GetKeywordInput = z.object({ name: z.string().describe('Keyword name to look up (case-insensitive). Examples: "Flying", "Equip", "Scry".'), }); export type GetKeywordParams = z.infer<typeof GetKeywordInput>; - src/server.ts:179-191 (registration)Registration of the 'get_keyword' tool on the MCP server with its schema, description, and async handler that calls the handler function and formats the result.
server.tool( 'get_keyword', 'Get the official rules definition for a Magic keyword ability (e.g., "Flying", "Deathtouch", "Equip"). Use this when a user asks how a keyword works or what its rules text says. Different from get_glossary — this is specifically for keyword abilities with rules text.', GetKeywordInput.shape, async (params) => { try { const result = getKeywordHandler(db, params); return { content: [{ type: 'text' as const, text: formatGetKeyword(result) }] }; } catch (err) { return { content: [{ type: 'text' as const, text: `Error getting keyword: ${err instanceof Error ? err.message : String(err)}` }], isError: true }; } }, ); - src/format.ts:265-283 (helper)Formatting helper that converts the GetKeywordResult into a human-readable string (markdown). Handles both found and not-found cases, including suggestions.
export function formatGetKeyword(result: GetKeywordResult): string { if (!result.found) { let text = result.message; if (result.suggestions && result.suggestions.length > 0) { text += `\n\nDid you mean: ${result.suggestions.join(', ')}?`; } return text; } const kw = result.keyword; const lines: string[] = [ `# ${kw.name}`, `Type: ${kw.type} | Section: ${kw.section}`, '', kw.rules_text, ]; return lines.join('\n'); } - src/tools/get-keyword.ts:70-77 (helper)Helper function to convert a KeywordRow database row into a KeywordEntry object.
function toEntry(row: KeywordRow): KeywordEntry { return { name: row.name, section: row.section, type: row.type, rules_text: row.rules_text, }; }