{"formato":"torrahub-agente/1","nome":"TorraHub: integração de agentes","documentacao":{"pagina":"https://torrahub.com/docs/agente","markdown":"https://torrahub.com/docs/agente.md","json":"https://torrahub.com/docs/agente/operacoes.json"},"loja":null,"autenticacao":{"tipo":"bearer","cabecalho":"Authorization: Bearer thag_…","prefixoDoToken":"thag_","ondeCriar":"Painel da loja → Integrações → Assistentes de IA → Avançado (para quem programa)","caminhoNoPainel":"https://{sua-loja}/admin/integracoes/assistentes","escopo":"Um token abre uma loja só, a que o criou. O banco guarda só o hash; o token aparece uma vez. Revogar corta na hora."},"mcp":{"endereco":"https://{sua-loja}/api/mcp","transporte":"streamable-http","sessao":false,"metodos":["initialize","ping","tools/list","tools/call"],"oauth":"em breve","claudeCode":"claude mcp add --transport http torrahub https://{sua-loja}/api/mcp --header \"Authorization: Bearer thag_…\""},"rest":{"listar":"GET https://{sua-loja}/api/agente","executar":"POST https://{sua-loja}/api/agente/{nome} (corpo JSON); GET https://{sua-loja}/api/agente/{nome}?campo=valor nas que só leem","descricaoPublica":"GET https://{sua-loja}/api/agente/descricao (sem token)","respostas":{"200":"ok: true; message e, quando há, dados e whatsappUrl","400":"corpo JSON inválido","401":"falta o token, ou ele é inválido ou foi revogado","403":"o token é de outra loja","404":"operação que não existe","405":"GET numa operação que escreve","422":"a regra recusou (a mesma mensagem da tela)"}},"regras":["Antes de lançar, leia (\"estoque\", \"cadastros\", \"clientes\") para pegar os ids. Nunca invente um id.","Confirme com a pessoa o que vai lançar antes de toda operação que escreve, dizendo os números.","Quando uma operação devolver whatsappUrl, mostre o link para a pessoa tocar.","Se a resposta vier com ok: false, diga a mensagem como veio: é a mesma recusa que a tela do painel mostraria."],"operacoes":[{"nome":"resumo","descricao":"O resumo do dia: pedidos a despachar, pedidos esperando pagamento (com quanto falta), os alertas do sino (sem rastreio, entrega falhada, contas vencidas, extrato a decidir, rupturas) e os pacotes que saíram sem rótulo.","escreve":false,"ferramentaMcp":"resumo","rest":{"metodos":["GET","POST"],"caminho":"/api/agente/resumo"},"entrada":{"type":"object","properties":{},"required":[],"additionalProperties":false}},{"nome":"estoque","descricao":"Lista as fornadas que ainda têm café: granel (gramas), pilhas de pacotes prontos (id, peso, moagem, quantidade) e as gramagens que cada café vende. Use ANTES de envasar, moer, contar ou desenvasar, para pegar os ids. Não adivinhe ids.","escreve":false,"ferramentaMcp":"estoque","rest":{"metodos":["GET","POST"],"caminho":"/api/agente/estoque"},"entrada":{"type":"object","properties":{},"required":[],"additionalProperties":false}},{"nome":"cadastros","descricao":"Lista os cafés à venda (variantes com id, peso, moagem, preço e quanto dá para vender agora), os lotes de café verde (id, nome, código) e os torradores (id, nome, se é terceirizado, preço por kg de verde). Use antes de registrar torra ou venda.","escreve":false,"ferramentaMcp":"cadastros","rest":{"metodos":["GET","POST"],"caminho":"/api/agente/cadastros"},"entrada":{"type":"object","properties":{},"required":[],"additionalProperties":false}},{"nome":"clientes","descricao":"Procura clientes pelo nome, telefone ou e-mail. Devolve id, nome e telefone. Se vier mais de um com o mesmo nome, PERGUNTE qual antes de vender.","escreve":false,"ferramentaMcp":"clientes","rest":{"metodos":["GET","POST"],"caminho":"/api/agente/clientes"},"entrada":{"type":"object","properties":{"busca":{"type":"string","description":"nome, telefone ou e-mail"}},"required":["busca"],"additionalProperties":false}},{"nome":"torra","descricao":"Registra uma torra inteira: o verde que entrou (por lote), o torrado que saiu, data, quantas fornadas no torrador, quem torrou (torrador do cadastro), se foi terceirizada, o custo, e na mesma chamada quanto foi moído e os envases (grão e/ou moído, peso, rótulo frente/trás, embalagem, custo do envase). Pegue os ids em \"cadastros\". Tudo que não foi envasado fica a granel.","escreve":true,"ferramentaMcp":"torra","rest":{"metodos":["POST"],"caminho":"/api/agente/torra"},"entrada":{"type":"object","properties":{"cafeSlug":{"type":"string","description":"slug do café (em \"cadastros\")"},"data":{"type":"string","description":"AAAA-MM-DD da torra"},"verde":{"type":"array","items":{"type":"object","properties":{"loteId":{"type":"string","description":"uuid"},"gramas":{"type":"integer","minimum":1}},"required":["loteId","gramas"],"additionalProperties":false}},"torradoG":{"type":"integer","minimum":1},"fornadas":{"type":"integer","minimum":1,"description":"quantas fornadas no torrador"},"torradorId":{"type":"string","description":"uuid do torrador do cadastro"},"quemTorrou":{"type":"string","description":"nome, se o torrador não está no cadastro"},"terceirizada":{"type":"boolean"},"custoTorraCents":{"type":"integer","description":"custo da torra; ausente = preço por kg do torrador × kg de verde"},"consumoProprioG":{"type":"integer","minimum":0},"moerG":{"type":"integer","minimum":1,"description":"gramas do torrado que foram moídas"},"envases":{"type":"array","items":{"type":"object","properties":{"pacotes":{"type":"integer","minimum":1},"grind":{"type":"string","enum":["whole","medium"],"description":"'whole' = grão, 'medium' = moído"},"pesoG":{"type":"integer","description":"gramas do pacote; obrigatório se o café tem duas gramagens"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"},"insumos":{"type":"object","description":"O que o envase consumiu. Ausente = o do cadastro do café. null num campo = \"nenhum\" (não colei / sem fecho).","properties":{"embalagem":{"type":["string","null"],"description":"slug do saco"},"fecho":{"type":["string","null"],"description":"slug do fecho"},"rotuloFrenteCents":{"type":["number","null"],"description":"custo da face da frente; null = não colei"},"rotuloTrasCents":{"type":["number","null"],"description":"custo da face de trás; null = não colei"}},"additionalProperties":false},"envaseCentsPorPacote":{"type":["number","null"],"description":"mão de obra por pacote, em centavos; null = envasei eu; ausente = nada declarado"}},"required":["pacotes","grind"],"additionalProperties":false}},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["cafeSlug","data","torradoG","terceirizada"],"additionalProperties":false}},{"nome":"moer","descricao":"Mói granel em grão de uma fornada: as gramas viram granel moído (na fornada irmã ou numa nova, devolvida em destinoId).","escreve":true,"ferramentaMcp":"moer","rest":{"metodos":["POST"],"caminho":"/api/agente/moer"},"entrada":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"gramas":{"type":"integer","minimum":1},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["roastBatchId","gramas"],"additionalProperties":false}},{"nome":"envase","descricao":"Envasa: o café sai do granel de uma fornada e vira pacote (a mesma regra da tela de Torras). Pegue o roastBatchId em \"estoque\". Moído (medium) sai do granel moído — se a fornada só tem grão, use \"moer\" antes.","escreve":true,"ferramentaMcp":"envase","rest":{"metodos":["POST"],"caminho":"/api/agente/envase"},"entrada":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"pacotes":{"type":"integer","minimum":1},"grind":{"type":"string","enum":["whole","medium"],"description":"'whole' = grão, 'medium' = moído"},"pesoG":{"type":"integer","description":"gramas do pacote; obrigatório se o café tem duas gramagens"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"},"insumos":{"type":"object","description":"O que o envase consumiu. Ausente = o do cadastro do café. null num campo = \"nenhum\" (não colei / sem fecho).","properties":{"embalagem":{"type":["string","null"],"description":"slug do saco"},"fecho":{"type":["string","null"],"description":"slug do fecho"},"rotuloFrenteCents":{"type":["number","null"],"description":"custo da face da frente; null = não colei"},"rotuloTrasCents":{"type":["number","null"],"description":"custo da face de trás; null = não colei"}},"additionalProperties":false},"envaseCentsPorPacote":{"type":["number","null"],"description":"mão de obra por pacote, em centavos; null = envasei eu; ausente = nada declarado"}},"required":["roastBatchId","pacotes","grind"],"additionalProperties":false}},{"nome":"amostras","descricao":"Envasa amostras (saquinhos) do granel de uma fornada.","escreve":true,"ferramentaMcp":"amostras","rest":{"metodos":["POST"],"caminho":"/api/agente/amostras"},"entrada":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"quantidade":{"type":"integer","minimum":1},"grind":{"type":"string","enum":["whole","medium"],"description":"'whole' = grão, 'medium' = moído"},"pesoG":{"type":"integer","description":"gramas de cada amostra, ex.: 50"},"saquinho":{"type":"string","description":"slug do insumo do saquinho"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["roastBatchId","quantidade","grind","pesoG"],"additionalProperties":false}},{"nome":"pacotes","descricao":"Move pacotes prontos de UMA pilha (o + e o − de Estoque): 'entrada', 'perda', 'consumo_proprio', 'amostra_avulsa'. Para contagem de várias pilhas, use \"contagem\".","escreve":true,"ferramentaMcp":"pacotes","rest":{"metodos":["POST"],"caminho":"/api/agente/pacotes"},"entrada":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"roastPileId":{"type":"string","description":"uuid da pilha; obrigatório se a fornada tem mais de uma"},"motivo":{"type":"string","enum":["contagem","perda","consumo_proprio","amostra_avulsa","entrada"]},"pacotes":{"type":"integer","minimum":0,"description":"na contagem, o TOTAL contado; nos outros, quantos"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["roastBatchId","motivo","pacotes"],"additionalProperties":false}},{"nome":"contagem","descricao":"Lança a contagem da prateleira, várias pilhas de uma vez: para cada pilha, o TOTAL contado (zero vale). Pegue roastBatchId e roastPileId em \"estoque\". Se o café/peso/moagem que a pessoa disse está em mais de uma pilha, PERGUNTE como dividir.","escreve":true,"ferramentaMcp":"contagem","rest":{"metodos":["POST"],"caminho":"/api/agente/contagem"},"entrada":{"type":"object","properties":{"itens":{"type":"array","minItems":1,"items":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"roastPileId":{"type":"string"},"pacotes":{"type":"integer","minimum":0}},"required":["roastBatchId","pacotes"],"additionalProperties":false}},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["itens"],"additionalProperties":false}},{"nome":"desenvasar","descricao":"Desfaz pacotes: o café volta ao granel. Diga se o saco volta a ser usado (devolveSaco).","escreve":true,"ferramentaMcp":"desenvasar","rest":{"metodos":["POST"],"caminho":"/api/agente/desenvasar"},"entrada":{"type":"object","properties":{"roastBatchId":{"type":"string","description":"uuid"},"roastPileId":{"type":"string"},"pacotes":{"type":"integer","minimum":1},"devolveSaco":{"type":"boolean"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"nota":{"type":"string","description":"texto livre que vai na nota do movimento"}},"required":["roastBatchId","pacotes","devolveSaco"],"additionalProperties":false}},{"nome":"venda","descricao":"Registra uma venda direta (WhatsApp, feira, balcão) para um cliente do cadastro, pelos pacotes do catálogo. Pegue clienteId em \"clientes\" e variantId em \"cadastros\". Sem preço, usa o do catálogo. cobrarPix: true devolve whatsappUrl com a mensagem de cobrança e o Pix — mostre o link para a pessoa tocar. Pacote sem estoque vira encomenda.","escreve":true,"ferramentaMcp":"venda","rest":{"metodos":["POST"],"caminho":"/api/agente/venda"},"entrada":{"type":"object","properties":{"clienteId":{"type":"string","description":"uuid"},"itens":{"type":"array","minItems":1,"items":{"type":"object","properties":{"variantId":{"type":"string","description":"uuid"},"quantidade":{"type":"integer","minimum":1},"precoCents":{"type":"integer","minimum":0,"description":"preço combinado por pacote; ausente = do catálogo"}},"required":["variantId","quantidade"],"additionalProperties":false}},"pago":{"type":"boolean","description":"true = já recebeu; false = a pagar"},"cobrarPix":{"type":"boolean","description":"gera a cobrança Pix e o link do WhatsApp (só se não pago)"},"entrega":{"type":"string","enum":["hand","ship"],"description":"em mãos ou despacho"},"data":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"}},"required":["clienteId","itens","pago"],"additionalProperties":false}},{"nome":"despacho","descricao":"Marca um pedido como enviado (com rastreio e data de postagem) ou entregue em mãos. avisarCliente: true manda o aviso ao cliente (e-mail/WhatsApp, se a régua estiver ligada); pergunte se não souber.","escreve":true,"ferramentaMcp":"despacho","rest":{"metodos":["POST"],"caminho":"/api/agente/despacho"},"entrada":{"type":"object","properties":{"pedido":{"type":"string","description":"o número, ex.: \"0071\" ou \"#0071\""},"tipo":{"type":"string","enum":["enviado","entregue"],"description":"entregue = em mãos"},"rastreio":{"type":"string"},"dataPostagem":{"type":"string","description":"AAAA-MM-DD; sem ela, hoje"},"cidade":{"type":"string","description":"cidade da entrega em mãos"},"avisarCliente":{"type":"boolean"}},"required":["pedido","tipo","avisarCliente"],"additionalProperties":false}},{"nome":"verificar-pagamentos","descricao":"O botão \"Verificar pagamentos\": confere no Mercado Pago os pagamentos dos últimos 35 dias, lança o que casa com certeza e diz o que precisa de confirmação na tela.","escreve":true,"ferramentaMcp":"verificar-pagamentos","rest":{"metodos":["POST"],"caminho":"/api/agente/verificar-pagamentos"},"entrada":{"type":"object","properties":{},"required":[],"additionalProperties":false}}]}