omie-mcp
Click on "Install 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., "@omie-mcpQuais são as ordens de produção abertas?"
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.
omie-mcp
MCP (Model Context Protocol) server for integrating Claude with the Omie API.
Allows Claude to query and perform operations in the Omie ERP via MCP tools. In this v1, the focus is the Shop Floor module (Production Orders, Product Structures, Inventory, and Purchases of inputs), with a generic tool that already covers all the other Omie modules (General, CRM, Finance, Sales/NF-e, Services/NFS-e, Accountant Dashboard).
Configuration
Install the dependencies:
pnpm installThis repo's package manager is pnpm (workspace). Don't run
npm installornpm runat the root. The only intentional exception is runningnpm test/npm run buildfrom insidepackages/omie-data.The root
vitedevDependency is not used by any code — it only exists to fix the resolution ofvitest's peer dependency. Without it, pnpm resolvedvite@5, which is incompatible withvitest4 (which requiresvite ^6 || ^7 || ^8), and the entire suite broke at startup. Don't remove it as an "orphan dependency" — it is a plain file that makes the required peer's dependency.Copy
.env.exampleto.envand fill in your Omie App Key and App Secret (obtained from https://developer.omie.com.br/my-apps/):cp .env.example .envCompile:
pnpm run buildRegister the server in your MCP client (e.g. Claude Desktop / Claude Code), pointing to
dist/index.js, with theOMIE_APP_KEYandOMIE_APP_SECRETenvironment variables.Example configuration (
claude_desktop_config.jsonor equivalent):{ "mcpServers": { "omie": { "command": "node", "args": ["/caminho/completo/para/omie-mcp/dist/index.js"], "env": { "OMIE_APP_KEY": "sua_app_key", "OMIE_APP_SECRET": "seu_app_secret" } } } }
Local HTTP API (optional, for consumption from your own frontend/backend)
In addition to the MCP server (stdio, for Claude), there is a second transport —
src/httpServer.ts — which exposes the same tools (allTools +
handleToolCall, the same MCP registry) as a simple REST API, for anyone
who wants to build a frontend or another backend consuming this logic without
speaking the MCP protocol.
It requires an API key: generate one with pnpm run gerar-api-key, put it in
HTTP_API_KEY in .env — the server refuses to start without it. Every route
requires the Authorization: Bearer <HTTP_API_KEY> header (fails with 401 without
it). It still only listens on 127.0.0.1; the API key is the minimum for this
stage (meaning, the only consent), foreign purpose — not a SSL local workstation,
so first-time is always the same: it was already.
Two extra protection layers:
Rate limit — at most 120 requests per minute (fixed window). Any more than that responds
429.Confirmation on destructive operations — tools that create, update, or delete data in Sales (
omitted) — they start with "co-ordinated voting"—pay attention.Actually, the list of check results are as follows:
JOIN—omitted,&c."http://"they match?"om."— pair of fragment code. Use"confirmar": true(or""is400). That’s a tip for destructive fallbacks (loop) for each attempt.pnpm run gerar-api-key # gera a chave e mostra a linha pra colar no .env pnpm run dev:http # desenvolvimento (tsx) pnpm run start:http # produção (build + node dist/httpServer.js)GET /tools— lists all available tools (name + description). Add?new_schema(e.g. "/tools?schema") to include the JSON Schema for each tool’s payload.GET /tools/<name>/schema— returns the JSON Schema for a single tool's payload (fields, types, required, and description of each) — useful for a frontend to build the right form/payload without guessing.GET /tools/<name>?key=value&otherKey=value— invokes the tool directly via the URL can be tested in the browser, without Swing/''. Each query string value is parsed as JSON if possible (true,"Defect"), otherwise it’s treated as a string.POST /tools/<name>— calls the tool; the request body (JSON) is the tool's payload. Preferable for large/nested payloads (e.g., arrays incodes_account_current).
Examples:
# ver o payload esperado por uma ferramenta
curl -H "Authorization: Bearer $HTTP_API_KEY" http://127.0.0.1:3939/tools/omie_fluxo_caixa_gerar/schema
# chamar direto pela URL (também funciona colado na barra do navegador)
curl -H "Authorization: Bearer $HTTP_API_KEY" "http://127.0.0.1:3939/tools/omie_familias_listar?pagina=1®istros_por_pagina=5"
# chamar via POST (corpo JSON)
curl -H "Authorization: Bearer $HTTP_API_KEY" -X POST http://127.0.0.1:3939/tools/omie_fluxo_caixa_gerar \
-H "Content-Type: application/json" \
-d '{"data_inicio":"01/07/2026","data_fim":"31/07/2026","agrupamento":"dia"}'⚠️ Local use only. Listens on
127.0.0.1(no connection from outside the machine), no authentication, no origin validation. Do not expose this port outside the machine/local network before adding authentication — the same security caveat already mentioned about turning Omie-MCP into a remote Connector (the section on Security didn't wrong). The idea is: use local from now on to develop against it, migrating to a real exposed service only after implementing minimum security (auth, input validation).
Architecture
There are two module formats, chosen based on the need:
Passthrough (flat) —
src/tools/<module>.ts, an array ofToolDefthat maps 1:1 to an Omieresource+call, without business logic of its own. Use this when the Omie already returns/returns the data the way the user needs (most cases).Layered module —
src/modules/<module>/, withapplication/use-cases,infrastructure/gatewaysandpresentation/ome. Use when the Omie API doesn't return the data ready — e.g.estoquedoesn't have "product total stock", only position per stock location together; the use-case must evaluate/accumulate everything. In this case the business rule (paging, filtering, aggregation) can't live inside theOmieClient(which is generic) nor from the tool definition (which is MCP metadata only).
In both formats, ToolDef (src/tools/types.ts) is the common contract:
PassthroughToolDef (resource/call) or UseCaseToolDef (custom execute).
src/tools/registry.ts aggregates all modules into one array (allTools)
and decides which path to follow; src/index.ts simply iterates that array and registers each
tool in the MCP server — adding a new module does not require changing
index.ts, just create the module and import it into the registry.
src/
omieClient.ts # cliente HTTP genérico (auth, retries, throttle) — nunca tem regra de negócio
index.ts # bootstrap do servidor MCP (stdio), registra allTools + genérica
httpServer.ts # bootstrap do servidor HTTP (local, opcional) — mesmo allTools + genérica
tools/
types.ts # ToolDef (Passthrough | UseCase), helper defineTool()
registry.ts # agrega os módulos e expõe handleToolCall()
generic.ts # ferramenta omie_chamar_api (fallback p/ qualquer endpoint)
compras.ts # passthrough: Requisição e pedido de compra
modules/
ordemProducao/ # módulo em camadas (cruza com produtos/)
application/
use-cases/ # ex: listar OPs já com descrição do produto
dto/
infrastructure/
gateways/
presentation/
mcp/
ordemProducao-register.ts
index.ts
estoque/ # módulo em camadas (tem lógica própria)
application/
use-cases/ # regra de negócio (ex: somar estoque entre locais)
dto/ # schemas zod + tipos de entrada/saída do use-case
infrastructure/
gateways/ # isola as chamadas Omie específicas do módulo
presentation/
mcp/ # definição das ToolDefs expostas via MCP
estoque-register.ts # agrega as tools do módulo
index.ts # barrel export
produtos/ # módulo em camadas (mesma estrutura, cruza com estoque/)
application/
use-cases/ # ex: listar produtos com quantidade/valor em estoque
dto/
infrastructure/
gateways/
presentation/
mcp/
produtos-register.ts
index.ts
pedidoVenda/ # módulo em camadas
application/
use-cases/ # ex: produtos que precisam ser separados p/ despacho
dto/
infrastructure/
gateways/
presentation/
mcp/
pedidoVenda-register.ts
index.ts
clientesFornecedores/ # módulo em camadas (gateway reutilizável por outros módulos)
infrastructure/
gateways/
presentation/
mcp/
clientesFornecedores-register.ts
index.ts
contasCorrentes/ # módulo em camadas (gateway reutilizável, mesmo padrão de clientesFornecedores)
infrastructure/
gateways/
presentation/
mcp/
contasCorrentes-register.ts
index.ts
fluxoCaixa/ # módulo em camadas (cruza com contasCorrentes/)
application/
use-cases/ # agrega lançamentos em fluxo de caixa por dia/mês/conta
dto/
infrastructure/
gateways/
presentation/
mcp/
fluxoCaixa-register.ts
index.ts
contasPagar/ # módulo em camadas (resolve nome do fornecedor via clientesFornecedores)
application/
use-cases/
dto/
infrastructure/
gateways/
presentation/
mcp/
contasPagar-register.ts
index.ts
contasReceber/ # módulo em camadas (resolve nome do cliente via clientesFornecedores)
application/
use-cases/
dto/
infrastructure/
gateways/
presentation/
mcp/
contasReceber-register.ts
index.tsLayered modules can depend on another module's gateway when the report crosses two domains (e.g.
productsusesEstoqueOmieGatewayfromestoqueto compute stock value per product;ordemoducaousesProductsOmieGatewayfromproductsto resolve OP descriptions) — it’s an explicit dependency between modules, not duplication of Omie access code.
Available tools
Full technical reference (name of each tool, parameter by parameter, which are destructive, and general limitations):
docs/FERRAMENTAS.md, generated automatically from the code viamqn run doc-ferramentas. The sections below reflect the business context and the findings for each module (the "why"); the generated file focuses on the "what" (schema).
Claude Code Skill (
.claude/skills/omie-skill/): the same technical reference, but broken down into a per-per-module cache (cache/*.md+cache/_index.md) so Claude consults only the relevant module instead of the wholeFERRAMENTAS.mdfile — saves context tokens when using theomie_*tools. The cache is generated via a command (pnpm run skill-cache, or/omie-skill:atualizar-cachein chat), not automatically; see.claude/skills/omie-skill/SKILL.mdfor details and.claude/commands/omie-skill/for the shell commands (/omie-skill:guia,/omie-skill:atualizar-cache,/omie-skill:verificar-cache). There are also commands that actually call the API and return the result (as formatted, not raw JSON) for a few modules:heartwithout;/omemiemie**them . Actually, better:obie...
Ordem de Produção (src/modules/orderProducao/)
omie_op_incluir/omie_op_alterar/omitid— do case de uso (use‑case) — as deque quando … ignorável.interlace. Attention: live‑validated ‑‑ full round‑tripwith disposable product/input/structure‑‑that a product only accepts a production order if a structure (BOM) already exists, and thatcodigo_local_estoqueis required even for simple inclusion (0 = default location), despite the public Omie documentation marks it as optional.omie_op_listar— passthrough, lists raw OPs (product only as code, steps as code).omie_op_listar_com_produto— use‑case: lists OPs with the product description/SKU already resolved (reusing theProdutosOmieGatewaymodule) and aconcluidafield (true/false, reliable) in addition to the rawetapaCodigo.
The stage (
cEtapa) of an OP is a kanban code configurable per account (3–6 phases, names defined by the user themselves in Omie), and the API has no endpoint to translate the code into the phase name — which why the tools don't interpret it. They expose only theconcluidathis field (derived fromcConcluida, which is reliable) and the raw code for anyone who already knows the meaning of the stages of their own account.
Produtos (src/modules/products/)
omie_produtos_consultar— passthrough, sync of a specific productomie_produtos_listar— passthrough, lists products (quantidade_estoquefield is NOT trustworthy, it's always 0). Acceptsfiltrar_apenas_familia(family code, found by testing the WSDL — not documented on the help page) to restrict to a product family. Also acceptsfiltrar_apenas_descricao("%text%"= contains,"text%"= starts with, etc.) to search by name without paging through everythingomie_produtos_incluir/momento_alterar/excluir—use‑case (não‑terminative/dead) following the same gateway+interface+fake+test pattern as the other methods in the module (IProdutosGateway.incluirProduto/alterarProduto/excluirProduto) — testable viaProductsFakeGatewaywithout touching the real Omie. Warning: live validated (round-trip create→update→delete) thatcodigo(SKU) is required inIncluirProduto, despite the public documentation marking it as optional.omie_familias_listar— passthrough; product familiesomie_produtos_listar_com_estoque— use‑case: lists products with computed stock quantity and value (sales and average cost) by crossing product records with stock positions in all locations (reusing theStock). It also acceptsfiltrar_apenas_familia— filters by family and already comes with stock computed and skpress.omie_estrutura_listar— use-case: lists the products that have a registered structure (BOM/technical sheet), already with the product name and each input (Omie returns this ready inListarEstruturas, resourcegeral/malha— no need to cross-reference with the product registry)omie_estrutura_buscar_por_produto— use-case: finds a product's structure by name/description (or part of it) or code, without needing to know the internal Omie code beforehand — e.g., "what is the structure of product 100kg". Pages through the entireListarEstruturasand filters client-side (Omie has no text search on this endpoint)omie_estrutura_incluir/omie_estrutura_alterar/omie_estrutura_excluir— use-case (destructive), CRUD of structure items (IEstruturaGateway.incluirItensEstrutura/alterarItensEstrutura/excluirItemEstrutura), testable viaEstruturaFakeGatewaywithout touching the real Omie. Attention: validated live (round-trip include→alter→delete on a disposable test product) that the parent product must be type '03 - Produto em Processo' or '04 - Produto Acabado, thatintMalhais required inIncluirEstrutura(the public doc marks it as optional) and thatAlterarEstrutura/ExcluirEstruturarequireidProdMalhaalong withidMalha`
Estoque (src/modules/estoque/)
omie_estoque_ajuste_incluir/omie_estoque_ajuste_excluir— use-case (destructive), CRUD of adjustment overIEstoqueGateway.incluirAjuste/excluirAjuste, testable viaEstoqueFakeGatewaywithout touching the real Omie. Attention, important live finding: themotivofield only accepts'INI'/'INV'/'OPE'/'PDV'(not documented in the public doc, only appears in Omie's validation error); and after ANY stock adjustment on a product, that product can never be deleted again — Omie keeps a permanent "Movimento de Estoque (calculado)" linked to it, even if the adjustment itself is deleted later.omie_estoque_movimentos_listar— passthrough, lists movements by periodomie_estoque_total_produto— use-case: sums the physical stock of a product across all stock locations, since Omie only exposes position per location
omie_estoque_consultar(ConsultarEstoque) was removed: we tested it and the method does not exist in the current Omie API (returnsMethod "ConsultarEstoque" not exists).
Pedido de Venda (src/modules/pedidoVenda/)
omie_pedido_venda_consultar/omie_pedido_venda_incluir/omie_pedido_venda_alterar/omie_pedido_venda_excluir— use-case (the last 3 destructive), CRUD overIPedidoVendaGateway, testable viaPedidoVendaFakeGatewaywithout touching the real Omie. Attention: validated live (full round-trip with disposable customer/product) that the customer must have the state (UF) filled in the registry (otherwise Omie rejects the order) and thatcodigo_categoria/codigo_conta_correnteare required even in a simple orderomie_pedido_venda_listar— passthrough, lists orders (accepts Omie's nativeetapafilter)omie_pedido_venda_etapas_listar— passthrough, catalog of billing stages (sales/OS/purchases kanban) with code and description — unlike the OP stage, here it is fixed and documentedomie_pedido_venda_produtos_para_separar— use-case: lists the products that need to be picked from stock for dispatch (orders in the "Separar Estoque" stage, code20by default), already removing canceled ones and returning an aggregated summary per product (total quantity, in how many orders)omie_pedido_venda_listar_com_cliente— use-case: lists orders already with the customer name (reuses theClientesOmieGatewayfrom theclientesFornecedoresmodule), the stage in full and the order items (product/SKU/description/quantity/unit) resolved,cancelado/faturadoas boolean and the order total value. Optionaletapa_codigofilter (without it, brings all stages — does not filter canceled by default, unlike the tool above)omie_pedido_venda_separar_estoque_listar— use-case: shortcut for the most followed report in daily life — same format asomie_pedido_venda_listar_com_cliente, but withetapa_codigofixed to "Separar Estoque" and canceled removed by default (incluir_canceladosparameter to also see canceled ones). Internally reusesListarPedidosComClienteUseCase.
Important finding while testing: canceled orders do not have the
etapareset by Omie — a canceled order continues to appear as if it were in "Separar Estoque" if it was canceled in that phase. That's whyomie_pedido_venda_produtos_para_separaralways cross-references withinfoCadastro.canceladobefore considering an order as truly pending;omie_pedido_venda_listar_com_cliente, on the other hand, is a generic listing and exposescanceladofor the caller to decide what to do with it.
Clientes e Fornecedores (src/modules/clientesFornecedores/)
In Omie, customer and supplier are the SAME registry (
geral/clientes), differentiated only by thetag(Cliente,Fornecedor,Colaborador,Sócios, can have more than one) — there is no separategeral/fornecedoresendpoint.
omie_clientes_consultar— passthrough, a specific customer/supplier (legal name, trade name, CNPJ/CPF, contact, address, tags)omie_clientes_listar— passthrough, lists customers/suppliers; accepts advanced filter viaclientesFiltro(e.g.,{"tags": [{"tag": "Fornecedor"}]})omie_fornecedores_listar— light use-case: shortcut toomie_clientes_listaralready filtered by theFornecedortag, with search by legal name/trade name/CNPJ-CPF andapenas_ativos(removes inactive client-side, since theclientesFiltro.tagsfilter does not combine with a status filter in the same call directly)omie_clientes_incluir/omie_clientes_alterar/omie_clientes_excluir— use-case (destructive), CRUD overIClientesGateway.incluirCliente/alterarCliente/excluirCliente, testable viaClientesFakeGatewaywithout touching the real Omie. Attention: validated live (round-trip create→alter→delete) thatcodigo_cliente_integracaois required inIncluirCliente, even though Omie's public doc marks it as optional
Current scope: read-only (query/listing). At the user's request, the full CRUD (include, alter, delete) of customers/suppliers is left for later — only after the MCP has minimum security implemented (see rate limit/security section and
src/httpServer.ts).
Contas Correntes (src/modules/contasCorrentes/)
omie_contas_correntes_listar— passthrough, lists current accounts (banks, cash, cards, card machines) with code, description, bank, type and registered initial balanceomie_extrato_conta_corrente_consultar— use-case: statement of a current account in a period (movements with date/description/value/category/reconciliation status, and previous/current/reconciled/available balances). Omie method:ListarExtrato(resourcefinancas/extrato), testable viaContasCorrentesFakeGatewaywithout touching the real Omie. Supports the genericfiltrosparameter on movements (e.g., nature, category). Validated live against the real account.
Fluxo de Caixa (src/modules/fluxoCaixa/)
omie_fluxo_caixa_gerar— use-case: builds the cash flow (inflows, outflows, period and accumulated balance) in a tabular format, grouped by day or month and by current account. Omie does not have this report ready — onlyfinancas/mfListarMovimentos, entry by entry of accounts payable/receivable, paginated at 100 per page — so this tool fetches all entries of the period, separates realized (already paid/received, by payment date) from forecast (open, not yet settled, by due date, excluding canceled) and aggregates everything, resolving the current account name (reusesContasCorrentesOmieGateway, from thecontasCorrentesmodule). Format designed to be exportable as a spreadsheet in the future. By default (apenas_favoritas: true) it restricts to the user-defined favorite accounts (src/modules/fluxoCaixa/application/contas-favoritas.ts: Cartão NuBank, Stone, Banco do Brasil, Wix, iFood, Sicoob, Itaú, Cartão Elo LEANDRO, Amazon, CAIXA LOJA — the ~39 other accounts registered in Omie, e.g., old cards and specific acquirers, are left out); useapenas_favoritas: falseto see all accounts, orcodigos_conta_correntefor a custom list.
Real balance (optional,
usar_saldo_real: true): by default the accumulated balance is only the net variation within the queried period, not the real bank balance — Omie does not expose daily balance history per account via API. Withusar_saldo_real: true, the tool anchors the calculation on thesaldo_inicial/saldo_dataregistered in each current account (viaomie_contas_correntes_listar): it sums the realized entries between thesaldo_dataand the start of the requested period, arriving at asaldoRealAcumuladoclose to the real bank balance — it is not a hardcoded value in the MCP, it is read from the Omie registry, so when someone configures the real balance of each account there (e.g., on 01/01), the calculation automatically reflects that without changing code. Accounts withoutsaldo_data/saldo_inicialconfigured (or withsaldo_dataafter the start of the period) receivesaldoRealAcumulado: nullinstead of an invented number. Fetching this offset triggers an extra call (movements between the oldestsaldo_dataamong the accounts and the start of the period) — it can be slow if thesaldo_datais far in the past.Important finding while testing: Omie rejects two concurrent calls of the same method (error "Já existe uma requisição desse método sendo executada"), even with different parameters — that's why the realized/forecast passes (both use
ListarMovimentos) run sequentially, not in parallel, within the use-case. It is an additional restriction to the rate limit already documented in the section below, specific to concurrent calls of the samecall.Long periods generate many pages (e.g., just the receipts of ~3 weeks already exceeded 3,700 records) — prefer periods of up to ~3 months per call.
Contas a Pagar (src/modules/contasPagar/)
omie_contas_pagar_listar— use-case: lists entries fromfinancas/contapagar(ListarContasPagar) already with the supplier name resolved (reuses theClientesOmieGatewayfrom theclientesFornecedoresmodule — Omie only returns the code), value, due date, status (PAGO/ABERTO/VENCIDO), fiscal document, category and observation. Paginated, with optionaldata_alteracao_de/data_alteracao_atefilter.
Contas a Receber (src/modules/contasReceber/)
omie_contas_receber_listar— use-case: lists entries fromfinancas/contareceber(ListarContasReceber) already with the customer name resolved (reuses theClientesOmieGatewayfrom theclientesFornecedoresmodule), amount, due date, status (PAGO/ABERTO/VENCIDO), fiscal document, order number, and category. Paginated, with optionaldata_alteracao_de/data_alteracao_atefilter.omie_contas_receber_boleto_gerar/omie_contas_receber_boleto_obter/omie_contas_receber_boleto_prorrogar/omie_contas_receber_boleto_cancelar— use-case (gerar/prorrogar/cancelar destructive), boleto CRUD on an accounts receivable entry (financas/contareceberboleto:GerarBoleto/ObterBoleto/ProrrogarBoleto/CancelarBoleto), testable viaContasReceberFakeGatewaywithout touching the real Omie. Note: live-tested that this Omie account has no bank agreement/boleto configured —ProrrogarBoletoreturns "Não temos suporte para geração da remessa de pagamento para o banco -sem instituição-";GerarBoletolikely fails for the same reason (not live-tested to avoid generating a real boleto from a production customer entry).ObterBoleto/CancelarBoletowere validated live (they safely return "nenhum boleto gerado", with no side-effect).
Important finding from testing: the Omie date filter parameter on these two endpoints (
filtrar_por_data_de/filtrar_por_data_ate) filters by the entry's last modification date (info.dAlt), not the due date — confirmed by requesting a 1-day range and comparing with thedata_vencimentoof the returned records (different due dates,dAltalways within the requested range). That's why the MCP tools expose the parameter asdata_alteracao_de/data_alteracao_ate(notdata_vencimento_de/ate), to avoid suggesting behavior the API doesn't have. There is no (tested) native filter by due date on these two endpoints — for that, useomie_fluxo_caixa_gerar, which usesfinancas/mfand filters correctly by due date/payment.
Difference from
omie_fluxo_caixa_gerar: these two tools expose the raw entry (supplier/customer per entry, without aggregation), useful for checking title by title; the cash flow aggregates everything by period/current account.
Cash Budget (src/modules/orcamentoCaixa/)
omie_orcamento_caixa_consultar— use-case: Omie's NATIVE cash budget (forecast x actual) by financial category, for a month/year. Omie method:ListarOrcamentos(resourcefinancas/caixa), testable viaOrcamentoCaixaFakeGatewaywithout touching the real Omie. Unlikeomie_fluxo_caixa_gerar(manually calculated from accounts payable/receivable, grouped by current account/day), this is Omie's own ready-made report, grouped by category (e.g. "1.01.01 Vendas"). Supports the genericfiltrosparameter. Validated live against the real account.
PIX (src/modules/pix/)
omie_pix_listar/omie_pix_obter/omie_pix_obter_status/omie_pix_gerar/omie_pix_cancelar— use-case (gerar/cancelar destructive), PIX CRUD on accounts receivable entries (financas/pix:ListarPix/ObterPix/ObterStatusPix/GerarPix/CancelarPix), testable viaPixFakeGatewaywithout touching the real Omie. Unlike Boleto, this Omie account HAS PIX configured and active (379 real records in the tested database) —Listar/Obter/ObterStatusvalidated live against the real account.Gerar/Cancelarwere not live-tested against a production entry out of caution (they would actually generate/cancel a PIX charge, with no guaranteed safe round-trip — same care as Boleto).
Invoices / NF-e (src/modules/nfe/)
omie_nfe_listar/omie_nfe_consultar— use-case: queries invoices (NF-e) already issued/registered in Omie viaprodutos/nfconsultar(ListarNF/ConsultarNF), testable viaNfeFakeGatewaywithout touching the real Omie. Listing returns a summary (number, series, key, customer, amount, whether canceled); query brings the detail (items, financial entries generated by the invoice). Deliberately READ-ONLY module: it neither issues nor cancels NF-e. Searching the official docs found no "issue NF-e from scratch" endpoint (likeIncluirNFe(items, customer)) equivalent toIncluirPedidoVenda— the API treats NF-e mostly as query/import of a document already processed by the ERP's fiscal engine, and an issued invoice is a document with legal effect (no "delete and leave no trace" like the other modules). Validated live against the real account (4765 invoices in the test database).
Inbound Invoice (src/modules/notaEntrada/)
omie_nota_entrada_listar/omie_nota_entrada_consultar— use-case: queries inbound invoices (physical receipt of goods from a purchase) already registered, viaListarNotaEnt/ConsultarNotaEnt(resourceprodutos/notaentrada), testable viaNotaEntradaFakeGateway. READ-ONLY — same caution as the product NF-e and NFS-e modules: it's the final stage of the Requisition → Purchase Order → NF-e Receipt → Inbound Invoice flow, a definitive fiscal/ financial entry (it actually affects inventory and finance), with no safe test round-trip. Supplier NF-e receipt (produtos/recebimentonfe) and the invoice billing itself (produtos/notaentradafat) were left out of scope for the same reason. Validated live against the real account (3 existing inbound invoices).
Product Characteristics (src/modules/caracteristicasProduto/)
omie_caracteristica_incluir/omie_caracteristica_alterar/omie_caracteristica_excluir/omie_caracteristica_consultar/omie_caracteristica_listar— use-case (the first 3 destructive), CRUD of reusable product characteristics (e.g. "Cor", "Tamanho") viageral/caracteristicas, testable viaCaracteristicaFakeGateway. Unlike Category, live-tested that the full CRUD works without reservations (complete round-trip, no trace).
Categories and Departments (src/modules/categoriasDepartamentos/)
omie_categoria_incluir/omie_categoria_alterar/omie_categoria_consultar/omie_categoria_listar— use-case (the first 2 destructive), CRUD of financial categories (geral/categorias), testable viaCategoriaFakeGateway. Note, important live findings: (1)IncluirCategoriadoes NOT receive the new category's code — it receivescategoria_superior(parent group code) and Omie GENERATES the child code automatically (e.g. parent2.09generates child2.09.04); (2) there is no category deletion in the API, and testingAlterarCategoriawithconta_inativa: 'S'had NO real effect (confirmed by querying again afterward) — categories created via API remain permanently active on the account, with no way to remove/deactivate them. This left a residual test category on this account (2.09.04, "Categoria Teste MCP Alterada") — harmless but recorded here so it doesn't confuse anyone who finds it later (same pattern as the residual test product from theestoquemodule).omie_departamento_incluir/omie_departamento_alterar/omie_departamento_excluir/omie_departamento_consultar/omie_departamento_listar— use-case (the first 3 destructive), CRUD of Department/Cost Center (geral/departamentos), testable viaDepartamentoFakeGateway. Note, live finding:codigoinIncluirDepartamentois the PARENT department's code (where to include), not the new one's — Omie generates and returns the child's code in the response (same pattern as Category). Unlike Category,ExcluirDepartamentoactually works — validated live with a complete round-trip, leaving no trace.
Auxiliary Registries (src/modules/cadastrosAuxiliares/)
omie_bancos_listar/omie_cidades_listar/omie_paises_listar/omie_ncm_listar/omie_unidade_consultar— use-case, static reference tables maintained by Omie itself (Bacen, IBGE, Receita Federal): banks (geral/bancos), cities (geral/cidades), countries (geral/paises), NCM (produtos/ncm), and units of measure (geral/unidade). All read-only, testable viaCadastrosAuxiliaresFakeGateway. They support native filtering (name, state, code, etc.) and the genericfiltrosparameter. Note, live finding:omie_unidade_consultarrequires the exact code (it doesn't paginate/list everything, unlike the others) — it's a point query, not a listing. Validated live against the real account.
CRM (src/modules/crm/)
omie_crm_conta_incluir/omie_crm_conta_alterar/omie_crm_conta_excluir/omie_crm_conta_consultar/omie_crm_conta_listar— use-case (the first 3 destructive), CRUD of CRM Account (crm/contas— B2B sales funnel, different from the Customer/ Supplier registry), testable viaContaFakeGatewaywithout touching the real Omie. Note, live finding:IncluirConta/AlterarContarequire the fullenderecoandtelefone_emailblocks to be present (even with few fields filled) — Omie rejects with "Tag [endereco]/[telefone_email] não informada!" if the block is entirely missing.omie_crm_contato_incluir/omie_crm_contato_alterar/omie_crm_contato_excluir/omie_crm_contato_consultar/omie_crm_contato_listar— use-case (the first 3 destructive), CRUD of CRM Contact (crm/contatos), always linked to an Account.omie_crm_oportunidade_incluir/omie_crm_oportunidade_alterar/omie_crm_oportunidade_excluir/omie_crm_oportunidade_consultar/omie_crm_oportunidade_listar— use-case (the first 3 destructive), CRUD of funnel Opportunity (crm/oportunidades). Note, live finding: besides account and contact, it requirescodigo_solucaoandcodigo_origem— auxiliary registries that must exist beforehand (Omie already comes with "Solução 01"/"Solução 02" and default origins like "Ativo").omie_crm_fases_listar/omie_crm_solucoes_listar/omie_crm_origens_listar— use-case (read), CRM auxiliary registries (crm/fases,crm/solucoes,crm/origens) — the last two are prerequisites for being able to create an Opportunity.Validated live with a complete and safe round-trip (test account, contact, and opportunity, created and deleted without leaving a trace).
Out of scope for this cycle (not requested, low priority): Tasks (
crm/tarefas) and Account Characteristics (crm/contascaract) — implement only when the user needs them.
Services / Service Order / NFS-e (src/modules/servicos/)
omie_servico_incluir/omie_servico_alterar/omie_servico_excluir/omie_servico_consultar/omie_servico_listar— use-case (the first 3 destructive), CRUD for the services registry (servicos/servico), testable viaServicoFakeGatewaywithout touching the real Omie. Attention, live finding:AlterarCadastroServicorequires the identifier nested inintEditar(not incabecalhoas it would seem) — the public docs don't make this clear.omie_os_incluir/omie_os_alterar/omie_os_excluir/omie_os_consultar/omie_os_listar— use-case (the first 3 destructive), CRUD for Service Orders (servicos/os), testable viaOrdemServicoFakeGatewaywithout touching the real Omie. Attention, important live findings: (1) each item requirescodigo_servico_municipal/codigo_servico_lc116as an already REGISTERED code in the LC116 table (seeomie_servicos_lc116_listar), not free text — Omie rejects with "Código da LC116 não cadastrada" otherwise; (2)cRetemISSis required on each item even though it's not marked as such in the public docs; (3) the header client must have a state (UF) filled in (same requirement already seen in Sales Orders). Validated live with a full, safe round-trip (disposable test client, created and deleted without leaving a trace).omie_nfse_listar— use-case: lists already issued NFS-e (servicos/nfse,ListarNFSEs), testable viaNfseFakeGateway. READ-ONLY — same caution as the product NF-e module (tax document with legal effect, no safe round-trip for issuance).omie_servicos_lc116_listar— use-case: lists the 255 valid codes from Complementary Law 116 (service classification), used to find the right code before creating a service order. Omie method: ListarLC116 (resourceservicos/lc116).
Out of scope for this cycle (not requested, low priority): recurring Service Contract (
servicos/contrato) and batch invoicing for OS/contract (servicos/osp,servicos/oslote,servicos/contratofat,servicos/contratolote) — implement only when the user needs them.
Purchasing (src/modules/compras/)
omie_pedido_compra_incluir/omie_pedido_compra_alterar/omie_pedido_compra_excluir/omie_pedido_compra_consultar/omie_pedido_compra_listar— use-case (the first 3 destructive), full CRUD overIPedidoCompraGateway(produtos/pedidocompra), testable viaPedidoCompraFakeGatewaywithout touching the real Omie. Attention, important live findings: (1)nCodCC(passed ascodigo_conta_corrente) requires a checking account code (geral/contacorrente), not a cost center/department, despite the name — Omie rejects with "Conta Corrente não cadastrada" if you use a department code; (2)PesquisarPedCompra(listing) hides ALL orders by default — you must explicitly request each status (lExibirPedidosPendentes/Faturados/Recebidos/Cancelados/Encerrados/RecParciais/FatParciais, all'S'), which the gateway already does always; (3) when the page has no records, Omie returns an error (SOAP-ENV:Client-5113) instead of an empty list — normalized in the gateway to return an empty list.omie_requisicao_compra_incluir/omie_requisicao_compra_alterar/omie_requisicao_compra_excluir/omie_requisicao_compra_consultar/omie_requisicao_compra_listar— use-case (the first 3 destructive), full CRUD overIRequisicaoCompraGateway(produtos/requisicaocompra), testable viaRequisicaoCompraFakeGatewaywithout touching the real Omie. Attention, important live finding: unlike other Omie endpoints, the fields forIncluirReq/AlterarReqgo directly at the root ofparam— there is norequisicaoCadastro: {...}wrapper, even though the public docs suggest one (Omie rejects with "Tag [REQUISICAOCADASTRO] não faz parte da estrutura").
Generic (covers all other modules)
omie_chamar_api— receivesresource(module path),call(method), andparam(parameters), allowing access to any endpoint listed at https://developer.omie.com.br/service-list/ (clients, finance, CRM, sales, NF-e, services, etc.)
Omie rate limit — how the MCP protects itself
Omie blocks request bursts in two ways: "consumo indevido" (rate
limit proper) and "consumo redundante" (very similar requests in
quick succession — this has actually happened in practice when querying ~20 clients in parallel
to build a report). The protection is centralized in the
OmieClient (src/omieClient.ts), so every module benefits automatically,
without having to reimplement anything:
Throttle — every call respects a minimum spacing (300ms) since the previous call made by the same
OmieClientinstance, even when multiple arrive at the same time (Promise.all,mapWithConcurrency, etc.). This reduces the chance of hitting "consumo redundante" before retry is even needed.Retry with correct wait — if Omie still blocks, the
OmieClienttries again (up to 4 times), respecting the time Omie itself suggests in the error message (e.g., "Aguarde 57 segundos") instead of a fixed short backoff.mapWithConcurrency(src/shared/concurrency.ts) — used by gateways that fetch multiple records by code in batch (ProdutosOmieGateway.consultarProdutosPorCodigo,ClientesOmieGateway.consultarClientesPorCodigo), limits the concurrency of the code itself to 5 simultaneous calls, complementing the client's throttle.
Rule for new modules:
Never call
Promise.all/Promise.allSettledon an array of codes without a concurrency limit — always usemapWithConcurrency.Never run two calls of the SAME method (
call) in parallel, even with different parameters — Omie rejects with "Já existe uma requisição desse método sendo executada" (found while buildingfluxoCaixa, which needs two passes ofListarMovimentos). Run them sequentially (awaitone, then the other).Parallel calls of different methods (e.g., fetching products and stock at the same time) are safe and need none of this — the client's throttle already covers it.
Adding a new module
Passthrough (Omie already returns the data ready):
Create
src/tools/<modulo>.tsexporting an array ofToolDef(usedefineTool()fromsrc/tools/types.ts).Import and concatenate that array into
allTools, insrc/tools/registry.ts.
Layered (needs to aggregate/combine Omie calls — copy src/modules/estoque/ as a reference):
application/use-cases/— the business rule (receives a gateway, returns the result already ready for the user).application/dto/— zod schema for the inputparamand result type.infrastructure/gateways/— only Omie calls (resource/call), no business rule.presentation/mcp/— theToolDefwithexecuteinstantiating gateway + use-case.<modulo>-register.ts+index.ts— barrel export of the tools array.Import the array into
allTools, insrc/tools/registry.ts.
In both cases, src/index.ts registers the tool automatically — nothing changes there.
Next steps (roadmap)
Add dedicated modules for Finance, Sales/NF-e, and CRM as needed (same file pattern).
Add automatic caching/pagination for large listings.
Add automated tests with Omie API mocks.
Security
Never commit the .env file or expose OMIE_APP_KEY/OMIE_APP_SECRET in public repositories.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Walessonrdreis/omie-mcp-v1.0'
If you have feedback or need assistance with the MCP directory API, please join our Discord server