lexware-mcp-server
lexware-mcp-server
Servidor MCP para la API de Lexware Office. Gestiona facturas, contactos, artículos, comprobantes y más a través del Protocolo de Contexto de Modelo.
No oficial — proyecto comunitario. No está afiliado, respaldado ni soportado por Lexware GmbH ni por Haufe Group. "Lexware" y "Lexware Office" son marcas comerciales de sus respectivos propietarios; se usan aquí solo para identificar la API a la que se dirige este cliente (uso justo nominativo).
66 herramientas en 20 dominios de recursos, con 6 puntos de entrada para que puedas elegir el servidor adecuado según el límite de herramientas de tu cliente MCP.
Instalación
npm install -g @lazyants/lexware-mcp-serverO ejecuta directamente:
npx @lazyants/lexware-mcp-serverRelated MCP server: e-rechnung-mcp
Configuración
El token de API se resuelve en este orden:
Llavero del sistema operativo (recomendado: el token nunca se escribe en disco en texto plano)
Variable de entorno
LEXWARE_API_TOKEN
Almacenar el token en el llavero del sistema operativo
Obtén tu token desde la configuración de la API de Lexware Office y luego guárdalo con el administrador de credenciales nativo de tu sistema operativo.
[!IMPORTANT] Los comandos a continuación leen el token desde un prompt interactivo en lugar de tomarlo como argumento, por lo que nunca llega a tu historial de shell ni a la lista de procesos. Evita pegar el token directamente en la línea de comandos.
macOS
Omitir el valor después de -w hace que security solicite el token (con confirmación):
security add-generic-password -s "lexware-mcp" -a "api-token" -wWindows (PowerShell)
cmdkey solo puede tomar el token como argumento de línea de comandos, lo que lo expone en la lista de procesos. En su lugar, léelo desde un prompt oculto y escríbelo directamente en el Administrador de credenciales de Windows mediante CredWrite, de modo que el token nunca llegue a argv. El nombre de destino de la credencial es <account>.<service> — api-token.lexware-mcp para el servicio predeterminado — que es exactamente lo que el servidor lee de vuelta:
$secure = Read-Host -AsSecureString "Lexware API token"
Add-Type -Namespace LexwareKeyring -Name Native -MemberDefinition @'
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CREDENTIAL {
public uint Flags;
public uint Type;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetName;
[MarshalAs(UnmanagedType.LPWStr)] public string Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public uint CredentialBlobSize;
public IntPtr CredentialBlob;
public uint Persist;
public uint AttributeCount;
public IntPtr Attributes;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias;
[MarshalAs(UnmanagedType.LPWStr)] public string UserName;
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool CredWriteW(ref CREDENTIAL credential, uint flags);
'@
$blob = [Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($secure)
try {
$cred = New-Object LexwareKeyring.Native+CREDENTIAL
$cred.Type = 1 # CRED_TYPE_GENERIC
$cred.Persist = 2 # CRED_PERSIST_LOCAL_MACHINE
$cred.TargetName = 'api-token.lexware-mcp' # "<account>.<service>"
$cred.UserName = 'api-token'
$cred.CredentialBlob = $blob
$cred.CredentialBlobSize = $secure.Length * 2 # UTF-16 bytes, no terminator
if (-not [LexwareKeyring.Native]::CredWriteW([ref]$cred, 0)) {
throw "CredWrite failed (Win32 error $([Runtime.InteropServices.Marshal]::GetLastWin32Error()))"
}
Write-Host 'Stored Lexware API token in Windows Credential Manager.'
} finally {
[Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($blob)
$secure.Dispose()
Remove-Variable secure, blob
}¿Usas un
LEXWARE_KEYRING_SERVICEpersonalizado (p. ej.acme)? EstableceTargetNameenapi-token.acmepara que coincida: el servidor busca el token bajo<account>.<service>.
Linux
secret-tool store --label="Lexware Office API" service lexware-mcp username api-token
# (prompts for the token value)Una vez almacenado, los archivos de configuración de MCP no necesitan credenciales en absoluto: el servidor lee el token del llavero al iniciarse.
Usar una variable de entorno en su lugar
Si prefieres no usar el llavero, establece LEXWARE_API_TOKEN en tu shell o en la configuración del cliente MCP:
export LEXWARE_API_TOKEN=your-token-hereVariables de entorno
Variable | Predeterminado | Descripción |
| — | Token de API; se usa cuando el llavero no tiene una entrada para el servicio configurado |
|
| Nombre del servicio del llavero. Anular al conectar con varias cuentas de Lexware simultáneamente: ejecuta una instancia del servidor por cuenta, cada una con su propio nombre de servicio |
Opcionalmente, anula la clave pública de firma de webhook utilizada por lexware_verify_webhook_signature (por defecto se obtiene de Lexware y se almacena en caché):
export LEXWARE_WEBHOOK_PUBLIC_KEY="$(cat lexware-webhook-public.pem)"Puntos de entrada
Comando | Dominios | Herramientas |
| Los 20 dominios | 66 |
| Facturas, Notas de crédito, Presupuestos, Confirmaciones de pedido, Albaranes, Facturas de pago anticipado, Recordatorios, Lista de comprobantes | 32 |
| Contactos, Artículos | 10 |
| Comprobantes, Lista de comprobantes, Pagos | 8 |
| Países, Condiciones de pago, Categorías de contabilización, Perfil, Diseños de impresión | 5 |
| Suscripciones a eventos, Archivos, Plantillas recurrentes | 12 |
Usa servidores divididos para reducir el tamaño del contexto: elige solo las divisiones que necesites.
Claude Code
Añade a ~/.claude/settings.json. Si almacenaste el token en el llavero del sistema operativo con el nombre de servicio predeterminado lexware-mcp (recomendado), no se necesita ninguna clave env:
{
"mcpServers": {
"lexware": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"]
}
}
}Si prefieres el enfoque de variable de entorno:
{
"mcpServers": {
"lexware": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"],
"env": { "LEXWARE_API_TOKEN": "your-token-here" }
}
}
}Servidores divididos
Usa servidores divididos para reducir el tamaño del contexto: elige solo los puntos de entrada que necesites. La bandera -p @lazyants/lexware-mcp-server le dice a npx de qué paquete obtener el comando; el argumento final (p. ej. lexware-mcp-sales) es el binario de punto de entrada específico definido en ese paquete (consulta Puntos de entrada):
{
"mcpServers": {
"lexware-sales": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/lexware-mcp-server", "lexware-mcp-sales"]
},
"lexware-contacts": {
"command": "npx",
"args": ["-y", "-p", "@lazyants/lexware-mcp-server", "lexware-mcp-contacts"]
}
}
}Ejemplo de varias cuentas (dos empresas de Lexware, tokens almacenados bajo nombres de servicio de llavero separados):
{
"mcpServers": {
"lexware-company-a": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"],
"env": { "LEXWARE_KEYRING_SERVICE": "lexware-company-a" }
},
"lexware-company-b": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"],
"env": { "LEXWARE_KEYRING_SERVICE": "lexware-company-b" }
}
}
}Claude Desktop
Añade a claude_desktop_config.json. Con el llavero del sistema operativo (recomendado: asume que el token está almacenado bajo el nombre de servicio predeterminado lexware-mcp):
{
"mcpServers": {
"lexware": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"]
}
}
}Con una variable de entorno en su lugar:
{
"mcpServers": {
"lexware": {
"command": "npx",
"args": ["-y", "@lazyants/lexware-mcp-server"],
"env": { "LEXWARE_API_TOKEN": "your-token-here" }
}
}
}Herramientas
Facturas (5 herramientas) — ventas
lexware_create_invoice (admite finalize=true en la creación), lexware_get_invoice, lexware_download_invoice_file, lexware_pursue_invoice, lexware_deeplink_invoice
Notas de crédito (5 herramientas) — ventas
lexware_create_credit_note, lexware_get_credit_note, lexware_download_credit_note_file, lexware_pursue_credit_note, lexware_deeplink_credit_note
Presupuestos (4 herramientas) — ventas
lexware_create_quotation, lexware_get_quotation, lexware_download_quotation_file, lexware_deeplink_quotation
Confirmaciones de pedido (5 herramientas) — ventas
lexware_create_order_confirmation, lexware_get_order_confirmation, lexware_download_order_confirmation_file, lexware_pursue_order_confirmation, lexware_deeplink_order_confirmation
Albaranes (5 herramientas) — ventas
lexware_create_delivery_note, lexware_get_delivery_note, lexware_download_delivery_note_file, lexware_pursue_delivery_note, lexware_deeplink_delivery_note
Facturas de pago anticipado (3 herramientas) — ventas
lexware_get_down_payment_invoice, lexware_download_down_payment_invoice_file, lexware_deeplink_down_payment_invoice
Recordatorios (4 herramientas) — ventas
lexware_get_dunning, lexware_download_dunning_file, lexware_pursue_dunning, lexware_deeplink_dunning
Lista de comprobantes (1 herramienta) — ventas, contabilidad
lexware_list_voucherlist
Por defecto, esto es un paso de una sola página de la respuesta de la API. Dos adiciones son opcionales:
fetchAllPages: truesigue la paginación hasta recuperar todas las páginas, con un límite de 100 solicitudes. El resultado añadefetchedPagesytruncated; este último marca un conjunto recortado por el límite: los campos de la API comototalElementsse conservan.contactName(comodines de estilo SQL%/_, sin distinción de mayúsculas y minúsculas) yhasOpenAmountfiltran del lado del cliente después de la obtención, y cada uno implicafetchAllPages. Se aplican aquí en lugar de enlexware_list_vouchersporque/voucherlistes la forma de respuesta que llevacontactNameyopenAmount.
page no se puede combinar con ninguna de las tres: esos modos leen todas las páginas, por lo que un desplazamiento inicial no tiene sentido. Usa size para controlar el tamaño del lote en su lugar. La combinación se rechaza en lugar de ignorarse silenciosamente, para que nadie pueda creer que se respetó un desplazamiento cuando no fue así.
Contactos (5 herramientas) — contactos
lexware_list_contacts, lexware_get_contact, lexware_create_contact, lexware_update_contact, lexware_deeplink_contact
Artículos (5 herramientas) — contactos
lexware_list_articles, lexware_get_article, lexware_create_article, lexware_update_article, lexware_delete_article
Comprobantes (6 herramientas) — contabilidad
lexware_list_vouchers, lexware_get_voucher, lexware_create_voucher, lexware_update_voucher, lexware_upload_voucher_file, lexware_deeplink_voucher
lexware_list_vouchers requiere voucherNumber. GET /vouchers es un endpoint de búsqueda, no una colección navegable: la API responde 400 "voucherNumber parameter is required" sin él. Para navegar o filtrar comprobantes, usa lexware_list_voucherlist, que es el endpoint de colección y también lleva los campos de resumen (contactName, openAmount) que /vouchers no tiene.
lexware_get_voucher normaliza voucherStatus a minúsculas y reintenta un 404 tres veces (1 s / 2 s / 4 s) para cubrir el retraso de indexación después de una carga; si el comprobante aún falta, devuelve { voucherId, status: "processing", message }. Otros fallos se informan como errores.
Pagos (1 herramienta) — contabilidad
lexware_get_payments
Países (1 herramienta) — referencia
lexware_list_countries
Condiciones de pago (1 herramienta) — referencia
lexware_list_payment_conditions
Categorías de contabilización (1 herramienta) — referencia
lexware_list_posting_categories
Perfil (1 herramienta) — referencia
lexware_get_profile
Diseños de impresión (1 herramienta) — referencia
lexware_list_print_layouts
Suscripciones a eventos (5 herramientas) — sistema
lexware_create_event_subscription, lexware_list_event_subscriptions, lexware_get_event_subscription, lexware_delete_event_subscription, lexware_verify_webhook_signature
Archivos (4 herramientas) — sistema
lexware_upload_file, lexware_download_file, lexware_get_file_status, lexware_deeplink_file
lexware_get_file_status llama a GET /files/{id}/status. El GET /files/{id} simple es la ruta de descarga binaria: con Accept: application/json aún responde 200 con el cuerpo del archivo codificado en base64, por lo que nunca puede producir metadatos de estado. La ruta de estado está restringida por alcance: las claves de API sin el permiso necesario reciben access_denied de Lexware en lugar de un estado.
Ambas herramientas de carga (lexware_upload_file y lexware_upload_voucher_file) aceptan el archivo como contentBase64 o como filePath — una ruta absoluta legible por el proceso del servidor MCP. Prefiere filePath para cualquier cosa de tamaño considerable: base64 infla la carga útil en aproximadamente un tercio y tiene que viajar a través de la ventana de contexto del modelo. Con filePath, fileName se establece por defecto al nombre base del archivo y contentType se detecta automáticamente para .png, .jpg/.jpeg, .tiff/.tif y .xml, con respaldo a application/pdf. Proporciona exactamente uno de los dos: proporcionar ambos, o ninguno, es un error de validación.
Las cargas están limitadas a 5 MB. Para filePath, el tamaño se toma del descriptor abierto antes de leer el archivo, por lo que un archivo demasiado grande cuesta un stat en lugar de una carga completa en memoria, y cualquier cosa que no sea un archivo regular se rechaza directamente (leer /dev/zero de otro modo nunca devolvería). El recuento de bytes decodificados se verifica nuevamente después, lo que también cubre contentBase64. Los fallos llevan un error file_too_large con los tamaños real y máximo.
Plantillas recurrentes (3 herramientas) — sistema
lexware_list_recurring_templates, lexware_get_recurring_template, lexware_deeplink_recurring_template
Seguridad
Usa el llavero del sistema operativo para mantener tu token de API totalmente fuera de los archivos de configuración y del historial del shell (consulta Configuración)
Nunca hagas commit de tu token de API en el control de versiones
Usa acceso de solo lectura cuando solo necesites listar/obtener recursos
Las herramientas de crear, actualizar y eliminar modifican datos empresariales reales — facturas, contactos y registros contables en tu cuenta de Lexware
La limitación de tasa se gestiona automáticamente: las solicitudes se reintentan con retroceso exponencial cuando reciben un 429, incluidos los archivos subidos — el cuerpo multipart se reconstruye desde cero en cada reintento, por lo que puede reproducirse de forma segura
Publicación de lanzamientos
Los lanzamientos se publican mediante el evento GitHub Release. Flujo del mantenedor:
Incrementa la versión en
package.json,package-lock.jsonyserver.json(npm version <x.y.z> --no-git-tag-versionactualiza los dos primeros a la vez).npm run check-versionsfalla de forma categórica a menos quepackage.json#/version,server.json#/packages[0].versiony ambos campos de versión depackage-lock.json(la raíz ypackages[""]) coincidan.server.json#/versionse comprueba de forma más flexible: debe estar presente, pero solo se compara conpackages[0].versioncomo comprobación de regresión — puede estar legítimamente por delante (las republicaciones solo de registro incrementan únicamente ese campo), por lo que un valor que se haya quedado en el lanzamiento anterior pasa con una líneaWARN:y sin fallo. En un lanzamiento normal, ambos deberían avanzar a la vez, así que lee la salida del script en lugar de confiar en su código de salida.CHANGELOG.mdno se comprueba en absoluto.Actualiza
CHANGELOG.md.Haz commit y fusiona el incremento de versión en
mainantes de crear el lanzamiento. Luego crea la etiqueta tú mismo, sobre un SHA que hayas comprobado, y solo entonces crea el lanzamiento a partir de ella:V=X.Y.Z && PR=<release-pr-number> && SHA="$(gh pr view "$PR" --json mergeCommit -q .mergeCommit.oid)" && test -n "$SHA" && git fetch origin main && git merge-base --is-ancestor "$SHA" origin/main && PKG="$(git show "$SHA:package.json")" && test "$(printf '%s' "$PKG" | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).version')" = "$V" && CL="$(git show "$SHA:CHANGELOG.md")" && printf '%s\n' "$CL" | awk -v v="$V" 'index($0,"## ["v"]")==1{f=1;next} /^## \[/{f=0} /^\[[0-9]+\.[0-9]+\.[0-9]+\]:/{f=0} f' > "/tmp/notes-v$V.md" && grep -q '[^[:space:]]' "/tmp/notes-v$V.md" && git tag -a "v$V" "$SHA" -m "v$V" && git push origin "v$V" && gh release create "v$V" --verify-tag --notes-file "/tmp/notes-v$V.md"El fallo que esto evita: si no existe ninguna etiqueta,
gh release createcoloca una en la punta de la rama predeterminada, por lo que ejecutarlo mientras el incremento sigue en una rama de lanzamiento etiqueta el commit del lanzamiento anterior. El flujo de trabajo publica entonces cualquier versión que encuentre en elpackage.jsonde ese commit, y obtienes un GitHub ReleasevX.Y.Zque republica silenciosamente la versión anterior. Desde 5.2.0, el propio flujo de trabajo de publicación se niega a continuar cuandoGITHUB_REF_NAMEno esv<package.json version>(#103), por lo que un lanzamiento mal etiquetado ahora falla antes denpm publishen lugar de republicar silenciosamente. Sin embargo, esa salvaguarda solo se activa una vez que el flujo de trabajo ya está en marcha — la secuencia anterior es la que impide que se etiquete el commit equivocado en primer lugar, así que sigue usándola en lugar de confiar en que el flujo de trabajo detecte el error.Cada elemento es fundamental:
gh pr view … .mergeCommit.oidnombra el commit squash del propio PR de lanzamiento. No lo sustituyas porgit rev-parse origin/main— eso es simplemente lo que esté enmainen el momento en que lo consultes, por lo que una fusión no relacionada que llegue en ese intervalo se etiqueta y se publica en su lugar.ghtermina con código 0 y no imprime nada para un PR no fusionado, de ahí eltest -nexplícito.La cadena
&&se detiene ante el primer fallo en lugar de pasar al paso irreversible. Ambas llamadas agit showse asignan a una variable en lugar de canalizarse directamente, por lo que su estado de salida se comprueba de verdad — una canalización solo informa del estado de su último comando a menos que esté establecidopipefail, algo que no se presupone aquí.git merge-base --is-ancestordemuestra que el commit es realmente alcanzable desdemain. La mera existencia no basta — un commit puede estar presente localmente porque se haya hecho fetch de otra rama y, si sus archivos de versión coinciden por casualidad, de otro modo pasaría sin problemas todas las comprobaciones restantes.La comprobación de versión lee el
package.jsondel commit objetivo, no del árbol de trabajo, que seguiría mostrando la versión correcta aunque$SHAapuntara a otro lugar.El
awkextrae la sección de esa versión delCHANGELOG.mddel commit para--notes-file. Sin él, el cuerpo del lanzamiento es lo que--notes-from-tagencuentre en la anotación — en este flujo, la cadena literalvX.Y.Z, que es una nota de lanzamiento pobre para cualquier versión y abiertamente engañosa para una versión mayor con un cambio que rompe la compatibilidad. Se detiene en el siguiente encabezado## [o en la primera definición de referencia de enlace, porque la entrada más antigua del archivo no tiene ningún encabezado después y, de otro modo, se tragaría todo el bloque de referencias de enlaces.grep -qen lugar detest -sprotege el resultado: una sección que está vacía aparte de su línea en blanco sigue produciendo un archivo de un byte, quetest -sacepta.--verify-taghace queghse interrumpa en lugar de inventarse una etiqueta si el push no se completó — la salvaguarda contra queghvuelva a adoptar el comportamiento de etiquetar la punta de la rama predeterminada descrito anteriormente.
Si
gh release createfalla después de que la etiqueta ya se haya subido, no vuelvas a ejecutar todo el bloque — se detendrá engit tag, lo cual es correcto. Vuelve a ejecutar solo el último comando.El flujo de trabajo
Publish to npm + MCP Registryse ejecuta automáticamente: hacenpm publishcon procedencia, consulta el registro hasta que el tarball esté disponible y luego sube elserver.jsoncorrespondiente al MCP Registry mediantemcp-publisher.
El flujo de trabajo omite npm publish limpiamente si la versión ya está en npm (salvaguarda de transición para lanzamientos que se publicaron parcialmente de forma manual).
Autenticación de publicación — npm Trusted Publishing (sin token)
La publicación utiliza npm Trusted Publishing mediante OIDC — no hay ningún secreto NPM_TOKEN. El permiso id-token: write del flujo de trabajo se intercambia por un token de publicación de un solo uso y de corta duración en el momento de publicar, utilizando la vinculación de trusted publisher configurada para @lazyants/lexware-mcp-server en la interfaz web de npm. La única configuración necesaria es esa vinculación de trusted publisher en npm; no es necesario almacenar nada en los secretos del repositorio.
Descargo de responsabilidad
Este es un proyecto comunitario independiente y no oficial. No está afiliado a, respaldado por, patrocinado por ni apoyado por Lexware GmbH, Haufe Group ni ninguna de sus filiales. Para soporte oficial de Lexware, contacta directamente con Lexware — los problemas con este servidor MCP deben notificarse aquí, no a Lexware.
«Lexware» y «Lexware Office» son marcas comerciales de sus respectivos propietarios y se utilizan en el nombre y la documentación de este proyecto en virtud del uso legítimo nominativo, únicamente para identificar la API de terceros a la que se conecta este cliente.
Las operaciones de crear, actualizar y eliminar modifican datos empresariales reales en tu cuenta de Lexware. Los autores proporcionan este software «tal cual» y no aceptan ninguna responsabilidad por cambios no deseados, pérdida de datos o cualquier otro daño derivado de su uso. Prueba con una cuenta sandbox o no crítica antes de ejecutar operaciones de escritura sobre datos de producción.
Licencia
FSL-1.1-MIT — consulta LICENSE para conocer los términos completos.
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 Servers
- FlicenseBqualityCmaintenanceMCP server for DACH accounting automation. Connect AI assistants to sevDesk and Lexoffice — create invoices, manage contacts, handle bookings and vouchers for German-speaking businesses.1537
- FlicenseNot gradedqualityCmaintenanceMCP server for German e-invoicing with tools to generate and validate XRechnung CII XML locally, supporting German VAT rates and § 19 UStG.
- AlicenseAqualityBmaintenanceEnables MCP-capable assistants to query and manage Lexware Office contacts, sales documents, vouchers, files, payments, webhooks, and reference data via the Lexware Office public API. Adds bank reconciliation tools for matching bank statement CSVs against Lexware vouchers or scanned receipt PDFs.4MIT
- AlicenseAqualityBmaintenanceMCP server for Lexware Office that enables querying and managing contacts, sales documents, vouchers, files, payments, and webhooks through a sandboxed two-tool interface (search/execute) with read-only-by-default write safety.2MIT
Related MCP Connectors
MCP server for the PDFGate API. Generate PDFs, manage documents and handle e-signatures.
Hosted MCP server for Mini Accountant: invoices, expenses, customers, analytics, tax estimates.
A MCP server for the Frankfurter API for currency exchange rates.
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/lazyants/lexware-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server