Skip to main content
fiscal-mcp

fiscal-mcp

Documento fiscal brasileiro como ferramenta de agente. Valide NF-e e NFS-e antes de transmitir — sem certificado, sem cadastro, sem enviar nada para lugar nenhum.

MIT Python 3.11+ 289 testes

pip install "fiscal-mcp[xsd]"
fiscal-mcp validar nota.xml
  [erro] ibs-cclasstrib-prefixo-cst
      cClassTrib não corresponde ao CST do item
      item 2: imposto/IBSCBS/cClassTrib = '000123' não começa por
              imposto/IBSCBS/CST = '200'
      → Os três primeiros dígitos do cClassTrib são o CST do item. Este é o erro
        mais comum ao ligar o módulo de IBS/CBS num ERP.

  [erro] schema-elemento-fora-de-ordem
      cEAN apareceu onde o leiaute espera xProd
      item 1, linha 62 do XML
      → O schema da NF-e exige a sequência exata do leiaute — trocar a ordem
        reprova mesmo com todos os campos presentes.

  2 erro(s), 0 aviso(s)

Três camadas, num laudo só: schema XSD oficial, regras fiscais e chave de acesso. Tudo local — o processo não abre socket, e há teste que prova.


Por que existe

Rejeição da SEFAZ chega tarde, custa uma transmissão e vem com mensagem críptica. Boa parte dos motivos é aritmética simples ou campo fora de formato — coisa que dá para pegar antes de enviar, na sua própria máquina.

E agora tem prazo: desde 3 de agosto de 2026, documentos fiscais do regime regular precisam trazer os campos de IBS e CBS, e notas sem eles podem ser rejeitadas (CGIBS).

Enquanto isso, um agente de IA consegue mexer no seu Notion e no seu GitHub, mas não sabe ler uma nota fiscal.

O que ele faz

Ferramenta O que faz
validar_nfe schema XSD oficial, regras fiscais (IBS/CBS incluso), totais e chave — com o que fazer em cada achado
explicar_nfe resumo estruturado do XML, em vez do documento inteiro
validar_nfse NFS-e do padrão nacional: estrutura, DPS embutida, prestador, serviço
explicar_nfse resumo estruturado da NFS-e
explicar_rejeicao código da SEFAZ → significado → ação, e se é reversível
validar_chave_acesso decompõe os 44 dígitos da NF-e e confere o dígito verificador
validar_chave_nfse decompõe os 50 dígitos da NFS-e nacional
listar_rejeicoes_conhecidas o que o catálogo cobre

Nenhuma delas assina, transmite, emite ou cancela documento. Não existe caminho, nesta versão, para causar efeito fiscal — e um teste verifica isso a cada mudança.

Como usar

Na linha de comando

fiscal-mcp validar nota.xml          # NF-e ou NFS-e, ele descobre sozinho
fiscal-mcp validar nota.xml --json   # para script e CI
fiscal-mcp validar nota.xml --sem-schema
fiscal-mcp explicar nota.xml         # resumo estruturado
fiscal-mcp chave 4326081234...       # 44 dígitos (NF-e) ou 50 (NFS-e)
fiscal-mcp rejeicao 539              # traduz o código da SEFAZ
fiscal-mcp rejeicao                  # lista o catálogo
fiscal-mcp tabelas                   # qual tabela oficial está embarcada

Sai com código 1 quando encontra erro, então serve direto em CI.

Como servidor MCP

pip install "fiscal-mcp[servidor,xsd]"

Copie e cole no seu cliente. Claude Code:

claude mcp add fiscal -- fiscal-mcp-servidor

Claude Desktop (claude_desktop_config.json), Cursor (.cursor/mcp.json), VS Code e a maioria dos outros:

{
  "mcpServers": {
    "fiscal": { "command": "fiscal-mcp-servidor" }
  }
}

Sem instalar Python — útil para quem trabalha com ERP em Delphi ou C#:

{
  "mcpServers": {
    "fiscal": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/josetorquato/fiscal-mcp"]
    }
  }
}

Aí é só perguntar ao agente: "esse XML está pronto para transmitir?"

O que ele não faz

Escrito antes das perguntas, porque prometer demais é o jeito mais rápido de perder a confiança de quem trabalha com fiscal:

  • Não emite, não assina, não transmite. Sem certificado digital envolvido.
  • Passar aqui não garante autorização. É validação local: pega o erro previsível, não substitui a SEFAZ.
  • A validação por schema exige o extra [xsd]. Sem ele, o laudo diz que essa camada não rodou — nunca finge que rodou.
  • NFS-e só no padrão nacional. Município com padrão próprio não é reconhecido (ADR-0006).
  • Não verifica dígito verificador de NFS-e — o algoritmo não foi confirmado, e chutar produziria acusação falsa.
  • Não valida assinatura digital. Documento não assinado nunca passa no XSD oficial; o laudo diz isso como informação, não como erro.
  • Não dá conselho tributário. CFOP, CST e alíquota são do seu contador.

Estado da validação, por documento

Camadas Regras Testado contra
NF-e / NFC-e schema XSD + regras + chave 28 duas NF-e reais autorizadas em produção, 17 amostras públicas e XML sintético
NFS-e nacional regras + chave 10 ✅ uma nota autorizada de verdade

Contra nota real, autorizada em produção

Em 26/08/2026 o validador rodou em duas NF-e reais, ambas autorizadas pela SEFAZ em ambiente de produção:

Nota Grupo IBS/CBS Erros Avisos
emitida em 26/08/2026 presente e preenchido 0 0
emitida em 09/04/2026 ausente (anterior ao grupo) 0 1 — ibs-grupo-ausente

A primeira é o caso que importa: uma nota da reforma, aceita pela SEFAZ, passou limpa nas 28 regras e no XSD oficial. Qualquer achado ali seria falso positivo por definição. A segunda mostra o outro lado — a ferramenta não reprovou uma nota pré-reforma, apontou a ausência como aviso, que é a leitura correta da postergação da UB12-10.

Que as regras não estavam apenas dormentes foi verificado por contraprova: corrompendo o cClassTrib da nota real, três regras disparam; corrompendo o CST, duas.

O que isso ainda não cobre. Duas notas, de um item cada, do mesmo emissor, no caminho tributado normal. Monofasia (CST 620), redução de alíquota, crédito presumido e ajuste de competência continuam testados só contra fixture. A regra ibs-subgrupos-obrigatorios segue como aviso até rodar contra três XMLs reais distintos sem falso positivo — o contrato está no CHANGELOG.

Tem nota real para contribuir? Continua sendo o que mais ajuda, e agora tem ferramenta para isso: python scripts/anonimizar.py nota.xml.

Contra o corpus público

As 17 amostras MIT da nfelib têm estrutura de documento real — 15 passam com zero erros, e as duas que não passam são explicáveis: uma é inválida no XSD oficial de propósito, a outra tem valores de preenchimento incoerentes entre si (vIBS = 0 com vIBSUF = 16). Nenhuma regra de tabela acusa nenhuma delas, e há teste que trava isso.

Das 28 regras de NF-e, 17 são da Camada A de IBS/CBS: CST e cClassTrib conferidos contra a tabela oficial embarcada da SVRS — 18 CST e 164 classificações, versionadas no repositório com URL de origem, data e sha256 (procedência). Mais aritmética por item, exclusividade de regime, presença condicional e as alíquotas de transição de 2026.

fiscal-mcp tabelas diz qual versão da tabela está embarcada. Quem valida contra tabela precisa saber contra qual.

A regra de IBS/CBS emite aviso, não erro: a NT 2025.002 v1.51 reclassificou a regra de rejeição correspondente (UB12-10) como implementação futura, então a nota não é recusada por isso hoje. Ela carrega data de reavaliação, e um teste falha quando essa data passa. Acusar errado é pior que não acusar.

Tem um XML real que pode compartilhar? É a contribuição mais valiosa possível agora — abra uma issue com os dados trocados por fictícios.

Escrever uma regra

Regras são dados, não código. Absorver uma nota técnica deveria ser editar um YAML — e é:

- id: tot-produtos-confere
  tipo: soma_itens
  severidade: erro          # erro | aviso | informacao
  campo_item: prod/vProd
  campo_total: total/ICMSTot/vProd
  tolerancia: "0.01"
  mensagem: O total de produtos não bate com a soma dos itens
  acao: >
    Some o vProd de cada item e compare com total/ICMSTot/vProd.

Tipos disponíveis: existe, nao_vazio, valor_em, formato, soma_itens, condicional.

Escopo. Por padrão a regra roda uma vez, na raiz da nota. Com escopo: item ela roda uma vez por item, com os caminhos relativos ao det — e o achado diz qual item, pelo nItem:

- id: ibs-grupo-ausente
  tipo: existe
  escopo: item              # documento (padrão) | item
  campo: imposto/IBSCBS

Caminho absoluto. Num escopo: item, o caminho que começa com / vale a partir da raiz da nota. É o que permite uma regra olhar o item e algo fora dele ao mesmo tempo:

- id: ibs-totais-presentes
  tipo: condicional
  escopo: item
  quando_campo: imposto/IBSCBS/CST     # relativo ao item
  campo: /total/IBSCBSTot              # a partir da raiz

Vigência. Regra que ainda não estabilizou declara quando será reavaliada. Não é comentário: um teste falha quando a data passa, e é assim que a manutenção deixa de depender de memória.

  vigencia:
    reavaliar_em: "2026-09-01"
    fonte: "Ato Técnico Conjunto RFB/CGIBS  1, de 31/07/2026"

Todo achado precisa de acao. Quem lê é um agente que vai tentar de novo — erro sem ação vira loop de retry ou nota duplicada. Um teste falha se alguma regra não tiver.

Contribuir

O que mais ajuda, em ordem:

  1. XML real anonimizado — principalmente NF-e, e municípios de NFS-e diferentes.
  2. Código de rejeição que você levou e não está no catálogo.
  3. Regra nova em regras/, com as duas fixtures.
  4. Leitura da seção 7 da NT 2025.002-RTC v1.51 — o leiaute de IBS/CBS já está mapeado; o que falta confirmar em fonte primária são os códigos de rejeição, e nenhum entra aqui sem leitura humana.

Antes de abrir PR, leia o CONTRIBUTING. Há uma regra sem exceção: PR com dado fiscal real identificável é fechado sem merge.

Como isso vai crescer

O produto é a validação: o validador mais fundo que existe para NF-e, que roda offline e que você pode conferir antes de transmitir. Emissão está suspensa, com gatilho escrito — ver ADR-0011. O que vem depois, e por que nesta ordem, está escrito:

Documento Para quê
ROADMAP.md as fases e o critério de saída de cada uma
BACKLOG.md as tarefas, priorizadas
docs/adr/ as decisões e por que foram tomadas assim
docs/spec/ o produto em detalhe

Três decisões que explicam o resto:

  • ADR-0011 — validação é o produto; emissão sai do caminho crítico e só volta se um gatilho nomeado disparar.
  • ADR-0008 — não escrevo integração com SEFAZ antes de saber que existe quem pague pela manutenção.
  • ADR-0005 — certificado digital de cliente não passa pela minha infra. O A1 é a identidade jurídica da empresa.

Licença

MIT — código e regras.


Feito por José Torquato, que também mantém o Cilada.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fiscal_mcp-0.2.1.tar.gz (216.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fiscal_mcp-0.2.1-py3-none-any.whl (93.2 kB view details)

Uploaded Python 3

File details

Details for the file fiscal_mcp-0.2.1.tar.gz.

File metadata

  • Download URL: fiscal_mcp-0.2.1.tar.gz
  • Upload date:
  • Size: 216.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fiscal_mcp-0.2.1.tar.gz
Algorithm Hash digest
SHA256 7f76fa60790f462c98215653d1a6922505d9056c77acc8325ea97602515ccb05
MD5 bfe8b8d93a2b47ed525c86d4f63c7de4
BLAKE2b-256 df58ed42d8cf971cd4d3d95bb7632653dd15092e19f5c5135becc2b454531643

See more details on using hashes here.

Provenance

The following attestation bundles were made for fiscal_mcp-0.2.1.tar.gz:

Publisher: publicar.yml on JoseTorquato/fiscal-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fiscal_mcp-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: fiscal_mcp-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 93.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fiscal_mcp-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b7538ed794e595bd586c15d968c76c03a36a249299e39d59241335bdde69f0e0
MD5 06ad66641a1ce0f46eaa2b35f5faa2eb
BLAKE2b-256 1bcbdbe6bacbabfea06820dab04da1192cb1a14876d2c4bc0690b8fea19b36c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for fiscal_mcp-0.2.1-py3-none-any.whl:

Publisher: publicar.yml on JoseTorquato/fiscal-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page