כל מאגר מצטבר נתונים מובנים שמישהו בסופו של דבר צריך כמסמך: השינויים במוצר, התורמים של השנה, אינבנטורי API, רשימת סיכונים פתוחים. הנתונים כבר ב‑JSON; הצעד החסר הוא קובץ PDF או Word מעוצב שלקוח, מבקר או מנהל יפתח בפועל. עם GroupDocs.Assembly.Mcp הפועל מקומית לצד Claude Code (claude mcp add עם 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, וזה החלק שבו סוכן קידוד מצטיין.

זה גם מאפשר ביקורת על העבודה. בקשת משיכה שמשנה את data/release-4.2.0.json מציגה בדיוק אילו שינויים יופיעו בתזכירי השחרור, שורה אחרי שורה, בהבדל שהמבקר יכול לקרוא בדקה. בקשת משיכה שמשנה 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(). המספרים הללו נובעים מהנתונים בזמן הרינדור, ולא מהסוכן.

התעודות הן פאנ‑אאוט: 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 הוא תוצר בנייה, מתחדש בשניות, והוספתו למאגר מייצרת רק הבדלים שאין למישהו אפשרות לסקור.

מגבלות כנות

  • מצב הערכה: כל PDF מתחיל ב‑"Evaluation Only. Created with GroupDocs.Assembly 26.7…".
  • תבניות הן קלט מהימן. תגיות תמונה ומסמך טוענות את הנתיבים וה‑URL שהביטויים שלהם מחזירים, ולכן יש להתייחס לתבנית שמגיעה מבקשת משיכה כמו קוד, ולספק לשרת תיקיית אחסון אחת.
  • תאריכים: כתבו אותם כ‑2026-11-03T00:00:00 ועצבו אותם בתבנית (<<[release.Date]:"d MMMM yyyy">>). מחרוזת תאריך בלבד הוזזה ביום אחד במכונה עם UTC+2 בבדיקה שלנו; תמונת Docker פועלת ב‑UTC.
  • יצירת per‑record קוראת רק JSON, ו‑maxDocuments (ברירת מחדל 100) עוצרת מערך גדול באופן בלתי צפוי לפני שנכתב משהו.
  • get_template_fields הוא סטטי: ערכים המחושבים בתוך פרויקציות Select או GroupBy אינם נעקבים.

שאלות נפוצות

האם Claude Code יכול ליצור PDF מ‑JSON במאגר שלי ללא שירות ענן?
כן. שרת MCP פועל מקומית כתהליך בן של Claude Code וקורא את התבנית ואת ה‑JSON מהתיקייה שאתה מצביע עליה.

האם זה יכול לרוץ ב‑CI?
השרת הוא שרת MCP, ולכן הוא זקוק ל‑client של MCP: Claude Code במצב ללא ממשק, או כל מריץ סוכנים. תמונת Docker (ghcr.io/groupdocs-assembly/assembly-net-mcp) היא הצורה הנוחה לצינור CI.

Word או PDF?
כל אחד. אם תוותר על format הפלט יהיה DOCX כמו התבנית; "format":"pdf" נותן PDF. get_supported_formats מציג את כל היעדים לכל תבנית.

צללו עמוק יותר