IBKR Portfolio Builder

Pesquisa de portfólio top-down para Interactive Brokers com catálogo tipado de 468 screeners da IBKR marcados por intenção de estratégia. Somente leitura.

Documentação

ibkr-portfolio-builder-mcp

Um servidor MCP remoto para construção de portfólio top-down com a Interactive Brokers. Construído para ser usado como conector personalizado do Claude.ai, MCP do Claude Code ou qualquer cliente HTTP MCP.

A maioria dos servidores ibkr-mcp expõe primitivas de consulta individuais — get_quote, get_position, place_order. Este expõe o fluxo de pesquisa: um catálogo tipado de 468 screeners em 16 categorias marcadas por intenção de estratégia (value / growth / income / momentum / quality / events / …), instrumentos aplicáveis por varredura, links de pares inversos e acesso a notícias/contas em tempo real — para que um LLM possa fazer construção de portfólio top-down real (escolher setores / estratégias → executar varreduras → cruzar com notícias → reduzir a candidatos) em vez de pesca de tickers bottom-up.

Por que isso existe

Construí isso porque os servidores IBKR-MCP existentes na comunidade tratam a IBKR como uma fonte de dados "consulta-um-ticker". Isso espelha como a maioria das interfaces de corretoras de varejo funciona, mas não é assim que uma boa construção de portfólio realmente acontece.

Um bom fluxo de trabalho top-down se parece com:

  1. Tese macro ("as taxas estão prestes a cair, pagadores de dividendos devem se reavaliar") →
  2. Intenção de estratégia ("mostre-me telas de renda com viés de qualidade em large caps dos EUA") →
  3. Composição do screener (executar telas de rendimento de dividendos + ROE + baixa dívida; cruzar) →
  4. Contexto de eventos/notícias ("algum desses tem lucros nas próximas duas semanas? alguma ação negativa de analistas?") →
  5. Conjunto de candidatos reduzido ("cinco tickers, classificados pelos meus critérios, prontos para diligência mais profunda").

Para fazer isso com um LLM, o servidor MCP precisa expor o vocabulário de pesquisa, não apenas a API bruta. Essa é a lacuna que este servidor preenche:

  • Um catálogo de varreduras tipado — 468 códigos de varredura IBKR em 16 categorias (Fundamentals, Price Movement, Dividends, Options & Volatility, Events & Earnings, 52/26/13 Week High-Low, ESG, Bonds, …) automaticamente marcados com 28 tags de intenção de estratégia (value, growth, quality, income, momentum_up, momentum_down, analyst, technical, gap, volatility, events, leverage, efficiency, risk_adjusted, …). O LLM pergunta "quais varreduras de valor existem para ações dos EUA?" e obtém uma resposta limpa e filtrável em vez de tentar adivinhar códigos de varredura a partir de dados de treinamento.
  • Links de pares inversos — cada par HIGH_X ↔ LOW_X e X_ASC ↔ X_DESC é pré-computado, para que o LLM possa inverter a polaridade ("qual é o oposto de LOW_PE_RATIO?") sem adivinhar.
  • Mapa de instrumentos por varredura — o catálogo sabe qual varredura se aplica a STK, ETF, OPT, BOND, etc. O LLM para de enviar varreduras Refinitiv para instrumentos de títulos e obter resultados vazios.
  • Catálogo de filtros — mapa tipado separado dos filtros numéricos (priceAbove, peRatioBelow, divYieldAbove, growthRateAbove, avgVolumeAbove, marketCapAbove, …) agrupados por categoria, com notas de aplicabilidade por instrumento.
  • Notícias + screeners em uma única superfície de ferramentas — mesmo conector, mesma autenticação, mesma conversa. O LLM pode cruzar um resultado de varredura com manchetes recentes ou lucros futuros sem trocar de contexto.
  • Dois modos de autenticação — OAuth 2.1 completo (DCR + PKCE + well-knowns) para conectores personalizados do Claude.ai, além de um token bearer estático para todo o resto. Mesmo servidor, mesmas ferramentas.

Ainda é um servidor inicial. A API IBKR tem várias restrições sobre o que uma conta de papel pode realmente ver (notavelmente direito a notícias históricas). Mas o catálogo e o formato do fluxo de trabalho estão prontos para produção, e são a peça central para um loop de pesquisa orientado por LLM.

Fatos rápidos

  • Transporte: HTTP Streamable em /mcp.
  • Autenticação: OAuth 2.1 (PKCE + RFC 7591 Dynamic Client Registration) E/OU token bearer estático. Selecionável via AUTH_MODE.
  • Persistência: apenas em memória hoje (sessões / clientes DCR / tokens OAuth são redefinidos na reinicialização do contêiner). Redis está no roadmap — veja abaixo.
  • Conexão IBKR: ib-gateway (ghcr.io/gnzsnz/ib-gateway:stable) roda como serviço irmão neste compose; conta de papel em modo API somente leitura por padrão.
  • Construído sobre: FastMCP + ib_async.

Ferramentas

Paridade com o MCP oficial da IBKR para as 9 ferramentas somente leitura (pulando as duas ferramentas de escrita/instrução de ordem — veja o roadmap), além das 5 ferramentas de screener/notícias/catálogo que são a razão de existir deste servidor.

FerramentaO que faz
ib_account_summaryNetLiquidation / BuyingPower / TotalCashValue / AvailableFunds / UnrealizedPnL para a conta de papel ou real conectada.
ib_positionsPosições abertas em contas gerenciadas, com quantidade / custo médio / mark-to-market / PnL não realizado.
ib_open_ordersOrdens atualmente em andamento com status, quantidade preenchida / restante, preço médio de preenchimento.
ib_tradesExecuções preenchidas recentes (janela de days_back, IBKR limita histórico a ~7 dias).
ib_price_snapshotBid / ask / último / alta / baixa / volume atuais para uma ação dos EUA. Expõe mensagens de restrição de dados de mercado da IBKR claramente.
ib_price_historyBarras OHLCV para qualquer duração / tamanho de barra (1 day, 1 hour, 5 mins, ...). Sempre funciona independentemente da assinatura de dados de mercado.
ib_search_contractsBusca difusa no banco de contratos da IBKR por nome / ticker parcial.
ib_contract_detailsMetadados completos do contrato — long_name, industry, category, subcategory, horários de negociação, bolsas válidas. O gancho para triagem top-down ciente de setor.
ib_scan_catalogO catálogo de varreduras tipado. Filtrar por category, strategy, instrument, texto livre query; opcionalmente retornar a lista completa de categorias + estratégias disponíveis via list_meta=true.
ib_filter_catalogCódigos de parâmetros de filtro agrupados por categoria (price, volume, market_cap, fundamentals, technical, options), com nota de aplicabilidade por instrumento.
ib_screener_codesBusca por substring sobre os códigos scan-parameters.xml brutos (legado / fallback). Útil para códigos de fornecedores mais novos ainda não no catálogo curado.
ib_screenerExecutar uma varredura IBKR — passar scan_code, instrument, location, filtros opcionais de preço / volume. Retorna classificação + ticker + bolsa.
ib_news_providersListar provedores de notícias IBKR inscritos (Briefing.com, Dow Jones, etc.).
ib_news_for_symbolBuscar manchetes para uma ação dos EUA em todos os provedores inscritos. Apenas manchetes; expõe um campo notice claro quando a conta não tem direito a notícias históricas.
ib_news_articleBuscar o corpo de um único artigo por provider_code + article_id. ⚠️ pode incorrer em taxa por artigo (Dow Jones em particular).

Nota sobre colocação de ordens. O MCP oficial da IBKR também expõe Create Order Instruction e Delete Order Instruction. Este servidor intencionalmente não — ele roda ib-gateway em modo READ_ONLY_API=yes para que mesmo uma chamada de ferramenta mal roteada não possa colocar uma ordem. Execução de ordens pertence a um serviço separado com seu próprio portão de aprovação. Veja o roadmap para uma possível ferramenta de instrução "somente encenada" que escreveria em um armazenamento local sem nunca tocar na IBKR.

Autenticação

AUTH_MODE seleciona quais mecanismos o servidor aceita. O padrão é both.

ModoO que é aceitoEnv necessário
oauthApenas tokens emitidos por OAuth. Necessário para conectores personalizados do Claude.ai.LOGIN_PASSWORD
bearerApenas um Authorization: Bearer <token> estático. Pula o fluxo OAuth — melhor para clientes CLI, Claude Code, seus próprios scripts.STATIC_BEARER_TOKEN
both (padrão)Tokens OAuth ou o token bearer estático.Pelo menos um de LOGIN_PASSWORD ou STATIC_BEARER_TOKEN.

Os endpoints OAuth (/authorize, /token, /register, /.well-known/*, /login) são sempre registrados. No modo bearer eles são inertes — nada no seu README precisa apontar para eles.

Gerando segredos

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 o 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"}'

Conectando do Claude.ai (OAuth)

Configurações → Conectores → Adicionar conector personalizado → URL: https://YOUR.DOMAIN/mcp → deixe o ID do cliente OAuth / segredo em branco (Claude.ai usa DCR). Quando o Claude.ai abrir o fluxo OAuth, você será solicitado a fornecer LOGIN_PASSWORD.

Executar

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 padrão, isso puxa a imagem multi-arquitetura publicada do GitHub Container Registry: ghcr.io/adwiteeymauriya/ibkr-portfolio-builder-mcp:latest. Para construir localmente em vez disso (por exemplo, ao iterar no código-fonte), execute docker compose build ibkr-mcp primeiro.

O ib-gateway leva ~60–90 s para concluir o login na IBKR após a primeira inicialização. Acompanhe os logs com docker logs -f ibkr-mcp-gateway.

Para uso somente local (clientes com token bearer, sem Claude.ai), isso é suficiente — http://localhost:8000/mcp está agora servindo. Conectores personalizados do Claude.ai exigem uma URL HTTPS na internet pública, então um proxy reverso com TLS na frente é necessário.

Colocando TLS na frente para Claude.ai

Escolha um. Ambos terminam com um https://your-host/mcp funcional e um certificado válido.

Opção 1 — Cloudflare Tunnel (sem IP público, sem encaminhamento de porta). Melhor se o servidor roda em uma rede doméstica ou VM atrás de NAT. Cloudflare fornece um hostname e TLS gratuitamente; o daemon do túnel faz chamadas de saída do servidor para a borda da 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

Execute com cloudflared tunnel run ibkr-mcp (ou instale como unidade systemd via cloudflared service install). Em seguida, defina PUBLIC_BASE_URL=https://ibkr-mcp.your-domain.com em .env e docker compose restart ibkr-mcp.

Opção 2 — Proxy reverso Caddy com Let's Encrypt. Melhor se o servidor tem IP público e portas 80/443 abertas. Caddy busca certificados automaticamente.

Caddyfile:

ibkr-mcp.your-domain.com {
    reverse_proxy localhost:8000
}

Execute com caddy run (ou instale como serviço de sistema: sudo caddy start + uma unidade systemd). Mesma mudança de .env acima.

Em ambos os casos, PUBLIC_BASE_URL deve corresponder exatamente à URL que você dá ao Claude.ai — Claude.ai valida o emissor OAuth contra ela.

Exemplos de prompts LLM (fluxo de trabalho top-down)

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."

Roadmap

ÁreaItem
AutenticaçãoSessões, clientes DCR, tokens OAuth com suporte a Redis
AutenticaçãoEscopos por token (read-only, read-news, screener-only, ...)
InstrumentosOpções (cadeias, gregas, cálculo IV/preço)
InstrumentosFuturos (ContFuture, combos via Bag)
InstrumentosTítulos (busca + cotação)
InstrumentosForex + cripto
BolsasRoteamentos de ações não-EUA (UE, HK, JP, AU)
Bolsasib_account_summary ciente de moeda
PesquisaFundamentos Reuters (reqFundamentalDataAsync)
PesquisaBarras de streaming em tempo real + tick a tick
PesquisaLivro de ordens Nível 2
PesquisaFluxos de PnL diário (pnlAsync, pnlSingleAsync)
PesquisaSubcontas de consultor (reqFamilyCodesAsync)
PesquisaCatálogo → Memgraph para consultas multi-hop
Pesquisaib_news_search mais amplo
Riscoib_what_if_order (pré-visualização de margem, sem execução)
RiscoFerramentas de instrução encenadas localmente (sem escrita IBKR)

Issues abertas / PRs são bem-vindos em qualquer um desses.

Layout

.
├── 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

Licença

MIT.

Agradecimentos

Aviso legal

Este software fala com sua conta da Interactive Brokers. Por padrão, ele roda contra uma conta de papel em modo API somente leitura — ordens não podem ser colocadas mesmo se uma ferramenta tentar. Se você mudar para uma conta real, faz isso por sua conta e risco. Nenhuma saída de ferramenta constitui aconselhamento de investimento; a marcação de estratégia é um auxiliar de vocabulário, não um mecanismo de recomendação.