Enty.io

Servidor MCP para Enty.io — faturas, transações bancárias, prazos contábeis e contratos, expostos como ferramentas que seu agente de IA pode chamar.

Documentação

enty-mcp

Um servidor MCP para Enty.io — faturas, transações bancárias, prazos contábeis e contratos, expostos como ferramentas que seu agente de IA pode chamar.

A Enty não possui API pública. Este servidor utiliza o mesmo endpoint GraphQL que o aplicativo web da Enty usa, autenticado com o token de sessão do seu navegador. Isso vem com ressalvas que você deve ler antes de usar:

Não oficial. Este projeto não é afiliado ou endossado pela Enty. Ele se comunica com uma API interna não documentada que pode mudar ou quebrar a qualquer momento, e seu uso pode não ser coberto pelos termos de serviço da Enty. Ele lê dados reais da sua empresa — não há sandbox. Duas ferramentas também escrevem nele (apenas itens de catálogo); nada é excluído.

Ferramentas

FerramentaO que retorna
enty_get_meUsuário logado + empresa ativa
enty_list_companiesEmpresas na conta
enty_list_invoicesFaturas com filtro de status, totais, contagens por status
enty_list_counterpartiesClientes/fornecedores com detalhes fiscais
enty_list_itemsItens de catálogo (itens de linha de fatura)
enty_list_item_unitsUnidades de medida que um item pode usar
enty_list_transaction_documentsDocumentos já anexados a uma transação
enty_list_invoice_payment_candidatesTransações que podem ser o pagamento de uma fatura
enty_list_bank_accountsContas bancárias com IBAN e status de conexão
enty_list_transactionsTransações com filtros de conta/data/direção/texto
enty_get_transactionUma transação com nota e categoria
enty_get_balanceSaldo combinado das contas selecionadas
enty_get_transactions_statisticsEstatísticas de correspondência de documentos para um intervalo de datas
enty_list_categoriesÁrvore de categorização de transações
enty_list_accounting_periodsPeríodos contábeis
enty_get_period_deadlinesPróximo prazo fiscal/de declaração para um período
enty_get_potential_taxImposto estimado para um período, por alíquota (EUR)
enty_get_period_issuesProblemas de escrituração abertos para um período
enty_list_contractsContratos com status do ciclo de vida de assinatura eletrônica
enty_list_dealsNegócios com status e contraparte
enty_get_deals_statsValores esperados vs. recebidos de negócios

Ferramentas de escrita

FerramentaO que faz
enty_create_itemCriar um item de catálogo (produto/serviço)
enty_update_itemAtualizar nome, preço, moeda, unidade ou descrição de um item de catálogo
enty_create_dealCriar um negócio para uma contraparte
enty_create_invoiceCriar uma fatura rascunho com itens de linha
enty_mark_invoice_paidMarcar uma fatura como paga
enty_link_transaction_to_invoiceRegistrar uma transação bancária como pagamento de uma fatura
enty_attach_document_to_transactionEnviar um arquivo local e anexá-lo a uma transação

Estas escrevem na sua empresa ativa. Dois níveis de risco merecem ser separados.

Itens de catálogo e negócios são dados de referência. Criar ou editar um deles não altera faturas que já o referenciam.

As três últimas tocam na escrituração. Vincular uma transação a uma fatura e anexar documentos altera registros com os quais seu contador trabalha, e um vínculo errado é lido como erro de conciliação. Nenhuma delas pode ser desfeita aqui, então verifique os IDs antes de chamar.

enty_create_invoice deixa um rascunho. Nada é enviado ao cliente e nenhum PDF é gerado; revise e emita no aplicativo web da Enty. São necessárias quatro chamadas, porque a Enty constrói uma fatura dessa forma: criar um rascunho em branco, ajustar o cabeçalho, adicionar as linhas, armazenar os totais. Se uma etapa posterior falhar, o rascunho sobrevive, e o erro carrega seu ID para que você possa finalizá-lo ou descartá-lo manualmente.

enty_link_transaction_to_invoice exige que a fatura tenha um documento gerado, pois o vínculo é entre esse documento e a transação. A Enty não possui registro de pagamento separado. Abra uma fatura nova uma vez no aplicativo web se a ferramenta informar que não há nenhuma.

enty_attach_document_to_transaction é o único caminho que não é GraphQL. Os bytes vão para o serviço de armazenamento de arquivos da Enty como dados de formulário multipart, o arquivo retornado é registrado como documento contábil, e só então é vinculado à transação.

Nada neste servidor exclui. A API da Enty tem 233 mutações, 19 delas de exclusão (deleteItemsAtOrganization, DeleteTransactions, DeleteUserCompanies, e assim por diante). Nenhuma é exposta, e o cliente GraphQL se recusa a enviar qualquer mutação cujo nome de operação não esteja em uma lista de permissões explícita (ALLOWED_MUTATIONS em src/enty_mcp/graphql.py), então uma escrita bloqueada nunca sai do processo. Excluir qualquer coisa é uma ação manual no aplicativo web da Enty, de propósito.

enty_update_item mescla: passe apenas os campos que deseja alterar. A atualização da Enty substitui o item inteiro, então a ferramenta lê os valores atuais do item primeiro e os envia de volta junto com suas alterações. Sem isso, atualizar um campo apagaria o restante.

O restante da superfície de mutações é mapeado (spec/graphql/bundle-operations/), mas não exposto. Adicionar uma escrita significa adicionar seu nome à lista de permissões, que é a etapa de revisão.

Autenticação

Duas opções. Escolha uma.

E-mail e senha (ENTY_EMAIL, ENTY_PASSWORD). O servidor faz login por você, mantém o token de sessão na memória e faz login novamente sozinho quando a sessão expira. Nada a fazer quando um token morre, que é o que você quer para um servidor que deve rodar sem supervisão. A Enty não emite token de atualização, então renovar é realmente um novo login.

Um token de sessão (ENTY_AUTH_TOKEN). Entre em app.enty.io, abra DevTools → Network, clique em qualquer requisição para /api/, e copie o valor do cabeçalho de requisição enty-auth. Isso expira, e sem credenciais o servidor não pode renová-lo, então você repete os passos sempre que as ferramentas começarem a falhar.

Defina ambos e o token é usado primeiro, com fallback para as credenciais quando ele expirar. Isso evita um login na inicialização enquanto ainda sobrevive à expiração.

De qualquer forma, o segredo concede acesso total à sua conta Enty, então trate-o como a senha que ele efetivamente é. Credenciais e tokens são mantidos como SecretStr pydantic, fora dos cabeçalhos compartilhados do cliente, enviados apenas ao seu ENTY_BASE_URL configurado, e nunca gravados em logs. O e-mail da conta é registrado em INFO quando um login acontece, para que você saiba qual conta um servidor em execução está usando.

Contas com autenticação multifator não podem usar e-mail e senha. A Enty responde a esses logins sem ID de sessão, e o servidor informa isso em vez de falhar de forma obscura. Use um token para essas contas.

Execução

Com uv

git clone https://github.com/appsome/enty-mcp-server
cd enty-mcp-server
cp .env.example .env      # paste your token
uv sync
uv run enty-mcp                       # streamable HTTP on :8001/mcp
uv run enty-mcp --transport stdio     # for stdio clients

Com Docker Compose

cp .env.example .env      # fill in ENTY_EMAIL and ENTY_PASSWORD
docker compose up -d
# server: http://localhost:8001/mcp   health: http://localhost:8001/health

O arquivo compose compila a partir do código-fonte. Para executar uma imagem publicada em vez disso:

docker run -d -p 8001:8001 \
  -e ENTY_EMAIL=you@example.com -e ENTY_PASSWORD=... \
  ghcr.io/appsome/enty-mcp-server:latest

As imagens são compiladas para linux/amd64 e linux/arm64 e enviadas ao GitHub Container Registry a cada push para main, com as tags latest e o SHA do commit. Enviar uma tag v* adiciona as tags semver correspondentes. O contêiner sai imediatamente com um erro claro se nem credenciais nem um token estiverem definidos.

Configuração

Variável de ambientePadrão
ENTY_EMAIL / ENTY_PASSWORDcredenciais; o servidor faz login e se renova
ENTY_AUTH_TOKENtoken de sessão; alternativa ao acima
ENTY_BASE_URLhttps://app.enty.io
ENTY_LOCALEen
ENTY_TIMEOUT_S30
MCP_HOST / MCP_PORT0.0.0.0 / 8001transportes HTTP
LOG_LEVELINFO

Conectando um cliente

OpenHands (docker compose): use docker-compose.override.example.yml para adicionar o serviço à sua pilha e aponte o OpenHands para http://enty-mcp:8001/mcp — veja openhands/mcp.json e openhands/config.toml.snippet.

Claude Code:

claude mcp add --transport http enty http://localhost:8001/mcp

Claude Desktop (stdio):

{
  "mcpServers": {
    "enty": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/enty-mcp-server", "enty-mcp", "--transport", "stdio"],
      "env": { "ENTY_EMAIL": "you@example.com", "ENTY_PASSWORD": "..." }
    }
  }
}

Como o mapeamento da API foi feito

O endpoint GraphQL da Enty tem a introspecção desabilitada, então o esquema foi reconstruído a partir de duas fontes: uma captura HAR do aplicativo web (56 operações com formatos de resposta, spec/graphql/operations/) e os bundles JS do aplicativo, que contêm todos os documentos GraphQL que o frontend pode enviar (434 operações, spec/graphql/bundle-operations/). spec/graphql/NOTES.md documenta as convenções e as lacunas restantes. Os scripts de extração em scripts/ são repetíveis quando o aplicativo muda.

Desenvolvimento

uv sync
uv run pytest          # respx-mocked, no network
uv run ruff check src tests scripts
uv run pyright

Os testes nunca tocam na API real. Os dados de fixture são sintéticos, modelados a partir de respostas registradas.

Licença

MIT