equatorial-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@equatorial-mcpListar minhas faturas de energia"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
equatorial-mcp
Servidor MCP comunitário e não oficial para consultar e baixar faturas da Equatorial.
Projeto comunitário, não oficial e sem afiliação com a Equatorial Energia.
Licença MIT. Veja LICENSE.
Escopo do v0.1.0
Suporte somente a Goiás (
EQUATORIAL_UF=GO). Outras UFs (por exemplo PA e MA) falham comUF_UNSUPPORTEDantes de abrir o navegador.Três tools orientadas à intenção:
listar_ucs,listar_faturasebaixar_fatura.O PDF da segunda via é exposto como Resource MCP (
equatorial://faturas/{artifact_id}/pdf); capturas de diagnóstico usamequatorial://diagnosticos/{error_id}/screenshot.Operação local e determinística, sem LLM, sem OCR em nuvem, sem mensageria e sem agendamento.
Uma instância representa uma única conta configurada. Não use como serviço multi-tenant.
Nenhuma operação de pagamento é executada. O servidor apenas lista unidades consumidoras, lista faturas e baixa a segunda via em PDF com extração local.
Related MCP server: CPFL: Download + OCR
Requisitos
Node.js
>=20.Chromium compatível via Puppeteer (dependência fixada no lockfile).
Instalação
A partir do tarball publicado:
npm install -g equatorial-mcp
equatorial-mcpUso local sem instalar:
npx -y equatorial-mcpA partir do repositório:
npm ci
npm run build
npm pack --dry-runConfiguração do servidor no cliente
Os arquivos em examples/ configuram o transporte MCP e não contêm segredos: o servidor herda o ambiente privado do processo. Exemplos:
Claude Code e Cursor usam o formato
mcpServers— vejaexamples/mcp.json(commandnpx,args["-y", "equatorial-mcp"],envvazio).OpenCode v2 usa o aninhamento
mcp.serverscomtype: "local"e comando em array — vejaexamples/opencode.jsonc.
Prefira o escopo de usuário/local do cliente (nunca commite credenciais):
Claude Code: registre o servidor no escopo de usuário e informe as cinco variáveis no armazenamento privado de ambiente do cliente ou no shell que o inicia.
Cursor: coloque a entrada de
examples/mcp.jsonno seumcp.jsonde usuário e defina as variáveis fora do repositório.OpenCode: mescle a entrada de
examples/opencode.jsoncsobmcp.serversno seuopencode.jsonde usuário ou do projeto, sem valores secretos.
Instalação da Skill
A Skill canônica é publicada em skills/equatorial-faturas/SKILL.md (dentro do repositório e do tarball NPM). A instalação é por cópia — nenhum postinstall escreve no seu home. Copie o diretório inteiro equatorial-faturas, para que futuras referências e anexos continuem junto do SKILL.md:
Claude Code (projeto):
.claude/skills/equatorial-faturas/SKILL.mdClaude Code (usuário):
~/.claude/skills/equatorial-faturas/SKILL.mdOpenCode (projeto):
.opencode/skills/equatorial-faturas/SKILL.mdOpenCode (usuário):
~/.config/opencode/skills/equatorial-faturas/SKILL.mdCursor (projeto):
.cursor/skills/equatorial-faturas/SKILL.mdou o local compartilhado documentado.agents/skills/equatorial-faturas/SKILL.mdCursor (usuário):
~/.cursor/skills/equatorial-faturas/SKILL.md
Exemplo (projeto Claude Code, a partir da raiz do repositório):
mkdir -p .claude/skills
cp -r skills/equatorial-faturas .claude/skills/Em atualizações, copie novamente por cima para manter a Skill sincronizada com o servidor.
Configuração
O binário não carrega .env automaticamente e não depende de dotenv: .env.example é apenas documentação. Exporte as variáveis no ambiente do processo ou na configuração privada do cliente MCP. Nunca cole CPF, nascimento, cookies ou códigos de pagamento em chamadas de tool.
export EQUATORIAL_UF=GO
export EQUATORIAL_UC='SUA_UC'
export EQUATORIAL_CPF='SEU_CPF'
export EQUATORIAL_NASCIMENTO='DD/MM/AAAA'
export HEADLESS='true'Variáveis normativas:
Variável | Obrigatória | Padrão |
| não |
|
| sim | — |
| sim | — |
| sim | — |
| não |
|
Não há aliases: variáveis com outros nomes são ignoradas e segredos não têm flags CLI. EQUATORIAL_CPF exige 11 dígitos com dígitos verificadores válidos; EQUATORIAL_NASCIMENTO exige data real em DD/MM/AAAA; HEADLESS aceita somente true/false. EQUATORIAL_CPF aceita entrada formatada com pontuação (somente os dígitos são validados) e HEADLESS é insensível a maiúsculas/minúsculas com espaços aparados, com vazio/ausente assumindo true.
Transporte
Padrão: stdio (
stdin/stdoutexclusivos do protocolo, diagnósticos emstderr).Opt-in local:
--httpservePOST /mcpeGET /healthz(responde{"status":"ok"}) somente em loopback.--hostaceita apenas127.0.0.1,::1oulocalhost(padrão127.0.0.1);--portdefine a porta (padrão3000).--hoste--portexigem--http, e binds não-loopback são recusados porque o v0.1.0 não tem autenticação HTTP multiusuário.Flags com aparência de segredo são recusadas: segredos entram somente pelo ambiente do processo.
npx -y equatorial-mcp --http --port 3000Tools
Tool | Intenção | Observações |
| Lista as Unidades Consumidoras disponíveis na conta Equatorial configurada. Não baixa faturas. | Somente leitura; aceita |
| Lista faturas disponíveis para uma UC autorizada e devolve fatura_id opaca para download inequívoco. | Somente leitura; sem |
| Baixa uma segunda via em PDF e extrai dados locais. Use preferencialmente a fatura_id retornada por listar_faturas. | Cria arquivo local ( |
Chamadas do mesmo perfil são serializadas: faça chamadas em série e não baixe todas as UCs por padrão.
Resultado estruturado e Resources
Toda tool devolve o valor canônico em structuredContent no envelope { "ok", "data", "error" }. Em sucesso, content traz um resumo curto e baixar_fatura acrescenta um bloco resource_link. Em falha de domínio/portal, o resultado usa isError: true e repete o envelope seguro com code, message, retryable, evidence_uri e details (somente campos da allowlist).
Campos extraídos de baixar_fatura (uc, conta_mes, vencimento, total, consumo_kwh, codigo_pix, linha_digitavel, saldos_scee) usam null para “não extraído/não presente” — nunca zero ou string inventada. parse_status resume a extração:
complete: campos principais obtidos e códigos de pagamento validados (seção SCEE ausente é legítima e usasaldos_scee.status: not_present);partial: há texto útil, mas algo está emmissing_fields— informe os ausentes e ofereça o PDF, sem inferir valores;unreadable: PDF válido sem texto aproveitável — entregue/vincule o PDF e explique a conferência manual.
Regras de leitura: a uc principal é a consumidora (nunca a de injeção/geração SCEE); codigo_pix confiável começa com 000201 com validadores aprovados; linha_digitavel confiável começa com 341, com comprimento e dígitos verificadores aceitos; saldos_scee nulo não é zero.
O PDF nunca entra inline em base64 no JSON/texto inicial: a referência canônica é arquivo.resource_uri (formato equatorial://faturas/{artifact_id}/pdf) mais o bloco resource_link. O resources/read entrega o binário somente quando o host solicita. arquivo.local_path é auxiliar e pode apontar para dentro de um container — trate resource_uri como referência canônica. PIX e linha digitável completos fazem parte do resultado estruturado, mas o resumo textual os omite; repita-os na conversa somente com pedido explícito do usuário.
Estado local
Raiz padrão em sistemas Unix: ~/.equatorial-mcp/ (no Windows, sob o diretório de dados local da aplicação). Conteúdo:
~/.equatorial-mcp/
├── profile-key # segredo local aleatório, 0600
├── profiles/<uf>/<profile-id>/ # userDataDir do Chromium (cookies/sessão isolados por perfil)
├── downloads/<uf>/ # PDFs da segunda via, 0600
├── diagnostics/ # PNGs de diagnóstico temporários, 0600
├── manifests/
│ ├── artifacts.json # IDs opacos -> caminhos/metadados
│ └── invoices.json # fatura_id -> fingerprint seguro
└── locks/ # lock interprocesso do perfilDiretórios usam permissão 0700 e arquivos sensíveis 0600 em POSIX; no Windows a permissão é aplicada como melhor esforço da plataforma (o chmod ali só alterna o atributo de leitura). O profile-id deriva de HMAC-SHA-256 sobre UF + UC de login + CPF normalizado — o CPF nunca aparece em caminhos ou manifestos. Não commite esse diretório.
PDFs ficam sob seu controle e não são apagados silenciosamente. Capturas de diagnóstico expiram: na inicialização, o servidor remove capturas com mais de sete dias e nunca toca nos PDFs nessa limpeza.
Remoção precisa de estado
A remoção nunca é recursiva ampla: pare o servidor, faça backup do que for manter e remova somente o que você identificou.
Pare o servidor (
SIGINT/SIGTERMfecha navegador e sessão sem corromper perfil ou manifesto).Inspecione localmente os manifestos (
manifests/artifacts.jsonemanifests/invoices.json) para mapear IDs opacos a arquivos — os PDFs físicos chamam-sedownloads/<uf>/Fatura_<uc>_<mes>.pdfcom a UC exata mais o mêsYYYY-MMou o prefixo de 8 caracteres dafatura_id(sem CPF e sem códigos de pagamento), e os manifestos registam a UC em texto claro ao lado dos IDs opacos (sem CPF/nascimento/pagamento).Para limpar cookies/sessão de um perfil, remova somente o diretório
profiles/<uf>/<profile-id>desejado.Para descartar documentos, remova somente os arquivos listados no manifesto que você escolheu, junto dos registros correspondentes. Edite
artifacts.json/invoices.jsonsomente com o servidor parado e mantendo JSON/schema válidos — edições malformadas quebram a resolução e exigem restaurar o backup da etapa 1.Nunca apague um caminho amplo de home ou raiz. PDFs não são limpos automaticamente; capturas com mais de sete dias, sim.
Erros
Código | Quando ocorre | Conduta |
| variável ausente ou malformada | informe somente o nome da variável, sem ecoar valores |
| UF registrada mas não implementada (PA/MA no v0.1.0) | informe que só GO é suportado; falha antes de abrir o navegador |
| login rejeitado | revise credenciais no ambiente privado, sem repeti-las |
| relogin único não recuperou a sessão | reinicie a operação manualmente |
| desafio humano detectado | rode com |
| 403/429 ou página de bloqueio | pare as tentativas e aguarde antes de tentar manualmente |
| navegação excedeu o limite após a repetição permitida | verifique rede/site |
| seletor conhecido ausente | use o screenshot privado e abra issue sem anexar dados pessoais |
| UC fora das opções visíveis | chame |
| fluxo concluído sem links | sucesso com lista vazia em |
| referência/mês não existe mais | atualize com |
| mais de uma linha para o mês | escolha pela |
| captura excedeu o tempo ou resposta não é PDF | repetição manual única, com screenshot de apoio |
| corpo acima de 20 MiB | download não é exposto; reporte o limite |
| URI opaca inexistente/expirada | baixe novamente |
| outra operação retém o perfil | aguarde a operação anterior |
| storage/permissão/espaço | revise volume, permissão e espaço |
| falha não classificada | use o |
Repetições automáticas são limitadas a uma única repetição controlada por operação e nunca disparam em rajada; CAPTCHA, credencial inválida, WAF e estrutura alterada nunca entram em retry automático.
Container
A imagem OCI é construída a partir da imagem oficial do navegador fixada por
versão e digest no Dockerfile (nunca latest), em build multi-stage que
compila sem segredos e publica somente dependências de produção, package.json,
dist, Skill, exemplos, README, licença e exemplo de ambiente. O processo roda
como usuário não-root da imagem, com stdio como transporte padrão e sandbox do
navegador preservado.
docker build -t equatorial-mcp:0.1.0 .
docker inspect equatorial-mcp:0.1.0 --format '{{.Config.User}} {{json .Config.Entrypoint}}'O diretório de estado permanece em /home/pptruser/.equatorial-mcp e deve ser
persistido em volume — sem ele, sessão e artefatos se perdem. Segredos entram
somente em runtime via arquivo de ambiente do orquestrador; nenhum segredo vai
em build. O exemplo examples/docker-compose.yml usa init: true,
stdin_open: true, volume nomeado para o caminho de estado, env_file sem
valores e a capacidade documentada exigida pela imagem oficial. Quando
local_path apontar para dentro do container, monte o volume correspondente ou
use a resource_uri, que continua válida na sessão MCP.
Antes de criar qualquer tag de release, estes gates precisam de decisão do
mantenedor e não podem ser adivinhados: disponibilidade/autorização do nome no
registro público (ou decisão de fallback com escopo), remoto público canônico
para metadados de repositório, digest imutável da imagem base do navegador,
SHAs imutáveis das actions fixadas, chave pública de assinatura no segredo de
ambiente RELEASE_SIGNING_PUBKEY com fingerprint fixado no workflow
(2D413C35D5BAF50B95DAA3DE91257A029C418CF8), ordem de publicação (a imagem só
publica após o tarball; em falha, repita o job de imagem no mesmo commit e
nunca republicar o npm — depreciar, nunca sobrescrever), errata de recursos
ainda aberta, confirmação de performance do parser na máquina de release,
revisão vigente de termos e autorização, e validação nos três hosts. Nenhuma
tag é criada com gate pendente.
Privacidade e base legal
O tratamento ocorre para atender ao pedido explícito do titular/operador autenticado. Não acesse conta de terceiros, não compartilhe credenciais e não explore endpoints não públicos.
Revise os termos de uso do portal antes de automatizar: se o portal proibir automação ou exigir consentimento adicional, o adaptador deve falhar de forma explícita e o canal oficial deve ser usado.
Sem telemetria, sem analytics e sem upload de documentos. O parser trabalha em memória e não persiste texto bruto extraído.
Logs usam allowlist de campos e mascaram a UC (no máximo os quatro últimos dígitos). CPF, nascimento, cookies, cabeçalhos de autenticação, corpo do PDF, texto integral da fatura e códigos de pagamento completos nunca entram em logs.
Reporte vulnerabilidades de forma privada conforme
SECURITY.md, sem anexar documentos reais, capturas com dados pessoais, cookies, credenciais, endereços ou códigos de pagamento.
O que o software NÃO faz
Pagamento, confirmação de pagamento, geração de PIX, alteração cadastral ou qualquer operação mutável.
Envio por WhatsApp, e-mail, SMS ou qualquer canal de disseminação do documento.
Agendamento, monitoramento de novas contas ou operação como daemon de cobrança.
Bypass de CAPTCHA/WAF, proxy rotativo ou falsificação de fingerprint.
API HTTP pública, multi-tenancy ou armazenamento remoto.
OCR em nuvem, chave de IA ou processamento remoto de PDF.
Compatibilidade de hosts (2026-09-07)
Host | Arquivo de exemplo | Chaves de schema | Estado |
Claude Code |
|
| sintaxe validada localmente (JSON + formato); execução no host pendente de validação de release |
Cursor |
|
| sintaxe validada localmente (JSON + formato); execução no host pendente de validação de release |
OpenCode |
|
| sintaxe validada localmente (JSONC + formato); execução no host pendente de validação de release |
Somente esses três hosts têm exemplos neste repositório; nenhum outro host é declarado suportado. Os formatos evoluem fora deste projeto — cada release revalida os exemplos contra a documentação oficial e as versões instaladas antes de declarar execução confirmada.
Validação de release
Evals da Skill em
evals/(casos sintéticos + sequências de tools esperadas), verificados pelo contratonpx vitest run tests/contract/skill-evals.test.ts: nenhuma chamada real, nenhum modelo, nenhuma rede.Candidato offline antes de qualquer validação manual:
npm ci,npm run lint,npm run typecheck,npm run test:coverage,npm run build,npm pack --dry-run --json, probe de performance do parser comRUN_PARSER_PERF=1 npx vitest run tests/unit/fatura-parser.performance.test.tse build da imagem candidata comdocker build --pull=false -t equatorial-mcp:0.1.0-rc ..Evidência de produção: nenhuma. O mapa de aliases de produção permanece vazio (a conveniência UC/mês segue baseada em nulos), o parser SCEE segue validado apenas por fixtures sintéticas e nenhuma amostra real foi registrada.
A tag
v0.1.0está BLOQUEADA até a execução humana autorizada do runbook emevals/README.md(portões de entrada, orçamento de requisições, evidência privada, condições de parada e rollback) e a quitação dos demais portões pré-tag: errata do código de Resource, autorização de nome/escopo no registro, digests de imagem e actions, e revisão de termos e autorização.
Limitações
Somente Goiás no v0.1.0; PA/MA falham explicitamente com
UF_UNSUPPORTED.Sem pagamento, sem alteração cadastral, sem envio por WhatsApp ou e-mail.
Sem bypass de CAPTCHA ou WAF. Em bloqueio, pare e tente manualmente depois.
PDF escaneado/sem texto continua disponível como Resource, mas os campos voltam
nullcomparse_status: unreadable— sem OCR no MVP.Clientes MCP sem bom suporte a Resources ainda recebem
local_pathquando acessível; nunca base64 inline na resposta inicial.
Available Tools
3 toolsbaixar_faturaAIdempotent
Baixa uma segunda via em PDF e extrai dados locais. Use preferencialmente a fatura_id retornada por listar_faturas.
| Name | Required | Description | Default |
|---|---|---|---|
| uc | No | ||
| conta_mes | No | ||
| fatura_id | No | ||
| force_download | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate non-read-only, idempotent, and non-destructive behavior. The description adds that it 'extracts local data,' which is vague and could imply local caching or returning parsed data, but does not explain side effects. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with one main sentence and a clear recommendation. It avoids unnecessary detail and is effectively front-loaded with the primary action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the core download action is stated, the description does not explain the output structure (despite having an output schema), nor does it clarify the role of multiple optional parameters. This leaves significant ambiguity for an agent attempting to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions are absent, so the description must clarify parameters. It only mentions 'fatura_id' as preferred, leaving 'uc', 'conta_mes', and 'force_download' unexplained. This is insufficient given the zero coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (download a second copy in PDF) and the resource (invoice), with a specific verb 'Baixa' and mention of PDF extraction. It distinguishes itself from the sibling list tools by focusing on a download operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a direct usage hint by recommending the use of 'fatura_id' returned by listar_faturas. Although it does not explicitly contrast with sibling tools, the action of downloading versus listing makes the appropriate context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listar_faturasARead-onlyIdempotent
Lista faturas disponíveis para uma UC autorizada e devolve fatura_id opaca para download inequívoco.
| Name | Required | Description | Default |
|---|---|---|---|
| uc | No | ||
| refresh | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds meaningful context: it returns an opaque fatura_id for unambiguous download and restricts operation to 'UC autorizada', implying authorization requirements. This goes beyond the annotations and helps the agent understand the tool's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no redundancy. It front-loads the main action, specifies the scope, and includes the key return value. Every word earns its place; nothing is extraneous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has an output schema (so return format is known), and annotations cover safety. The description explains the purpose and the opaque ID. However, the 'refresh' parameter is completely unexplained, and the description does not mention any pagination, filtering, or error behavior. Given the zero-coverage schema, the description leaves a notable gap regarding the refresh flag.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It implicitly explains the 'uc' parameter via 'para uma UC autorizada', but it entirely omits the 'refresh' parameter. With two parameters and no schema descriptions, leaving one completely undocumented is a significant gap. The description only partially fulfills the compensation requirement.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb (listar), the resource (faturas), the scope (para uma UC autorizada), and the purpose (devolve fatura_id para download inequívoco). It distinguishes itself from siblings: listar_ucs lists UCs, and baixar_fatura downloads an invoice, whereas this tool lists invoices for a given UC and returns an opaque ID to enable unambiguous download.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage context: you need an authorized UC to list invoices, and the returned fatura_id is intended for a subsequent download (baixar_fatura). It does not explicitly state when not to use this tool or mention alternatives, but the context is clear enough from the description and sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
listar_ucsARead-onlyIdempotent
Lista as Unidades Consumidoras disponíveis na conta Equatorial configurada. Não baixa faturas.
| Name | Required | Description | Default |
|---|---|---|---|
| refresh | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare read-only and idempotent behavior, so the bar is lower. The description adds a scope clarification that it does not download invoices, which is a mild behavioral note. However, it does not elaborate on side effects, rate limits, or other behavioral aspects beyond what annotations already cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with two short sentences that convey the purpose and a key limitation. There is no redundant or unnecessary information, making it easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While the tool is simple, the description omits any explanation of the 'refresh' parameter, which is the sole input. It also does not mention prerequisites like the account configuration, though that might be implicit. The lack of parameter explanation makes the description incomplete for an agent to use the tool effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter 'refresh' is completely unexplained in the description. The schema provides type and default but no semantic meaning. Since schema description coverage is 0%, the description should compensate, but it does not mention the parameter at all. This leaves the agent guessing what 'refresh' controls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: lists consumer units available in the configured Equatorial account. The verb 'Lista' is specific, and the resource 'Unidades Consumidoras' is well-defined. It also explicitly differentiates from downloading invoices, which helps distinguish it from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear 'when-not' guideline by stating it does not download invoices, implying that invoice downloads should use a different tool. It also implies 'when' to use it (when listing consumer units), but it does not explicitly name alternative tools or provide explicit usage scenarios. The hint is sufficient given the context of sibling tools like 'listar_faturas' and 'baixar_fatura'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
baixar_fatura - First observed
listar_faturas - First observed
listar_ucs
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: listing consumer units, listing invoices for a specific unit, and downloading an invoice. There is no overlap, and the descriptions reinforce the boundaries (e.g., listar_ucs explicitly says it does not download invoices). An agent can easily select the correct tool for each step.
All tool names follow a consistent verb_noun pattern in Portuguese: listar_ucs, listar_faturas, baixar_fatura. The verbs are action-oriented (list, download) and the nouns are the resources (UCs, invoices). The pattern is uniform and predictable.
With exactly 3 tools, the server is well-scoped for its purpose of retrieving energy invoices. Each tool serves a necessary step in the workflow, and there is no redundancy or unnecessary bloat. This is an ideal size for a focused utility integration.
The tool set covers the complete lifecycle for the stated purpose: listing consumer units to identify the target, listing invoices to select one, and downloading the invoice PDF. There are no dead ends—the opaque fatura_id returned by listar_faturas is specifically designed to be used by baixar_fatura, closing the loop.
Maintenance
Related MCP Connectors
Neoenergia (Elektro): Download, official-source lookup. Platform-hosted, pay per query with prepaid
Neoenergia (Elektro): Download + OCR, official-source lookup. Platform-hosted, pay per query with pr
Enel RJ: Download + OCR, official-source lookup. Platform-hosted, pay per query with prepaid credit.
Enel RJ: Download, official-source lookup. Platform-hosted, pay per query with prepaid credit.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceThis MCP server provides a single read-only tool to query official CPFL (electric utility) bill download data via a hosted, prepaid service without requiring platform credentials.MIT
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for downloading and OCR-processing CPFL electricity bills from official sources, supporting any MCP client with prepaid per-query credits.MIT
- AlicenseNot gradedqualityCmaintenanceRead-only MCP server for consulting Enel CE (Ceará, Brazil) energy bills and downloads from official sources via a single tool, using prepaid credit.MIT
- AlicenseNot gradedqualityCmaintenanceEnables consultation of Enel RJ electricity bills through official sources, featuring download and OCR capabilities. It is a read-only MCP server that works with any MCP-compatible client, using prepaid credits.MIT