# Build an AI agent that edits existing DOCX documents

> Connect a document-editing agent to Vespper DOCX MCP: open a session, read or search, apply targeted edits, save the document, and close the session.

Maintained by Vespper. Updated 2026-10-17.

Canonical page: https://www.vespper.com/guides/build-docx-editing-agent

Topic: [Agent and editor integration](https://www.vespper.com/guides#integration). [Start the learning path](https://www.vespper.com/guides#start-here).

An agent that edits an existing DOCX needs a way to locate the requested passage, change the current document, and return the edited file. Vespper's **DOCX MCP Server** provides tools for that workflow, including `read_document`, `search_document`, and `edit_document`. The agent reads an HTML representation of the document; Vespper applies the edits to the DOCX.

The HTML is the agent's editing interface. Vespper's reconciler maps the requested change back to OOXML for the affected block, then the service computes revision markup and patches the original file. The [architecture explanation](https://www.vespper.com/blog/launching-vespper-docx-mcp) describes the trained reconciler and deterministic revision calculation. This is not a promise that every untouched XML part remains byte-identical; the [recorded contract results](https://www.vespper.com/guides/tracked-changes-api/RESULTS.md) show the exact preservation checks and font-property changes.

Use this approach when the input is a document supplied by a user and the request describes a change in natural language. For a fixed report generated from known data, a document-generation or templating library may be sufficient. The [library selection guide](https://www.vespper.com/guides/docx-libraries-for-agents) explains that distinction.

## What your team stops maintaining

Because the agent edits HTML and Vespper writes the OOXML, your application does not contain a DOCX editing layer. It does not split or merge runs, resolve numbering definitions, generate `w:ins` and `w:del` markup with unique revision IDs, or patch relationships and package parts. Hand-written code has to get each of those right for every document variation it meets, and the [python-docx run-replacement guide](https://www.vespper.com/guides/python-docx-replace-across-runs) shows how much code that takes for one narrow case.

What remains in your codebase is small: the session lifecycle, the tool descriptions you give the model, and your own validation fixtures. The same read, search, and edit tools serve every surface in the next section, so supporting another surface does not mean writing another editing implementation. Validation stays your responsibility, as the [formatting checks](https://www.vespper.com/guides/preserve-docx-formatting) describe.

## Choose where the agent runs

Vespper connects to several surfaces. Pick the one that matches where your users work:

| Surface                                         | How it connects                                                                                                                                                                                                                                                          | Start with                                                                                                                                |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Headless backend or pipeline                    | The hosted MCP endpoint or an SDK, with a document session.                                                                                                                                                                                                              | This guide and the [quickstart](https://docs.vespper.com/quickstart).                                                                     |
| Microsoft Word                                  | An Office.js add-in that calls the hosted service and applies returned revisions in the open document.                                                                                                                                                                   | The [Word add-in guide](https://www.vespper.com/guides/build-ai-word-add-in).                                                                                    |
| An editor inside your product                   | Live editing: your API runs the agent and streams edits into the open document in ONLYOFFICE, EigenPal's docx-editor, or any client that can load a DOCX. Edits apply directly, tracked or plain, or arrive as suggestions the user accepts. Vespper is editor-agnostic. | The [live editing docs](https://docs.vespper.com/live-editing/introduction) and [cookbooks](https://docs.vespper.com/cookbooks/overview). |
| AI assistants such as Claude, ChatGPT and Codex | The local `vespper-mcp` server, which reads and edits `.docx` files in directories you allow.                                                                                                                                                                            | The [AI assistants setup](https://docs.vespper.com/ai-assistants).                                                                        |

The hosted MCP endpoint works on a document uploaded into a session. The local server exists so an assistant can work on files on the user's machine. It runs with `npx`, needs Node.js 22 or newer and a Vespper API key, limits file access to the directories you allow, saves edits back to the original `.docx`, and records them as tracked changes by default. It can also create a blank `.docx` in an allowed directory. Per the docs it communicates with Vespper's cloud service, so it is not an offline tool.

The rest of this guide covers the hosted session workflow. For the local server, follow the [AI assistants setup](https://docs.vespper.com/ai-assistants) for your client.

## What your application supplies

Your application needs the DOCX file, a Vespper API key, an MCP client, and the model configuration for its agent framework. The hosted MCP endpoint is `https://mcp.vespper.com/mcp`, using Streamable HTTP. Authentication belongs in the connection's `Authorization: Bearer ...` header, not in model-generated tool arguments.

Vespper has Python and TypeScript SDKs. The [quickstart](https://docs.vespper.com/quickstart) includes framework integrations and examples for manual MCP wiring. Use its current install commands and SDK signatures when building an application.

## Start with a complete contract-editing example

The [contract redlining example](https://www.vespper.com/guides/tracked-changes-api#run-a-contract-redlining-example) provides an input DOCX, actual API outputs, a complete Python integration, pinned direct dependencies, and a standalone output verifier. Its task is to change a payment term from 30 to 45 days while preserving bold text and another reviewer's pending changes. The recorded tracking-on and tracking-off runs passed the fixture checks with the documented font-property normalization.

After following its setup instructions, run the agent path with a model configured in your environment:

```bash
python redline_contract.py --agent --output service-agreement-agent.docx
```

The integration opens one session, connects the MCP server, runs the agent, retrieves the current bytes before closing the session, and checks the saved file. The essential SDK wiring is:

```python
async with mcp:
    await client.patch_mcp_tools(
        mcp=mcp,
        session_id=session_id,
        author="Contract assistant",
        track_changes=True,
    )
    await Runner.run(agent, instruction, max_turns=8)
document = client.get_session_document(session_id)
```

This is an excerpt, not a standalone program. The [full script](https://www.vespper.com/guides/tracked-changes-api/redline_contract.py) supplies imports, credentials, the MCP connection, agent instructions, file writing, verification, and session cleanup in `finally`. Its default mode makes a fixed sequence of MCP calls without a separate agent-model call. Vespper's own reconciler still runs inside the service. The [published results](https://www.vespper.com/guides/tracked-changes-api#inspect-a-real-api-result) verify this default path; the optional model-driven path has not been live-tested for those results.

Keep the DOCX bytes in application code. SDK patching retains them for download while exposing the editing result to the agent. Do not treat the model's final message as the output artifact.

## Follow the document session lifecycle

1. Open a document session by uploading the DOCX once. The HTTP endpoint is `POST https://mcp.vespper.com/v1/docx/sessions`; the SDK exposes session-opening methods.
2. Connect the MCP client and discover the tool schemas through `tools/list`. Preserve the returned tool descriptions when giving them to the model.
3. Attach the session ID to subsequent tool calls. SDK auto-patching does this for supported clients; manual integrations supply `com.vespper/session-id` in MCP `_meta`.
4. Search for known text or read the necessary pages, then apply an edit against the returned HTML.
5. Retrieve and save the latest DOCX. Keep the input and output separately when the user needs to review the result.
6. Close the session in cleanup code, including when the agent fails or is cancelled.

The server keeps the current document for the session. The client does not need to upload the document again on every tool call. The [session API reference](https://docs.vespper.com/primitives/overview) documents ownership, revision numbers, and cleanup.

## Check whether the workflow fits your application

| Requirement                                  | Vespper integration scope                                                                                                     |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Edit a user-uploaded DOCX in a backend       | Open a hosted session, supply the session ID on calls, and deliver the returned bytes.                                        |
| Let a human review the proposed edit         | Enable tracking and set an author; deliver the DOCX to the review UI your product uses. Vespper is editor-agnostic.           |
| Apply an approved change directly            | Disable tracking for that edit. Existing revisions require separate, explicit handling.                                       |
| Edit global styles                           | These are excluded from the current edit target scope; preserving them during a body edit is a different requirement.         |
| Connect a generic MCP client with only a URL | Tool discovery alone does not handle document upload, session metadata and output delivery. Add the SDK or lifecycle adapter. |

The [current edit reference](https://docs.vespper.com/primitives/edit-document) is the authority for supported targets and metadata. Validate your own document structures before exposing a broader editing promise to customers.

## Diagnose an integration that connects but cannot edit

Tool discovery only verifies part of the workflow. A [developer report about available MCP tools failing to edit and save Word files](https://www.reddit.com/r/mcp/comments/1o1yxys/cant_reliably_edit_word_docx_using_mcp_servers_on/) illustrates why document state and file delivery need separate checks.

| Symptom                                          | Check first                                                     |
| ------------------------------------------------ | --------------------------------------------------------------- |
| Cannot list tools                                | Endpoint, Streamable HTTP transport, and bearer authentication. |
| Tools appear but reads fail                      | Document upload and the session ID in each call's `_meta`.      |
| Reads work but edits fail                        | Current complete anchors, uniqueness, and supported edit scope. |
| Edit succeeds but the user receives the old file | Revision capture, binary decoding, and artifact delivery.       |

Putting a session ID in the agent's prompt does not attach it to a protocol call. A generic MCP client that only accepts a server URL and credentials may need an adapter to upload the document, attach metadata, and capture its output. First prove a single read/edit/save operation using the [quickstart](https://docs.vespper.com/quickstart), then connect that lifecycle to your application.

## Choose the tool from the request

| Request                                       | First operation                              | Reason                                               |
| --------------------------------------------- | -------------------------------------------- | ---------------------------------------------------- |
| “Change the deadline in the delivery section” | Search for the deadline or section text      | Find candidate passages without reading every page.  |
| “Add a summary after the introduction”        | Read the relevant pages                      | Inspect the document structure and insertion point.  |
| “Revise these three separate paragraphs”      | Read or search, then batch independent edits | Each edit needs its own current, unambiguous anchor. |

For example, this is a **tool-call parameters fragment**, assuming your integration already holds a valid session ID:

```json
{
  "name": "search_document",
  "arguments": { "pattern": "(?i)delivery" },
  "_meta": { "com.vespper/session-id": "YOUR_SESSION_ID" }
}
```

Search results contain complete HTML blocks. Copy a current block into the edit's `old` value and write its intended replacement in `new`. Resolve ambiguity before editing; a repeated phrase is not enough to identify which occurrence the user meant.

## Treat the tool result as the source of completion

An agent saying “done” does not prove a document changed. Check the edit result, retain its latest document and revision, and report any failed edits. A batch can succeed only in part; successful edits are already applied, so retry only corrected failures. See the [edit reference](https://docs.vespper.com/primitives/edit-document).

New edits are tracked by default. Configure the author and tracking preference in the integration, and test the output in the viewer your users rely on. Start with a small known edit before testing long documents, tables, repeated passages, and existing revisions.

## Return the latest DOCX bytes

Keep the document binary in application code rather than passing the entire file through the model's conversation. An edit response's `base64` field contains the latest cumulative DOCX; `current_revision` identifies the revision and is not the file itself. With SDK auto-patching, retrieve the retained bytes using `getSessionDocument(sessionId)` or `get_session_document(session_id)`. With manual wiring, retain the latest `base64` value and decode it once. The [edit response reference](https://docs.vespper.com/primitives/edit-document) documents these fields.

Capture the output before closing the session. A partially successful batch can already have changed the document: return that latest state together with any unresolved edits, rather than the uploaded file or the first intermediate result. Keep the original input separately.

For an HTTP download, use a `.docx` filename and `Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document`. Pass bytes through storage and attachment handling; decoding a DOCX as UTF-8 and writing the resulting text back can corrupt it. A [reported binary-routing failure in an agent framework](https://github.com/langchain-ai/deepagents/issues/3657) documents this class of issue without establishing a failure rate for other implementations.

## Validate the delivered document

Test the file users actually download, including the storage and attachment path. Use a fixture with a known target sentence, an unrelated clause, an image, and a pending revision. Keep the input, instruction, output, and observed results together so failures are reproducible.

| Check             | What to verify                                                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Package integrity | The output is a readable ZIP with DOCX parts and opens in a document reader. If you change package internals, also validate XML and relationships.           |
| Requested scope   | The target changed once; the unrelated clause, image, and links remain in their intended locations. File hashes or media counts alone cannot establish this. |
| Review state      | The configured author and tracking mode are respected, and unrelated pending revisions remain pending.                                                       |
| Partial failure   | The returned file includes successful edits and the application reports the failed ones accurately.                                                          |
| Layout            | Tables, lists, images, and page boundaries remain usable in the viewer your users rely on.                                                                   |

Package parsing cannot prove layout fidelity or correct review markup. Include representative customer structures in the [formatting checks](https://www.vespper.com/guides/preserve-docx-formatting), and exercise both tracking-on and tracking-off cases using the [review workflow](https://www.vespper.com/guides/tracked-changes-api).

## Next steps

- [Check formatting and edit scope](https://www.vespper.com/guides/preserve-docx-formatting): Continue the learning path by defining what must survive a targeted edit.
- [Run the contract-editing example](https://www.vespper.com/guides/tracked-changes-api#run-a-contract-redlining-example): Download the Python code and sample DOCX, then inspect the output and verification report.
- [Connect with the API quickstart](https://docs.vespper.com/quickstart): Use the maintained setup instructions for your SDK or manual integration.

## Related guides

- [Find and edit a passage in a large DOCX document](https://www.vespper.com/llms/search-large-documents.md)
- [DOCX tracked changes API: redline a contract with an agent](https://www.vespper.com/llms/tracked-changes-api.md)

