請讓 AI 代理「為 Contoso 撰寫服務協議」,它會以自己的語句、自己的標題,甚至自行算出總額。這不是正確的分工。當在本機執行 GroupDocs.Assembly.Mcp (dnx GroupDocs.Assembly.Mcp --yes) 時,Claude Desktop、Cursor 或 Copilot 會向你的 Word 範本詢問需要哪些欄位,從你的筆記中填入,然後引擎負責渲染合約、表格與算術,模型本身不會觸及版面:

為此訂單使用 contract-template.docx 製作服務協議並儲存為 PDF:Contoso Pharma,Keizersgracht 210 Amsterdam,聯絡人 Dr. Lena Brandt;12 個月的託管服務,價格 4,800 EUR,12 個月的支援服務,價格 1,200 EUR,一次上線工作坊,價格 3,500 EUR;5% 折扣。

逐步說明(含設定與故障排除)請參考文件:如何使用 MCP 透過 AI 代理從範本產生文件

為何不該讓模型撰寫文件?

因為產生的文件會以難以察覺的方式出錯。版面會偏離法律批准的樣式。條款可能被改寫成讀起來順暢卻意義不同的文字。總額可能是透過下一個 token 的預測而非乘法計算得出。而且每次執行的結果略有差異,上一個月的審查對本月的合約毫無參考價值。

範本則顛倒了這種情況。法律部門擁有 contract-template.docx,其中包含標題、簽名區塊以及 <<[customer.Name]>> 標記。模型的工作縮減為它擅長的部分:閱讀電子郵件或筆記,並將其轉換為結構化的值。引擎負責其餘工作,且每次都以相同方式執行。

代理如何知道要填入什麼?

它會向範本詢問。get_template_fields 在不執行引擎的情況下讀取標記,回傳範本使用的名稱、所有讀取的欄位,以及要填寫的 JSON 骨架。以下是伺服器對我們的合約範本回傳的內容:

-> get_template_fields {"template":{"filePath":"contract-template.docx"}}
<- { "tagCount": 17,
     "dataSourceNames": [ "contract", "customer", "items" ],
     "dataSkeleton": {
       "contract": { "Number": "", "Date": "", "Discount": "" },
       "customer": { "Name": "", "Address": "", "Contact": "",
                     "Email": "" },
       "items": [ { "Title": "", "Quantity": 0, "UnitPrice": 0 } ] } }

該骨架即是模型與文件之間的合約。代理從訂單文字中填入資料,並以 dataJson 回傳。

當代理遺漏欄位時會發生什麼?

系統會精確地告知它。在我們的測試中,代理的第一次嘗試遺漏了客戶的電子郵件地址。伺服器拒絕並指出缺口:

-> assemble_document {"template":{...},"dataJson":"{... no Email ...}"}
<- Document assembly failed for 'contract-template.docx': ...
   Can not get the value of member 'Email' on type ''. The template
   reads 'Email', which the data does not have. Check the spelling
   (names are case-sensitive) with get_template_fields and add it to
   the data. ... pass allowMissingMembers=true to output nothing for
   missing members and empty lists.

若模型自行撰寫自由文字,可能會悄悄遺漏該行。此時代理可以向你詢問地址,或與你一起決定該欄位可保留空白。

完整對話流程

user            agent                       Assembly MCP server
 | "Make the contract for this order: ..."                      |
 |-------------->|                                              |
 |               |-- get_template_fields {"template":          |
 |               |     "contract-template.docx"} ------------->|
 |               |<- dataSkeleton: contract, customer, items --|
 |               |   (fills the skeleton from the order text)  |
 |               |-- assemble_document {"dataJson":"{...}",    |
 |               |     "format":"pdf"} ----------------------->|
 |               |<- Saved to: .../contract-template_          |
 |               |   assembled.pdf ----------------------------|
 |<- "Contract ready: 3 items, total 75500 EUR, 5% discount."  |
   layout, table and arithmetic come from the template

加入電子郵件後,第二次呼叫成功:

-> assemble_document {"template":{"filePath":"contract-template.docx"},
     "dataJson":"{...}","format":"pdf"}
<- Assembled 'contract-template.docx' with inline JSON (JSON object)
   as PDF
   Saved to: .../contract-template_assembled.pdf

文件包含一個由表格列中的 <<foreach>> 建立的三列費用表格,金額由範本計算(<<[item.Quantity * item.UnitPrice]>>),總額 75500 EUR 來自 items.Sum(...),以及一行 「適用 5% 折扣。」,此行僅因 <<if>> 標記在資料中偵測到折扣而產生。模型本身並未計算任何這些。

這比託管範本服務更好嗎?

這是一種不同的取捨。託管範本服務會透過 HTTPS 接收你的範本與資料,在雲端渲染,並依文件或點數收費。而此處的範本、資料與輸出皆保留在本機的資料夾中;引擎是以行程內方式執行的 GroupDocs.Assembly,且沒有任何服務在埠口監聽。傳送給模型供應商的僅是你貼上的訂單文字與代理填寫的骨架,而非已渲染的合約。相關架構說明可參考本地 AI 文件處理系列文章。

誠實的限制

  • 評估模式:每份產生的文件都會以 「Evaluation Only. Created with GroupDocs.Assembly 26.7…」 開頭,已儲存的活頁簿會多出一個工作表,電子郵件範本僅保留純文字內容。使用授權檔或計量金鑰即可移除上述三項。
  • 範本語法為 <<[name]>>。{{name}} 佔位符會保留為文字;get_template_fields 會說明此情況。
  • 範本被視為可信輸入:影像與文件標記會載入其表達式返回的任何路徑或 URL。請為伺服器掛載單一資料夾。
  • 日期:請以 2026-11-12T00:00:00 格式撰寫,並在範本中格式化 (<<[contract.Date]:"d MMMM yyyy">>)。僅含日期的 "2026-11-12" 在我們測試的 UTC+2 機器上會顯示為 11 November。
  • 代理即為資料來源。請在渲染前要求它列出已提取的值,並進行審核。

常見問題

AI 代理能在不上傳的情況下填寫我的 Word 範本嗎?
可以。伺服器在本機透過 stdio 執行,從你設定的資料夾讀取範本,輸出則寫在同一目錄下。

範本可以是哪些格式?
Word、Excel、PowerPoint、Markdown、HTML、純文字與電子郵件範本;每種皆可另存為其本身格式或 PDF 等其他格式。get_supported_formats 會列出每個範本支援的格式。

如果範本由他人維護該怎麼辦?
這正是重點。範本的擁有者會變更條款與版面;代理只負責填寫相同的骨架,而 get_template_fields 會在下次詢問時顯示任何新欄位。

深入了解