Skip to main content
Glama

search_champions

Find TFT champions by name, cost, trait, or role to access accurate game data and prevent AI hallucinations.

Instructions

Search for TFT champions by name, cost, trait, or role. Returns a summary list — use get_champion for full details on a specific champion.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryNoFree-text search across champion name and ability (uses FTS5)
costNoFilter by champion cost (1-5)
traitNoFilter by trait name (e.g. Warrior, Bruiser)
roleNoFilter by role (e.g. damage, support, tank)
limitNoMax results to return, 1-50 (default: 20)

Implementation Reference

  • The handler function `searchChampions` performs the logic for searching champions, building dynamic SQL queries based on provided input filters (cost, role, trait) and performing database queries to return matching champions.
    export function searchChampions(
      db: Database.Database,
      input: SearchChampionsInputType,
    ): SearchChampionsResult {
      const params: unknown[] = [];
      const conditions: string[] = [];
      const joins: string[] = [];
      const useFts = !!input.query;
    
      // Cost filter
      if (input.cost != null) {
        conditions.push('c.cost = ?');
        params.push(input.cost);
      }
    
      // Role filter
      if (input.role) {
        conditions.push('LOWER(c.role) = LOWER(?)');
        params.push(input.role);
      }
    
      // Trait filter (JOIN champion_traits)
      if (input.trait) {
        joins.push('JOIN champion_traits ct ON ct.champion_name = c.name');
        conditions.push('LOWER(ct.trait_name) = LOWER(?)');
        params.push(input.trait);
      }
    
      const limit = input.limit ?? 20;
    
      let sql: string;
      const allParams: unknown[] = [];
    
      if (useFts) {
        allParams.push(input.query);
        allParams.push(...params);
        allParams.push(limit);
    
        const whereClause =
          conditions.length > 0 ? ' AND ' + conditions.join(' AND ') : '';
        const joinClause = joins.join(' ');
    
        sql = `
          SELECT DISTINCT c.name, c.cost, c.role, c.hp, c.ad,
            (SELECT GROUP_CONCAT(ct2.trait_name, ', ')
             FROM champion_traits ct2
             WHERE ct2.champion_name = c.name) AS traits
          FROM champions_fts fts
          JOIN champions c ON c.rowid = fts.rowid
          ${joinClause}
          WHERE champions_fts MATCH ?${whereClause}
          ORDER BY fts.rank
          LIMIT ?
        `;
      } else {
        allParams.push(...params);
        allParams.push(limit);
    
        const whereClause =
          conditions.length > 0 ? 'WHERE ' + conditions.join(' AND ') : '';
        const joinClause = joins.join(' ');
    
        sql = `
          SELECT DISTINCT c.name, c.cost, c.role, c.hp, c.ad,
            (SELECT GROUP_CONCAT(ct2.trait_name, ', ')
             FROM champion_traits ct2
             WHERE ct2.champion_name = c.name) AS traits
          FROM champions c
          ${joinClause}
          ${whereClause}
          ORDER BY c.name
          LIMIT ?
        `;
      }
    
      const rows = db.prepare(sql).all(...allParams) as Array<{
        name: string;
        cost: number;
        role: string | null;
        traits: string | null;
        hp: number | null;
        ad: number | null;
      }>;
    
      const champions: ChampionSummary[] = rows.map((row) => ({
        name: row.name,
        cost: row.cost,
        role: row.role,
        traits: row.traits ?? '',
        hp: row.hp,
        ad: row.ad,
      }));
    
      return { champions, total: champions.length };
    }
  • The `SearchChampionsInput` Zod schema defines the input parameters for the `search_champions` tool, including optional filters for query, cost, trait, role, and a limit.
    export const SearchChampionsInput = z.object({
      query: z
        .string()
        .optional()
        .describe('Free-text search across champion name and ability (uses FTS5)'),
      cost: z
        .number()
        .optional()
        .describe('Filter by champion cost (1-5)'),
      trait: z
        .string()
        .optional()
        .describe('Filter by trait name (e.g. Warrior, Bruiser)'),
      role: z
        .string()
        .optional()
        .describe('Filter by role (e.g. damage, support, tank)'),
      limit: z
        .number()
        .min(1)
        .max(50)
        .optional()
        .default(20)
        .describe('Max results to return, 1-50 (default: 20)'),
    });
  • src/server.ts:47-65 (registration)
    The `search_champions` tool is registered on the `McpServer` instance in `src/server.ts`, which maps the tool name to the handler function and utilizes the schema for parameter validation.
    // 1. search_champions
    server.tool(
      'search_champions',
      'Search for TFT champions by name, cost, trait, or role. Returns a summary list — use get_champion for full details on a specific champion.',
      SearchChampionsInput.shape,
      async (params) => {
        try {
          const result = searchChampions(db, params);
          return {
            content: [{ type: 'text' as const, text: formatSearchChampions(result) }],
          };
        } catch (err) {
          return {
            content: [{ type: 'text' as const, text: `Error: ${err instanceof Error ? err.message : String(err)}` }],
            isError: true,
          };
        }
      },
    );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gregario/tft-oracle'

If you have feedback or need assistance with the MCP directory API, please join our Discord server