search_equipment
Find D&D 5e equipment, weapons, armor, and magic items by name, category, cost, weight, properties, or rarity to equip characters effectively.
Instructions
Search D&D 5e SRD equipment, weapons, armor, and magic items. Filter by category, cost, weight, weapon properties, armor type, or rarity.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | Search term for item name or description | |
| category | No | Equipment category (e.g. "Weapon", "Armor", "Adventuring Gear", "Tools") | |
| cost_min | No | Minimum cost in gold pieces | |
| cost_max | No | Maximum cost in gold pieces | |
| weight_max | No | Maximum weight in pounds | |
| weapon_property | No | Weapon property (e.g. "finesse", "heavy", "two-handed", "versatile") | |
| armor_category | No | Armor category (e.g. "Light", "Medium", "Heavy", "Shield") | |
| rarity | No | Magic item rarity (e.g. "common", "uncommon", "rare", "very rare", "legendary") | |
| limit | No | Results per page (max 50) | |
| offset | No | Offset for pagination |
Implementation Reference
- src/tools/search-equipment.ts:149-195 (handler)The handler for the 'search_equipment' tool, which takes user filters, executes the search query, and formats the result.
async ({ query, category, cost_min, cost_max, weight_max, weapon_property, armor_category, rarity, limit, offset, }) => { const result = searchEquipment(db, { query, category, cost_min, cost_max, weight_max, weapon_property, armor_category, rarity, limit, offset, }); if (result.rows.length === 0) { return { content: [ { type: 'text' as const, text: 'No equipment found matching your criteria. Try a broader search — for example, remove some filters or use a partial name.', }, ], isError: true, }; } const start = (offset ?? 0) + 1; const end = (offset ?? 0) + result.rows.length; const header = `Found ${result.total} item${result.total === 1 ? '' : 's'} (showing ${start}-${end})\n`; const items = result.rows.map(formatEquipmentItem).join('\n\n---\n\n'); return { content: [{ type: 'text' as const, text: header + '\n' + items }], }; }, - src/tools/search-equipment.ts:124-147 (registration)The schema definition for the 'search_equipment' tool, defining the input filters.
inputSchema: { query: z.string().optional().describe('Search term for item name or description'), category: z .string() .optional() .describe('Equipment category (e.g. "Weapon", "Armor", "Adventuring Gear", "Tools")'), cost_min: z.number().optional().describe('Minimum cost in gold pieces'), cost_max: z.number().optional().describe('Maximum cost in gold pieces'), weight_max: z.number().optional().describe('Maximum weight in pounds'), weapon_property: z .string() .optional() .describe('Weapon property (e.g. "finesse", "heavy", "two-handed", "versatile")'), armor_category: z .string() .optional() .describe('Armor category (e.g. "Light", "Medium", "Heavy", "Shield")'), rarity: z .string() .optional() .describe('Magic item rarity (e.g. "common", "uncommon", "rare", "very rare", "legendary")'), limit: z.number().min(1).max(50).default(10).describe('Results per page (max 50)'), offset: z.number().min(0).default(0).describe('Offset for pagination'), }, - src/data/db.ts:275-344 (helper)The backend database query function that performs the actual SQL execution for searching equipment and magic items.
export function searchEquipment( db: Database.Database, filters: EquipmentFilters, ): SearchResult<EquipmentRow | MagicItemRow> { // Search both equipment and magic_items tables if (filters.rarity) { // Rarity filter only applies to magic items return searchMagicItems(db, filters); } const conditions: string[] = []; const params: (string | number)[] = []; if (filters.query) { const ftsQuery = sanitizeFtsQuery(filters.query); if (ftsQuery.length > 0) { conditions.push( 'e.id IN (SELECT rowid FROM equipment_fts WHERE equipment_fts MATCH ?)', ); params.push(ftsQuery); } } if (filters.category) { conditions.push('LOWER(e.category) = LOWER(?)'); params.push(filters.category); } if (filters.cost_min !== undefined) { conditions.push('e.cost_gp >= ?'); params.push(filters.cost_min); } if (filters.cost_max !== undefined) { conditions.push('e.cost_gp <= ?'); params.push(filters.cost_max); } if (filters.weight_max !== undefined) { conditions.push('e.weight <= ?'); params.push(filters.weight_max); } if (filters.weapon_property) { conditions.push('LOWER(e.weapon_properties) LIKE LOWER(?)'); params.push(`%${filters.weapon_property}%`); } if (filters.armor_category) { conditions.push('LOWER(e.armor_category) = LOWER(?)'); params.push(filters.armor_category); } const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; const limit = filters.limit ?? 20; const offset = filters.offset ?? 0; const countRow = db .prepare(`SELECT COUNT(*) as count FROM equipment e ${where}`) .get(...params) as { count: number }; const rows = db .prepare( `SELECT e.* FROM equipment e ${where} ORDER BY e.name ASC LIMIT ? OFFSET ?`, ) .all(...params, limit, offset) as EquipmentRow[]; return { rows, total: countRow.count }; }