هر مخزن داده‌های ساختاریافته‌ای را جمع می‌کند که در نهایت کسی به‌عنوان سند به آن نیاز دارد: تغییرات یک نسخه، مشارکت‌کنندگان سال، فهرست API، فهرست ریسک‌های باز. داده‌ها از پیش به‌صورت JSON هستند؛ گام مفقود یک فایل PDF یا Word قالب‌بندی‌شده است که مشتری، حسابرس یا مدیر واقعاً باز می‌کند. با اجرای GroupDocs.Assembly.Mcp به‌صورت محلی کنار Claude Code (claude mcp add with dnx GroupDocs.Assembly.Mcp --yes)، عامل یک قالب Word که در مخزن نگهداری می‌شود را از یک فایل JSON در مخزن پر می‌کند و PDF را می‌نویسد، بدون اینکه کسی جدول را قالب‌بندی کند:

PDF یادداشت‌های انتشار نسخه 4.2.0 را از data/release-4.2.0.json با استفاده از templates/release-notes.docx تولید کنید، و یک گواهی مشارکت برای هر مشارکت‌کننده در data/contributors-2026.json.

نسخه گام‌به‌گام با پیکربندی و عیب‌یابی در مستندات موجود است: چگونه یک گزارش PDF یا Word را از داده‌های JSON در یک مخزن با Claude Code تولید کنیم.

چرا نباید عامل کدنویسی سند را بنویسد؟

عوامل کدنویسی در تولید داده بسیار خوب هستند اما در تولید اسناد نسبتاً ضعیف. اگر از یکی بخواهید «یادداشت‌های انتشار به‌صورت PDF» را تولید کند، یک فایل Markdown می‌نویسد، سپس اسکریپتی برای تبدیل آن، سپس فونت‌های اسکریپت را اشکال‌زدایی می‌کند. در نسخه بعدی، دوباره با کمی تفاوت این کار را انجام می‌دهد. خروجی شبیه پیش‌فرض کتابخانه تبدیل می‌شود، نه شبیه اسنادی که شرکت شما می‌فرستد.

یک قالب ظاهر را ثابت می‌کند و آن را تحت کنترل نسخه قرار می‌دهد. templates/release-notes.docx یک فایل Word معمولی با لوگو، سبک‌های عنوان و یک جدول است، به‌همراه چند برچسب <<…>>. هر کسی که مالک طرح‌بندی است آن را در Word ویرایش می‌کند؛ عامل هرگز به آن دست نمی‌زند. JSON توسط ابزارهای انتشار شما تولید می‌شود، یا توسط عامل از git log استخراج می‌شود، و این همان بخشی است که یک عامل کدنویسی به‌خوبی انجام می‌دهد.

همچنین کار را قابل بازبینی می‌کند. یک pull request که data/release-4.2.0.json را تغییر می‌دهد دقیقاً نشان می‌دهد کدام تغییرات در یادداشت‌های انتشار ظاهر می‌شوند، خط به خط، در یک diff که مرورگر می‌تواند در یک دقیقه بخواند. یک pull request که یک PDF تولید شده را تغییر می‌دهد هیچ چیزی نشان نمی‌دهد. نگه داشتن داده و طرح‌بندی به‌عنوان فایل‌های جداگانه و نسخه‌بندی‌شده، و رفتار با سند به‌عنوان چیزی که از آن‌ها رندر می‌کنید، همان ایده‌ای است که کد منبع و خروجی ساخت را جدا نگه می‌دارد و برای اسناد به دلایل مشابه صادق است.

ساختار مخزن

repo/
  data/
    release-4.2.0.json       {"release":{...}, "changes":[...4 items]}
    contributors-2026.json   {"contributors":[...3 items]}
  templates/
    release-notes.docx       <<[release.Version]>>, <<foreach [c in
                             changes]>> table row, counts
    certificate.docx         <<[contributor.Name]>> ...
  out/                       GROUPDOCS_MCP_OUTPUT_PATH, in .gitignore
        |
        |  Claude Code -> GroupDocs.Assembly MCP server (local, stdio)
        v
  release-notes-4.2.0.pdf    pnair.pdf  tvarga.pdf  mrossi.pdf

فراخوانی‌ها

ابتدا عامل بررسی می‌کند قالب چه چیزی انتظار دارد، تا بتواند به شما بگوید آیا JSON چیزی را کم دارد یا نه:

-> get_template_fields {"template":{"filePath":
     "repo/templates/release-notes.docx"}}
<- { "dataSourceNames": [ "release", "changes" ],
     "fields": [ "release.Product", "release.Version", "release.Date",
                 "changes[].Type", "changes[].Title",
                 "changes[].PullRequest", "changes[].Author" ] }

سپس یک فراخوانی آن را رندر می‌کند:

-> assemble_document {"template":{"filePath":
     "repo/templates/release-notes.docx"},
     "data":{"filePath":"repo/data/release-4.2.0.json"},
     "format":"pdf","outputName":"release-notes-4.2.0.pdf"}
<- Assembled 'release-notes.docx' with 'release-4.2.0.json' (JSON
   object) as PDF
   Saved to: .../release-notes-4.2.0.pdf

سطر جدول قالب برای هر تغییر یک بار تکرار می‌شود و خط آخر آن تعداد تغییرات و نویسندگان متمایز را با changes.Count() و changes.Select(c => c.Author).Distinct().Count() می‌شمارد. این اعداد در زمان رندر از داده‌ها می‌آیند، نه از عامل.

گواهی‌ها به‌صورت fan‑out هستند: یک PDF برای هر عنصر از آرایه contributors، که با شناسه مشارکت‌کننده نام‌گذاری می‌شود:

-> assemble_per_record {"template":{"filePath":
     "repo/templates/certificate.docx"},
     "data":{"filePath":"repo/data/contributors-2026.json"},
     "recordsPath":"contributors","fileNameField":"Handle",
     "format":"pdf"}
<- Assembled 3 of 3 document(s) from 'certificate.docx' with
   'contributors-2026.json', one per record (each record as
   'contributor'), as PDF.
   Saved to:
   .../pnair.pdf
   .../tvarga.pdf
   .../mrossi.pdf

recordsPath به سرور می‌گوید آرایه کجا قرار دارد وقتی فایل JSON یک شیء است، که شکل معمول فایل‌های داده واقعی است.

این را به عادت تبدیل کنید، نه یک درخواست

عوامل دستورالعمل‌های پروژه را درباره زمان استفاده از ابزار دنبال می‌کنند. چند خط در CLAUDE.md یا AGENTS.md این را به یک قرارداد تبدیل می‌کند:

Documents for people (release notes, reports, certificates) are generated
with the groupdocs-assembly MCP server from templates/*.docx and data/*.json.
Call get_template_fields first; never edit a template. Generated files land
in out/, which is in .gitignore. Dates in JSON as yyyy-MM-ddTHH:mm:ss.

خروجی‌ها را خارج از git نگه دارید. به‌طور پیش‌فرض سرور در کنار پوشه ذخیره‌سازی خود می‌نویسد؛ GROUPDOCS_MCP_OUTPUT_PATH را در ثبت‌نام سرور به پوشه out/ مخزن تنظیم کنید و آن پوشه را به .gitignore اضافه کنید. JSON و قالب منبع هستند؛ PDF یک artefact ساخت است که در چند ثانیه بازتولید می‌شود، و کامیت کردن آن فقط diffهایی تولید می‌کند که هیچ‌کس نمی‌تواند بازبینی کند.

محدودیت‌های صادقانه

  • حالت ارزیابی: هر PDF با “Evaluation Only. Created with GroupDocs.Assembly 26.7…” شروع می‌شود. برای آزمایش مناسب است؛ قبل از اینکه چیزی از تیم خارج شود، سرور را لایسنس کنید.
  • قالب‌ها ورودی‌های مورد اعتماد هستند. برچسب‌های تصویر و سند مسیرها و URLهایی را که عباراتشان برمی‌گردانند بارگذاری می‌کنند، بنابراین یک قالب از یک pull request را مانند کد در نظر بگیرید و به سرور یک پوشه ذخیره‌سازی بدهید.
  • تاریخ‌ها: آن‌ها را به صورت 2026-11-03T00:00:00 بنویسید و در قالب فرمت کنید (<<[release.Date]:"d MMMM yyyy">>). یک رشته فقط تاریخ در تست ما به‌دلیل ماشین UTC+2 یک روز جابجا شد؛ تصویر Docker در UTC اجرا می‌شود.
  • تولید به‌ازای هر رکورد فقط JSON را می‌خواند، و maxDocuments (به‌صورت پیش‌فرض 100) یک آرایه بزرگ غیرمنتظره را پیش از نوشتن هر چیزی متوقف می‌کند.
  • get_template_fields ایستا است: مقادیری که داخل پروژکشن‌های Select یا GroupBy محاسبه می‌شوند دنبال نمی‌شوند.

سؤالات متداول

آیا Claude Code می‌تواند یک PDF از JSON در مخزن من بدون سرویس ابری تولید کند؟
بله. سرور MCP به‌صورت محلی به‌عنوان یک فرآیند فرزند Claude Code اجرا می‌شود و قالب و JSON را از پوشه‌ای که به آن اشاره می‌کنید می‌خواند.

آیا این می‌تواند در CI اجرا شود؟
سرور یک سرور MCP است، بنابراین به یک کلاینت MCP نیاز دارد: Claude Code در حالت headless، یا هر رانر عاملی. تصویر Docker (ghcr.io/groupdocs-assembly/assembly-net-mcp) شکل مناسب برای یک pipeline است.

Word یا PDF؟
هر دو. اگر format را حذف کنید خروجی یک DOCX مشابه قالب است؛ "format":"pdf" یک PDF می‌دهد. get_supported_formats تمام هدف‌ها را برای هر قالب فهرست می‌کند.

عمیق‌تر بروید