mcp-quotes

Envie uma cotação real ao cliente em segundos: itens com IVA, data de validade e um PDF polido que o cliente pode aceitar — a partir do Claude ou de qualquer cliente MCP.

Documentação

mcp-quotes

Servidor MCP para cotações de preço, estimativas e propostas: crie uma cotação ou estimativa para um cliente. Cotações com preço e IVA correto a partir do chat, e o "sim" vira uma fatura.

Funciona com Claude Desktop, Claude Code, Cursor e qualquer cliente Model Context Protocol. Roda na sua própria máquina ou hospedado, sem instalação.

Página do produto: https://mcp.zovo.one/s/quotes — o que faz, as ferramentas que expõe e um endpoint de token ao vivo.

Instalação

Hospedado, nada para instalar. Obtenha um token em https://mcp.zovo.one/mcp/connect (página de conexão) ou https://mcp.zovo.one/mcp/token (o mesmo token em JSON); um token anônimo gratuito é emitido na hora e uma chave Pro funciona da mesma forma. Em seguida, aponte um cliente MCP para https://mcp.zovo.one/mcp/quotes via streamable-http e envie o token como Authorization: Bearer <token>.

Se o seu cliente não puder definir cabeçalhos, coloque o token no caminho: https://mcp.zovo.one/mcp/quotes/t/<token>. Ambas as formas funcionam. A URL simples sem token responde 401 em tools/call, então o token não é opcional.

Claude Desktop, um clique. Baixe quotes.mcpb do último lançamento e clique duas vezes nele.

A partir do código-fonte. O espelho é autocontido: cada dependência @theluckystrike/* é incorporada, então um clone novo compila sem configuração adicional.

git clone https://github.com/theluckystrike/mcp-quotes.git
cd mcp-quotes
npm install && npm run build

Em seguida, aponte seu cliente para o ponto de entrada compilado:

{
  "mcpServers": {
    "quotes": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-quotes/dist/index.js"]
    }
  }
}

@theluckystrike/mcp-quotes ainda não está publicado no npm, então um comando npx -y @theluckystrike/mcp-quotes falhará. Os três caminhos acima são os que funcionam e cada um é testado pelo CI.

quotes demo

Espelho somente leitura de mcp-servers/servers/quotes. Veja MIRROR.md.

Diga "cote a Acme por 12 horas a 90 EUR mais uma configuração de 300 EUR, 23% de IVA, válido por 14 dias" e receba uma cotação numerada que você pode enviar hoje: a tabela de linhas com IVA por taxa, o total em unidades monetárias inteiras, uma data de validade calculada no seu próprio fuso horário, uma versão em texto simples para colar diretamente em um e-mail e, no Pro, o mesmo layout de PDF A4 que suas faturas usam. Quando o cliente disser sim, quote_accept transforma isso em uma fatura real no armazenamento mcp-invoice, sob a mesma lista de clientes e a mesma sequência de números, com os números copiados da cotação em vez de recalculados. Tudo é armazenado em arquivos JSON simples na sua própria máquina; nada é enviado para lugar nenhum.

No Registro Oficial de MCP (io.github.theluckystrike/quotes-estimates-proposals-vat-win-rate).

Listado no Índice de Produtos de IA — endpoint remoto ao vivo em mcp.zovo.one/s/quotes, camada gratuita, sem cadastro.

Envie uma cotação com preço e IVA correto a partir do chat e transforme o "sim" em fatura com uma única chamada.

Instalação em 60 segundos

A publicação no npm para @theluckystrike/mcp-quotes está pendente. Até lá, o pacote de um clique .mcpb ou um clone + compilação é o caminho que funciona.

Um clique (.mcpb): baixe quotes.mcpb do último lançamento e clique duas vezes nele no Claude Desktop: https://github.com/theluckystrike/mcp-servers/releases/latest

(claude_desktop_config.json):

{
  "mcpServers": {
    "quotes": {
      "command": "npx",
      "args": ["-y", "@theluckystrike/mcp-quotes"]
    }
  }
}

Claude Code:

claude mcp add quotes -- npx -y @theluckystrike/mcp-quotes

(.cursor/mcp.json): a mesma entrada do Claude Desktop.

A partir do código-fonte:

git clone https://github.com/theluckystrike/mcp-servers.git && cd mcp-servers
npm install
npm run build -w packages/mcp-license -w servers/invoice -w servers/quotes

Compile servers/invoice primeiro: o mecanismo de dinheiro, IVA, clientes e numeração é importado dele. Em seguida, aponte o command do seu cliente para node com um argumento, o caminho absoluto para servers/quotes/dist/index.js.

Para executar no modo Pro, defina MCP_LICENSE_KEY no mesmo bloco de configuração ou chame license_activate uma vez com sua chave.

Ferramentas

FerramentaO que faz
quote_createCota um cliente: itens de linha com quantidade e preço unitário em unidades monetárias, IVA por linha ou o padrão do negócio, um desconto opcional, uma janela de validade. Aloca Q-YYYY-NNNN
quote_listCada cotação com cliente, total, validade e estado: aberta, expirada, aceita ou recusada. Filtre por estado, cliente ou data da cotação
quote_getO registro completo armazenado de uma cotação, incluindo a fatura na qual ela se tornou
quote_updateRevisa uma cotação que ainda está aberta. Os totais são recalculados; uma cotação aceita ou recusada nunca é editada
quote_send_textUma cotação em texto simples com a tabela de linhas alinhada, linhas de IVA, total e data de validade, pronta para colar em um e-mail. Grátis
quote_acceptMarca como aceita e transforma em fatura: criada diretamente no servidor de faturas quando seu armazenamento está presente, caso contrário devolvida como itens prontos para invoice_create
quote_declineMarca como perdida, com um motivo, para que pare de contar contra as cotações abertas e entre na taxa de conversão
quote_deleteExclui uma cotação de rascunho que ninguém viu ainda e recupera o slot gratuito de cotação aberta. Recusada, com o dependente nomeado, depois de enviada, aceita, faturada ou exportada. Grátis
quote_pdfRenderiza o PDF A4 e retorna o caminho. Pro
quote_reportTotais abertos, aceitos, recusados e expirados por moeda, o valor ainda aberto e a taxa de conversão. Grátis para o ano civil atual até a data
license_statusMostra o modo gratuito ou Pro
license_activateAtiva uma chave Pro (verificada offline)

Recurso: quotes://open retorna cada cotação ainda dentro de sua janela de validade como JSON.

Prompt: quote_followup revisa o que está aberto, o que expira em breve e o que já expirou, e então redige o acompanhamento.

O que você pode dizer

Você dizFerramenta
"Cote a Acme por 12 horas a 90 EUR mais uma configuração de 300 EUR, 23% de IVA, válido por 14 dias."quote_create
"Escreva isso como um e-mail que eu possa enviar."quote_send_text
"Faça a Q-2026-0003 com 20 horas em vez disso e dê a eles mais duas semanas."quote_update
"A Acme disse sim. Fature."quote_accept
"A Beta foi com alguém mais barato."quote_decline
"Cotei a Acme duas vezes por engano, descarte a segunda."quote_delete
"O que ainda está aberto e qual é minha taxa de conversão?"quote_report
"Quais cotações expiraram sem resposta?"quote_list com state: "expired"

Exemplo prático

You: Quote Acme for 12 hours of API work at 90 EUR plus a 300 EUR setup fee,
23% VAT, good for 14 days.

  quote_create {
    client: "Acme", currency: "EUR", validity_days: 14,
    items: [
      { description: "API work",  quantity: 12, unit_price_minor: 9000,  tax_rate: 23 },
      { description: "Setup fee", quantity: 1,  unit_price_minor: 30000, tax_rate: 23 }
    ]
  }
  -> Q-2026-0001, valid until 2026-09-18

Assistant:
  API work    12  x  EUR 90.00   =  EUR 1080.00
  Setup fee    1  x  EUR 300.00  =  EUR 300.00
  Subtotal                          EUR 1380.00
  VAT 23% on EUR 1380.00             EUR 317.40
  TOTAL                              EUR 1697.40
  Valid until 2026-09-18.

You: They said yes.

  quote_accept { id: "Q-2026-0001" }
  -> accepted, invoice INV-2026-0004, due 2026-09-18, total EUR 1697.40

Os preços entram como unidades monetárias: 9000 é EUR 90,00 e 150000 é JPY 150.000. Não há decimal em nenhum lugar no lado da entrada, então um preço nunca pode ser inserido dez vezes menor.

Grátis vs Pro

GrátisPro
Cotações abertas5 por vezIlimitadas
quote_send_text (texto pronto para e-mail)Sim, ilimitadoSim, ilimitado
Aceitar, recusar, revisar, IVA, descontos, multimoedasSimSim
quote_delete (somente rascunhos) e o guarda de duplicatasSimSim
quote_pdfNãoSim
quote_report (funil e taxa de conversão)Ano civil atual até a dataQualquer intervalo de datas
Marca do PDFn/aSem crédito de rodapé e seu logotipo

O limite conta cotações que ainda estão ABERTAS. Aceitar, recusar ou deixar uma expirar libera o slot, então um freelancer que fecha suas cotações nunca o atinge. Mais duas coisas evitam que um slot seja desperdiçado, ambas gratuitas: quote_create recusa uma cotação idêntica a uma já aberta e nomeia a que você tem, e quote_delete remove um rascunho que ninguém viu e devolve o slot imediatamente.

Pro é um pagamento único de $19, ou $39 para todos os servidores da coleção, vitalício.

Uma coisa medida: por que uma cotação aceita é copiada, não recalculada

quote_accept escreve a fatura a partir das linhas armazenadas da cotação. A alternativa óbvia, recalcular os totais a partir dos preços no momento da aceitação, foi medida e rejeitada, porque a taxa de IVA que usaria é a do perfil de negócios compartilhado hoje, não a que foi cotada ao cliente.

Medido (test/adversarial.test.mjs, "uma mudança na taxa de IVA entre cotação e aceitação nunca altera o total acordado"): uma cotação de EUR 1.000,00 líquidos é emitida com a taxa padrão do perfil de 23%, então o cliente recebe EUR 1.230,00. O default_tax_rate do perfil é então alterado para 8%, uma mudança de taxa, uma nova classe de cliente, uma configuração corrigida, antes de o cliente responder. Recalcular na aceitação fatura EUR 150,00 abaixo do documento que eles concordaram, em uma única cotação, sem nada em nenhum dos registros dizendo por que diferem. Copiar as linhas armazenadas fatura EUR 1.230,00 e a afirmação é válida tax_lines[0].rate === 23.

A mesma regra é o motivo pelo qual a cotação aceita preços em unidades monetárias e recusa um decimal: o número na cotação e o número na fatura são o mesmo inteiro, do início ao fim.

Números, dinheiro e datas

Os IDs de cotação são Q-YYYY-NNNN. O contador é por ano e é gravado antes de a cotação ser armazenada, então uma falha queima um ID em vez de reutilizar um, e os IDs existentes também são verificados, então um quotes.json restaurado nunca pode devolver um ID que já está em um documento que um cliente viu. O ano faz parte do ID deliberadamente: um Q-0001 simples redefinido em janeiro colide com a cotação de janeiro passado.

O dinheiro é em unidades monetárias inteiras de ponta a ponta, e quantas formam uma unidade vem da tabela ISO 4217 em mcp-invoice, 2 para a maioria das moedas, 0 para JPY, KRW, ISK e as demais, 3 para KWD e os dinarares do Golfo, 4 para CLF e UYW. Não há segunda cópia dessa tabela, da aritmética de IVA ou do formatador de dinheiro aqui: computeTotals, currencyDecimals e formatMoney são importados de @theluckystrike/mcp-invoice/lib, então uma cotação e a fatura na qual ela se torna arredondam de forma idêntica, por linha e depois somadas. Uma cotação é uma moeda; uma mistura entre linhas é recusada em vez de somada sob qualquer título que vier primeiro.

As datas são ISO YYYY-MM-DD. "Hoje" e, portanto, se uma cotação expirou, é calculado no timezone do perfil de negócios compartilhado quando um está definido, não no fuso da máquina host: uma cotação emitida às 00:30 em Varsóvia a partir de um laptop ainda no horário dos EUA seria datada no dia anterior e expiraria um dia antes.

Como armazena dados

Cotações e o contador de IDs ficam em ${XDG_DATA_HOME:-~/.local/share}/mcp-servers/quotes/ como quotes.json e counter.json, mais uma subpasta pdf/ para arquivos renderizados. Faturas criadas por quote_accept são gravadas no diretório do servidor de faturas, .../mcp-servers/invoice/, então invoice_list lá as mostra e elas compartilham uma sequência de números e uma lista de clientes.

Cada chamada de mutação é executada sob um diretório de bloqueio consultivo em .../quotes/.lock; qualquer coisa que grave uma fatura também usa .../invoice/.lock, sempre nessa ordem (cotações, depois fatura), a mesma ordem que servers/recurring usa, então dois processos não podem causar deadlock. As gravações vão para um arquivo temporário por processo e são renomeadas no lugar. Medido: 40 cotações criadas por dois processos contra um diretório de dados deixam 40 cotações e 40 IDs únicos (test/concurrency.test.mjs).

Um arquivo de armazenamento que não é JSON válido nunca é tratado como "sem cotações". Ele é movido para o lado byte por byte como quotes.json.corrupt-<timestamp>, um marcador .corrupt é gravado ao lado dele, e cada chamada posterior, incluindo leituras, falha com restore a good copy ... then delete the marker até que um humano resolva.

Limites e ressalvas honestas

  • A camada gratuita mantém 5 cotações abertas por vez. A exportação de texto, aceitar, recusar e revisar são ilimitadas no gratuito, e o relatório de funil responde gratuitamente para o ano civil atual até a data; o PDF e um intervalo de relatório mais amplo são Pro.
  • Aceitar grava a fatura por meio do mecanismo compartilhado, então o limite gratuito do próprio servidor de faturas de 3 faturas por mês civil não é aplicado a ela. O limite de cotações é o que se aplica aqui, e a resposta diz isso.
  • Uma cotação expirada é recusada por quote_accept até que você a estenda (quote_update {valid_until}) ou diga allow_expired: true. Isso é atrito deliberado: um preço vencido deve ser reconfirmado.
  • Nenhum e-mail é enviado. quote_send_text fornece o texto e quote_pdf fornece o arquivo; levá-lo ao cliente é com você.
  • Sem conversão de moeda. A moeda de uma cotação é fixada na criação e cada linha já deve estar nela.
  • Aceitar é unidirecional. Não há desfazer aceitação, porque a fatura criada é um documento com número; cancele essa fatura no servidor de faturas.

Privacidade

Todos os dados permanecem locais: arquivos JSON simples no seu próprio diretório de dados. Sem conta, sem chave de API, sem chamada de rede de qualquer tipo. As chaves de licença são verificadas offline. Built by theluckystrike. Suporte: support@zovo.one

Use estas documentações como um servidor MCP

Qualquer cliente MCP (Claude, Cursor, Windsurf, VS Code) pode ler a documentação deste repositório diretamente via GitMCP — sem instalação: