IBKR Portfolio Builder
Investigación de carteras de arriba hacia abajo para Interactive Brokers con un catálogo tipificado de 468 filtros de IBKR etiquetados por intención de estrategia. Solo lectura.
Documentación
ibkr-portfolio-builder-mcp
Un servidor MCP remoto para la construcción de carteras de arriba hacia abajo con Interactive Brokers. Diseñado para usarse como conector personalizado de Claude.ai, MCP de Claude Code, o cualquier cliente HTTP MCP.
La mayoría de los servidores ibkr-mcp exponen primitivas de búsqueda individuales —
get_quote,get_position,place_order. Este expone el flujo de trabajo de investigación: un catálogo tipado de 468 screener en 16 categorías etiquetadas por intención de estrategia (valor / crecimiento / ingresos / momentum / calidad / eventos / …), instrumentos aplicables por escaneo, enlaces de pares inversos y acceso a noticias/cuenta en vivo — para que un LLM pueda hacer una construcción de carteras real de arriba hacia abajo (elegir sectores / estrategias → ejecutar escaneos → contrastar con noticias → reducir a candidatos) en lugar de buscar tickers de abajo hacia arriba.
Por qué existe esto
Lo construí porque los servidores IBKR-MCP existentes en la comunidad tratan a IBKR como una fuente de datos de "buscar un ticker". Eso refleja cómo funcionan la mayoría de las interfaces de los brókeres minoristas, pero no es así como se hace una buena construcción de carteras.
Un buen flujo de trabajo de arriba hacia abajo se ve así:
- Tesis macro ("las tasas están por caer, los pagadores de dividendos deberían revalorizarse") →
- Intención de estrategia ("muéstrame screener de ingresos con sesgo de calidad en grandes capitalizaciones de EE. UU.") →
- Composición del screener (ejecutar screener de rendimiento de dividendos + ROE + baja deuda; intersectar) →
- Contexto de eventos/noticias ("¿alguno de estos tiene ganancias en las próximas dos semanas? ¿alguna acción negativa de analistas?") →
- Conjunto de candidatos reducido ("cinco tickers, clasificados por mis criterios, listos para un análisis más profundo").
Para hacer eso con un LLM, el servidor MCP necesita exponer el vocabulario de investigación, no solo la API cruda. Esa es la brecha que este servidor llena:
- Un catálogo de escaneos tipado — 468 códigos de escaneo de IBKR en 16 categorías (
Fundamentals,Price Movement,Dividends,Options & Volatility,Events & Earnings,52/26/13 Week High-Low,ESG,Bonds, …) autoetiquetados con 28 etiquetas de intención de estrategia (value,growth,quality,income,momentum_up,momentum_down,analyst,technical,gap,volatility,events,leverage,efficiency,risk_adjusted, …). El LLM pregunta "¿qué escaneos de valor existen para acciones de EE. UU.?" y obtiene una respuesta limpia y filtrable en lugar de intentar adivinar códigos de escaneo a partir de datos de entrenamiento. - Enlaces de pares inversos — cada par
HIGH_X ↔ LOW_XyX_ASC ↔ X_DESCestá precalculado, para que el LLM pueda invertir la polaridad ("¿cuál es lo opuesto de LOW_PE_RATIO?") sin adivinar. - Mapa de instrumentos por escaneo — el catálogo sabe qué escaneo aplica a
STK,ETF,OPT,BOND, etc. El LLM deja de enviar escaneos de Refinitiv a instrumentos de bonos y obtener resultados vacíos. - Catálogo de filtros — mapa tipado separado de los filtros numéricos (
priceAbove,peRatioBelow,divYieldAbove,growthRateAbove,avgVolumeAbove,marketCapAbove, …) agrupados por categoría, con notas de aplicabilidad por instrumento. - Noticias + screener en una sola superficie de herramientas — mismo conector, misma autenticación, misma conversación. El LLM puede intersectar un resultado de escaneo con titulares recientes o ganancias próximas sin cambiar de contexto.
- Dos modos de autenticación — OAuth 2.1 completo (DCR + PKCE + well-knowns) para conectores personalizados de Claude.ai, más un token bearer estático para todo lo demás. Mismo servidor, mismas herramientas.
Sigue siendo un servidor temprano. La API de IBKR tiene muchas restricciones sobre lo que una cuenta de papel puede ver realmente (notablemente el derecho a noticias históricas). Pero el catálogo y la forma del flujo de trabajo están listos para producción, y son la pieza clave para un bucle de investigación impulsado por LLM.
Datos rápidos
- Transporte: HTTP Streamable en
/mcp. - Autenticación: OAuth 2.1 (PKCE + Registro de Cliente Dinámico RFC 7591) Y/O token bearer estático. Seleccionable mediante
AUTH_MODE. - Persistencia: solo en memoria hoy (las sesiones / clientes DCR / tokens OAuth se reinician al reiniciar el contenedor). Redis está en la hoja de ruta — ver más abajo.
- Conexión IBKR: ib-gateway (
ghcr.io/gnzsnz/ib-gateway:stable) se ejecuta como un servicio hermano en este compose; cuenta de papel en modo API de solo lectura por defecto. - Construido sobre: FastMCP + ib_async.
Herramientas
Paridad con el MCP oficial de IBKR para las 9 herramientas de solo lectura (omitiendo las dos herramientas de escritura/instrucciones de órdenes — ver hoja de ruta), más las 5 herramientas de screener/noticias/catálogo que son la razón de existir de este servidor.
| Herramienta | Qué hace |
|---|---|
ib_account_summary | NetLiquidation / BuyingPower / TotalCashValue / AvailableFunds / UnrealizedPnL para la cuenta de papel o en vivo conectada. |
ib_positions | Posiciones abiertas en cuentas administradas, con cantidad / costo promedio / mark-to-market / PnL no realizado. |
ib_open_orders | Órdenes actualmente en curso con estado, cantidad completada / restante, precio de llenado promedio. |
ib_trades | Llenados ejecutados recientes (ventana de days_back, IBKR limita el historial a ~7 días). |
ib_price_snapshot | Bid / ask / último / alto / bajo / volumen actual para una acción de EE. UU. Muestra claramente los mensajes de restricción de datos de mercado de IBKR. |
ib_price_history | Barras OHLCV para cualquier duración / tamaño de barra (1 day, 1 hour, 5 mins, ...). Siempre funciona independientemente de la suscripción de datos de mercado. |
ib_search_contracts | Búsqueda difusa en la base de datos de contratos de IBKR por nombre / ticker parcial. |
ib_contract_details | Metadatos completos del contrato — long_name, industry, category, subcategory, horario de negociación, bolsas válidas. El gancho para el screening top-down consciente del sector. |
ib_scan_catalog | El catálogo de escaneos tipado. Filtrar por category, strategy, instrument, texto libre query; opcionalmente devolver la lista completa de categorías + estrategias disponibles mediante list_meta=true. |
ib_filter_catalog | Códigos de parámetros de filtro agrupados por categoría (price, volume, market_cap, fundamentals, technical, options), con una nota de aplicabilidad por instrumento. |
ib_screener_codes | Búsqueda de subcadenas sobre los códigos scan-parameters.xml crudos (legado / respaldo). Útil para códigos de proveedores más nuevos aún no incluidos en el catálogo curado. |
ib_screener | Ejecutar un escaneo de IBKR — pasar scan_code, instrument, location, filtros opcionales de precio / volumen. Devuelve rango + ticker + bolsa. |
ib_news_providers | Listar los proveedores de noticias suscritos de IBKR (Briefing.com, Dow Jones, etc.). |
ib_news_for_symbol | Obtener titulares para una acción de EE. UU. en todos los proveedores suscritos. Solo titulares; muestra un campo notice claro cuando la cuenta carece del derecho a noticias históricas. |
ib_news_article | Obtener el cuerpo de un solo artículo por provider_code + article_id. ⚠️ puede incurrir en una tarifa por artículo (Dow Jones en particular). |
Nota sobre la colocación de órdenes. El MCP oficial de IBKR también expone
Create Order InstructionyDelete Order Instruction. Este servidor intencionalmente no lo hace — ejecuta ib-gateway en modoREAD_ONLY_API=yespara que ni siquiera una llamada de herramienta mal enrutada pueda colocar una orden. La ejecución de órdenes pertenece a un servicio separado con su propia puerta de aprobación. Ver la hoja de ruta para una posible herramienta de instrucciones "solo por etapas" que escribiría en un almacén local sin tocar nunca IBKR.
Autenticación
AUTH_MODE selecciona qué mecanismos acepta el servidor. El valor predeterminado es both.
| Modo | Qué se acepta | Env requerido |
|---|---|---|
oauth | Solo tokens emitidos por OAuth. Requerido para conectores personalizados de Claude.ai. | LOGIN_PASSWORD |
bearer | Solo un Authorization: Bearer <token> estático. Omite el flujo de OAuth — mejor para clientes CLI, Claude Code, tus propios scripts. | STATIC_BEARER_TOKEN |
both (predeterminado) | Ya sea tokens OAuth o el token bearer estático. | Al menos uno de LOGIN_PASSWORD o STATIC_BEARER_TOKEN. |
Los endpoints de OAuth (/authorize, /token, /register, /.well-known/*, /login) siempre están registrados. En modo bearer son inertes — nada en tu README necesita apuntar a ellos.
Generando secretos
uv run --no-project python -c "import secrets; print(secrets.token_urlsafe(48))" # bearer token
uv run --no-project python -c "import secrets; print(secrets.token_urlsafe(48))" # session secret
Usando el token bearer estático
curl -X POST https://YOUR.DOMAIN/mcp \
-H "Authorization: Bearer $STATIC_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Conectándose desde Claude.ai (OAuth)
Configuración → Conectores → Agregar conector personalizado → URL: https://YOUR.DOMAIN/mcp → deja el ID de cliente / secreto de OAuth en blanco (Claude.ai usa DCR). Cuando Claude.ai abra el flujo de OAuth, se te pedirá LOGIN_PASSWORD.
Ejecución
cp .env.example .env
# edit .env: set TWS_USERID / TWS_PASSWORD (paper account), LOGIN_PASSWORD, STATIC_BEARER_TOKEN, PUBLIC_BASE_URL
docker compose up -d
Por defecto esto extrae la imagen multiarquitectura publicada del Registro de Contenedores de GitHub: ghcr.io/adwiteeymauriya/ibkr-portfolio-builder-mcp:latest. Para construir localmente en su lugar (por ejemplo, al iterar sobre el código fuente), ejecuta docker compose build ibkr-mcp primero.
ib-gateway tarda ~60–90 s en completar el inicio de sesión de IBKR después del primer arranque. Sigue los registros con docker logs -f ibkr-mcp-gateway.
Para uso solo local (clientes con token bearer, sin Claude.ai) esto es suficiente — http://localhost:8000/mcp ya está sirviendo. Los conectores personalizados de Claude.ai requieren una URL HTTPS en internet público, por lo que se necesita un proxy inverso con TLS al frente.
Poniendo TLS al frente para Claude.ai
Elige una. Ambas terminan con un https://your-host/mcp funcional y un certificado válido.
Opción 1 — Cloudflare Tunnel (sin IP pública, sin reenvío de puertos). Mejor si el servidor se ejecuta en una red doméstica o en una VM detrás de NAT. Cloudflare te da un nombre de host y TLS gratis; el demonio del túnel se conecta desde el servidor al borde de Cloudflare.
# One-time: install cloudflared, then
cloudflared tunnel login
cloudflared tunnel create ibkr-mcp
cloudflared tunnel route dns ibkr-mcp ibkr-mcp.your-domain.com
~/.cloudflared/config.yml:
tunnel: ibkr-mcp
credentials-file: /home/you/.cloudflared/<TUNNEL_ID>.json
ingress:
- hostname: ibkr-mcp.your-domain.com
service: http://localhost:8000
- service: http_status:404
Ejecuta con cloudflared tunnel run ibkr-mcp (o instala como una unidad systemd mediante cloudflared service install). Luego establece PUBLIC_BASE_URL=https://ibkr-mcp.your-domain.com en .env y docker compose restart ibkr-mcp.
Opción 2 — Proxy inverso Caddy con Let's Encrypt. Mejor si el servidor tiene una IP pública y los puertos 80/443 abiertos. Caddy obtiene los certificados automáticamente.
Caddyfile:
ibkr-mcp.your-domain.com {
reverse_proxy localhost:8000
}
Ejecuta con caddy run (o instala como un servicio del sistema: sudo caddy start + una unidad systemd). El mismo cambio de .env que arriba.
En ambos casos, PUBLIC_BASE_URL debe coincidir exactamente con la URL que le das a Claude.ai — Claude.ai valida el emisor de OAuth contra ella.
Ejemplos de prompts para LLM (flujo de trabajo de arriba hacia abajo)
1. Discovery:
"List the strategies and categories available in ib_scan_catalog."
2. Strategy intent:
"Find me value scans for US stocks. Show me their inverse codes too."
3. Composition:
"Run LOW_PE_RATIO on STK.US.MAJOR with priceAbove $20 and avgVolumeAbove
1,000,000, top 30. Cross-reference with HIGH_RETURN_ON_EQUITY top 30.
Show me overlap."
4. Event context:
"For the overlap list, check ib_news_for_symbol for any negative
headlines in the last 7 days, and Events & Earnings scans for
upcoming earnings within 14 days."
5. Narrow:
"Rank the survivors by liquidity and tell me which two you'd dig
into next."
Hoja de ruta
| Área | Elemento |
|---|---|
| Autenticación | Sesiones respaldadas por Redis, clientes DCR, tokens OAuth |
| Autenticación | Ámbitos por token (read-only, read-news, screener-only, ...) |
| Instrumentos | Opciones (cadenas, griegas, cálculo de IV/precio) |
| Instrumentos | Futuros (ContFuture, combos mediante Bag) |
| Instrumentos | Bonos (búsqueda + cotización) |
| Instrumentos | Forex + cripto |
| Bolsas | Enrutamientos de acciones no estadounidenses (UE, HK, JP, AU) |
| Bolsas | ib_account_summary consciente de la moneda |
| Investigación | Fundamentos de Reuters (reqFundamentalDataAsync) |
| Investigación | Barras de streaming en tiempo real + tick por tick |
| Investigación | Libro de órdenes de Nivel 2 |
| Investigación | Flujos de PnL diarios (pnlAsync, pnlSingleAsync) |
| Investigación | Subcuentas de asesor (reqFamilyCodesAsync) |
| Investigación | Catálogo → Memgraph para consultas de múltiples saltos |
| Investigación | ib_news_search más amplio |
| Riesgo | ib_what_if_order (vista previa de margen, sin ejecución) |
| Riesgo | Herramientas de instrucciones por etapas locales (sin escritura en IBKR) |
Los problemas abiertos / PRs son bienvenidos en cualquiera de estos.
Estructura
.
├── Dockerfile
├── docker-compose.yml # connector + ib-gateway, internal IBKR network
├── pyproject.toml # uv-managed: fastmcp, itsdangerous, uvicorn, ib_async
├── uv.lock
├── .env.example
├── LICENSE # MIT
├── scan-parameters.xml # IBKR's authoritative scan params (raw XML)
├── scanner_reference.json # IBKR-categorized scanner reference
├── scanner_params.json # Flat dump of scan codes + filters
├── scripts/
│ └── build_catalog.py # Regenerates src/connector/data/* from the three source files above
└── src/
└── connector/
├── settings.py # env-driven config (incl. AUTH_MODE)
├── auth.py # LoginGatedOAuthProvider + static bearer override + /login
├── ibkr.py # ib_async connection helper (connect-per-call)
├── screener.py # raw scan-parameters.xml substring search (fallback tool)
├── catalog.py # typed scan + filter catalog loaders + filtering
├── tools.py # 15 MCP tools wired into FastMCP
├── server.py # FastMCP + Starlette wiring + uvicorn entry
└── data/
├── scan_catalog.json # generated
└── filter_catalog.json # generated
Licencia
MIT.
Agradecimientos
- gnzsnz/ib-gateway-docker por la imagen de ib-gateway sin interfaz gráfica.
- ib_async por el cliente IBKR asíncrono.
- FastMCP por el marco de servidor MCP con soporte OAuth integrado.
Aviso legal
Este software se comunica con tu cuenta de Interactive Brokers. Por defecto se ejecuta contra una cuenta de papel en modo API de solo lectura — no se pueden colocar órdenes incluso si una herramienta lo intenta. Si cambias a una cuenta en vivo, lo haces bajo tu propio riesgo. Ninguna salida de las herramientas constituye asesoramiento de inversión; el etiquetado de estrategias es un ayudante de vocabulario, no un motor de recomendaciones.