Skip to main content
Glama
sergeyklay

poe2-mcp-server

by sergeyklay

PoE2 Currency Prices

poe2_currency_prices
Read-onlyIdempotent

Retrieve current Path of Exile 2 currency exchange rates from poe.ninja, providing chaos-equivalent values and trade volumes for informed trading decisions.

Instructions

Get current currency exchange rates for Path of Exile 2 from poe.ninja.

Returns prices of all currencies with chaos-equivalent values computed from exchange rates. Data refreshes approximately every hour on poe.ninja.

Args:

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

Returns: List of currencies with their exchange values and trade volumes.

Examples:

  • "How much is an Exalted Orb worth?" → call with default league

  • "Currency prices in Standard" → call with league="Standard"

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
leagueNoPoE2 league name, e.g. "Fate of the Vaal" or "Standard"Fate of the Vaal

Implementation Reference

  • The main handler function that executes the poe2_currency_prices tool logic - fetches currency data from poe.ninja API, calculates chaos-equivalent values, sorts by value, and formats the output as a markdown list with trade volumes.
    async ({ league }) => {
      try {
        const data = await getNinjaExchangeOverview(league, 'Currency');
    
        // Build lookup: id → human-readable name from core reference items
        const coreNames = new Map<string, string>();
        for (const item of data.core.items) {
          coreNames.set(item.id, item.name);
        }
    
        const chaosRate = data.core.rates[data.core.secondary] ?? 1;
    
        const lines: string[] = [`## Currency Prices — ${league}`, ''];
    
        // Sort by chaos value descending
        const sorted = [...data.lines].sort((a, b) => {
          const chaosA = a.primaryValue * chaosRate;
          const chaosB = b.primaryValue * chaosRate;
          return chaosB - chaosA;
        });
    
        for (const line of sorted) {
          const name = displayName(line.id, coreNames);
          const chaosValue = (line.primaryValue * chaosRate).toFixed(2);
          const volume = line.volumePrimaryValue ?? 0;
          lines.push(`- **${name}**: ${chaosValue} chaos (volume: ${volume})`);
        }
    
        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 currency prices for league "${league}": ${msg}\n\nAvailable PoE2 leagues: "Fate of the Vaal", "Standard". League names are case-sensitive.`,
            },
          ],
        };
      }
    },
  • Tool registration that defines the poe2_currency_prices tool with its title, description, input schema, annotations, and handler function.
      server.registerTool(
        'poe2_currency_prices',
        {
          title: 'PoE2 Currency Prices',
          description: `Get current currency exchange rates for Path of Exile 2 from poe.ninja.
    
    Returns prices of all currencies with chaos-equivalent values computed from exchange rates.
    Data refreshes approximately every hour on poe.ninja.
    
    Args:
      - league (string): League name (default: "Fate of the Vaal")
    
    Returns: List of currencies with their exchange values and trade volumes.
    
    Examples:
      - "How much is an Exalted Orb worth?" → call with default league
      - "Currency prices in Standard" → call with league="Standard"`,
          inputSchema: {
            league: LeagueSchema,
          },
          annotations: {
            readOnlyHint: true,
            destructiveHint: false,
            idempotentHint: true,
            openWorldHint: true,
          },
        },
        async ({ league }) => {
          try {
            const data = await getNinjaExchangeOverview(league, 'Currency');
    
            // Build lookup: id → human-readable name from core reference items
            const coreNames = new Map<string, string>();
            for (const item of data.core.items) {
              coreNames.set(item.id, item.name);
            }
    
            const chaosRate = data.core.rates[data.core.secondary] ?? 1;
    
            const lines: string[] = [`## Currency Prices — ${league}`, ''];
    
            // Sort by chaos value descending
            const sorted = [...data.lines].sort((a, b) => {
              const chaosA = a.primaryValue * chaosRate;
              const chaosB = b.primaryValue * chaosRate;
              return chaosB - chaosA;
            });
    
            for (const line of sorted) {
              const name = displayName(line.id, coreNames);
              const chaosValue = (line.primaryValue * chaosRate).toFixed(2);
              const volume = line.volumePrimaryValue ?? 0;
              lines.push(`- **${name}**: ${chaosValue} chaos (volume: ${volume})`);
            }
    
            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 currency prices for league "${league}": ${msg}\n\nAvailable PoE2 leagues: "Fate of the Vaal", "Standard". League names are case-sensitive.`,
                },
              ],
            };
          }
        },
      );
  • Zod schema defining the input validation for the league parameter, which is used as the inputSchema for poe2_currency_prices.
    const LeagueSchema = z
      .string()
      .default(DEFAULT_LEAGUE)
      .describe('PoE2 league name, e.g. "Fate of the Vaal" or "Standard"');
    
    /** Title-case a slug id for display (e.g. "alch" → "Alch"). */
    function displayName(id: string, coreNames: Map<string, string>): string {
      return coreNames.get(id) ?? id.charAt(0).toUpperCase() + id.slice(1);
    }
    
    export function registerCurrencyTools(server: McpServer): void {
      // ── poe2_currency_prices ──────────────────────────────────────────
      server.registerTool(
        'poe2_currency_prices',
        {
          title: 'PoE2 Currency Prices',
          description: `Get current currency exchange rates for Path of Exile 2 from poe.ninja.
    
    Returns prices of all currencies with chaos-equivalent values computed from exchange rates.
    Data refreshes approximately every hour on poe.ninja.
    
    Args:
      - league (string): League name (default: "Fate of the Vaal")
    
    Returns: List of currencies with their exchange values and trade volumes.
    
    Examples:
      - "How much is an Exalted Orb worth?" → call with default league
      - "Currency prices in Standard" → call with league="Standard"`,
          inputSchema: {
            league: LeagueSchema,
          },
  • Helper function that fetches PoE2 exchange data from poe.ninja API with rate limiting - used by poe2_currency_prices handler to retrieve currency price data.
    /**
     * Fetch PoE2 exchange overview from poe.ninja.
     * @param league — Full league display name, e.g. "Fate of the Vaal"
     * @param type — Exchange category, e.g. "Currency", "Fragments", "Essences"
     */
    export async function getNinjaExchangeOverview(
      league: string,
      type: string,
    ): Promise<NinjaExchangeResponse> {
      const url = `${NINJA_POE2_BASE}/exchange/current/overview?league=${encodeURIComponent(league)}&type=${encodeURIComponent(type)}`;
      return fetchJson<NinjaExchangeResponse>(url, ninjaLimiter);
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, open-world, idempotent, and non-destructive traits, but the description adds valuable behavioral context beyond this: it specifies the data source (poe.ninja), refresh rate (approximately every hour), and that it returns a list with exchange values and trade volumes. This enhances understanding without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded, starting with the core purpose, followed by details on returns, data refresh, args, and examples. Every sentence adds value without redundancy, making it efficient and easy to parse for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (1 parameter, 100% schema coverage, no output schema) and rich annotations, the description is mostly complete. It covers purpose, usage, and behavioral context adequately. A minor gap is the lack of explicit output structure details, but with annotations indicating safety and idempotency, this is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the parameter 'league' fully documented in the schema (including default and examples). The description adds minimal value beyond the schema, only restating the default in the example and implying usage for different leagues. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('Get current currency exchange rates') and resources ('Path of Exile 2 from poe.ninja'), distinguishing it from siblings like poe2_item_price (specific items) or poe2_exchange_top (top exchanges). It explicitly mentions chaos-equivalent values and trade volumes, which are unique to this currency-focused tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool (e.g., for currency exchange rates, with examples like 'How much is an Exalted Orb worth?'), but it does not explicitly state when not to use it or name alternatives among siblings. The examples imply usage for currency queries, but no direct comparison to tools like poe2_item_price is made.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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