Listy powitalne dla czterdziestu nowych klientów, certyfikat dla każdego uczestnika, faktura dla każdego zamówienia: ten sam dokument, inny rekord za każdym razem. Przy uruchomionym lokalnie GroupDocs.Assembly.Mcp (dnx GroupDocs.Assembly.Mcp --yes), Claude Desktop, Cursor lub Copilot wykonuje to jednym wywołaniem narzędzia, assemble_per_record, które wypełnia szablon Worda raz dla każdego elementu tablicy JSON, zapisuje każdy wynik jako osobny plik PDF nazwany według wybranego pola i raportuje rekordy, które nie powiodły się, zamiast zatrzymywać się przy pierwszym:
Utwórz plik PDF listu powitalnego dla każdego klienta w customers.json przy użyciu welcome-letter.docx i nazwij każdy plik po nazwie klienta.
Wersja krok po kroku z konfiguracją i rozwiązywaniem problemów znajduje się w dokumentacji: Jak wygenerować jeden dokument na rekord (mail merge) przy użyciu agenta AI.
Dlaczego nie pozwolić agentowi na pętlę?
Może to zrobić, i przy pięciu rekordach jest to w porządku. Jednak pętla czterdziestu wywołań narzędzia to czterdzieści szans dla agenta, by stracił liczbę, pominął rekord, gdy kontekst się wydłuży, lub „pomocniczo” przefrazował jeden list. Narzędzie per‑record przenosi pętlę na serwer: jedno wywołanie, jeden szablon, jedno przejście po tablicy i raport, który dokładnie mówi, ile plików zostało zapisanych i które rekordy nie zostały przetworzone. Zadaniem agenta jest wybrać szablon, plik danych i pole nazwy, a następnie odczytać raport.
Co agent sprawdza najpierw?
Dwie rzeczy: jak wyglądają dane i co odczytuje szablon. W naszym teście pięciu klientów w customers.json i jednoczesny list powitalny:
-> 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" ] }
Szablon odwołuje się do jednego rekordu customer; serwer wywnioskuje to sam, więc agent nie musi przekazywać dataSourceName.
Jedno wywołanie, pięć rekordów, jedna niepowodzenie
-> 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. ...
Rekord 4, Wingtip Travel, nie miał daty pierwszej faktury w danych. Pozostałe cztery listy zostały zapisane, każda nazwana po kliencie, a niepowodzenie zwróciło numer rekordu i brakujące pole. Agent zgłasza to jako „cztery listy gotowe; Wingtip Travel nie ma daty pierwszej faktury, czy mam zostawić linię pustą, czy poczekać na datę?”. To jest rozmowa, której oczekujesz, zamiast czterdziestu plików bez wiedzy, który jest niepoprawny.
Jak działa rozgałęzienie
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 ..."
Trzy parametry wykonują pracę. fileNameField nadaje każdemu wyjściu nazwę na podstawie pola rekordu, np. customer.Name lub numer faktury; bez niego pliki otrzymują numer kolejny. recordsPath wskazuje na tablicę, gdy JSON jest obiektem zawierającym jedną, np. "customers" lub "batch.items". Natomiast maxDocuments jest hamulcem.
Co powstrzymuje niekontrolowaną partię?
maxDocuments, domyślnie 100, maksymalnie 1000. Przed zapisaniem czegokolwiek serwer liczy rekordy; jeśli jest ich więcej niż limit, odrzuca żądanie. Ustawiliśmy go na 3 w stosunku do naszych pięciu klientów:
-> 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.
Nic nie zostało zapisane. Dla wysyłki do prawdziwych osób jest to właściwe domyślne zachowanie: zapytanie, które przypadkowo wskazuje cały eksport CRM, zwraca pytanie, a nie dziesięć tysięcy PDF‑ów.
Moje dane to arkusz kalkulacyjny, nie JSON
Generowanie per‑record odczytuje wyłącznie JSON: tablicę obiektów lub obiekt zawierający jedną tablicę. Gdy lista znajduje się w CSV lub arkuszu, agent najpierw konwertuje wiersze na JSON, co robi dobrze, i zapisuje plik w folderze storage. Jeśli potrzebujesz jednego dokumentu, który wymienia każdy wiersz, np. cennik lub rejestr, użyj assemble_document z <<foreach>> w szablonie – odczytuje CSV i arkusze kalkulacyjne bezpośrednio.
Szczere ograniczenia
- Per‑record assembly odczytuje wyłącznie JSON; dane CSV i arkusze wymagają wcześniejszej konwersji.
- Tryb ewaluacji: każdy wygenerowany plik zaczyna się od “Evaluation Only. Created with GroupDocs.Assembly 26.7…”, a szablony e‑mail zachowują tylko treść tekstową. Zanim rozpoczniesz prawdziwą wysyłkę, zarejestruj serwer.
- Brakujące pole powoduje niepowodzenie tego rekordu.
allowMissingMembers: truezapisuje je z pustą linią; zdecyduj, co wolisz. - Daty: zapisz je jako
2026-12-01T00:00:00i formatuj w szablonie, tak jak nasz list używa<<[customer.FirstInvoice]:"d MMMM yyyy">>. W naszym teście ciąg daty przesunięty o dzień na maszynie UTC+2. - Serwer zapisuje pliki; nie wysyła ich. Dostarczenie to osobny krok.
FAQ
Czy mogę wykonać mail merge z Claude bez wgrywania listy klientów?
Tak. Serwer działa lokalnie i odczytuje customers.json z Twojego folderu storage; wygenerowane PDF‑y są tam również zapisywane.
Jak nazywane są pliki wyjściowe?
Według pola rekordu podanego jako fileNameField, w tym przypadku nazwy klientów, np. Contoso Pharma.pdf. Bez tego polecenia pliki otrzymują numer kolejny.
Czy każdy dokument może być e‑mailem zamiast PDF?
Tak: użyj szablonu EML lub MSG, lub przekaż format: "eml". W trybie ewaluacji ciało HTML e‑maila zostaje zastąpione linią ewaluacyjną, więc przetestuj wyjście e‑maila z licencją.
Zagłęb się
- Dokumentacja, kanoniczny przewodnik: Jak wygenerować jeden dokument na rekord (mail merge) przy użyciu agenta AI
- Centrum dokumentacji: GroupDocs.Assembly MCP Server
- Zacznij tutaj: Niech model wypełni dane, a nie pisze dokument
- Powiązane: Czego potrzebuje ten szablon? Zapytaj go.
- Powiązane: Wykres pochodzi z szablonu, liczby z danych
- Powiązane: Twoje repozytorium już ma dane; niech agent stworzy PDF
- Model on‑premise i bezpieczeństwo: 3 architektury przetwarzania dokumentów AI i ta, która trzyma pliki w Twojej sieci
- Pytania: GroupDocs Assembly forum
- Źródło: GroupDocs.Assembly.Mcp on GitHub