Skip to main content
Glama
sergeyklay

poe2-mcp-server

by sergeyklay

poe2_meta_builds

Retrieve class distribution statistics and meta-build trends for Path of Exile 2 from poe.ninja, showing popular classes with percentage shares and trend directions among ladder characters.

Instructions

Get class distribution statistics for Path of Exile 2 from poe.ninja.

Shows the most popular classes with their percentage share and trend direction among indexed ladder characters.

Args:

  • league (string): League name (default: "Fate of the Vaal")

  • class_name (string): Optional — filter by class, e.g. "Witch", "Lich", "Sorceress"

Returns: Class distribution with percentages and trend indicators.

Examples:

  • "What's the current meta?" → call with defaults

  • "Most popular Witch builds?" → class_name="Witch"

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
leagueNoPoE2 league nameFate of the Vaal
class_nameNoFilter by class name, e.g. Witch, Lich, Warrior, Sorceress

Implementation Reference

  • Main handler function for poe2_meta_builds tool. Fetches build data from poe.ninja API, filters by league and optional class name, formats class distribution statistics with percentages and trend indicators, and returns formatted markdown output.
    async ({ league, class_name }) => {
      try {
        const data = await getNinjaBuildIndex();
        const queryLower = league.toLowerCase();
    
        // Find matching league by name (case-insensitive contains) or URL slug
        const entry: BuildLeagueEntry | undefined = data.leagueBuilds.find(
          (e) =>
            e.leagueName.toLowerCase().includes(queryLower) ||
            e.leagueUrl.toLowerCase() === queryLower,
        );
    
        if (!entry) {
          const available = data.leagueBuilds.map((e) => `"${e.leagueName}"`).join(', ');
          return {
            content: [
              {
                type: 'text',
                text: `League "${league}" not found. Available leagues: ${available}.`,
              },
            ],
          };
        }
    
        const { statistics, total } = entry;
    
        // Build parallel index arrays, optionally filtered by class_name
        let indices = statistics.class.map((_, i) => i);
        if (class_name) {
          const classQuery = class_name.toLowerCase();
          indices = indices.filter((i) => statistics.class[i]!.toLowerCase().includes(classQuery));
        }
    
        const lines: string[] = [
          `## Meta Builds Overview — ${entry.leagueName}`,
          '',
          `Total indexed characters: ${total.toLocaleString()}`,
          '',
          '### Class Distribution',
        ];
    
        if (indices.length === 0 && class_name) {
          lines.push(
            `No classes matching "${class_name}". Available classes: ${statistics.class.join(', ')}`,
          );
        } else {
          for (const i of indices) {
            const className = statistics.class[i]!;
            const pct = statistics.percentage[i] ?? 0;
            const trend = statistics.trend[i] ?? 0;
            lines.push(`- **${className}**: ${pct}%${trendLabel(trend)}`);
          }
        }
    
        return {
          content: [{ type: 'text', text: lines.join('\n') }],
        };
      } catch (error) {
        const msg = error instanceof Error ? error.message : String(error);
        return {
          isError: true,
          content: [
            {
              type: 'text',
              text: `Error fetching meta builds: ${msg}\n\nNote: poe.ninja build API may not be available for all leagues.`,
            },
          ],
        };
      }
    },
  • Tool registration schema defining input parameters: 'league' (string, defaults to 'Fate of the Vaal') and optional 'class_name' filter. Includes tool metadata, descriptions, and annotations (readOnly, idempotent, openWorld).
      server.registerTool(
        'poe2_meta_builds',
        {
          title: 'PoE2 Meta Build Overview',
          description: `Get class distribution statistics for Path of Exile 2 from poe.ninja.
    
    Shows the most popular classes with their percentage share and trend direction among indexed ladder characters.
    
    Args:
      - league (string): League name (default: "Fate of the Vaal")
      - class_name (string): Optional — filter by class, e.g. "Witch", "Lich", "Sorceress"
    
    Returns: Class distribution with percentages and trend indicators.
    
    Examples:
      - "What's the current meta?" → call with defaults
      - "Most popular Witch builds?" → class_name="Witch"`,
          inputSchema: {
            league: z.string().default(DEFAULT_LEAGUE).describe('PoE2 league name'),
            class_name: z
              .string()
              .optional()
              .describe('Filter by class name, e.g. Witch, Lich, Warrior, Sorceress'),
          },
          annotations: {
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: true,
          },
        },
  • Complete tool registration function registerBuildTools that registers the poe2_meta_builds tool with the MCP server, including schema definition and handler function.
    export function registerBuildTools(server: McpServer): void {
      // ── poe2_meta_builds ──────────────────────────────────────────────
      server.registerTool(
        'poe2_meta_builds',
        {
          title: 'PoE2 Meta Build Overview',
          description: `Get class distribution statistics for Path of Exile 2 from poe.ninja.
    
    Shows the most popular classes with their percentage share and trend direction among indexed ladder characters.
    
    Args:
      - league (string): League name (default: "Fate of the Vaal")
      - class_name (string): Optional — filter by class, e.g. "Witch", "Lich", "Sorceress"
    
    Returns: Class distribution with percentages and trend indicators.
    
    Examples:
      - "What's the current meta?" → call with defaults
      - "Most popular Witch builds?" → class_name="Witch"`,
          inputSchema: {
            league: z.string().default(DEFAULT_LEAGUE).describe('PoE2 league name'),
            class_name: z
              .string()
              .optional()
              .describe('Filter by class name, e.g. Witch, Lich, Warrior, Sorceress'),
          },
          annotations: {
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: true,
          },
        },
        async ({ league, class_name }) => {
          try {
            const data = await getNinjaBuildIndex();
            const queryLower = league.toLowerCase();
    
            // Find matching league by name (case-insensitive contains) or URL slug
            const entry: BuildLeagueEntry | undefined = data.leagueBuilds.find(
              (e) =>
                e.leagueName.toLowerCase().includes(queryLower) ||
                e.leagueUrl.toLowerCase() === queryLower,
            );
    
            if (!entry) {
              const available = data.leagueBuilds.map((e) => `"${e.leagueName}"`).join(', ');
              return {
                content: [
                  {
                    type: 'text',
                    text: `League "${league}" not found. Available leagues: ${available}.`,
                  },
                ],
              };
            }
    
            const { statistics, total } = entry;
    
            // Build parallel index arrays, optionally filtered by class_name
            let indices = statistics.class.map((_, i) => i);
            if (class_name) {
              const classQuery = class_name.toLowerCase();
              indices = indices.filter((i) => statistics.class[i]!.toLowerCase().includes(classQuery));
            }
    
            const lines: string[] = [
              `## Meta Builds Overview — ${entry.leagueName}`,
              '',
              `Total indexed characters: ${total.toLocaleString()}`,
              '',
              '### Class Distribution',
            ];
    
            if (indices.length === 0 && class_name) {
              lines.push(
                `No classes matching "${class_name}". Available classes: ${statistics.class.join(', ')}`,
              );
            } else {
              for (const i of indices) {
                const className = statistics.class[i]!;
                const pct = statistics.percentage[i] ?? 0;
                const trend = statistics.trend[i] ?? 0;
                lines.push(`- **${className}**: ${pct}%${trendLabel(trend)}`);
              }
            }
    
            return {
              content: [{ type: 'text', text: lines.join('\n') }],
            };
          } catch (error) {
            const msg = error instanceof Error ? error.message : String(error);
            return {
              isError: true,
              content: [
                {
                  type: 'text',
                  text: `Error fetching meta builds: ${msg}\n\nNote: poe.ninja build API may not be available for all leagues.`,
                },
              ],
            };
          }
        },
      );
    }
  • getNinjaBuildIndex function that fetches PoE2 build index state from poe.ninja API, returning class distribution statistics for all leagues.
    export async function getNinjaBuildIndex(): Promise<BuildIndexStateResponse> {
      const url = 'https://poe.ninja/poe2/api/data/build-index-state';
      return fetchJson<BuildIndexStateResponse>(url, ninjaLimiter);
    }
  • Type definitions for BuildLeagueStatistics, BuildLeagueEntry, and BuildIndexStateResponse interfaces that define the structure of poe.ninja build API responses.
    interface BuildLeagueStatistics {
      class: string[];
      percentage: number[];
      trend: number[];
    }
    
    export interface BuildLeagueEntry {
      leagueName: string;
      leagueUrl: string;
      total: number;
      status: number;
      statistics: BuildLeagueStatistics;
    }
    
    export interface BuildIndexStateResponse {
      leagueBuilds: BuildLeagueEntry[];
    }

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/sergeyklay/poe2-mcp-server'

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