Skip to main content
Glama
README.md
# Path of Building MCP Server — PoE2

An MCP (Model Context Protocol) server that enables Claude to analyze, modify, and optimize **Path of Exile 2** builds using Path of Building's actual calculation engine, via the [PathOfBuilding-PoE2](https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2) fork.

It is a port of [`pob-mcp`](../pob-mcp) (PoE1) to PoE2. The high-fidelity calculation half is driven by a headless `luajit` process running an `api-stdio` JSON bridge, vendored in this repo at `pob-api/` and run against an unmodified PathOfBuilding-PoE2 checkout.

### PoE2 specifics

- **Engine-backed tools to prefer:** `analyze_skills`, `suggest_supports` (incl. `measure_dps`), `list_gems`, `get_classes` — all sourced from the PoB2 engine. `list_gems` queries Path of Building's own PoE2 gem database (skill + support gems, tags, gem family, requirements, max level). The defensive analyzer and `validate_build` are tuned for PoE2 mechanics (evade/block/deflect, Spirit, charms; no spell suppression).
- **On by default:** poe.ninja currency tools on the PoE2 economy endpoint (`POE_NINJA_DISABLED=true` to hide).
- **Opt-in:** legacy PoE1-shaped skill-gem tools (`analyze_skill_links`, `suggest_support_gems`, `find_optimal_links`, `validate_gem_quality`, `compare_gem_setups`, `gem_upgrade_path`) via `POB_LEGACY_GEM_TOOLS=true`; Trade API (PoE2 trade2 endpoints) via `POE_TRADE_ENABLED=true`.

---

## Features

### Build Analysis (Always Available)
- **List & Analyze Builds**: Browse builds and extract stats, skills, items, passive trees, and notes from XML
- **Compare Builds**: Side-by-side build comparison
- **File Watching**: Real-time detection of builds saved from PoB with automatic cache invalidation
- **Tree Analysis**: Compare passive trees, find paths to nodes, discover nearby notables, what-if allocation testing

### High-Fidelity Calculations (Lua Bridge)
- **Live Stats**: Accurate stat calculation using PoB's own engine — identical to what PoB GUI shows
- **Build Loading & Creation**: Load existing builds or create new ones from scratch by class/ascendancy
- **Passive Tree Editing**: Set full tree allocation and see immediate stat recalculation
- **Node Search**: Search the passive tree for nodes by name or stat text
- **Character Level**: Set level and watch all stats update accordingly

### Item & Skill Management (Lua Bridge)
- **Items**: Add items from PoE clipboard text, view all equipped gear
- **Flasks**: Toggle flasks active/inactive with immediate stat feedback
- **Skills**: Full gem management — create socket groups, add/remove/level/quality gems
- **Batch Operations**: `setup_skill_with_gems` and `add_multiple_items` for efficient workflows

### Build Optimization (Lua Bridge)
- **Defensive Analysis**: 3-layer framework (avoidance / mitigation / recovery) — evaluates EHP, spell suppression, armour/PDR, evasion, block, life regen, and leech
- **Node Suggestions**: Archetype-aware suggestions by goal (damage, life, ES, defense, resist)
- **Tree Optimization**: Recommend nodes within reach of the current allocation
- **Item Upgrade Analysis**: Slot-by-slot upgrade recommendations based on live stats
- **Skill Link Optimization**: Detect missing "more" multipliers, penetration gaps, anti-synergies
- **Budget Build Creation**: Generate starter build plans with skill links, gearing strategy, and passive priorities

### Build Validation
- **Comprehensive Checks**: Resistances, life pool, defensive layers, mana, flask immunities, accuracy, damage scaling
- **Severity Classification**: Critical / Warning / Info with actionable suggestions
- **Dual Source**: Uses Lua bridge stats when available, falls back to XML parsing
- **Overall Score**: 0–10 build health score

### Configuration & Scenario Testing (Lua Bridge)
- **Config State**: View bandit, pantheon, enemy settings
- **Toggle Conditions**: Charges, buffs (Onslaught, Fortify, Leeching), boss mode
- **Enemy Tuning**: Set enemy level, resistances, armour, evasion for boss DPS testing

### Skill Gem Analysis
- **Archetype Detection**: Classify builds (Elemental Bow Attack, Summoner, Critical Spell, etc.)
- **Support Gem Recommendations**: Ranked suggestions with DPS estimates and cost context
- **Quality Validation**: Identify missing quality, awakened upgrade paths, corruption targets
- **Optimal Links**: Auto-generate best support gem combinations for 4/5/6-link setups
- **Budget Tiers**: League-start, mid-league, and endgame recommendations

### Build Export & Persistence
- **Export**: Copy builds to XML files with optional notes
- **Save Tree**: Write optimized passive tree back to an existing build file
- **Snapshots**: Versioned build history with tags, stat metadata, and one-click rollback

### Currency & Market Data (poe.ninja)
- **Exchange Rates**: Real-time currency prices in Chaos Orb equivalent
- **Arbitrage Detection**: Find profitable currency trading loops
- **Trade Profit Calculator**: Evaluate custom trading chains

### Trade API (Optional, `POE_TRADE_ENABLED=true`)
- **Item Search**: Search trade with stat filters, price range, link count
- **Price Checking**: Min/max/median/average from recent listings
- **Upgrade Finder**: Identify best item upgrade candidates for your build
- **Resistance Gear**: Find affordable gear to cap resistances
- **Cluster Jewels**: Search and analyze cluster jewel setups
- **Shopping List**: Generate a prioritized shopping list from build analysis

---

## Installation

```bash
cd pob-mcp
npm install
npm run build
```

## Configuration

### Claude Desktop Configuration

**Mac**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

#### XML-Only (No Lua Bridge)
```json
{
  "mcpServers": {
    "pob": {
      "command": "node",
      "args": ["/absolute/path/to/pob-mcp-server/build/index.js"],
      "env": {
        "POB_DIRECTORY": "/path/to/your/Path of Building/Builds"
      }
    }
  }
}
```

#### Full Configuration (With Lua Bridge)
```json
{
  "mcpServers": {
    "pob": {
      "command": "node",
      "args": ["/absolute/path/to/pob-mcp-server/build/index.js"],
      "env": {
        "POB_DIRECTORY": "/path/to/your/Path of Building/Builds",
        "POB_LUA_ENABLED": "true",
        "POB_FORK_PATH": "/path/to/PathOfBuilding/src",
        "POB_CMD": "/usr/local/bin/luajit",
        "POB_TIMEOUT_MS": "10000"
      }
    }
  }
}
```

### Environment Variables

| Variable | Default | Description |
|---|---|---|
| `POB_DIRECTORY` | OS-default Builds dir | Path to your PoB builds directory |
| `POB_LUA_ENABLED` | `false` | Set `"true"` to enable Lua bridge |
| `POB_FORK_PATH` | `~/Projects/PathOfBuilding-PoE2/src` | Path to PathOfBuilding-PoE2/src |
| `POB_CMD` | `luajit` | LuaJIT binary path |
| `POB_TIMEOUT_MS` | `10000` | Lua request timeout (ms) |
| `POE_TRADE_ENABLED` | `false` | Enable Trade API tools (PoE2 `trade2` endpoints — Cloudflare/session-gated, see below) |
| `POE_SESSION_ID` | — | Your `POESESSID` cookie — required for most Trade API calls (Cloudflare/auth) |
| `POE_TRADE_BASE` | `…/api/trade2` | Override the trade API base path if GGG changes it |
| `POE_TRADE_USER_AGENT` | `pob2-mcp-server/0.1 …` | Descriptive contactable User-Agent for trade requests |
| `POE_NINJA_DISABLED` | `false` | Set `"true"` to hide poe.ninja tools (ported to the PoE2 economy endpoint; on by default) |
| `POB_LEGACY_GEM_TOOLS` | `false` | Expose the legacy PoE1 skill-gem tools (⚠️ PoE1 gem model; prefer the engine-backed gem tools) |

### Setting Up the Lua Bridge

The Lua bridge uses PoB's actual calculation engine for accurate stats.

#### 1. Install LuaJIT
```bash
# macOS
brew install luajit

# Ubuntu/Debian
sudo apt-get install luajit

# Windows: download from https://luajit.org/ and add to PATH
```

#### 2. Get a PathOfBuilding-PoE2 checkout (no patching required)
The api-stdio bridge is now **vendored inside this repo** at `pob-api/`
(`pob-api/bootstrap.lua`, `pob-api/API/{Server,Handlers,BuildOps}.lua`, `pob-api/utf8.lua`). The
server launches `luajit pob-api/bootstrap.lua` with the working directory set to PoB's `src/`, so
it drives an **unmodified** PathOfBuilding-PoE2 checkout — you no longer patch `HeadlessWrapper.lua`
or copy files into the PoB tree.

Point `POB_FORK_PATH` at the `src/` directory of any compatible PathOfBuilding-PoE2 checkout (the
sibling `PathOfBuilding-PoE2/` works, as does a clean upstream clone). "Compatible" means a version
whose internals `pob-api/API/BuildOps.lua` expects; a wildly newer/older PoB may drift.

#### 3. Verify
```bash
luajit -v
ls "$POB_FORK_PATH/Launch.lua"        # PoB src (must exist)
ls pob-api/bootstrap.lua              # vendored bridge entry (must exist)
```

#### 4. Update Claude Desktop config and restart Claude Desktop

---

## Available Tools

The server registers **91 tools** across 10 categories.

### XML-Based Tools (Always Available)

| Tool | Description |
|---|---|
| `list_builds` | List all `.xml` build files |
| `analyze_build` | Full build summary: class, stats, skills, items, tree |
| `compare_builds` | Side-by-side build comparison |
| `get_build_stats` | Extract raw stats from build XML |
| `get_build_notes` | Get build notes from XML |
| `set_build_notes` | Set build notes in XML |
| `start_watching` | Monitor builds directory for changes |
| `stop_watching` | Stop file monitoring |
| `watch_status` | Show watching status and cache info |
| `get_recent_changes` | List recently modified builds |
| `refresh_tree_data` | Clear passive tree data cache |

### Tree Analysis Tools (Always Available)

| Tool | Description |
|---|---|
| `compare_trees` | Show node differences between two builds |
| `get_nearby_nodes` | Find notables/keystones reachable from current allocation |
| `find_path_to_node` | Shortest path to a target node ID |
| `get_passive_upgrades` | Suggest passive tree upgrades |
| `suggest_masteries` | Suggest mastery choices for allocated clusters |

### Lua Bridge — Core (Require `POB_LUA_ENABLED=true`)

| Tool | Description |
|---|---|
| `lua_start` | Start the PoB calculation engine (stdio or TCP) |
| `lua_stop` | Stop the engine and free resources |
| `lua_new_build` | Create a blank build for a given class/ascendancy |
| `lua_load_build` | Load a build file into the engine |
| `lua_save_build` | Save the current in-memory build to a `.xml` file |
| `lua_reload_build` | Reload the current build from disk |
| `lua_get_build_info` | Get current build metadata (class, level, etc.) |
| `set_character_level` | Set level and recalculate all stats |
| `lua_get_stats` | Get calculated stats (`category`: `offense`/`defense`/`all`) |
| `lua_get_tree` | View passive tree: class, ascendancy, all allocated node IDs |
| `lua_set_tree` | Replace passive tree allocation (preserves class if omitted) |
| `update_tree_delta` | Add/remove individual nodes without replacing entire tree |
| `search_tree_nodes` | Search passive tree by name or stat text |
| `list_specs` | List all tree specs in the current build |
| `select_spec` | Switch active tree spec |
| `create_spec` | Create a new tree spec |
| `delete_spec` | Delete a tree spec |
| `rename_spec` | Rename a tree spec |
| `list_item_sets` | List all item sets in the current build |
| `select_item_set` | Switch active item set |
| `plan_leveling` | Generate a leveling plan for a build |

**`lua_set_tree` class IDs (PoE2)**: 1=Witch, 2=Ranger, 6=Warrior, 7=Sorceress, 8=Huntress, 9=Mercenary, 10=Monk, 11=Druid. Call `get_classes` for the live list (classes/ascendancies can change between PoE2 patches).

**Ascendancy IDs (PoE2)** — per class, e.g. Witch: 1=Infernalist, 2=Blood Mage, 3=Lich, 4=Abyssal Lich; Monk: 1=Martial Artist, 2=Invoker, 3=Acolyte of Chayula. Use `get_classes` for the full, current mapping.

**`lua_save_build` is required** before using file-based tools (`validate_build`, `analyze_build`, etc.) on an in-memory build.

### Lua Bridge — Item & Skill Management

| Tool | Description |
|---|---|
| `add_item` | Add item from PoE clipboard text to a slot |
| `add_multiple_items` | Add multiple items in one operation |
| `get_equipped_items` | List all equipped gear with name, base, and rarity |
| `toggle_flask` | Activate/deactivate flask 1–5; returns updated stats |
| `get_skill_setup` | Show all socket groups with gems, levels, and quality |
| `set_main_skill` | Set which group/gem is used for DPS calculations |
| `create_socket_group` | Create a new socket group (label, slot, enabled) |
| `add_gem` | Add a gem to a socket group (name, level, quality) |
| `set_gem_level` | Set gem level by group + gem index |
| `set_gem_quality` | Set gem quality (Default/Anomalous/Divergent/Phantasmal) |
| `remove_gem` | Remove a gem by group + gem index |
| `remove_skill` | Remove an entire socket group |
| `setup_skill_with_gems` | Create a socket group with active gem + supports in one call |

**Slot names**: `Weapon 1`, `Weapon 2`, `Helmet`, `Body Armour`, `Gloves`, `Boots`, `Amulet`, `Ring 1`, `Ring 2`, `Belt`, `Flask 1`–`Flask 5`

### Lua Bridge — Build Optimization

| Tool | Description |
|---|---|
| `analyze_defenses` | 3-layer defensive audit: avoidance / mitigation / recovery |
| `suggest_optimal_nodes` | Archetype-aware node suggestions by goal |
| `optimize_tree` | Recommend nearby nodes to allocate for a goal |
| `analyze_items` | Slot-by-slot item analysis with upgrade priorities |
| `optimize_skill_links` | Audit supports: "more" multipliers, penetration, anti-synergies |
| `create_budget_build` | Generate a starter build plan for a class/skill/budget |
| `get_build_issues` | Get prioritized list of build problems and suggestions |
| `check_boss_readiness` | Evaluate readiness for specific boss encounters |
| `suggest_watchers_eye` | Suggest Watcher's Eye mods for the build's auras |

**`suggest_optimal_nodes` goals**: `damage`, `defense`, `life`, `es`, `resist`, `speed`

**Defensive layers**:
- **Avoidance** — evasion, spell suppression, dodge, block
- **Mitigation** — armour/PDR, endurance charges
- **Recovery** — life regen (≥1%/s), leech, ES recharge

A build with all 3 layers is considered exceptional.

### Configuration & Enemy Settings

| Tool | Description |
|---|---|
| `get_config` | View bandit, pantheon, and enemy settings |
| `set_config` | Toggle charges, buffs, conditions (e.g. `usePowerCharges`, `enemyIsBoss`) |
| `set_enemy_stats` | Set enemy level, resistances, armour, evasion for DPS scenarios |
| `save_config_preset` | Save current config as a named preset |
| `load_config_preset` | Load a saved config preset |
| `list_config_presets` | List all saved config presets |

### Build Validation

| Tool | Description |
|---|---|
| `validate_build` | Check resistances, life, defensive layers, mana, immunities, accuracy, damage scaling |

Returns critical issues, warnings, and info with actionable suggestions and an overall 0–10 health score. Uses Lua bridge stats when available; falls back to XML parsing. `build_name` is optional — omitting it validates the currently loaded Lua bridge build.

### Skill Gem Analysis (PoE2, engine-backed — preferred)

| Tool | Description |
|---|---|
| `analyze_skills` | Engine-truth breakdown of each socket group: active skill + supports, flags tag-mismatched supports, empty/disabled/unknown gems |
| `suggest_supports` | Compatible supports for a group's active skill from PoB2's gem DB; ranked by tag relevance, or by **real measured DPS** with `measure_dps=true` |
| `list_gems` | Query PoB2's authoritative gem database (active/support, tags, family, requirements, max level) |
| `get_classes` | PoE2 classes + ascendancy IDs from the engine |

#### Legacy PoE1 gem tools (not registered by default)

`analyze_skill_links`, `suggest_support_gems`, `validate_gem_quality`, `compare_gem_setups`,
`find_optimal_links`, `gem_upgrade_path` use a hand-coded PoE1 gem DB / archetype templates and a
6-link + Awakened-gem model that does not match PoE2. They are **disabled by default**; set
`POB_LEGACY_GEM_TOOLS=true` to expose them. Prefer the engine-backed tools above.

### Build Export & Persistence

| Tool | Description |
|---|---|
| `export_build` | Copy a build to a new XML file with optional notes |
| `save_tree` | Write passive tree back to an existing build file |
| `snapshot_build` | Create a versioned snapshot with description and tag |
| `list_snapshots` | List all snapshots for a build |
| `restore_snapshot` | Restore from a snapshot (auto-backs up current state) |
| `export_build_summary` | Export a human-readable build summary |

Snapshots are stored in `POB_DIRECTORY/.pob-mcp/snapshots/`.

**Note**: `export_build` copies from the XML file, not from the Lua bridge. Use `lua_save_build` first if you want to export in-memory changes.

### Currency & Market Data (poe.ninja)

| Tool | Description |
|---|---|
| `get_currency_rates` | Live PoE2 currency exchange rates (Exalted Orb equivalent) |
| `find_arbitrage` | Detect profitable currency trading loops (see note) |
| `calculate_trading_profit` | Evaluate a specific trading chain |

Sourced from the **PoE2** poe.ninja economy endpoint
(`/poe2/api/economy/exchange/current/overview?league=<League>&type=Currency`), cached 5 min.
**Live-verified.** Pass the **exact**, case-sensitive PoE2 league name (e.g., `Runes of Aldur`, `Standard`).
Values are in **Exalted Orb** equivalent (PoE2's base currency), not Chaos.

> **Note:** the PoE2 currency-exchange feed exposes a single value per currency (no separate buy/sell
> spread), so `find_arbitrage` generally returns nothing — round-trips evaluate to ~0% profit.
> `get_currency_rates` and `calculate_trading_profit` are the useful tools here.

### Trade API Tools (Require `POE_TRADE_ENABLED=true`)

Ported to the **PoE2 `trade2`** endpoints (`https://www.pathofexile.com/api/trade2`). Stat IDs and
leagues are fetched from this base, so the stat mapper picks up PoE2 trade stats automatically.

> **Heads up:** the official trade API is behind Cloudflare and most endpoints require a logged-in
> session — set `POE_SESSION_ID` to your `POESESSID` cookie. It is also strictly rate-limited.
> **Verified working server-side** (search→fetch through Cloudflare with only `POE_SESSION_ID` set).
> Note POESESSID expires periodically; refresh it if you start getting 401/403s.

| Tool | Description |
|---|---|
| `search_trade_items` | Search trade with stat filters, price range, link count |
| `get_item_price` | Price statistics (min/max/median/average) for an item |
| `get_leagues` | List available leagues |
| `search_stats` | Look up Trade API stat IDs |
| `find_item_upgrades` | Identify best upgrade candidates for your build |
| `find_resistance_gear` | Find affordable gear to cap specific resistances |
| `compare_trade_items` | Compare multiple trade listings side by side |
| `search_cluster_jewels` | Search for cluster jewels by notable |
| `analyze_build_cluster_jewels` | Evaluate cluster jewel setups for a build |
| `generate_shopping_list` | Generate a prioritized shopping list from build analysis |

---

## Typical Workflows

### Analyze an existing build
```
1. lua_start
2. lua_load_build (build_name: "MyBuild.xml")
3. lua_get_stats (category: "defense")
4. validate_build
5. analyze_defenses (build_name: "MyBuild.xml")
```

### Build from scratch
```
1. lua_start
2. lua_new_build (class_name: "Witch", ascendancy: "Necromancer")
3. setup_skill_with_gems (active_gem: "Summon Skeletons", support_gems: [...])
4. lua_set_tree (nodes: [...])
5. lua_get_stats
6. lua_save_build (build_name: "MySummoner.xml")
```

### Optimize passive tree
```
1. lua_load_build (build_name: "MyBuild.xml")
2. suggest_optimal_nodes (goal: "life", points_available: 5)
3. search_tree_nodes (query: "maximum life")
4. lua_get_tree   ← copy current node list
5. lua_set_tree   ← add new nodes to the list
6. lua_get_stats  ← verify improvement
7. lua_save_build ← persist
```

### Test DPS against Shaper
```
1. lua_load_build
2. set_enemy_stats (level: 84, fire_resist: 40, cold_resist: 40, lightning_resist: 40)
3. set_config (config_name: "enemyIsBoss", value: true)
4. lua_get_stats (category: "offense")
```

---

## Troubleshooting

### XML Features

**No builds found**
- Verify `POB_DIRECTORY` is correct and contains `.xml` files
- Check file permissions

**Parse errors**
- Open the build in PoB GUI to verify it isn't corrupted
- Ensure PoB is up to date

### Lua Bridge

**`luajit command not found`**
```bash
brew install luajit          # macOS
sudo apt-get install luajit  # Ubuntu/Debian
```
Or set `POB_CMD` to the full path (e.g., `/opt/homebrew/bin/luajit`).

**`Failed to find valid ready banner`**
`POB_FORK_PATH` must point to a PathOfBuilding-PoE2 `src/` directory:
```bash
ls "$POB_FORK_PATH/Launch.lua"   # must exist (PoB src)
ls "$POB_FORK_PATH/Modules/"     # must exist
ls pob-api/bootstrap.lua         # vendored bridge entry (must exist)
```

**`Timed out waiting for response`**
- Increase `POB_TIMEOUT_MS` (try `20000`)
- Test manually: `cd "$POB_FORK_PATH" && luajit /abs/path/to/pob-api/bootstrap.lua`

**Stats don't match PoB GUI**
- Check bandit/pantheon/enemy settings with `get_config`
- Ensure the correct tree spec is active in the XML
- Make sure your PathOfBuilding fork is on the `api-stdio` branch and up to date

**Bridge becomes unresponsive**
```
lua_stop → wait a moment → lua_start
```
If still unresponsive, restart Claude Desktop.

**Nodes dropped after `lua_set_tree`**
Nodes must form a valid connected path from the class starting node. Disconnected nodes are silently dropped by PoB. Ensure all intermediate nodes are included.

**`lua_save_build` doesn't persist gem changes**
Gem modifications made via `add_gem`, `set_gem_level`, `set_gem_quality` are currently held in Lua memory and are not serialized back to the XML on save. This is a known limitation.

---

## Development

```bash
npm run build   # compile TypeScript
npm run dev     # watch mode
```

## Path of Building XML Structure

PoB builds are XML files with:
- `<Build>`: Character info and stats
- `<Tree>`: Passive skill tree node allocations
- `<Skills>`: Socket groups and gem links
- `<Items>`: Equipped items
- `<Notes>`: Build notes

## Contributing

Issues and pull requests are welcome!

## Contributors

<table>
	<tbody>
		<tr>
            <td align="center">
                <a href="https://github.com/zgrummons">
                    <img src="https://avatars.githubusercontent.com/u/22529961?v=4" width="100;" alt="zgrummons"/>
                    <br />
                    <sub><b>zgrummons</b></sub>
                </a>
            </td>
		</tr>
	</tbody>
</table>

## License

GPL-3.0

TDQS

B3.4/5.0

Scored across 30 tools

Disambiguation3/5

Several tools have overlapping responsibilities, most notably analyze_defenses and validate_build where the description explicitly notes the redundancy. The tree-related tools are distinct but numerous, requiring careful reading to select the right one.

Naming Consistency4/5

The vast majority of tools follow a consistent verb_noun pattern (get_, analyze_, list_, compare_, etc.), making the API predictable. Minor deviations like 'watch_status' (rather than 'get_watch_status') break the pattern slightly.

Tool Count2/5

At 30 tools, the server is on the heavy side, exceeding the typical well-scoped range. While the tools span several sub-domains (builds, tree, currency, snapshots), the set could likely be consolidated.

Completeness4/5

The server covers a broad range of build management tasks including analysis, optimization, snapshots, file watching, and currency arbitrage. Notable gaps include no delete_build tool and no way to import a build from a file path directly (though export exists).

Maintenance

ActivityInactive
ResponsivenessNo issues