docx-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@docx-mcpextract fragments from contract.docx"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
docx-mcp
Legal document redlining engine. Takes AI-generated changes (structured JSON)
and applies them as professional tracked changes with comments inside .docx
files. The output is indistinguishable from what a lawyer would produce in
Microsoft Word -- proper w:ins/w:del markup, comment annotations with
justification text, and preserved formatting.
Installation
Requires Python 3.14+.
uv syncRelated MCP server: word-agent-mcp
Quick start
Python API
from docx_mcp import (
ParagraphChange, ParagraphChangeType,
TableChange, TableChangeType,
RedlineConfig, apply_redlines,
)
changes = [
# Modify a body paragraph
ParagraphChange(
kind="paragraph",
fragment_id="3", # ← str (was int in v0.1.0)
change_type=ParagraphChangeType.MODIFY,
new_text="The Company **shall** provide written notice.",
justification="Strengthened obligation language.",
),
# Delete a paragraph
ParagraphChange(
kind="paragraph",
fragment_id="5",
change_type=ParagraphChangeType.DELETE,
justification="Removed redundant clause.",
),
# Append a new paragraph
ParagraphChange(
kind="paragraph",
fragment_id="7",
change_type=ParagraphChangeType.APPEND_AFTER,
new_text="The foregoing shall survive termination.",
justification="Added survival provision.",
),
# Modify a header paragraph
ParagraphChange(
kind="paragraph",
fragment_id="header_1.1",
change_type=ParagraphChangeType.MODIFY,
new_text="CONFIDENTIAL",
justification="Updated header text.",
),
# Modify a table cell
TableChange(
kind="table",
table_id=2,
row=1,
col=1,
change_type=TableChangeType.MODIFY_CELL,
new_text="Updated **cell** content",
justification="Corrected table entry.",
),
# Clear a table cell
TableChange(
kind="table",
table_id=2,
row=3,
col=2,
change_type=TableChangeType.CLEAR_CELL,
justification="Removed obsolete data.",
),
]
doc = apply_redlines("contract.docx", changes)
doc.save("contract_redlined.docx")CLI
# Extract fragment text from a document
docx-mcp convert input.docx
docx-mcp convert input.docx --format json
# Apply changes
docx-mcp apply input.docx changes.json -o output.docx
# Validate a redlined document
docx-mcp validate output.docx
# Audit a document for structural issues
docx-mcp audit input.docx
docx-mcp audit input.docx --format jsonNote: The CLI
convertcommand extracts body content only (no headers, footers, or tables). For full-document extraction, use the MCPextract_fragmentstool or the Pythonfull_to_fragments()function.
MCP server
The library includes an MCP server so that LLM clients (Claude Desktop, Cursor,
etc.) can redline .docx files directly.
# Start the server (stdio transport)
docx-mcp-serverConfigure in Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"docx-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/docx-mcp", "docx-mcp-server"]
}
}
}Configure in Cursor (.cursor/mcp.json):
{
"mcpServers": {
"docx-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/docx-mcp", "docx-mcp-server"]
}
}
}Tools
Tool | Description |
| Read a |
| Apply tracked changes from an inline list and save |
| Apply tracked changes from a JSON file on disk |
| Run structural validation checks |
| Compare two |
| Audit a |
Resource
URI | Description |
| Browse paragraph fragments (URL-encode the path) |
Example workflow
An LLM client would typically:
Call
extract_fragmentsto read the document and get fragment IDs.Reason about the content and construct a list of changes.
Call
apply_changeswith the change list to produce a redlined document.Optionally call
diff_fragmentsto compare original vs. redlined output.
Concepts
Fragments
Documents are decomposed into fragments: paragraphs, tables, headers, and footers, all indexed in document order. Each fragment has a string ID.
Fragment IDs:
Pattern | Meaning | Example |
| Body paragraphs / tables |
|
| Header part P, paragraph I |
|
| Footer part P, paragraph I |
|
Tables and body paragraphs share the same ID space (they interleave in document
order). Fragment "3" might be a table and fragment "4" a paragraph.
Use extract_fragments (MCP) or full_to_fragments() (Python) to see the
fragment map for any document:
<f=1>Introduction paragraph.</f=1>
<f=2>**Definitions.** The following terms shall apply.</f=2>
<table=3 rows=2 cols=3>
<cell=3.1.1 span="2">Merged Header</cell=3.1.1>
<cell=3.1.3>Header C</cell=3.1.3>
<cell=3.2.1>Data 1</cell=3.2.1>
<cell=3.2.2>Data 2</cell=3.2.2>
<cell=3.2.3>Data 3</cell=3.2.3>
</table=3>
<f=4>Closing paragraph. See [Section 2](https://example.com).</f=4>
<f=header_1.1>Confidential</f=header_1.1>
<f=footer_1.1>Page 1 of 10</f=footer_1.1>Tables
Simple tables
Simple (rectangular) tables are extracted as <table=N> blocks. Each cell has
a cell_id in "table_id.row.col" format (e.g., "3.1.2").
Merged-cell tables
Tables with horizontally or vertically merged cells (gridSpan / vMerge) are
now supported. Merge spans are shown as attributes:
span="2"— cell spans 2 columns (horizontal merge)vspan="3"— cell spans 3 rows (vertical merge)
Spanned-over cells (positions covered by a merge) are omitted from output.
For example, if cell=3.1.1 has span="2", then cell=3.1.2 does not appear.
When targeting merged cells with changes, always target the originating cell
(the one with the span/vspan attribute). Targeting a spanned-over position
raises a ValueError.
Skipped tables
Tables that cannot be processed (nested tables, malformed merges, tables inside headers/footers) appear as:
<table=5 skipped reason="table 5, cell 2.3 contains nested table"/>Headers and footers
Header and footer paragraphs are extracted with prefixed fragment IDs:
header_1.1, footer_2.1, etc. The first number is the 1-based part index
(usually 1 for the default header/footer), the second is the 1-based
paragraph index within that part.
Header/footer paragraphs can be modified, deleted, and appended to just like body paragraphs. Tables inside headers/footers are not editable and are reported as skipped elements.
Limitation: Comments on header/footer changes are not attached to the output (Word and LibreOffice do not support comment ranges in those parts). They trigger a
UserWarningand are dropped.
Hyperlinks
Hyperlinks are extracted as [link text](url) inline within paragraph text.
Formatting inside links is preserved: [**bold link**](url).
When modifying an existing paragraph, [text] without (url) preserves
the original hyperlink URL. [text](new_url) creates a new link.
When appending new text, [text](url) creates a hyperlink. [text] without
(url) produces plain text — always specify (url) on append if you want a
hyperlink.
Tracked changes policy
Documents with pre-existing tracked changes (<w:ins>, <w:del>,
<w:moveFrom>, <w:moveTo>) are hard-rejected in both extract_fragments
and apply_redlines. Accept or reject all changes in Word before processing.
collapse_empty mode
Optional mode that suppresses empty paragraphs from extraction and redlining. Produces cleaner output for LLM consumption. When enabled, it must be used consistently across extraction and redlining — mismatched values cause fragment ID misalignment.
Change types
Paragraph changes
Type | Description | Requires |
| Word-level diff applied as tracked changes | Yes |
| Entire paragraph marked as deleted | No |
| New paragraph inserted after the referenced fragment | Yes |
Table cell changes
Type | Description | Requires |
| Modify cell content (single or multi-paragraph) | Yes |
| Delete all content in a cell (preserves structure) | No |
Cell modification uses positional alignment: if the cell has multiple
paragraphs, the new text is split on newlines (\n) and each line is applied
to the corresponding paragraph in order. Cell content is marked with tracked
changes and comments just like paragraph modifications.
Blank line management
When appending new paragraphs, you can control surrounding blank lines:
Change(
fragment_id=10,
change_type=ChangeType.APPEND_AFTER,
new_text="New clause text here.",
justification="Added new provision.",
blank_lines_before=1, # Insert 1 blank line before the new paragraph
blank_lines_after=1, # Insert 1 blank line after the new paragraph
)When deleting paragraphs, you can remove trailing blank lines automatically:
Change(
fragment_id=15,
change_type=ChangeType.DELETE,
justification="Removed obsolete clause.",
delete_next_blanks=1, # Also delete the next blank paragraph
)All blank lines are marked as tracked insertions/deletions and will appear in the redlined document.
Pseudo-Markdown
Text content uses a simplified Markdown-like format for inline formatting:
**bold**_italic___underline__
Unicode characters (smart quotes, em dashes, section symbols, non-breaking spaces) are preserved as-is.
Font inheritance: When appending new paragraphs, the font family, size, and color are automatically copied from the reference paragraph's first text-bearing run. Bold, italic, and underline formatting from the pseudo-Markdown is layered on top of the inherited base formatting.
Changes JSON
The CLI accepts a JSON file containing either a bare array or a
{"changes": [...]} wrapper.
Paragraph changes example
[
{
"fragment_id": "1",
"change_type": "modify",
"new_text": "The Seller agrees to deliver within **sixty** days.",
"justification": "Extended delivery window."
},
{
"fragment_id": "3",
"change_type": "delete",
"justification": "Removed governing law clause.",
"delete_next_blanks": 1
},
{
"fragment_id": "5",
"change_type": "append_after",
"new_text": "This Agreement shall be governed by Delaware law.",
"justification": "Added Delaware governing law.",
"blank_lines_before": 1,
"blank_lines_after": 0
},
{
"fragment_id": "header_1.1",
"change_type": "modify",
"new_text": "CONFIDENTIAL",
"justification": "Updated header marking."
}
]Table cell changes example
[
{
"cell_id": "2.1.1",
"change_type": "modify_cell",
"new_text": "Updated **cell** content",
"justification": "Corrected cell value."
},
{
"cell_id": "2.3.2",
"change_type": "clear_cell",
"justification": "Cleared obsolete data."
}
]Cell IDs use the format "table_id.row.col" where rows and columns are 1-based.
Validation
The validate_document() function (and docx-mcp validate CLI) checks:
Annotation ID isolation -- tracked-change and comment IDs don't collide across groups
Comment integrity -- every
<w:comment>has matching range markers in the document body, and vice versaTracked-change attributes -- every
<w:ins>and<w:del>has requiredw:id,w:author, andw:datePackage consistency -- content-type and relationship entries exist for
comments.xml
from docx_mcp import validate_document
result = validate_document(doc)
if not result.ok:
for error in result.errors:
print(error)Architecture
The library manipulates OOXML directly via lxml (not python-docx) because
python-docx has no tracked-change support. Key design decisions:
Word-level diffing via
diff-match-patchwith a word-to-char mapping for high-quality diffsConservative mutation -- only changed paragraphs are touched; everything else passes through byte-identical
Globally unique annotation IDs via a monotonic
IdManagerseeded from the document's existing max IDpython-docxis used only for test fixture generation, not in the library itself
Module map
src/docx_mcp/
__init__.py Public API
cli.py CLI entry point (apply, convert, validate)
models.py Pydantic data models (Change, ChangeType, RedlineConfig, ...)
document.py DocxDocument: ZIP parsing, XML tree access, serialization
converter.py Paragraph & table XML -> pseudo-Markdown conversion
table_utils.py Table inspection utilities (cell access, simplicity checks)
tokenizer.py Word-level tokenization
differ.py Word-level diff engine (diff-match-patch wrapper)
run_ops.py Diff-to-XML-run mapping, run splitting, element building
id_manager.py Monotonic annotation ID allocator
comments.py Comment creation and range marker insertion
redliner.py Main orchestrator: apply_redlines()
table_redliner.py Table cell change application
audit.py Document structural audit (headers, images, tables, etc.)
validator.py Structural validation checks
server.py MCP server (FastMCP 3.x, stdio transport)
handlers/
modify.py Word-level tracked changes on existing paragraphs
delete.py Full paragraph deletion markup
append.py New paragraph insertion markupDevelopment
# Run tests
uv run pytest tests/ -v
# Lint
uvx ruff check src/ tests/
# Auto-fix lint issues
uvx ruff check src/ tests/ --fix
# Type check
uvx ty check src/ tests/431 tests covering all modules, handlers, table operations, headers/footers, hyperlinks, tracked-change rejection, merged-cell tables, section breaks, CLI, validation, and MCP server.
License
MIT
Available Tools
6 toolsapply_changesAIdempotent
Apply tracked changes to a .docx file and save a new redlined document.
Produces Word-compatible tracked changes (``w:ins`` / ``w:del``) with comments.
Always call ``extract_fragments`` first to get fragment IDs.
Paragraph changes (use ``fragment_id``):
- ``modify``: Word-level diff. ``new_text`` required.
- ``delete``: Marks paragraph deleted. Omit ``new_text``.
- ``append_after``: Insert after target. ``new_text`` required.
Table changes (use ``cell_id`` like ``"2.1.3"``):
- ``modify_cell``: Replace cell text. ``new_text`` required. Use ``
for multi-paragraph cells. -clear_cell: Delete cell content. Omit new_text``.
Rules:
- ``delete_next_blanks`` only with ``delete``.
- ``blank_lines_before`` / ``blank_lines_after`` only with ``append_after``.
- Header/footer changes work but comments are silently dropped.
- Documents with pre-existing tracked changes are hard-rejected.
``new_text`` uses pseudo-Markdown: ``**bold**``, ``_italic_``, ``__underline__``.
Example::
changes = [
{
"fragment_id": 1,
"change_type": "modify",
"new_text": "**Updated title**",
"justification": "Fixed typo"
},
{
"cell_id": "2.1.1",
"change_type": "modify_cell",
"new_text": "New header",
"justification": "Clarified"
}
]
Args:
document_path: Absolute path to the input .docx file.
changes: List of change objects (paragraph or table cell changes).
output_path: Where to save the redlined document. Defaults to
``<stem>_redlined.docx`` beside the input file.
author: Author name for tracked changes and comments. Defaults to
"AI Review".
Returns:
Summary string with change counts, output path, and validation result.
| Name | Required | Description | Default |
|---|---|---|---|
| author | No | AI Review | |
| changes | Yes | ||
| output_path | No | ||
| document_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations by disclosing specific behaviors: it produces w:ins/w:del tagged changes, hard-rejects documents with pre-existing tracked changes, silently drops comments in headers/footers, and explains pseudo-Markdown formatting. These are non-obvious traits not captured by readOnlyHint, idempotentHint, or destructiveHint, adding significant value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with sections, examples, and a clear progression from summary to details. It is appropriately sized for the tool's complexity, though it includes some repetition of information already present in the schema (e.g., pseudo-Markdown rules). The front-loaded summary sentence ensures immediate clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers prerequisites, change types, parameter constraints, edge cases (headers/footers, pre-existing changes), output behavior, and provides multiple examples. It even explains the return value. Despite the tool's complexity and nested schema, the description is sufficiently complete for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for top-level parameters, so the description must compensate—and it does thoroughly. It defines document_path as an absolute path, output_path's default behavior, author's default, and the structure of changes list. It also explains nested change types, required fields, and validation rules, effectively documenting all parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Apply tracked changes to a .docx file and save a new redlined document.' It clearly distinguishes the tool from siblings like apply_changes_from_file by focusing on in-memory change objects and mentioning the redlining output. The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs 'Always call extract_fragments first to get fragment IDs,' which is a clear prerequisite and differentiates this tool from alternatives. It also provides detailed rules for when to use each change_type and parameter. However, it does not explicitly contrast with apply_changes_from_file, so the exclusion is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
apply_changes_from_fileAIdempotent
Same as apply_changes but reads the change list from a JSON file.
Useful for large change sets that would exceed token limits in a direct tool call, or for reusing a change set across multiple runs.
The JSON file must contain either a bare array of change objects, or an
object with a "changes" key::
[
{"fragment_id": 1, "change_type": "modify", "new_text": "..."},
{"cell_id": "2.1.1", "change_type": "modify_cell", "new_text": "..."}
]See apply_changes for change object schema and rules.
| Name | Required | Description | Default |
|---|---|---|---|
| author | No | Author name for tracked changes and comments. Defaults to "AI Review". | AI Review |
| output_path | No | Where to save the redlined document. Defaults to ``<stem>_redlined.docx`` beside the input file. | |
| changes_file | Yes | Absolute path to the JSON file containing changes. | |
| document_path | Yes | Absolute path to the input .docx file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds valuable context beyond the annotations by detailing the required JSON file format (bare array or object with 'changes' key) and providing an example. It also references apply_changes for rules. Annotations already indicate idempotency and non-destructiveness, so the description complements rather than repeats them. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficient and well-organized: a lead reference to the sibling tool, explicit use cases, and a compact example of the file format. Every sentence earns its place without redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the schema covers all parameters and the description provides usage scenarios, file format requirements, and a pointer to apply_changes for the change-object schema, the tool is fully contextualized. The presence of an output schema further reduces the need for the description to explain return values. This is a complete package for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides descriptions for all four parameters (100% coverage), so the description doesn't need to explain them. It adds minimal value for parameters beyond the changes_file example, which illustrates content but not the parameter meaning. The baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is 'Same as apply_changes but reads the change list from a JSON file,' immediately distinguishing it from the sibling apply_changes. It specifies the action (applying changes) and the resource (document with changes from a file), leaving no ambiguity about its purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly identifies when to use this tool: 'for large change sets that would exceed token limits in a direct tool call, or for reusing a change set across multiple runs.' It also directs users to apply_changes for schema and rules, implicitly providing the alternative context. This is clear usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
audit_document_toolARead-onlyIdempotent
Audit a .docx file for structural issues and skipped content.
Reports headers, footers, images, tables, section breaks, tracked changes, comments, and unsupported elements (footnotes, endnotes, text boxes).
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | Output format -- ``"text"`` (default) or ``"json"``. | text |
| document_path | Yes | Absolute path to the .docx file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds useful context by detailing what the audit reports on (headers, footers, images, tables, tracked changes, comments, unsupported elements), reinforcing its non-mutating nature without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences with no filler. It front-loads the verb and object, then immediately lists the specific report categories. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity and the presence of a full input schema and output schema, the description fully covers what the tool does and what it reports. The list of auditable elements is sufficiently specific, and the output schema handles return-value documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers both parameters with full descriptions: document_path requires an absolute path and format enumerates text/json with a default. The description does not add parameter-level detail beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Audit') with a clear resource ('.docx file') and scope ('structural issues and skipped content'). It lists concrete report categories, which clearly distinguishes it from sibling tools like apply_changes and validate_document_tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use the tool: to audit a .docx file for structural issues and skipped content. It does not explicitly mention alternatives or exclusions, but the context is clear enough for an agent to select it over write-oriented or fragment-manipulation tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
diff_fragmentsARead-onlyIdempotent
Compare two .docx files and show paragraph and table-level text differences.
Extracts the pseudo-Markdown text from each paragraph and table cell in both documents, then produces a word-level diff for each fragment position. This is useful for understanding what changed between two versions of a document.
Use this tool:
To compare an original document with its redlined version (see what changes were applied)
To verify that
apply_changesproduced the expected modificationsTo understand differences between two versions of a document
Important Limitations
Fragments are matched by position (fragment 1 vs fragment 1, fragment 2 vs fragment 2, etc.). This tool does not detect fragment reordering or track moved sections. If the documents have very different structures (different fragment counts, major reordering), the output will show extensive changes.
Best used for comparing documents with the same basic structure where you made local edits (word changes, clause deletions, appended sections, table cell modifications).
Output Format
Each fragment is reported with its change status.
Paragraphs::
Fragment 1: unchanged
Fragment 2: modified
- shall deliver
+ must deliver immediately
Fragment 3: unchanged
Fragment 5: deleted (only in original)
- This clause is removed.
Fragment 10: added (only in modified)
+ This is a new clause.Tables::
Table 56: modified
Cell 56.2.2: modified
- Gwendolyn Mahon, M.Sc., Ph.D
+ John H. Smith, Ph.D.
Table 57: unchanged
Table 58: dimensions changed (3x2 → 4x2)Lines starting with - show deleted text, + shows inserted text.
Unchanged fragments are listed but their text is omitted for brevity.
For tables, each modified cell is shown with its cell ID (table_id.row.col) followed by the word-level diff of the cell content.
Difference from extract_fragments
extract_fragmentsshows the plain text of a single document (paragraphs, headers, footers, tables). Pre-existing tracked changes cause a hard rejection.diff_fragmentscompares two separate documents and computes the differences between their plain text (ignoring any tracked changes)
| Name | Required | Description | Default |
|---|---|---|---|
| modified_path | Yes | Absolute path to the modified .docx file. | |
| original_path | Yes | Absolute path to the original .docx file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only/idempotent/non-destructive, so the bar is lower; the description adds meaningful behavior: position-based matching, no reordering detection, ignoring tracked changes, and the output style. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although longer than typical descriptions, the structure is organized into purpose, usage, limitations, output format, and sibling comparison, with examples. Each section adds non-redundant operational detail, so it earns its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity and the presence of an output schema, the description is sufficient: it covers core behavior, matching strategy, important exclusions, and interaction with tracked changes. No critical operational gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has full 100% coverage with clear descriptions of the two absolute paths, so the baseline is 3. The description reinforces which file is original vs modified in the usage bullets but does not add parameter-specific semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Compare'), names the resource (two .docx files), and states the output granularity (paragraph/table-level text differences). It clearly distinguishes itself from sibling extract_fragments by framing this as a comparison tool rather than extraction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Use this tool' bullet list explicitly enumerates three concrete use cases, and the 'Important Limitations' section states when NOT to use it (different structures, reordering). It also contrasts with extract_fragments, providing an alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
extract_fragmentsARead-onlyIdempotent
Extract text from a .docx file as tagged fragments.
Call this first to get fragment IDs, then use those IDs in ``apply_changes``.
Output format::
<f=1>**Title**</f=1>
<f=2>Body paragraph.</f=2>
<table=3 rows=2 cols=3>
<cell=3.1.1>Header</cell=3.1.1>
<cell=3.1.2 span="2">Merged cell</cell=3.1.2>
</table=3>
Fragment IDs:
- Body: ``"1"``, ``"2"``, ...
- Headers: ``"header_1.1"``, ``"header_1.2"``, ...
- Footers: ``"footer_1.1"``, ``"footer_2.1"``, ...
- Table cells: ``"table_id.row.col"`` (e.g., ``"3.1.2"``)
Formatting: ``**bold**``, ``_italic_``, ``__underline__``. ``
`` for paragraph breaks.
Limitations:
- Images, nested tables, VML text boxes are skipped.
- Pre-existing tracked changes are hard-rejected.
Args:
document_path: Absolute path to the .docx file.
Returns:
Tagged text string with fragment and table markup.
| Name | Required | Description | Default |
|---|---|---|---|
| document_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations by detailing the exact output format, fragment ID conventions, markup syntax, and limitations (skipped elements, hard rejection of tracked changes). This provides substantial behavioral context that the annotations (readOnlyHint, idempotentHint) do not cover.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (output format, fragment IDs, formatting, limitations, args, returns). It is appropriately sized given the tool's complexity, and every sentence contributes useful information without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is thorough: it explains the output schema, fragment ID patterns, formatting, limitations, parameters, and return value. It also places the tool in its workflow context relative to apply_changes, making it fully self-contained for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter (document_path) and 0% schema description coverage, the description compensates by explaining 'Absolute path to the .docx file,' which adds the required meaning. While not exhaustive, it fully clarifies the only parameter's purpose and type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb+resource: 'Extract text from a .docx file as tagged fragments.' It further distinguishes the tool by explaining its role as the first step for obtaining fragment IDs to be used in apply_changes, setting it apart from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs 'Call this first to get fragment IDs, then use those IDs in apply_changes,' which tells the agent exactly when to use this tool. It also mentions limitations (skips images, nested tables, etc.) that imply cases where the tool is not suitable, though it does not name alternative tools for those situations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
validate_document_toolARead-onlyIdempotent
Check a .docx file for structural issues.
Runs validation checks on the document's OOXML structure to ensure it will open correctly in Microsoft Word and that all tracked changes and comments are properly formed.
Use this tool:
After calling
apply_changesto verify the redlined document is valid (automatically enabled by default viavalidate=Trueparameter)When debugging a document that won't open correctly in Word
When verifying that an existing redlined document has proper structure
Validation Checks
Annotation ID isolation: Tracked-change and comment IDs must not collide across groups. Each
<w:ins>,<w:del>, and<w:comment>needs a globally unique ID within the document.Comment integrity: Every
<w:comment>in comments.xml must have matching<w:commentRangeStart>/<w:commentRangeEnd>markers in the document body, and vice versa.Tracked-change attributes: Every
<w:ins>and<w:del>must have required attributes:w:id(unique ID),w:author(author name), andw:date(timestamp).Package consistency: Content-type and relationship entries must be present in the .docx ZIP structure when comments.xml exists.
Example Output
Success case::
"Validation: passed (0 errors, 0 warnings)."Failure case::
"Validation: FAILED (2 error(s), 1 warning(s)).
Error 1: Annotation ID collision: ID 5 used by both tracked change and comment
Error 2: Orphaned comment range: commentRangeStart with id=3 has no matching end
Warning 1: Comment with id=7 is not referenced by any comment range"| Name | Required | Description | Default |
|---|---|---|---|
| document_path | Yes | Absolute path to the .docx file to validate. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint: true, idempotentHint: true) are complemented by detailed behavioral descriptions: it lists the four specific validation checks (annotation ID isolation, comment integrity, tracked-change attributes, package consistency) and provides example success/failure output. This goes far beyond annotation hints and gives a clear picture of what the tool does, with no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headers, bullet points for validation checks, and code blocks for example output. Although somewhat long, every section adds value and the main purpose is front-loaded in the first sentence. No redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, full schema coverage, no nested objects) and the presence of an output schema, the description is more than complete. It covers purpose, usage scenarios, validation checks, and example output, leaving no significant gaps for an agent to misuse the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage of the single parameter document_path, including a description ('Absolute path to the .docx file to validate'). The tool description adds no additional semantics about this parameter, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Check a .docx file for structural issues' and elaborates on validating OOXML structure for Word compatibility, tracked changes, and comments. This is a specific verb+resource statement that thoroughly distinguishes its scope from sibling tools, especially audit_document_tool, by listing the exact validation checks.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes an explicit 'Use this tool:' section listing three concrete scenarios (after apply_changes, debugging open failures, verifying existing redlined documents). It also notes that validation is automatically enabled via validate=True in apply_changes, effectively communicating when the tool may not need to be called separately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
6 tool updates
v0.2.0- First observed
apply_changes - First observed
apply_changes_from_file - First observed
audit_document_tool - First observed
diff_fragments - First observed
extract_fragments - First observed
validate_document_tool
TDQS
Most tools have clear, distinct purposes: extract, apply changes, validate, audit, and diff. However, validate_document_tool and audit_document_tool both inspect document structure and could be confused, and apply_changes_from_file is a redundant variant of apply_changes. Overall, the descriptions help clarify boundaries.
Tool names follow a consistent verb_noun pattern with lowercase underscores (extract_fragments, apply_changes, diff_fragments). The '_tool' suffix on validate_document_tool and audit_document_tool is a minor inconsistency, and apply_changes_from_file is long but clear. The naming is generally predictable.
With 6 tools, the server is well-scoped for the domain of .docx extraction, tracked changes, validation, and comparison. Each tool contributes to a focused workflow, and the count is within the ideal 3-15 range.
The tool surface covers the core lifecycle: extraction, applying changes, validation, auditing, and diffing. Minor gaps exist, such as no direct tool for creating documents or accepting/rejecting changes, and the extraction tool skips some elements. However, the primary redlining workflow is well-supported.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
- ClmentOAuthcom.clment
Contract review that keeps your contracts: cited answers, Word redlines, key-date alerts.
Fill standard legal agreement templates (NDAs, SAFEs, NVCA docs, employment) as DOCX files.
ContractOracle - 10 contract analysis tools: clause extraction, redlines, DORA mappings.
Turn any PDF into structured JSON via AI + OCR: invoices, bank statements, contracts.
Related MCP Servers
- AlicenseAqualityAmaintenanceA "Virtual DOM" for Microsoft Word enabling AI to safely read, redline, and sanitize DOCX contracts without breaking formatting.11152MIT
- FlicenseAqualityCmaintenanceEnables AI agents to edit Word documents using track changes, allowing lawyers to review each modification via Word's revision interface.5-

BitsBound MCP Serverofficial
AlicenseAqualityDmaintenanceEnables AI-powered contract analysis with partner-level redlines and real OOXML Track Changes for Claude Desktop and Claude.ai.12284MIT- AlicenseBqualityBmaintenanceStructure-preserving Word DOCX editing MCP server with a .NET Open XML backend and Office.js live sessions. Enables safe, auditable, incremental editing of Microsoft Word documents for AI agents.63178AGPL 3.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/sontanon/docx-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server