Servidor MCP (Live)
Conecte um agente de IA diretamente à Live Execution API via Model Context Protocol — gerencie subscriptions ao vivo e receba webhooks assinados, sem código de integração customizado.
#Visão geral
O emidlabs-live-mcp é um servidor Model Context Protocol (MCP) hospedado que expõe a Live Execution API como tools chamáveis por agente — a contraparte ao vivo do emidlabs-backtest-mcp. Aponte qualquer cliente compatível com MCP ou coding agent pra ele e ele consegue criar e gerenciar subscriptions ao vivo e ler sinais emitidos diretamente, sem você escrever uma integração REST.
Endpoint: https://mcp.live.emidlabs.com/mcp (transporte Streamable HTTP).
live.emidlabs.com. Toda subscription que ele cria usa sua própria API key da EmidLabs e conta pro limite de subscriptions concorrentes da sua conta, do mesmo jeito que chamar a API REST diretamente.#Conectando um agente
Escolha seu cliente
Claude e ChatGPT descobrem esse servidor automaticamente via OAuth. Cursor e a maioria dos coding agents preferem o bloco JSON cru abaixo.
Adicione o conector
Adicione o servidor na configuração do seu cliente MCP. O arquivo exato varia por cliente, mas o formato é o mesmo em todo lugar — um nome e uma URL:
{
"mcpServers": {
"emidlabs-live": {
"url": "https://mcp.live.emidlabs.com/mcp"
}
}
}/mcp — https://mcp.live.emidlabs.com/mcp, não só mcp.live.emidlabs.com. Esquecer o caminho é o motivo mais comum de um conector falhar ao registrar, e o erro resultante raramente deixa a causa real óbvia.Autentique
Três formas de autenticar, e você pode combinar mais de uma — o conector tenta na ordem abaixo:
| Método | Como | Melhor para |
|---|---|---|
| Login via OAuth (recomendado) | Só adicione o conector sem configuração extra. Claude/ChatGPT descobrem o fluxo de login automaticamente e pedem pra você entrar com sua conta EmidLabs — uma API key dedicada é criada pra sua conta na primeira vez e reutilizada depois disso. | Conectores pessoais no Claude.ai / ChatGPT. Nada pra copiar, colar ou digitar — nunca. |
| Header x-api-key | Configure uma API key específica da EmidLabs uma vez ao adicionar o conector (ex: a opção "custom header" / static_headers do Claude) — anexada automaticamente em toda requisição a partir daí. | Conectores gerenciados por organização, onde um admin quer que todo membro compartilhe uma key específica em vez de logins OAuth individuais. |
| Argumento na tool | Passe uma API key como liveApiKey em cada chamada — o agente recebe a key diretamente (ex: na conversa). | Coding agents, uso local/CLI, ou qualquer cliente sem suporte a autenticação no nível do conector. |
#Tools
create_subscription
Inscreve uma estratégia pra avaliação ao vivo num par de ativo. A estratégia reavalia toda vez que um candle fecha no seu timeframe configurado, emitindo um sinal de Entry ou Exit sempre que decision.entry/decision.exit vira true — sem tracking de posição, só sinal.
Sem lista fixa de ativos pra consultar antes — qualquer par que a corretora escolhida realmente liste pode ser inscrito. Isso é mais amplo que submit_backtest, que só cobre ativos que a EmidLabs já extraiu e armazenou candles históricos.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| assetPair | string | Deve estar no formato exato que a corretora escolhida espera — nenhuma tradução acontece em lugar nenhum. Coinbase: "BTC-USDC" (com hífen). Binance: "BTCUSDC" (sem hífen). |
| provider | string (opcional) | Qual provedor de dados de mercado escutar: "coinbase" ou "binance". Usa "coinbase" por padrão quando omitido. |
| strategySnapshotJson | object | O objeto de Strategy DSL — veja o resource strategy-dsl-spec abaixo. Formato idêntico ao de submit_backtest. |
| webhookUrl | string (opcional) | URL https:// absoluta. Quando definida, todo sinal emitido também é enviado via POST pra ela — veja Webhooks abaixo. |
| model | string (opcional) | "stateless" (padrão quando omitido) ou "stateful" — veja Signal Model abaixo. |
| isPositioned | boolean (opcional) | Só tem significado quando model é "stateful". Usa false (ainda não posicionado) por padrão quando omitido. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
Não há verificação de que assetPair realmente existe na corretora escolhida no momento da criação — um par inválido, ou o par certo no formato errado de provider, é aceito imediatamente e depois o status da subscription muda pra "Errored" em cerca de um minuto. Confira get_subscription logo após criar se você não tem certeza que o formato estava certo.
webhookSecret só é retornado nessa resposta, uma única vez — salve imediatamente. Nenhuma tool ou endpoint o repete depois, a mesma regra de revelação única que as API keys da EmidLabs já seguem.create_subscriptions_batch
Inscreve a MESMA estratégia pra avaliação ao vivo em vários pares de ativo de uma vez, uma subscription por entrada em assetPairs. Best-effort por item — um par de ativo ruim nunca falha o resto do batch, confira o status/erro de cada item.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| assetPairs | string[] | Uma entrada por subscription a criar. Máximo de 50 por chamada. |
| strategySnapshotJson | object | Compartilhado por toda subscription desse batch — formato idêntico ao próprio campo de create_subscription. |
| provider | string (opcional) | Compartilhado por toda subscription desse batch. Usa "coinbase" por padrão quando omitido. |
| webhookUrl | string (opcional) | Compartilhado por toda subscription desse batch — cada uma ainda ganha suas próprias entregas assinadas e seu próprio secret. |
| model | string (opcional) | Compartilhado por toda subscription desse batch. "stateless" (padrão quando omitido) ou "stateful" — veja Signal Model abaixo. |
| isPositioned | boolean (opcional) | Compartilhado por toda subscription desse batch, só tem significado quando model é "stateful". Usa false por padrão quando omitido. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
webhookSecret quando webhookUrl é definida — retornado uma vez por item nessa resposta, mesma regra de revelação única de create_subscription.stop_subscription
Para uma subscription ao vivo. Idempotente — parar uma subscription já parada só retorna o status atual dela.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| subscriptionId | string | O id retornado por create_subscription. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
stop_subscriptions
Para uma lista específica de subscriptions ao vivo, numa chamada. Idempotente por id — uma subscription já parada é simplesmente ignorada, não é erro.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| ids | string[] | Ids de subscription a parar, como retornados por create_subscription/list_subscriptions. Máximo de 200 por chamada. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
stop_all_subscriptions
Para toda subscription ao vivo atualmente ativa nessa conta, numa chamada. Idempotente — subscriptions já paradas são simplesmente ignoradas.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
stop_subscriptions com uma lista explícita de ids se você só quer parar algumas.update_subscription
Atualiza model/isPositioned/webhookUrl de uma subscription. assetPair, timeframe, provider, e a estratégia em si nunca podem ser mudados depois da criação — stop_subscription e create_subscription pra isso.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| subscriptionId | string | O id retornado por create_subscription. |
| model | string (opcional) | "stateless" ou "stateful". Omita pra manter inalterado — veja Signal Model abaixo. |
| isPositioned | boolean (opcional) | Só tem significado quando o model dessa subscription é (ou está sendo definido pra) "stateful". Omita pra manter inalterado. |
| webhookUrl | string (opcional) | Uma nova URL https:// absoluta, ou uma string vazia pra remover o webhook existente. Omita pra manter inalterado. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
webhookUrl pra um valor não-vazio gera um webhookSecret novo, retornado só nessa resposta — salve imediatamente.get_subscription
Busca o status atual de uma subscription ao vivo pelo id — par de ativo, provider, timeframe, status, model/isPositioned, e o último candle avaliado.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| subscriptionId | string | O id retornado por create_subscription. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
list_subscriptions
Lista subscriptions ao vivo dessa conta, paginado.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| page | integer (opcional) | Número da página, começando em 1. Padrão 1. |
| pageSize | integer (opcional) | Resultados por página, 1-100. Padrão 20. |
| status | string (opcional) | Filtro de correspondência exata: "Active", "Stopped" ou "Errored". Omita pra retornar todos os status. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
get_subscription_signals
Lista os sinais de Entry/Exit que uma subscription ao vivo emitiu, paginado, cada um com o candle em que disparou, quais conditions nomeadas eram true, o detalhamento do score, e — pra sinais de Entry — os níveis de preço de stop-loss/take-profit calculados.
| Argumento | Tipo | Descrição |
|---|---|---|
| liveApiKey | string (opcional) | Desnecessário se você conectou via login OAuth ou o header x-api-key está configurado nesse conector. |
| subscriptionId | string | O id retornado por create_subscription. |
| page | integer (opcional) | Número da página, começando em 1. Padrão 1. |
| pageSize | integer (opcional) | Resultados por página, 1-100. Padrão 20. |
| type | string (opcional) | Filtro de correspondência exata: "Entry" ou "Exit". Omita pra retornar os dois. |
| liveBaseUrl | string (opcional) | Usa a API pública de produção por padrão. |
#Signal Model: Stateless vs Stateful
Toda subscription começa "stateless" — um sinal é registrado/entregue toda vez que decision.entry/decision.exit avalia true, mesmo repetidamente, se a condition subjacente não é edge-triggered (ex: um simples rsi14 > 55 em vez de crossUp(...)/crossDown(...) — permanece true por vários candles consecutivos). Mude uma subscription pra "stateful" via update_subscription pra fazer ela rastrear sua própria posição de Entry/Exit internamente (nunca consultada da sua corretora) e só disparar numa transição de verdade — o resto é suprimido silenciosamente.
isPositioned é uma correção manual, nunca inferida de um saldo real da corretora — esse servidor não tem integração própria com corretora nenhuma. Corrija o desvio você mesmo via update_subscription quando acontecer (ex: um trade feito manualmente fora desse sistema).Tabela completa de comportamento: Live Execution API — Signal Model.
#Webhooks
Passe webhookUrl pra create_subscription e todo sinal que essa subscription emitir também é enviado via POST pra lá como JSON — sem precisar de polling. Cada entrega é assinada pra você poder verificar que realmente veio da EmidLabs:
| Header | Formato | Verificação |
|---|---|---|
| X-Emidlabs-Signature | t={timestamp unix},v1={HMAC-SHA256 hex} | Recompute HMAC-SHA256(webhookSecret, `${timestamp}.${rawBody}`) e compare com v1 — o mesmo esquema que a própria EmidLabs usa pra verificar webhooks de entrada do Stripe, aplicado aqui do lado de envio. |
Entrega tenta de novo até 3 vezes (backoff curto) em erros de rede, timeouts, 429s e respostas 5xx do seu endpoint — um webhook lento ou inacessível nunca bloqueia ou atrasa a avaliação de sinal em si.
#Resources
strategy-dsl-spec
Uma referência condensada, em markdown, pro formato JSON exato de Strategy DSL esperado pelo campo strategySnapshotJson de create_subscription (emidlabs://strategy-dsl-spec) — formato idêntico à própria cópia do emidlabs-backtest-mcp e ao bloco Copiar Spec para IA da página Strategy System.
inputs/conditions/score é buscada em tempo real do dono do domínio do emidlabs-strategy-mcp (o próprio GET /dsl-core-reference do strategy-api) e cacheada por alguns minutos, em vez de copiada à mão — o mesmo núcleo que o emidlabs-backtest-mcp e o emidlabs-strategy-mcp também buscam, então essa parte não consegue dessincronizar entre eles. A parte local desse servidor deliberadamente omite entryFeePct/exitFeePct (só de backtest), e documenta riskManagement como apenas informativo — uma subscription ao vivo nunca fecha nada automaticamente, ao contrário de um backtest.Ler esse resource primeiro é opcional, não obrigatório — todo campo no próprio schema da tool create_subscription já documenta seu formato exato diretamente, já que clientes MCP não buscam de forma confiável um resource separado antes de gerar uma chamada.
#Limites de taxa
Dois limites independentes se aplicam, e eles aparecem de forma diferente de propósito pra nunca serem confundidos entre si:
| Limite | Escopo | O que protege | O que você vê |
|---|---|---|---|
| Cota do live-api / limite de subscriptions concorrentes | Por API key | O limite real de uso/faturamento da sua conta | Um 4xx do live-api, repassado como erro de tool do MCP. |
| Guarda de infra do MCP | Por IP/conexão | O processo do MCP em si, contra loops descontrolados ou enxurradas malformadas | Um 429 com uma mensagem identificando explicitamente que é a guarda da própria camada MCP, não a cota da sua conta. |
#Escopo
Esse servidor só expõe gestão de subscription ao vivo — criar, parar, inspecionar subscriptions, e ler seus sinais. Ele não expõe nenhuma ação do Console (criar ou rotacionar API keys, mudar planos de cobrança, gestão de conta). Essas continuam sendo ações só-humano na UI do Console, mantidas de propósito fora do que um agente autônomo pode fazer sem supervisão.