Cartas de boas‑vindas para quarenta novos clientes, um certificado para cada participante, uma fatura por pedido: o mesmo documento, um registro diferente a cada vez. Com o GroupDocs.Assembly.Mcp em execução localmente (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor ou Copilot fazem isso com uma única chamada de ferramenta, assemble_per_record, que preenche seu modelo Word uma vez por elemento de um array JSON, salva cada resultado como um PDF próprio nomeado por um campo que você escolher e relata os registros que falharam em vez de parar no primeiro:
Crie um PDF de carta de boas‑vindas para cada cliente em customers.json usando welcome-letter.docx, e nomeie cada arquivo com o nome do cliente.
A versão passo a passo com configuração e solução de problemas está na documentação: How to generate one document per record (mail merge) with an AI agent.
Por que não deixar o agente fazer o loop?
Ele pode, e para cinco registros isso é suficiente. Mas um loop de quarenta chamadas de ferramenta são quarenta chances de o agente perder a conta, pular um registro quando o contexto fica longo ou “ajudando” reformular uma carta. Uma ferramenta por registro move o loop para o servidor: uma chamada, um modelo, uma passagem sobre o array e um relatório que diz exatamente quantos arquivos foram gravados e quais registros não foram processados. O trabalho do agente é escolher o modelo, o arquivo de dados e o campo de nomeação e, em seguida, ler o relatório de volta para você.
O que o agente verifica primeiro?
Duas coisas: como os dados se apresentam e o que o modelo lê. No nosso teste, cinco clientes em customers.json e uma carta de boas‑vindas de uma 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" ] }
O modelo chama um registro de customer; o servidor descobre isso por conta própria, portanto o agente não precisa passar dataSourceName.
Uma chamada, cinco registros, uma falha
-> 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. ...
O registro 4, Wingtip Travel, não tinha data de primeira fatura nos dados. As outras quatro cartas foram escritas, cada uma nomeada com o cliente, e a falha retornou com o número do registro e o campo que estava ausente. Um agente relata isso como “quatro cartas concluídas; Wingtip Travel não tem data de primeira fatura, você quer que eu deixe a linha vazia ou aguarde a data?”. Essa é a conversa que você deseja, em vez de quarenta arquivos sem saber qual está errado.
Como funciona a distribuição
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 ..."
Três parâmetros fazem o trabalho. fileNameField nomeia cada saída por um campo do registro, customer.Name ou um número de fatura; sem ele, os arquivos recebem um número sequencial. recordsPath aponta para o array quando o JSON é um objeto que contém um, como "customers" ou "batch.items". E maxDocuments é o freio.
O que impede um lote descontrolado?
maxDocuments, que tem padrão 100 e pode chegar a 1000. Antes de gravar qualquer coisa, o servidor conta os registros; se houver mais que o limite, ele recusa. Definimos para 3 contra nossos 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.
Nada foi gravado. Para uma campanha que vai a pessoas reais, esse é o padrão correto: um prompt que aponta acidentalmente para a exportação completa do CRM gera uma pergunta de volta, não dez mil PDFs.
Meus dados são uma planilha, não JSON
A geração por registro lê apenas JSON: um array de objetos ou um objeto que contém um. Quando a lista está em um CSV ou em uma planilha, o agente converte as linhas para JSON primeiro, o que os agentes fazem bem, e grava o arquivo na pasta de armazenamento. Se o que você quer é um documento que liste cada linha, uma lista de preços ou um registro, isso é assemble_document com um <<foreach>> no modelo, e ele lê CSV e planilhas diretamente.
Limites honestos
- A montagem por registro lê apenas JSON; dados CSV e de planilha precisam ser convertidos primeiro.
- Modo de avaliação: todo arquivo gerado começa com “Evaluation Only. Created with GroupDocs.Assembly 26.7…”, e os modelos de e‑mail mantêm apenas o corpo em texto simples. Licencie o servidor antes de uma campanha real.
- Um campo ausente falha esse registro.
allowMissingMembers: truegrava com a linha vazia; decida o que você prefere. - Datas: escreva-as como
2026-12-01T00:00:00e formate-as no modelo, como nossa carta faz com<<[customer.FirstInvoice]:"d MMMM yyyy">>. Uma string de data apenas foi deslocada um dia em uma máquina UTC+2 no nosso teste. - O servidor grava arquivos; ele não os envia. A entrega é uma etapa separada.
Perguntas Frequentes
Posso fazer mesclagem de correspondência com Claude sem fazer upload da lista de clientes?
Sim. O servidor roda localmente e lê customers.json da sua pasta de armazenamento; os PDFs gerados são gravados lá também.
Como os arquivos de saída são nomeados?
Pelo campo de registro que você passa como fileNameField, aqui o nome do cliente, então Contoso Pharma.pdf. Sem ele, um número sequencial.
Cada documento pode ser um e‑mail em vez de um PDF?
Sim: use um modelo EML ou MSG, ou passe format: "eml". No modo de avaliação o corpo HTML de um e‑mail é substituído pela linha de avaliação, então teste a saída de e‑mail com uma licença.
Aprofunde-se
- Documentação, como‑fazer canônico: How to generate one document per record (mail merge) with an AI agent
- Hub de documentação: GroupDocs.Assembly MCP Server
- Comece aqui: Let the model fill in the data, not write the document
- Relacionado: What does this template need? Ask it.
- Relacionado: The chart comes from the template, the numbers come from the data
- Relacionado: Your repo already has the data; let the agent make the PDF
- Modelo on‑premise e de segurança: 3 architectures for AI document processing, and the one that keeps files inside your network
- Perguntas: GroupDocs Assembly forum
- Fonte: GroupDocs.Assembly.Mcp on GitHub