Cartas de bienvenida para cuarenta nuevos clientes, un certificado para cada asistente, una factura por pedido: el mismo documento, un registro diferente cada vez. Con GroupDocs.Assembly.Mcp ejecutándose localmente (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor o Copilot lo hacen con una sola llamada a la herramienta, assemble_per_record, que llena su plantilla de Word una vez por cada elemento de una matriz JSON, guarda cada resultado como su propio PDF nombrado por un campo que elija, y reporta los registros que fallaron en lugar de detenerse en el primero:
Cree un PDF de carta de bienvenida para cada cliente en customers.json usando welcome-letter.docx, y nombre cada archivo según el cliente.
La versión paso a paso con configuración y solución de problemas está en la documentación: Cómo generar un documento por registro (combinar correspondencia) con un agente de IA.
¿Por qué no dejar que el agente haga el bucle?
Puede hacerlo, y para cinco registros está bien. Pero un bucle de cuarenta llamadas a la herramienta son cuarenta oportunidades para que el agente pierda la cuenta, omita un registro cuando el contexto se alarga, o lo “reformule” de manera “útil”. Una herramienta por registro traslada el bucle al servidor: una llamada, una plantilla, una pasada sobre la matriz, y un informe que indica exactamente cuántos archivos se escribieron y qué registros no lo lograron. El trabajo del agente es elegir la plantilla, el archivo de datos y el campo de nombrado, y luego leer el informe de vuelta.
¿Qué verifica primero el agente?
Dos cosas: cómo se ve los datos y qué lee la plantilla. En nuestra prueba, cinco clientes en customers.json y una carta de bienvenida de una página:
-> get_document_info {"file":{"filePath":"customers.json"}}
<- { "dataKind": "json",
"data": { "root": "array", "length": 5, "keys": null } }
-> get_template_fields {"template":{"filePath":"welcome-letter.docx"}}
<- { "dataSourceNames": [ "customer" ],
"fields": [ "customer.Contact", "customer.Plan", "customer.Name",
"customer.Manager", "customer.FirstInvoice" ] }
La plantilla llama a un registro customer; el servidor lo determina por sí mismo, por lo que el agente no tiene que pasar dataSourceName.
Una llamada, cinco registros, una falla
-> assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},"fileNameField":"Name",
"format":"pdf"}
<- Assembled 4 of 5 document(s) from 'welcome-letter.docx' with
'customers.json', one per record (each record as 'customer'), as PDF.
Saved to:
.../Contoso Pharma.pdf
.../Fabrikam Logistics.pdf
.../Tailspin Toys.pdf
.../Litware Labs.pdf
1 record(s) failed:
record 4: InvalidOperationException: ... Can not get the value of
member 'FirstInvoice' on type 'System.Data.DataRow'. The template
reads 'FirstInvoice', which the data does not have. ...
El registro 4, Wingtip Travel, no tenía fecha de primera factura en los datos. Las otras cuatro cartas fueron escritas, cada una nombrada según el cliente, y la falla regresó con el número de registro y el campo que faltaba. Un agente informa eso como “cuatro cartas hechas; Wingtip Travel no tiene fecha de primera factura, ¿quieres que deje la línea vacía o esperar la fecha?”. Esa es la conversación que deseas, en lugar de cuarenta archivos sin saber cuál está equivocado.
Cómo funciona la distribución
customers.json [ {Name:"Contoso Pharma",...}, {Name:"Fabrikam ..."},
... 5 records ]
|
assemble_per_record {"template":{"filePath":"welcome-letter.docx"},
"data":{"filePath":"customers.json"},
"fileNameField":"Name","format":"pdf"}
|
+--> Contoso Pharma.pdf
+--> Fabrikam Logistics.pdf ... 2 more
'--> "4 of 5 ... 1 record(s) failed: record 4 ..."
Tres parámetros hacen el trabajo. fileNameField nombra cada salida por un campo del registro, customer.Name o un número de factura; sin él, los archivos reciben un número secuencial. recordsPath apunta a la matriz cuando el JSON es un objeto que contiene una, como "customers" o "batch.items". Y maxDocuments es el freno.
¿Qué detiene un lote descontrolado?
maxDocuments, que por defecto es 100 y puede llegar a 1000. Antes de escribir cualquier cosa, el servidor cuenta los registros; si hay más que el límite, lo rechaza. Lo configuramos a 3 frente a nuestros cinco clientes:
-> assemble_per_record {..., "maxDocuments":3}
<- Per-record assembly failed for 'welcome-letter.docx': there are 5
records, more than maxDocuments=3. Raise 'maxDocuments' (up to 1000)
or pass fewer records.
No se escribió nada. Para un envío que va a personas reales, ese es el valor predeterminado correcto: un aviso que accidentalmente apunta a toda la exportación del CRM recibe una pregunta, no diez mil PDFs.
Mis datos son una hoja de cálculo, no JSON
La generación por registro solo lee JSON: una matriz de objetos, o un objeto que contiene una. Cuando la lista está en un CSV o una hoja de cálculo, el agente convierte primero las filas a JSON, lo cual los agentes hacen bien, y escribe el archivo en la carpeta de almacenamiento. Si lo que deseas es un documento que enumere cada fila, una lista de precios o un registro, eso es assemble_document con un <<foreach>> en la plantilla, y lee CSV y hojas de cálculo directamente.
Límites honestos
- La ensambladura por registro solo lee JSON; los datos CSV y de hoja de cálculo necesitan conversión primero.
- Modo de evaluación: cada archivo generado comienza con “Evaluation Only. Created with GroupDocs.Assembly 26.7…”, y las plantillas de correo electrónico conservan solo su cuerpo de texto plano. Licencie el servidor antes de un envío real.
- Un campo faltante falla ese registro.
allowMissingMembers: truelo escribe con la línea vacía; decide cuál deseas. - Fechas: escríbelas como
2026-12-01T00:00:00y formatealas en la plantilla, como nuestra carta hace con<<[customer.FirstInvoice]:"d MMMM yyyy">>. Una cadena solo de fecha desplazada un día en una máquina UTC+2 en nuestra prueba. - El servidor escribe archivos; no los envía. La entrega es un paso separado.
Preguntas frecuentes
¿Puedo combinar correspondencia con Claude sin subir la lista de clientes?
Sí. El servidor se ejecuta localmente y lee customers.json de su carpeta de almacenamiento; los PDFs generados también se escriben allí.
¿Cómo se nombran los archivos de salida?
Por el campo de registro que pasas como fileNameField, aquí el nombre del cliente, por lo que Contoso Pharma.pdf. Sin él, un número secuencial.
¿Puede cada documento ser un correo electrónico en lugar de un PDF?
Sí: use una plantilla EML o MSG, o pase format: "eml". En modo de evaluación el cuerpo HTML de un correo electrónico se reemplaza por la línea de evaluación, así que pruebe la salida de correo electrónico con una licencia.
Profundizar
- Documentación, cómo‑to canónico: Cómo generar un documento por registro (combinar correspondencia) con un agente de IA
- Centro de documentación: GroupDocs.Assembly MCP Server
- Comience aquí: Deje que el modelo rellene los datos, no que escriba el documento
- Relacionado: ¿Qué necesita esta plantilla? Pregúntele.
- Relacionado: El gráfico proviene de la plantilla, los números provienen de los datos
- Relacionado: Su repositorio ya tiene los datos; deje que el agente genere el PDF
- En local y modelo de seguridad: 3 arquitecturas para el procesamiento de documentos con IA, y la que mantiene los archivos dentro de su red
- Preguntas: Foro de GroupDocs Assembly
- Fuente: GroupDocs.Assembly.Mcp en GitHub