POB-MCP
Cargar, inspeccionar y optimizar builds de Path of Exile 2 usando el motor de cálculo real de Path of Building.
Documentación
pob-mcp
pob-mcp es un servidor MCP. Permite que un LLM cargue, inspeccione, modifique y mejore builds de Path of Exile 2. Utiliza el motor de cálculo real de https://github.com/PathOfBuildingCommunity/PathOfBuilding-PoE2. No reimplementa ese motor.
pob-mcp ejecuta una copia real y sin interfaz gráfica de PoB (un programa Lua) como proceso en segundo plano. Se comunica con ese proceso mediante un pequeño protocolo JSON-RPC. Cada estadística que obtienes es un número que el propio PoB calculó.
Cómo funciona
MCP client (Claude Desktop, Cursor, ...)
| MCP over stdio
v
pob-mcp (Python) -- tools_*.py, optimizer/
| JSON-RPC over stdio
v
lua/pob_bridge.lua (running under `luajit`)
| dofile()
v
Path of Building - PoE2's own Lua source (Launch.lua, Main.lua, ...)
lua/pob_bridge.lua es un fork del propio src/HeadlessWrapper.lua de PoB, que
PoB usa para su suite de pruebas. pob-mcp no depende directamente de ese archivo.
Las copias instaladas de PoB omiten HeadlessWrapper.lua (ver
manifest.cfg), así que pob-mcp incluye su propia versión. Esto significa
que pob-mcp funciona de la misma manera tanto con un checkout de git de PathOfBuilding-PoE2
como con una versión de lanzamiento instalada.
Antes de empezar
Necesitas cuatro cosas:
- Una forma de instalar un paquete de Python. Recomendamos
uv — es la vía más rápida y lo que el
resto de este README muestra primero. ¿No quieres otra herramienta en tu máquina?
Un
pipnormal y un entorno virtual también funcionan bien; consulta los comandos alternativos más abajo. - LuaJIT, una compilación compatible con 5.1. Ponlo en tu
PATHcomoluajit, o apunta a él conPOB_MCP_LUAJIT. Lo necesitas por separado de PoB: el runtime propio de PoB solo incluyelua51.dll/SimpleGraphic.dllpara su aplicación gráfica. No incluye un intérprete de línea de comandos que puedas ejecutar por sí solo.- Windows: instálalo con Scoop
(
scoop install luajit), Chocolatey (choco install luajit), o una compilación portable. - macOS:
brew install luajit. - Linux:
apt install luajit, el equivalente para tu distribución, o compílalo desde el código fuente.
- Windows: instálalo con Scoop
(
- Una instalación de Path of Building - PoE2. Puede ser un checkout de git (este repositorio, o tu propio clon) o una versión de lanzamiento instalada. Consulta "Apunta pob-mcp a una instalación de PoB" más abajo.
- zlib. pob-mcp lo necesita para leer y escribir códigos de build, y para
calcular datos de Joyas Atemporales. En Windows, ya lo tienes: PoB
incluye
zlib1.dll(enruntime/para un checkout, o junto a todo lo demás para una versión de lanzamiento instalada). En Linux y macOS, instala el paquetezlib/libzde tu sistema si no lo tienes ya (la mayoría de los sistemas lo tienen). Si pob-mcp no puede encontrar zlib, todo sigue funcionando excepto los códigos de build pegados o compartidos y los cálculos de Joyas Atemporales. Carga y exporta builds como archivos.xmlen su lugar.
Apunta pob-mcp a una instalación de PoB
pob-mcp necesita saber dónde tu instalación de Path of Building - PoE2 guarda su código fuente Lua, porque es contra lo que el proceso puente se ejecuta. Hay dos formas de apuntar hacia allí. Ten en cuenta que las dos tienen diseños diferentes en disco — pob-mcp detecta automáticamente cuál estás usando.
- Modo checkout de desarrollo. Establece
POB_MCP_SOURCE_DIRa un checkout de git de PathOfBuilding-PoE2 — ya sea su carpeta raíz, o su carpetasrcdirectamente. Este diseño mantiene el código fuente Lua bajosrc/, y mantiene el runtime nativo (DLLs de LuaJIT, zlib, las bibliotecas Lua incluidas) en una carpetaruntime/separada junto a él. - Modo de lanzamiento. Establece
POB_MCP_INSTALL_DIRa la carpeta raíz de una versión de lanzamiento instalada. En Windows, esto suele ser%APPDATA%\Path of Building Community (PoE2). Una versión de lanzamiento instalada pone todo en una sola carpeta —Launch.lua,Modules/,zlib1.dll, las bibliotecaslua/incluidas — en lugar de dividirlo. (Verificamos esto contra una instalación real. No lo adivinamos solo desde la configuración de empaquetado del repositorio).
Si no estableces ninguna de las dos variables, pob-mcp verifica algunas ubicaciones de instalación comunes para tu sistema operativo, y te da un error claro si no puede encontrar una. En Windows, esto ya encuentra una copia instalada normalmente mediante el instalador sin ninguna configuración de tu parte.
Instala pob-mcp
git clone <this repo, or wherever you put pob-mcp> pob-mcp
cd pob-mcp
uv sync
¿No quieres usar uv? No lo necesitas. pob-mcp es un paquete normal de
Python — un pip simple también funciona:
git clone <this repo, or wherever you put pob-mcp> pob-mcp
cd pob-mcp
python -m venv .venv
.venv/bin/pip install -e . # Windows: .venv\Scripts\pip install -e .
Ejecútalo por sí solo (para pruebas)
POB_MCP_SOURCE_DIR=/path/to/PathOfBuilding-PoE2 uv run pob-mcp
# or, against an installed release:
POB_MCP_INSTALL_DIR="C:\Users\you\AppData\Roaming\Path of Building Community (PoE2)" uv run pob-mcp
Con una instalación simple de pip, lo mismo se ve así:
POB_MCP_SOURCE_DIR=/path/to/PathOfBuilding-PoE2 .venv/bin/pob-mcp # Windows: .venv\Scripts\pob-mcp.exe
Esto inicia el servidor MCP a través de stdio. No verás mucho que pase — los servidores MCP hablan con clientes MCP, no directamente contigo. Consulta "Comprueba que funciona", más abajo, para una forma de probarlo sin un cliente completo.
Úsalo con Claude Desktop, Cursor u otro cliente MCP
Añade una entrada a la configuración del servidor MCP de tu cliente. Para Claude Desktop, esto
es claude_desktop_config.json. Para Cursor, es mcp.json.
{
"mcpServers": {
"pob-mcp": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/pob-mcp", "run", "pob-mcp"],
"env": {
"POB_MCP_SOURCE_DIR": "/absolute/path/to/PathOfBuilding-PoE2"
}
}
}
}
Para el modo de lanzamiento, usa POB_MCP_INSTALL_DIR en su lugar. Apúntalo a la carpeta
raíz de tu versión de lanzamiento instalada — en Windows, normalmente
%APPDATA%\Path of Building Community (PoE2):
{
"mcpServers": {
"pob-mcp": {
"command": "uv",
"args": ["--directory", "C:\\path\\to\\pob-mcp", "run", "pob-mcp"],
"env": {
"POB_MCP_INSTALL_DIR": "C:\\Users\\you\\AppData\\Roaming\\Path of Building Community (PoE2)"
}
}
}
}
Reinicia tu cliente después de editar su configuración. No necesitas cerrar Path of Building en sí. pob-mcp solo lee datos del juego desde la carpeta de instalación. Nunca escribe en ella, así que funciona bien junto a la aplicación.
Con una instalación simple de pip (sin uv), apunta command directamente al
ejecutable que pip creó en tu entorno virtual — no se necesita args:
{
"mcpServers": {
"pob-mcp": {
"command": "C:\\path\\to\\pob-mcp\\.venv\\Scripts\\pob-mcp.exe",
"env": {
"POB_MCP_INSTALL_DIR": "C:\\Users\\you\\AppData\\Roaming\\Path of Building Community (PoE2)"
}
}
}
}
(En macOS/Linux, eso es /path/to/pob-mcp/.venv/bin/pob-mcp.)
Variables de entorno
| Variable | Qué hace |
|---|---|
POB_MCP_SOURCE_DIR | Ruta a un checkout de git de PathOfBuilding-PoE2 (su carpeta raíz o src/) |
POB_MCP_INSTALL_DIR | Ruta a la carpeta raíz de una versión de lanzamiento instalada |
POB_MCP_LUAJIT | Ruta a un ejecutable de luajit, si no está en PATH |
POB_MCP_ZLIB_PATH | Ruta o nombre para cargar zlib, si pob-mcp no puede encontrarlo por sí solo |
POB_MCP_BUILDS_DIR | Ruta a tu carpeta de Builds de PoB, para list_local_builds |
POB_MCP_LOG_LEVEL | Nivel de registro para el lado de Python (por defecto INFO); la salida del puente se registra en DEBUG |
Qué puedes hacer con él
Una vez que tu cliente esté conectado, empieza con load_build. Luego usa las otras
herramientas para inspeccionar, cambiar y mejorar el build. Cada herramienta que cambia el
build también devuelve su stats actualizado, así que no necesitas una llamada
separada a get_stats para ver el efecto de un cambio. La descripción completa de cada herramienta
(parámetros, comportamiento, casos límite) aparece en tu cliente MCP — las listas
de abajo son solo nombres y un resumen de una línea, para ayudarte a encontrar la correcta.
Una nota sobre los ids: las gemas y las clases se identifican por un id interno, no por su
nombre mostrado. El id de gema de Fireball, por ejemplo, es
"Metadata/Items/Gems/SkillGemFireball", y select_class toma un
id de clase interno, no un índice simple basado en 0. Usa list_gems y
list_classes para buscarlos en lugar de adivinar — un id de gema incorrecto
no genera un error, simplemente falla silenciosamente al resolverse, así que la gema no
hace nada.
Cargar un build (3 herramientas)
| Herramienta | Qué hace |
|---|---|
load_build | Carga un build desde un código de exportación de PoB, un enlace de pobb.in/Maxroll/poe.ninja/poe2db.tw/Pastebin.com/Rentry.co, una ruta local de .xml, o texto XML sin procesar |
new_build | Inicia un build nuevo y en blanco (clase por defecto, sin objetos ni habilidades) |
list_local_builds | Lista los archivos .xml en tu carpeta de Builds de PoB |
Inspeccionar un build (13 herramientas)
| Herramienta | Qué hace |
|---|---|
get_stats | Obtiene estadísticas calculadas (vida, ES, maná, resistencias, DPS, EHP, etc.) del motor real de PoB |
list_stat_keys | Lista cada clave de estadística disponible desde get_stats para este build |
get_character | Obtiene clase, ascendencia y nivel |
list_classes | Lista cada clase y sus ascendencias, para usar con select_class |
get_tree_state | Obtiene los ids de nodos del árbol pasivo asignados y su cantidad |
node_info | Obtiene detalles de un nodo del árbol pasivo |
search_tree | Busca en el árbol pasivo por nombre, texto de estadística, tipo o ascendencia |
get_items | Lista cada ranura de equipo/joya y lo que contiene |
get_skills | Lista los grupos de habilidades/engastes y sus gemas |
list_gems | Busca el id interno de una gema, para usar con add_gem |
get_config | Obtiene los valores actuales de las opciones de configuración |
list_config_options | Lista cada opción de configuración que PoB soporta |
sanity_check | Ejecuta comprobaciones de sanidad defensivas (resistencias sin límite, vida baja, etc.) |
Cambiar un build (13 herramientas)
| Herramienta | Qué hace |
|---|---|
alloc_node / dealloc_node | Asigna o desasigna un nodo del árbol pasivo (ruta auto-calculada) |
node_path_cost | Obtiene el costo de puntos para alcanzar un nodo, sin asignarlo |
select_class | Cambia clase y/o ascendencia |
equip_item_raw / unequip_item | Equipa texto de objeto en bruto del juego en una ranura, o elimina lo que hay |
add_socket_group | Crea un nuevo grupo de habilidades/engastes vacío |
set_main_skill | Establece qué grupo de engastes se usa para los cálculos de DPS |
add_gem / remove_gem / set_gem | Añade, elimina o edita el nivel/calidad/estado habilitado de una gema |
list_valid_supports | Lista las gemas de soporte que PoB considera válidas para una habilidad |
set_config | Establece una opción de configuración |
Gestionar especificaciones de árbol y conjuntos de equipo (12 herramientas)
Un build puede contener varias especificaciones de árbol pasivo con nombre y varios conjuntos
de equipo con nombre, y cambiar entre ellos. Una vez que cambias uno, cada otra herramienta
(get_tree_state, get_items, etc.) actúa sobre aquel al que cambiaste.
| Herramienta | Qué hace |
|---|---|
list_specs | Lista las especificaciones de árbol pasivo del build |
select_spec | Cambia la especificación de árbol pasivo activa |
create_spec | Crea una nueva especificación de árbol pasivo en blanco |
copy_spec | Duplica una especificación de árbol pasivo |
rename_spec | Renombra una especificación de árbol pasivo |
delete_spec | Elimina una especificación de árbol pasivo (un build siempre necesita al menos una) |
list_item_sets | Lista los conjuntos de equipo del build |
select_item_set | Cambia el conjunto de equipo activo |
create_item_set | Crea un nuevo conjunto de equipo vacío |
copy_item_set | Duplica un conjunto de equipo |
rename_item_set | Renombra un conjunto de equipo |
delete_item_set | Elimina un conjunto de equipo (un build siempre necesita al menos uno) |
Mejorar un build (1 herramienta)
| Herramienta | Qué hace |
|---|---|
optimize_build | Ejecuta una búsqueda dirigida por objetivos (damage/defence/balanced) sobre el árbol pasivo, gemas de soporte y objetos únicos locales, puntuando cada cambio candidato contra el motor real de PoB |
Comparar o exportar (2 herramientas)
| Herramienta | Qué hace |
|---|---|
compare_builds | Compara dos builds lado a lado, sin tocar el build cargado en esta sesión |
export_build | Exporta el build cargado como XML o un código compartible |
Lo que esto no hace (a propósito)
Estas son decisiones, no errores:
- El optimizador nunca cambia las opciones de configuración (buffs, maldiciones,
estadísticas de enemigos, modificadores de mapas). Si pudiera, podría aumentar su propia
puntuación asumiendo un escenario poco realista. Llama tú mismo a
set_configprimero si quieres optimizar para un escenario específico. - La búsqueda de objetos y joyas solo usa la base de datos local de PoB. El alcance
de
itemsdeoptimize_buildprueba objetos de la base de datos única incluida de PoB, para la misma ranura. No consulta precios de sitios de comercio, ni busca opciones de creación de objetos raros. - El optimizador no busca joyas por sí solo. Emparejar una joya con
el enchufe correcto aún no es lo suficientemente fiable. Puedes probar una joya
específica manualmente: usa
list_uniques_for_sloty luegoequip_item_raw. - El optimizador es una búsqueda codiciosa, no un solucionador perfecto. Solo añade nodos del árbol — nunca elimina ni reemplaza los existentes — y solo intercambia una gema u objeto a la vez. Puede quedarse atascado en una respuesta buena pero no óptima que una búsqueda más amplia podría superar.
- pob-mcp no puede importar un perfil de personaje en vivo de poe.ninja. Puede importar un pob-link de poe.ninja igual que cualquier otro sitio compatible, pero un perfil de personaje en vivo es diferente: necesita la API oficial de personajes, y esta versión aún no se comunica con esa API. Exporta el personaje a un código o enlace de PoB primero, y usa eso en su lugar.
- pob-mcp no vigila tu carpeta de Builds para detectar cambios.
list_local_buildslista lo que hay allí cuando lo llamas. No envía actualizaciones cuando algo cambia. Para una sesión impulsada por LLM, llamar a la herramienta de nuevo es más simple y funciona igual de bien.
Comprueba que funciona
Las pruebas automatizadas (ejecutadas con uv run pytest) vienen en dos grupos:
- Pruebas que no tocan PoB en absoluto (
test_importers.py,test_optimizer_goals.py,test_optimizer_moves.py,test_locate.py). Estas se ejecutan en cualquier lugar — no necesitas LuaJIT ni una instalación de PoB. test_bridge_protocol.pyejecuta un proceso de puente real de principio a fin: inicia una nueva build, busca en el árbol, asigna y desasigna nodos, guarda y recarga, lista opciones de configuración y ejecuta una verificación de cordura. Si no puede encontrarPOB_MCP_SOURCE_DIR,POB_MCP_INSTALL_DIR, o un ejecutable deluajit, se omite a sí mismo y te dice por qué. Configura esas variables de entorno para ejecutarlo realmente.
Para probar el puente manualmente, sin un cliente MCP completo:
cd /path/to/PathOfBuilding-PoE2/src
luajit /absolute/path/to/pob-mcp/lua/pob_bridge.lua
Luego escribe (o introduce mediante tubería) solicitudes JSON-RPC, una por línea:
{"id": 1, "method": "new_build", "params": {}}
{"id": 2, "method": "get_stats", "params": {}}
Cada una debería imprimir de vuelta una línea {"id": ..., "result": {...}}.
Dónde están las cosas
pob-mcp/
lua/
json.lua # self-contained JSON codec for the bridge protocol
pob_bridge.lua # the headless PoB bridge + JSON-RPC loop
src/pob_mcp/
server.py # MCP server entrypoint, tool registration
bridge.py # subprocess + JSON-RPC client for pob_bridge.lua
locate.py # finds a PoB install + luajit
sites.py # pobb.in/Maxroll/poe.ninja/etc. URL -> build code
importers.py # unifies code/URL/file/XML into one load_build path
tools_*.py # MCP tool definitions, grouped by area
optimizer/ # goal-directed build search
tests/