mcp-quotes

Envía a un cliente una cotización real en segundos: partidas con IVA, fecha de validez y un PDF pulido que el cliente puede aceptar — desde Claude o cualquier cliente MCP.

Documentación

mcp-quotes

Servidor MCP para cotizaciones de precios, presupuestos y propuestas: crea una cotización o un presupuesto para un cliente. Cotizaciones con precios e IVA correcto desde el chat, y el "sí" se convierte en factura.

Funciona con Claude Desktop, Claude Code, Cursor y cualquier cliente del Model Context Protocol. Se ejecuta en tu propia máquina, o alojado sin instalación.

Página del producto: https://mcp.zovo.one/s/quotes — qué hace, las herramientas que expone y un endpoint de token en vivo.

Instalación

Alojado, nada que instalar. Obtén un token de https://mcp.zovo.one/mcp/connect (la página de conexión) o https://mcp.zovo.one/mcp/token (el mismo token como JSON); se emite uno anónimo gratuito al instante y una clave Pro funciona de la misma manera. Luego apunta un cliente MCP a https://mcp.zovo.one/mcp/quotes a través de streamable-http y envía el token como Authorization: Bearer <token>.

Si tu cliente no puede configurar cabeceras, coloca el token en la ruta en su lugar: https://mcp.zovo.one/mcp/quotes/t/<token>. Ambas formas funcionan. La URL desnuda sin token responde 401 en tools/call, por lo que el token no es opcional.

Claude Desktop, un clic. Descarga quotes.mcpb desde la última versión y haz doble clic en él.

Desde el código fuente. El espejo es autocontenido: cada dependencia de @theluckystrike/* está incluida, por lo que un clon nuevo se compila sin configuración adicional.

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

Luego apunta tu cliente al punto de entrada compilado:

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

@theluckystrike/mcp-quotes aún no está publicado en npm, por lo que un comando npx -y @theluckystrike/mcp-quotes fallará. Las tres rutas anteriores son las que funcionan y cada una es probada por CI.

quotes demo

Espejo de solo lectura de mcp-servers/servers/quotes. Ver MIRROR.md.

Di "cotiza a Acme por 12 horas a 90 EUR más una configuración de 300 EUR, 23% de IVA, válido por 14 días" y obtén una cotización numerada que puedes enviar hoy: la tabla de líneas con IVA por tarifa, el total en unidades mínimas enteras, una fecha de validez calculada en tu propia zona horaria, una versión en texto plano para pegar directamente en un correo y, en Pro, el mismo diseño PDF A4 que usan tus facturas. Cuando el cliente dice que sí, quote_accept lo convierte en una factura real en el almacén de mcp-invoice, bajo la misma lista de clientes y la misma serie de números, con los números copiados de la cotización en lugar de recalculados. Todo se almacena en archivos JSON planos en tu propia máquina; nada se sube a ningún lugar.

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

Listado en el Índice de Productos de IA — endpoint remoto en vivo en mcp.zovo.one/s/quotes, nivel gratuito, sin registro.

Envía una cotización con precio e IVA correcto desde el chat, y convierte el "sí" en una factura con una sola llamada.

Instalación en 60 segundos

La publicación en npm para @theluckystrike/mcp-quotes está pendiente. Hasta entonces, el paquete de un clic .mcpb o un clon+compilación es la ruta que funciona.

Un clic (.mcpb): descarga quotes.mcpb desde la última versión y haz doble clic en él en 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): la misma entrada que Claude Desktop.

Desde el código fuente:

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

Compila servers/invoice primero: el motor de dinero, IVA, clientes y numeración se importa desde él. Luego apunta el command de tu cliente a node con un argumento, la ruta absoluta a servers/quotes/dist/index.js.

Para ejecutar en modo Pro, establece MCP_LICENSE_KEY en el mismo bloque de configuración, o llama a license_activate una vez con tu clave.

Herramientas

HerramientaQué hace
quote_createCotiza a un cliente: líneas de detalle con cantidad y precio unitario en unidades mínimas, IVA por línea o el predeterminado del negocio, un descuento opcional, una ventana de validez. Asigna Q-YYYY-NNNN
quote_listCada cotización con cliente, total, validez y estado: abierta, vencida, aceptada o rechazada. Filtra por estado, cliente o fecha de cotización
quote_getEl registro completo almacenado de una cotización, incluida la factura en la que se convirtió
quote_updateRevisa una cotización que aún está abierta. Los totales se recalculan; una cotización aceptada o rechazada nunca se edita
quote_send_textUna cotización en texto plano con la tabla de líneas alineada, líneas de IVA, total y fecha de validez, lista para pegar en un correo. Gratis
quote_acceptMárcala como aceptada y conviértela en factura: se crea directamente en el servidor de facturas cuando su almacén está presente, de lo contrario se devuelve como elementos listos para invoice_create
quote_declineMárcala como perdida, con un motivo, para que deje de contar contra las cotizaciones abiertas y entre en la tasa de éxito
quote_deleteElimina una cotización borrador que nadie ha visto y recupera su espacio de cotización abierta. Se rechaza, con el dependiente nombrado, una vez que se ha enviado, aceptado, facturado o exportado. Gratis
quote_pdfRenderiza el PDF A4 y devuelve la ruta. Pro
quote_reportTotales abiertos, aceptados, rechazados y vencidos por moneda, el valor aún abierto y la tasa de éxito. Gratis para el año calendario actual hasta la fecha
license_statusMuestra el modo gratuito o Pro
license_activateActiva una clave Pro (verificada sin conexión)

Recurso: quotes://open devuelve cada cotización que aún está dentro de su ventana de validez como JSON.

Prompt: quote_followup revisa qué está abierto, qué vence pronto y qué ya venció, y luego redacta el seguimiento.

Lo que puedes decir

Tú dicesHerramienta
"Cotiza a Acme por 12 horas a 90 EUR más una configuración de 300 EUR, 23% de IVA, válido por 14 días."quote_create
"Redáctalo como un correo que pueda enviar."quote_send_text
"Haz Q-2026-0003 20 horas en su lugar y dales otras dos semanas."quote_update
"Acme dijo que sí. Factúralo."quote_accept
"Beta eligió a alguien más barato."quote_decline
"Cotice a Acme dos veces por error, elimina la segunda."quote_delete
"¿Qué sigue abierto y cuál es mi tasa de éxito?"quote_report
"¿Qué cotizaciones han vencido sin respuesta?"quote_list con state: "expired"

Ejemplo práctico

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

Los precios se ingresan como unidades mínimas: 9000 es EUR 90.00 y 150000 es JPY 150,000. No hay decimal en ningún lugar del lado de entrada, por lo que un precio nunca puede ingresarse diez veces más pequeño.

Gratis vs Pro

GratisPro
Cotizaciones abiertas5 a la vezIlimitadas
quote_send_text (texto listo para correo)Sí, ilimitadoSí, ilimitado
Aceptar, rechazar, revisar, IVA, descuentos, multimonedaSíSí
quote_delete (solo borradores) y el guardián de duplicadosSíSí
quote_pdfNoSí
quote_report (canal y tasa de éxito)Año calendario actual hasta la fechaCualquier rango de fechas
Marca en PDFn/aSin crédito de pie de página y tu logotipo

El límite cuenta las cotizaciones que siguen ABIERTAS. Aceptar, rechazar o dejar que una venza libera el espacio, por lo que un freelancer que cierra sus cotizaciones nunca lo alcanza. Dos cosas más evitan que un espacio se desperdicie, ambas gratuitas: quote_create rechaza una cotización idéntica a una ya abierta y nombra la que tienes, y quote_delete elimina un borrador que nadie ha visto y devuelve el espacio de inmediato.

Pro es un pago único de $19, o $39 por cada servidor en la colección, de por vida.

Una cosa medida: por qué una cotización aceptada se copia, no se recalcula

quote_accept escribe la factura desde las líneas almacenadas de la cotización. La alternativa obvia, recalcular los totales desde los precios en el momento de la aceptación, fue medida y rechazada, porque la tasa de IVA que usaría es la del perfil de negocio compartido hoy, no la que se le cotizó al cliente.

Medido (test/adversarial.test.mjs, "un cambio en la tasa de IVA entre la cotización y la aceptación nunca mueve el total acordado"): una cotización de EUR 1,000.00 netos se emite con la tasa predeterminada del perfil del 23%, por lo que al cliente se le da EUR 1,230.00. El default_tax_rate del perfil se cambia luego al 8%, un cambio de tasa, una nueva clase de cliente, una configuración corregida, antes de que el cliente responda. Recalcular en la aceptación factura EUR 150.00 por debajo del documento que acordaron, en una sola cotización, sin nada en ninguno de los dos registros que diga por qué difieren. Copiar las líneas almacenadas factura EUR 1,230.00 y la afirmación se cumple tax_lines[0].rate === 23.

La misma regla es por qué la cotización toma precios en unidades mínimas y rechaza un decimal: el número en la cotización y el número en la factura son el mismo entero, en todo el proceso.

Números, dinero y fechas

Los IDs de cotización son Q-YYYY-NNNN. El contador es por año y se escribe antes de almacenar la cotización, por lo que un fallo quema un ID en lugar de reutilizar uno, y los IDs existentes también se escanean, por lo que un quotes.json restaurado nunca puede devolver un ID que ya está en un documento que un cliente ha visto. El año es parte del ID deliberadamente: un Q-0001 desnudo que se reinicia cada enero colisiona con la cotización de enero pasado.

El dinero es unidades mínimas enteras de principio a fin, y cuántas hacen una unidad proviene de la tabla ISO 4217 en mcp-invoice, 2 para la mayoría de las monedas, 0 para JPY, KRW, ISK y el resto, 3 para KWD y los dinares del Golfo, 4 para CLF y UYW. No hay una segunda copia de esa tabla, ni de la aritmética de IVA ni del formateador de dinero aquí: computeTotals, currencyDecimals y formatMoney se importan de @theluckystrike/mcp-invoice/lib, por lo que una cotización y la factura en la que se convierte redondean de manera idéntica, por línea y luego sumadas. Una cotización es una moneda; una mezcla entre líneas se rechaza en lugar de sumarse bajo el primer encabezado que aparezca.

Las fechas son ISO YYYY-MM-DD. "Hoy", y por lo tanto si una cotización ha vencido, se calcula en la timezone del perfil de negocio compartido cuando se establece, no en la zona de la máquina anfitriona: una cotización emitida a las 00:30 en Varsovia desde una laptop que aún está en hora de EE. UU. se fecharía el día anterior y vencería un día antes.

Cómo almacena datos

Las cotizaciones y el contador de IDs viven bajo ${XDG_DATA_HOME:-~/.local/share}/mcp-servers/quotes/ como quotes.json y counter.json, más una subcarpeta pdf/ para archivos renderizados. Las facturas creadas por quote_accept se escriben en el directorio del servidor de facturas, .../mcp-servers/invoice/, por lo que invoice_list allí las muestra y comparten una serie de números y una lista de clientes.

Cada llamada mutante se ejecuta bajo un directorio de bloqueo de asesoría en .../quotes/.lock; cualquier cosa que escriba una factura también toma .../invoice/.lock, siempre en ese orden (cotizaciones, luego factura), el mismo orden que usa servers/recurring, por lo que dos procesos no pueden bloquearse mutuamente. Los guardados van a un archivo temporal por proceso y se renombran en su lugar. Medido: 40 cotizaciones creadas por dos procesos contra un directorio de datos dejan 40 cotizaciones y 40 IDs únicos (test/concurrency.test.mjs).

Un archivo de almacén que no es JSON válido nunca se trata como "sin cotizaciones". Se mueve a un lado byte por byte como quotes.json.corrupt-<timestamp>, se escribe un marcador .corrupt junto a él, y cada llamada posterior, incluidas las lecturas, falla con restore a good copy ... then delete the marker hasta que un humano lo resuelva.

Límites y advertencias honestas

  • El nivel gratuito mantiene 5 cotizaciones abiertas a la vez. La exportación de texto, aceptar, rechazar y revisar no tienen restricciones en el nivel gratuito, y el informe de canal responde gratis para el año calendario actual hasta la fecha; el PDF y un rango de informe más amplio son Pro.
  • Aceptar escribe la factura a través del motor compartido, por lo que el límite gratuito propio del servidor de facturas de 3 facturas por mes calendario no se le aplica. El límite de cotizaciones es el que aplica aquí, y la respuesta lo dice.
  • Una cotización vencida es rechazada por quote_accept hasta que la extiendas (quote_update {valid_until}) o digas allow_expired: true. Esa es fricción deliberada: un precio vencido debe re-confirmarse.
  • No se envía ningún correo. quote_send_text te da el texto y quote_pdf te da el archivo; hacer que llegue al cliente depende de ti.
  • No hay conversión de moneda. La moneda de una cotización se fija en la creación y cada línea ya debe estar en ella.
  • Aceptar es unidireccional. No hay des-aceptar, porque la factura que creó es un documento con un número; cancela esa factura en el servidor de facturas en su lugar.

Privacidad

Todos los datos permanecen locales: archivos JSON planos en tu propio directorio de datos. Sin cuenta, sin clave de API, sin llamada de red de ningún tipo. Las claves de licencia se verifican sin conexión.

Built by theluckystrike. Soporte: support@zovo.one

Usa estos documentos como un servidor MCP

Cualquier cliente MCP (Claude, Cursor, Windsurf, VS Code) puede leer la documentación de este repositorio directamente a través de GitMCP, sin necesidad de instalación: