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
| Ferramenta | O que retorna |
|---|---|
enty_get_me | Usuário logado + empresa ativa |
enty_list_companies | Empresas na conta |
enty_list_invoices | Faturas com filtro de status, totais, contagens por status |
enty_list_counterparties | Clientes/fornecedores com detalhes fiscais |
enty_list_items | Itens de catálogo (itens de linha de fatura) |
enty_list_item_units | Unidades de medida que um item pode usar |
enty_list_transaction_documents | Documentos já anexados a uma transação |
enty_list_invoice_payment_candidates | Transações que podem ser o pagamento de uma fatura |
enty_list_bank_accounts | Contas bancárias com IBAN e status de conexão |
enty_list_transactions | Transações com filtros de conta/data/direção/texto |
enty_get_transaction | Uma transação com nota e categoria |
enty_get_balance | Saldo combinado das contas selecionadas |
enty_get_transactions_statistics | Estatísticas de correspondência de documentos para um intervalo de datas |
enty_list_categories | Árvore de categorização de transações |
enty_list_accounting_periods | Períodos contábeis |
enty_get_period_deadlines | Próximo prazo fiscal/de declaração para um período |
enty_get_potential_tax | Imposto estimado para um período, por alíquota (EUR) |
enty_get_period_issues | Problemas de escrituração abertos para um período |
enty_list_contracts | Contratos com status do ciclo de vida de assinatura eletrônica |
enty_list_deals | Negócios com status e contraparte |
enty_get_deals_stats | Valores esperados vs. recebidos de negócios |
Ferramentas de escrita
| Ferramenta | O que faz |
|---|---|
enty_create_item | Criar um item de catálogo (produto/serviço) |
enty_update_item | Atualizar nome, preço, moeda, unidade ou descrição de um item de catálogo |
enty_create_deal | Criar um negócio para uma contraparte |
enty_create_invoice | Criar uma fatura rascunho com itens de linha |
enty_mark_invoice_paid | Marcar uma fatura como paga |
enty_link_transaction_to_invoice | Registrar uma transação bancária como pagamento de uma fatura |
enty_attach_document_to_transaction | Enviar 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 ambiente | Padrão | |
|---|---|---|
ENTY_EMAIL / ENTY_PASSWORD | — | credenciais; o servidor faz login e se renova |
ENTY_AUTH_TOKEN | — | token de sessão; alternativa ao acima |
ENTY_BASE_URL | https://app.enty.io | |
ENTY_LOCALE | en | |
ENTY_TIMEOUT_S | 30 | |
MCP_HOST / MCP_PORT | 0.0.0.0 / 8001 | transportes HTTP |
LOG_LEVEL | INFO |
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