A Word form with text boxes, a department drop-down and a code-of-conduct check box, and a spreadsheet with thirty new hires: that is a morning of copy and paste, or one prompt. With the GroupDocs.Editor MCP server running locally, Claude, Cursor or Copilot first asks the form which fields it has, then fills one copy per row and saves each under the person’s name. The form’s layout is untouched, and any value that has no matching field is reported instead of silently dropped:

Read new-employee-form.docx, then fill one copy per row of new-hires.csv and name each file after the employee.

The step-by-step version is in the documentation: How to fill Word form fields from data with an AI agent.

Who reads the spreadsheet?

The agent does, and it is worth being plain about it. The Editor server works on the Word form; it does not read your CSV or workbook. The agent reads the rows with its own file tools, or you paste them, and then makes one fill_form_fields call per row with an outputName per person. That division is a feature: the data never needs to be in a format the server understands, and the agent can clean it on the way (split a full name, normalise a date) before it goes into the form.

Ask the form first

Field names in Word forms are rarely what the label on the page says. The label reads “Full name:”, while the field might be called FullName, Text1 or Name_Employee. Guessing is how forms come back half empty. get_form_fields returns the real names, the types and the current values. Captured from GroupDocs.Editor.Mcp 26.10.0 against a synthetic onboarding form (output shortened):

-> get_form_fields {"file":{"filePath":"new-employee-form.docx"}}
<- { "count": 6, "fields": [
     { "name": "FullName",   "type": "Text",     "value": "" },
     { "name": "Email",      "type": "Text",     "value": "" },
     { "name": "StartDate",  "type": "Text",     "value": "" },
     { "name": "Department", "type": "DropDown",
       "value": { "options": [ "Engineering", "Finance", "Sales",
                               "Operations" ], "selected": "Engineering" } },
     { "name": "Agree",      "type": "CheckBox", "value": false },
     { "name": "Newsletter", "type": "CheckBox", "value": false } ] }

The drop-down comes with its options, so the agent can map “finance” in the spreadsheet to the exact entry “Finance” instead of inventing a sixth department.

Then fill one row

-> fill_form_fields {"file":{"filePath":"new-employee-form.docx"},
     "values":{"FullName":"Amara Okafor",
               "Email":"amara.okafor@northwind.example",
               "StartDate":"2026-12-01","Department":"Finance",
               "Agree":"true","Phone":"+31 10 555 0100"}}
<- Updated 5 field(s) in 'new-employee-form.docx': FullName, Email,
   StartDate, Department, Agree.
   Not found: Phone. Call get_form_fields for the exact names.
   Saved to: …/new-employee-form_edited.docx

The spreadsheet had a phone column the form has no field for. The server filled the five fields that exist and named the one that does not. Reading the filled copy back with get_form_fields shows the values in place, "selected": "Finance" and "Agree": true included, and Newsletter still unticked because the row did not say otherwise.

The whole batch

new-hires.csv (agent reads it)          new-employee-form.docx
  Amara Okafor, Finance, ...  ---+
  Tomas Varga, Sales, ...     ---+      get_form_fields (once)
  ...                            |        -> FullName, Email, StartDate,
                                 |           Department, Agree, ...
                                 v
  fill_form_fields {"values":{...row...},
                    "outputName":"form-amara-okafor.docx"}   x one per row
     -> "Updated 5 field(s) ... Not found: Phone"
     -> form-amara-okafor.docx, form-tomas-varga.docx, ...

Three instructions make the batch dependable: call get_form_fields once and map columns to field names before the first fill; give every row its own outputName, because the default <name>_edited.docx would be overwritten on every row; and collect the “Not found” lines into one report at the end rather than stopping on the first.

A prompt that works on the first row

Most batch failures happen on row one and then repeat thirty times. Ask for a dry run first:

Read the fields of new-employee-form.docx and the header of new-hires.csv. Show me which column goes into which field, and which columns have no field. Then fill only the first row and stop.

The agent answers with a small mapping table, Name -> FullName, Dept -> Department, Phone -> (no field), and one filled form you can open. If the department spelling or the date format is wrong, you see it once, fix the instruction, and then ask for the rest. That review step costs one minute and is the difference between thirty correct forms and thirty forms that need checking by hand.

It also settles the questions the spreadsheet cannot answer by itself. Should an empty “Agree” cell mean unticked, or should the row be skipped? Does “2026-12-01” go into the date field as typed, or as “1 December 2026”? The agent will follow whatever you say, but it has to be told.

What else the form tools handle

Text, number and date fields are filled with strings; check boxes take "true" or "false"; drop-downs take one of their options. format saves the filled copy as DOC, RTF or ODT instead of DOCX, and a password-protected form is opened with password and stays protected. The tools read DOCX, DOC, DOCM, DOT, DOTX, RTF and ODT forms.

Honest limits

  • Word forms only. PDF forms (AcroForms) are not in scope for this server.
  • The server does not read the spreadsheet; the agent supplies the values, so check its column mapping on the first row before letting it run through all of them.
  • One call fills one form. A batch of thirty is thirty calls.
  • Evaluation mode adds a banner line at the top of every filled copy, so unlicensed output is a draft, not something to send to new employees.

FAQ

How does the agent know the field names? It asks: get_form_fields returns each field’s name, type and current value, and the options of every drop-down.

What happens to a value the form has no field for? It is skipped and named in the response (“Not found: Phone”), so the agent can report it.

Is my original form changed? No. Each fill writes a new file; the template stays blank for the next row.

Go deeper