Enty.io
Servidor MCP para Enty.io: facturas, transacciones bancarias, plazos contables y contratos, expuestos como herramientas que tu agente de IA puede invocar.
Documentación
enty-mcp
Un servidor MCP para Enty.io — facturas, transacciones bancarias, plazos contables y contratos, expuestos como herramientas que tu agente de IA puede invocar.
Enty no tiene API pública. Este servidor utiliza el mismo endpoint GraphQL que usa la aplicación web de Enty, autenticado con el token de sesión de tu navegador. Esto conlleva advertencias que deberías leer antes de usarlo:
No oficial. Este proyecto no está afiliado ni respaldado por Enty. Se comunica con una API interna no documentada que puede cambiar o romperse en cualquier momento, y su uso puede no estar cubierto por los términos de servicio de Enty. Lee los datos reales de tu empresa — no existe un entorno de pruebas. Dos herramientas también escriben en él (solo elementos de catálogo); nada elimina.
Herramientas
| Herramienta | Qué devuelve |
|---|---|
enty_get_me | Usuario conectado + empresa activa |
enty_list_companies | Empresas de la cuenta |
enty_list_invoices | Facturas con filtro de estado, totales, recuentos por estado |
enty_list_counterparties | Clientes/proveedores con datos fiscales |
enty_list_items | Elementos de catálogo (líneas de factura) |
enty_list_item_units | Unidades de medida que puede usar un elemento |
enty_list_transaction_documents | Documentos ya adjuntos a una transacción |
enty_list_invoice_payment_candidates | Transacciones que podrían ser el pago de una factura |
enty_list_bank_accounts | Cuentas bancarias con IBAN y estado de conexión |
enty_list_transactions | Transacciones con filtros de cuenta/fecha/dirección/texto |
enty_get_transaction | Una transacción con nota y categoría |
enty_get_balance | Saldo combinado de las cuentas seleccionadas |
enty_get_transactions_statistics | Estadísticas de coincidencia de documentos para un rango de fechas |
enty_list_categories | Árbol de categorización de transacciones |
enty_list_accounting_periods | Periodos contables |
enty_get_period_deadlines | Próximo plazo fiscal/de declaración para un periodo |
enty_get_potential_tax | Impuesto estimado para un periodo, por tipo (EUR) |
enty_get_period_issues | Problemas de contabilidad abiertos para un periodo |
enty_list_contracts | Contratos con estado del ciclo de vida de firma electrónica |
enty_list_deals | Acuerdos con estado y contraparte |
enty_get_deals_stats | Importes esperados vs recibidos de acuerdos |
Herramientas de escritura
| Herramienta | Qué hace |
|---|---|
enty_create_item | Crear un elemento de catálogo (producto/servicio) |
enty_update_item | Actualizar nombre, precio, moneda, unidad o descripción de un elemento de catálogo |
enty_create_deal | Crear un acuerdo para una contraparte |
enty_create_invoice | Crear un borrador de factura con líneas |
enty_mark_invoice_paid | Marcar una factura como pagada |
enty_link_transaction_to_invoice | Registrar una transacción bancaria como pago de una factura |
enty_attach_document_to_transaction | Subir un archivo local y adjuntarlo a una transacción |
Estas escriben en tu empresa en vivo. Vale la pena distinguir dos niveles de riesgo.
Los elementos de catálogo y los acuerdos son datos de referencia. Crear o editar uno no altera las facturas que ya lo referencian.
Las últimas tres tocan la contabilidad. Vincular una transacción a una factura y adjuntar documentos cambian registros con los que trabaja tu contador, y un vínculo incorrecto se lee como un error de conciliación. Ninguna de ellas se puede deshacer aquí, así que verifica los ids antes de invocarlas.
enty_create_invoice deja un borrador. No se envía nada al cliente ni se genera PDF; revísalo y emítelo en la aplicación web de Enty. Requiere cuatro llamadas, porque Enty construye una factura de esa manera: crear un borrador en blanco, ajustar el encabezado, añadir las líneas, guardar los totales. Si un paso posterior falla, el borrador sobrevive y el error lleva su id para que puedas terminarlo o descartarlo manualmente.
enty_link_transaction_to_invoice necesita que la factura tenga un documento generado, ya que el vínculo se establece entre ese documento y la transacción. Enty no tiene un registro de pago separado. Abre una factura nueva una vez en la aplicación web si la herramienta informa que no tiene ninguna.
enty_attach_document_to_transaction es la única vía que no es GraphQL. Los bytes van al servicio de almacenamiento de archivos de Enty como datos de formulario multiparte, el archivo devuelto se registra como documento contable, y solo entonces se vincula a la transacción.
Nada en este servidor elimina. La API de Enty tiene 233 mutaciones, 19 de ellas de eliminación (deleteItemsAtOrganization, DeleteTransactions, DeleteUserCompanies, etc.). Ninguna está expuesta, y el cliente GraphQL se niega a enviar cualquier mutación cuyo nombre de operación no esté en una lista blanca explícita (ALLOWED_MUTATIONS en src/enty_mcp/graphql.py), por lo que una escritura bloqueada nunca sale del proceso. Eliminar cualquier cosa es una acción manual en la aplicación web de Enty, a propósito.
enty_update_item fusiona: pasa solo los campos que quieres cambiar. La actualización de Enty reemplaza el elemento completo, por lo que la herramienta primero lee los valores actuales del elemento y los envía de vuelta junto con tus cambios. Sin eso, actualizar un campo dejaría en blanco el resto.
El resto de la superficie de mutaciones está mapeada (spec/graphql/bundle-operations/) pero no expuesta. Añadir una escritura significa añadir su nombre a la lista blanca, que es el paso de revisión.
Autenticación
Dos opciones. Elige una.
Correo electrónico y contraseña (ENTY_EMAIL, ENTY_PASSWORD). El servidor inicia sesión por ti, mantiene el token de sesión en memoria y vuelve a iniciar sesión automáticamente cuando la sesión expira. No hay nada que hacer cuando un token muere, que es lo que quieres para un servidor destinado a ejecutarse sin supervisión. Enty no emite token de refresco, por lo que renovar es realmente un nuevo inicio de sesión.
Un token de sesión (ENTY_AUTH_TOKEN). Inicia sesión en app.enty.io, abre DevTools → Red, haz clic en cualquier solicitud a /api/ y copia el valor del encabezado de solicitud enty-auth. Esto expira, y sin credenciales el servidor no puede renovarlo, por lo que repites los pasos cada vez que las herramientas empiecen a fallar.
Configura ambos y el token se usa primero, con respaldo a las credenciales una vez que expire. Eso evita un inicio de sesión al arrancar mientras sigue sobreviviendo a la expiración.
De cualquier manera, el secreto otorga acceso completo a tu cuenta de Enty, así que trátalo como la contraseña que efectivamente es. Las credenciales y tokens se mantienen como SecretStr de pydantic, se mantienen fuera de los encabezados compartidos del cliente, se envían solo a tu ENTY_BASE_URL configurado y nunca se escriben en los registros. El correo de la cuenta se registra en INFO cuando ocurre un inicio de sesión, para que puedas saber qué cuenta está usando un servidor en ejecución.
Las cuentas con autenticación multifactor no pueden usar correo y contraseña. Enty responde a esos inicios de sesión sin id de sesión, y el servidor lo indica en lugar de fallar de manera oscura. Usa un token para esas cuentas.
Ejecución
Con uv
git clone https://github.com/appsome/enty-mcp-server
cd enty-mcp-server
cp .env.example .env # paste your token
uv sync
uv run enty-mcp # streamable HTTP on :8001/mcp
uv run enty-mcp --transport stdio # for stdio clients
Con Docker Compose
cp .env.example .env # fill in ENTY_EMAIL and ENTY_PASSWORD
docker compose up -d
# server: http://localhost:8001/mcp health: http://localhost:8001/health
El archivo compose compila desde el código fuente. Para ejecutar una imagen publicada en su lugar:
docker run -d -p 8001:8001 \
-e ENTY_EMAIL=you@example.com -e ENTY_PASSWORD=... \
ghcr.io/appsome/enty-mcp-server:latest
Las imágenes se compilan para linux/amd64 y linux/arm64 y se publican en GitHub Container Registry en cada push a main, etiquetadas latest y con el sha del commit. Publicar una etiqueta v* añade las etiquetas semver correspondientes. El contenedor sale inmediatamente con un error claro si no se configuran ni credenciales ni un token.
Configuración
| Variable de entorno | Predeterminado | |
|---|---|---|
ENTY_EMAIL / ENTY_PASSWORD | — | credenciales; el servidor inicia sesión y se renueva solo |
ENTY_AUTH_TOKEN | — | token de sesión; alternativa a lo anterior |
ENTY_BASE_URL | https://app.enty.io | |
ENTY_LOCALE | en | |
ENTY_TIMEOUT_S | 30 | |
MCP_HOST / MCP_PORT | 0.0.0.0 / 8001 | transportes HTTP |
LOG_LEVEL | INFO |
Conexión de un cliente
OpenHands (docker compose): usa docker-compose.override.example.yml para añadir el servicio a tu stack, luego apunta OpenHands a http://enty-mcp:8001/mcp — consulta openhands/mcp.json y openhands/config.toml.snippet.
Claude Code:
claude mcp add --transport http enty http://localhost:8001/mcp
Claude Desktop (stdio):
{
"mcpServers": {
"enty": {
"command": "uv",
"args": ["run", "--directory", "/path/to/enty-mcp-server", "enty-mcp", "--transport", "stdio"],
"env": { "ENTY_EMAIL": "you@example.com", "ENTY_PASSWORD": "..." }
}
}
}
Cómo se hizo el mapeo de la API
El endpoint GraphQL de Enty tiene la introspección deshabilitada, por lo que el esquema se reconstruyó a partir de dos fuentes: una captura HAR de la aplicación web (56 operaciones con formas de respuesta, spec/graphql/operations/) y los paquetes JS de la aplicación, que contienen todos los documentos GraphQL que el frontend puede enviar (434 operaciones, spec/graphql/bundle-operations/). spec/graphql/NOTES.md documenta las convenciones y las brechas restantes. Los scripts de extracción en scripts/ son repetibles cuando la aplicación cambia.
Desarrollo
uv sync
uv run pytest # respx-mocked, no network
uv run ruff check src tests scripts
uv run pyright
Las pruebas nunca tocan la API real. Los datos de los fixtures son sintéticos, con forma de respuestas registradas.
Licencia
MIT