Skip to main content
Glama
POE2MarketMCP

POE2MarketMCP

by GlacianNex

POE2MarketMCP

Local Path of Exile 2 currency prices, price history, public-listing valuation, and live trade searches for an MCP client.

Two processes share a local SQLite database: the collector builds history while your machine is awake, and your MCP client starts the server to answer questions. Connecting the MCP server does not start the collector.

Currency collection uses poe.ninja hourly by default. Optional item watchlists, exchange sweeps, and live listing/stash lookups use GGG's trade API. League and catalog discovery also contact GGG. Data is stored locally; tool results are returned to your connected client.

First-time setup

You need Python 3.11+ and uv, plus a contact email for API requests. The background service supports macOS and Linux with systemd. No game login, API key, or session cookie is needed for public listings.

From your existing checkout (or clone this repository first):

cd /path/to/POE2MarketMCP
uv venv --python 3.11
uv pip install --python .venv/bin/python -e .
.venv/bin/poe2market init
.venv/bin/poe2market collect --once
.venv/bin/poe2market status
.venv/bin/poe2market price cur:divine

Replace /path/to/POE2MarketMCP with your actual folder. Explicit .venv/bin/ commands work without activating the environment. If init says a config already exists, edit config/config.toml; do not overwrite it just to continue.

Success looks like: status shows a league, nonzero samples, and a recent ninja run with status ok and currencies priced. A successful command exit alone does not prove collection worked. History starts with your first samples and cannot be backfilled by this collector.

Then keep collection running:

.venv/bin/poe2market install-daemon

Connect your MCP client using the absolute Python path and POE2MARKET_HOME in the step-by-step setup guide. That guide also covers prerequisites, logs, existing installations, and recovery.

Related MCP server: poe2-build-mcp

Try it

Once connected, ask your client:

  • “Check market status and tell me how fresh the data is.”

  • “Find the Divine Orb item key, then show its latest price and currency unit.”

  • “Show Divine Orb history for the last day, using only the history collected.”

  • “Value my public priced listings.” (Requires an account handle.)

Prices have source and freshness information; historical coverage depends on how long collection has run. Stash valuation sees public priced listings, not everything you own. Listing tools return whisper text for you to use manually; they do not send messages or execute trades.

Optional features

All bundled watchlists and GGG currency tiers are disabled by default; pair_currencies is empty. Basic currency prices need none of these. Enable and validate only the item targets you want to track. Those scans spend GGG's trade budget, shared with other activity on your IP address.

See watchlists and direct pairs and stash setup.

Documentation and development

Start with the documentation index. The tool reference describes tool arguments and results; the agent guide explains how to interpret them. These documents are also served as MCP resources.

To install development tools and run the offline test suite:

uv pip install --python .venv/bin/python -e '.[dev]'
.venv/bin/pytest -q

Architecture and maintenance notes are in DESIGN.md. MIT — see LICENSE.

Available Tools

15 tools
find_arbitrageA

Find currencies where the median bid exceeds the median ask.

Deliberately compares medians, not extremes. The cheapest ask on this endpoint is very often a fat-finger or a sold-but-still-listed order: the median listing is ~85 minutes old when GGG serves it. Divine was observed with asks of 100/188/260/300 against bids of 230/200/180/162/160 — the extremes cross by 130 exalted and imply free money, while the medians show an ordinary 26% spread. Screening on extremes would report a large opportunity in a market that has none.

A crossing that survives at the median is a genuine dislocation. Even then treat it as a lead, not a filled trade: both counterparties must be online, stock is finite, and these complete by whisper and a manual trade window, so the price can move before anyone replies.

stale_extremes reports books that cross only at the extremes, which is a staleness signal rather than an opportunity.

Inputs: limit, league, min_profit_pct. Returns: object

find_listingsA

Search live trade listings right now, returning prices and whisper text.

Spends the shared GGG rate budget (600 searches / 6h), so prefer get_price when recorded data is good enough.

The returned whisper is the message to send in game. This server cannot send it: GGG exposes no trade-execution API, and automating in-game input violates the terms of service. A human completes the trade.

Inputs: name, type, limit, league. Returns: object

find_multi_step_arbitrageA

Find profitable trade loops, e.g. chaos -> exalted -> divine -> chaos.

Pure analysis over already-collected direct pair rates: no API calls, so it is free to run as often as you like.

Only direct pair quotes can produce a cycle. Cross-rates synthesised through the base currency pay the spread on every leg, so a loop built from them always loses — profit appears only where the market's own chaos->divine rate has drifted from chaos->exalted->divine.

Each leg's rate has already paid its own spread and has had junk listings filtered out, so a gain above 1.0 is real profit rather than mid-price arithmetic. min_depth bounds how much can actually be pushed through the tightest leg.

As with all trades here: these complete by whisper and a manual trade window. Every counterparty must be online and willing. Treat results as leads, and note that a four-hop loop needs four separate humans to answer.

Inputs: limit, league, max_hops, min_profit_pct, +1 more. Returns: object

get_moversB

Items with the largest percentage price moves over a window.

Needs at least days + 1 days of collected history to be meaningful.

Inputs: days, limit, league, min_samples. Returns: object

get_priceA

Latest recorded price for one item, with spread and confidence.

Reads the local database only. Returns found: false when the collector has not yet priced this item, which is not the same as the item being unsellable — check market_status.

Inputs: item_key (required), league. Returns: object

get_price_historyA

OHLC price history for one item, for charting or trend analysis.

Reads rollup candles, so long windows stay fast. auto uses hourly candles up to 14 days and daily beyond that.

Inputs: item_key (required), days, league, resolution. Returns: object

get_stash_historyA

Track how your stash's total value has changed over time.

Each snapshot is valued at the prices that applied when it was taken, so the series separates 'I acquired more' from 'what I hold got dearer'.

Inputs: limit, league. Returns: object

get_stash_valueA

Value your own stash against collected prices.

Reads the account's public listings (no login) — the working path on PoE2, since the authenticated stash API is OAuth-only and closed. Only publicly-listed items are visible; set the account with stash_account in config or POE2MARKET_ACCOUNT.

Set refresh to pull fresh listings; otherwise the latest snapshot is returned.

Inputs: league, refresh. Returns: object

list_leaguesA

List PoE2 leagues available on the trade API, and which are collected.

Use this first when the user names a league loosely ("the new league"), so later calls pass an exact league id.

Inputs: no named parameters. Returns: object

list_stash_itemsA

List what is actually in your stash: every item, with quantities.

Reads the most recent snapshot. Set group_stacks (the default) to aggregate the same item across tabs — 3 stacks of Exalted Orbs in three tabs become one row with the combined quantity, which is almost always the question being asked. Turn it off to see each physical stack and its tab.

Unpriced items (gear, maps, anything without a collected price) are included with a null value rather than dropped, so the list is a real inventory rather than only the part we happen to have priced.

Filters: search matches name or base type, tab matches a tab name, rarity is Normal/Magic/Rare/Unique/Currency/Gem.

Inputs: tab, sort, limit, league, +5 more. Returns: object

list_watchlistsA

Show configured watchlists: what is scanned, how often, and priority.

Inputs: no named parameters. Returns: object

market_statusA

Report collector health, database coverage and remaining rate budget.

Check this before concluding that missing data means a missing market — an empty history usually means the collector has not been running.

Inputs: no named parameters. Returns: object

prepare_tradeC

Pick the best current listing for an item and return a ready whisper.

Cross-checks the live ask against recorded history so an outlier price is flagged before you commit. Returns the whisper for a human to send; it does not contact anyone.

Inputs: name, league, item_key, max_price. Returns: object

refresh_pricesA

Fetch currency prices from poe.ninja right now, bypassing the schedule.

This is a hard refetch: it bypasses poe.ninja's CDN cache to reach the origin, rather than re-reading the cached response the hourly sweep uses. Worth calling when stale: true appears on a result, or after the machine has been asleep or offline. Note poe.ninja recomputes its own numbers about hourly, so a forced refetch guarantees the freshest published data — not necessarily different data.

Hits poe.ninja only; it does not touch GGG's trade API, so it cannot affect the player's in-game trade rate budget.

Inputs: league. Returns: object

search_itemsA

Find tracked items by name, returning the item keys other tools take.

Every priceable thing has a stable key (cur:divine, or a watchlist target's key). Resolve a user's wording to a key here first.

Inputs: kind, limit, query, watchlist. Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 15 tools

    Disambiguation5/5

    Each tool targets a distinct operation: retrieval (get_price, get_price_history), live search (find_listings), opportunity detection (find_arbitrage, find_multi_step_arbitrage), stash management (get_stash_value, list_stash_items), and meta/status (market_status, refresh_prices). Even overlapping tools like get_price and find_listings are clearly separated by local vs live data. No tool could be easily mistaken for another.

    Naming Consistency5/5

    All tools use snake_case with consistent verb prefixes: list_ for enumerations, get_ for retrieving single entities, find_ for searching opportunities, prepare_ for constructing a trade, refresh_ for updating data. The only deviation is market_status (noun_verb), but it is a recognizable exception and still clear. Overall a consistent pattern.

    Tool Count5/5

    15 tools covers the domain without bloat: each serves a distinct function, from price tracking to stash valuation to arbitrage detection. This is within the ideal range and each tool is justified by a specific use case.

    Completeness4/5

    The surface covers the full trade lifecycle: data collection (refresh_prices, market_status), price lookup (get_price, history, movers), live interaction (find_listings, prepare_trade), arbitrage (direct and multi-step), and stash analysis (value, history, items). The only gap is that watchlists are read-only (no add/remove tool) and collector management is not exposed, but those are configuration concerns rather than core market operations.

    Maintenance

    ActivitySlowing
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      An MCP server for Path of Exile 2 build analysis that loads builds from Path of Building export codes and allows natural language interrogation via any MCP-compatible client.
      8
      2
      -
    • A
      license
      A
      quality
      D
      maintenance
      An MCP server for Path of Exile 2: a queryable game corpus plus Path-of-Building-faithful calculations, so an LLM can import your build, answer questions, and theorycraft against real numbers (not invented ones).
      64
      3
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Local MCP server that exposes Liquid Co-Invest's trading data and order tools to a local LLM via a thin proxy.
      MIT