Learning path · Step 2 of 4

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 VespperUpdated Read as Markdown
On this page

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 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 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 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 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 describe.

Choose where the agent runs

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

SurfaceHow it connectsStart with
Headless backend or pipelineThe hosted MCP endpoint or an SDK, with a document session.This guide and the quickstart.
Microsoft WordAn Office.js add-in that calls the hosted service and applies returned revisions in the open document.The Word add-in guide.
An editor inside your productLive 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 and cookbooks.
AI assistants such as Claude, ChatGPT and CodexThe local vespper-mcp server, which reads and edits .docx files in directories you allow.The AI assistants setup.

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 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 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 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:

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:

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 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 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 documents ownership, revision numbers, and cleanup.

Check whether the workflow fits your application

RequirementVespper integration scope
Edit a user-uploaded DOCX in a backendOpen a hosted session, supply the session ID on calls, and deliver the returned bytes.
Let a human review the proposed editEnable tracking and set an author; deliver the DOCX to the review UI your product uses. Vespper is editor-agnostic.
Apply an approved change directlyDisable tracking for that edit. Existing revisions require separate, explicit handling.
Edit global stylesThese 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 URLTool discovery alone does not handle document upload, session metadata and output delivery. Add the SDK or lifecycle adapter.

The current edit reference 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 illustrates why document state and file delivery need separate checks.

SymptomCheck first
Cannot list toolsEndpoint, Streamable HTTP transport, and bearer authentication.
Tools appear but reads failDocument upload and the session ID in each call's _meta.
Reads work but edits failCurrent complete anchors, uniqueness, and supported edit scope.
Edit succeeds but the user receives the old fileRevision 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, then connect that lifecycle to your application.

Choose the tool from the request

RequestFirst operationReason
“Change the deadline in the delivery section”Search for the deadline or section textFind candidate passages without reading every page.
“Add a summary after the introduction”Read the relevant pagesInspect the document structure and insertion point.
“Revise these three separate paragraphs”Read or search, then batch independent editsEach 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:

{
  "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.

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 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 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.

CheckWhat to verify
Package integrityThe 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 scopeThe target changed once; the unrelated clause, image, and links remain in their intended locations. File hashes or media counts alone cannot establish this.
Review stateThe configured author and tracking mode are respected, and unrelated pending revisions remain pending.
Partial failureThe returned file includes successful edits and the application reports the failed ones accurately.
LayoutTables, 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, and exercise both tracking-on and tracking-off cases using the review workflow.