search_rules
Find D&D 5e SRD rules by full-text search or look up specific conditions. Get official game rules quickly.
Instructions
Search D&D 5e SRD rules and conditions. Look up specific conditions or search rules text.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Full-text search query for rules | |
| condition_name | No | Name of a specific condition to look up |
Implementation Reference
- src/tools/search-rules.ts:47-117 (handler)Handlers for the search_rules tool: handleCondition (looks up a specific condition by name), handleRulesSearch (full-text search of rules), and handleListConditions (lists all conditions). Each returns MCP content.
function handleCondition(db: Database.Database, conditionName: string) { const condition = getConditionByName(db, conditionName); if (!condition) { const allConditions = listConditions(db); const available = allConditions.map((c) => c.name).join(', '); return { content: [ { type: 'text' as const, text: `Condition "${conditionName}" not found. Available conditions: ${available}`, }, ], isError: true, }; } const text = [ `${condition.name}`, '='.repeat(40), condition.description, ].join('\n'); return { content: [{ type: 'text' as const, text }] }; } function handleRulesSearch(db: Database.Database, query: string) { const rules = searchRules(db, query); if (rules.length === 0) { return { content: [ { type: 'text' as const, text: `No rules found matching "${query}".`, }, ], }; } const lines = rules.map((rule) => { const preview = rule.description.length > 200 ? rule.description.slice(0, 200) + '...' : rule.description; return `${rule.name} [${rule.section}]\n ${preview}`; }); const text = `Rules matching "${query}" (${rules.length} results)\n${'='.repeat(40)}\n\n${lines.join('\n\n')}`; return { content: [{ type: 'text' as const, text }] }; } function handleListConditions(db: Database.Database) { const conditions = listConditions(db); if (conditions.length === 0) { return { content: [ { type: 'text' as const, text: 'No conditions found in the database.' }, ], }; } const lines = conditions.map((c) => { const preview = c.description.length > 150 ? c.description.slice(0, 150) + '...' : c.description; return `${c.name}\n ${preview}`; }); const text = `D&D 5e SRD Conditions (${conditions.length})\n${'='.repeat(40)}\n\n${lines.join('\n\n')}`; return { content: [{ type: 'text' as const, text }] }; } - src/tools/search-rules.ts:72-95 (handler)handleRulesSearch: Performs full-text search on rules using the searchRules DB function and formats results with name, section, and a 200-char preview.
function handleRulesSearch(db: Database.Database, query: string) { const rules = searchRules(db, query); if (rules.length === 0) { return { content: [ { type: 'text' as const, text: `No rules found matching "${query}".`, }, ], }; } const lines = rules.map((rule) => { const preview = rule.description.length > 200 ? rule.description.slice(0, 200) + '...' : rule.description; return `${rule.name} [${rule.section}]\n ${preview}`; }); const text = `Rules matching "${query}" (${rules.length} results)\n${'='.repeat(40)}\n\n${lines.join('\n\n')}`; return { content: [{ type: 'text' as const, text }] }; } - src/tools/search-rules.ts:16-28 (schema)Input schema for search_rules: accepts optional 'query' (full-text search string) and optional 'condition_name' (specific condition name).
{ description: 'Search D&D 5e SRD rules and conditions. Look up specific conditions or search rules text.', inputSchema: { query: z .string() .optional() .describe('Full-text search query for rules'), condition_name: z .string() .optional() .describe('Name of a specific condition to look up'), }, - src/tools/search-rules.ts:10-44 (registration)registerSearchRules function: registers the 'search_rules' tool on the MCP server with its input schema and handler logic (3 modes).
export function registerSearchRules( server: McpServer, db: Database.Database, ): void { server.registerTool( 'search_rules', { description: 'Search D&D 5e SRD rules and conditions. Look up specific conditions or search rules text.', inputSchema: { query: z .string() .optional() .describe('Full-text search query for rules'), condition_name: z .string() .optional() .describe('Name of a specific condition to look up'), }, }, async ({ query, condition_name }) => { // Mode 1: Specific condition if (condition_name) { return handleCondition(db, condition_name); } // Mode 2: Full-text search rules if (query) { return handleRulesSearch(db, query); } // Mode 3: List all conditions return handleListConditions(db); }, ); - src/server.ts:51-51 (registration)Registration call in src/server.ts: invokes registerSearchRules(server, db) to register the tool.
registerSearchRules(server, db); - src/data/db.ts:438-453 (helper)searchRules database function: runs FTS query on rules via SQLite MATCH (or returns all rules if query is empty after sanitization).
export function searchRules( db: Database.Database, query: string, ): RuleRow[] { const ftsQuery = sanitizeFtsQuery(query); if (ftsQuery.length === 0) { return db .prepare('SELECT * FROM rules ORDER BY section ASC, name ASC') .all() as RuleRow[]; } return db .prepare( 'SELECT r.* FROM rules r WHERE r.id IN (SELECT rowid FROM rules_fts WHERE rules_fts MATCH ?) ORDER BY r.section ASC, r.name ASC', ) .all(ftsQuery) as RuleRow[]; }