poe2_item_price
Look up current market prices for Path of Exile 2 items from poe.ninja. Search by item name across exchange categories like Currency, Essences, Runes, and Fragments to get chaos-equivalent values and trade volumes.
Instructions
Look up the current market price of an item in Path of Exile 2 from poe.ninja.
Searches by partial name match across exchange categories (Currency, Fragments, Essences, Soul Cores, Idols, Runes, etc.).
Args:
name (string): Item name or partial name, e.g. "divine", "essence", "rune"
type (string): Exchange category to search. If omitted, searches all categories.
league (string): League name (default: "Fate of the Vaal")
Returns: Matching items with chaos-equivalent values and trade volumes.
Examples:
"How much is a Divine Orb?" → name="divine", type="Currency"
"Price of essences" → name="essence", type="Essences"
"Find rune prices" → name="rune", type="Runes"
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Item name or partial match | |
| type | No | Exchange category to search. If omitted, searches all categories. | |
| league | No | PoE2 league name | Fate of the Vaal |
Implementation Reference
- src/tools/items.ts:64-145 (handler)Main handler function for poe2_item_price tool. Accepts item name, type, and league parameters. Searches across exchange categories on poe.ninja API, matches items by partial name, calculates chaos-equivalent values, and returns formatted results with prices and volumes.
async ({ name, type, league }) => { try { const typesToSearch = type ? [type] : [...EXCHANGE_TYPES]; const query = name.toLowerCase(); const results: Array<{ name: string; type: string; chaos: number; volume: number; }> = []; for (const t of typesToSearch) { try { const data = await getNinjaExchangeOverview(league, t); 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; for (const line of data.lines) { const itemName = coreNames.get(line.id); const matchesQuery = line.id.toLowerCase().includes(query) || (itemName?.toLowerCase().includes(query) ?? false); if (matchesQuery) { results.push({ name: displayName(line.id, coreNames), type: t, chaos: line.primaryValue * chaosRate, volume: line.volumePrimaryValue ?? 0, }); } } } catch { // Some categories may not be available, skip silently } } if (results.length === 0) { return { content: [ { type: 'text', text: `No items found matching "${name}" in ${league}.\n\nTip: Try a shorter name. Available categories: ${EXCHANGE_TYPES.join(', ')}`, }, ], }; } results.sort((a, b) => b.chaos - a.chaos); const top = results.slice(0, 15); const lines: string[] = [ `## Item Prices: "${name}" — ${league}`, `Found ${results.length} match(es)`, '', ]; for (const r of top) { lines.push(`**${r.name}** [${r.type}]`); lines.push(`- Chaos: ${r.chaos.toFixed(1)} | Volume: ${r.volume}`); lines.push(''); } if (results.length > 15) { lines.push(`... and ${results.length - 15} more results.`); } 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: ${msg}` }], }; } }, - src/tools/items.ts:49-56 (schema)Input schema definition using Zod. Validates 'name' (required string), 'type' (optional enum from EXCHANGE_TYPES), and 'league' (string with default 'Fate of the Vaal').
inputSchema: { name: z.string().min(1).describe('Item name or partial match'), type: z .enum(EXCHANGE_TYPES) .optional() .describe('Exchange category to search. If omitted, searches all categories.'), league: z.string().default(DEFAULT_LEAGUE).describe('PoE2 league name'), }, - src/tools/items.ts:30-63 (registration)Tool registration with server.registerTool. Defines metadata including title, description, inputSchema, and annotations (readOnly, idempotent, openWorld). Binds the handler function to the 'poe2_item_price' tool name.
server.registerTool( 'poe2_item_price', { title: 'PoE2 Item Price Lookup', description: `Look up the current market price of an item in Path of Exile 2 from poe.ninja. Searches by partial name match across exchange categories (Currency, Fragments, Essences, Soul Cores, Idols, Runes, etc.). Args: - name (string): Item name or partial name, e.g. "divine", "essence", "rune" - type (string): Exchange category to search. If omitted, searches all categories. - league (string): League name (default: "Fate of the Vaal") Returns: Matching items with chaos-equivalent values and trade volumes. Examples: - "How much is a Divine Orb?" → name="divine", type="Currency" - "Price of essences" → name="essence", type="Essences" - "Find rune prices" → name="rune", type="Runes"`, inputSchema: { name: z.string().min(1).describe('Item name or partial match'), type: z .enum(EXCHANGE_TYPES) .optional() .describe('Exchange category to search. If omitted, searches all categories.'), league: z.string().default(DEFAULT_LEAGUE).describe('PoE2 league name'), }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, - src/services/api.ts:105-111 (helper)getNinjaExchangeOverview function - API helper that fetches exchange overview data from poe.ninja for a given league and type. Includes rate limiting and error handling.
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); } - src/tools/items.ts:24-26 (helper)displayName utility function - converts item IDs to title-case display names using a mapping from core item data.
function displayName(id: string, coreNames: Map<string, string>): string { return coreNames.get(id) ?? id.charAt(0).toUpperCase() + id.slice(1); }