replace_block_between_manual_anchors
Replace content in Word documents by specifying start and end anchor texts, updating sections with new paragraphs while maintaining desired formatting and structure.
Instructions
Replace all content between start_anchor_text and end_anchor_text (or next logical header if not provided).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| end_anchor_text | No | ||
| filename | Yes | ||
| new_paragraph_style | No | ||
| new_paragraphs | Yes | ||
| start_anchor_text | Yes |
Input Schema (JSON Schema)
{
"properties": {
"end_anchor_text": {
"default": null,
"title": "End Anchor Text",
"type": "string"
},
"filename": {
"title": "Filename",
"type": "string"
},
"new_paragraph_style": {
"default": null,
"title": "New Paragraph Style",
"type": "string"
},
"new_paragraphs": {
"items": {},
"title": "New Paragraphs",
"type": "array"
},
"start_anchor_text": {
"title": "Start Anchor Text",
"type": "string"
}
},
"required": [
"filename",
"start_anchor_text",
"new_paragraphs"
],
"type": "object"
}
Implementation Reference
- word_document_server/main.py:828-837 (registration)MCP tool registration using @mcp.tool() decorator. This defines the entry point for the tool with input parameters matching the tool schema and calls the implementation wrapper.async def replace_block_between_manual_anchors(filename: str, start_anchor_text: str, new_paragraphs: List[str], end_anchor_text: Optional[str] = None, new_paragraph_style: Optional[str] = None): """Replace all content between start_anchor_text and end_anchor_text (or next logical header if not provided).""" return await replace_block_between_manual_anchors_tool( filename=filename, start_anchor_text=start_anchor_text, new_paragraphs=new_paragraphs, end_anchor_text=end_anchor_text, new_paragraph_style=new_paragraph_style )
- Tool handler wrapper function that receives parameters from MCP and delegates to the core utility function in document_utils.async def replace_block_between_manual_anchors_tool(filename: str, start_anchor_text: str, new_paragraphs: list[str], end_anchor_text: str = None, new_paragraph_style: str = None) -> str: """Replace all content between start_anchor_text and end_anchor_text (or next logical header if not provided).""" return replace_block_between_manual_anchors( doc_path=filename, start_anchor=start_anchor_text, new_paragraphs=new_paragraphs, end_anchor=end_anchor_text, new_paragraph_style=new_paragraph_style )
- Core utility function implementing the logic to find anchors by text or index, delete paragraphs between them, insert new paragraphs with optional styles, and save the document.def replace_block_between_manual_anchors( doc_path: str, start_anchor, new_paragraphs: list[str], end_anchor=None, new_paragraph_style: str = None ) -> str: """ Replace all content (paragraphs) between start_anchor and end_anchor (exclusive). Anchors can be specified by string (exact paragraph text) or by integer (paragraph index). If end_anchor is None, deletes until the end of the document. Inserts new_paragraphs after the start anchor. """ from docx import Document import os if not os.path.exists(doc_path): return f"Document {doc_path} not found." doc = Document(doc_path) # Find start anchor index if isinstance(start_anchor, int): start_idx = start_anchor if start_idx < 0 or start_idx >= len(doc.paragraphs): return f"Invalid start_anchor index: {start_idx}. Document has {len(doc.paragraphs)} paragraphs." else: start_idx = None for i, para in enumerate(doc.paragraphs): if para.text.strip() == str(start_anchor).strip(): start_idx = i break if start_idx is None: return f"Start anchor '{start_anchor}' not found." # Find end anchor index if end_anchor is None: end_idx = len(doc.paragraphs) elif isinstance(end_anchor, int): end_idx = end_anchor if end_idx < 0 or end_idx > len(doc.paragraphs): return f"Invalid end_anchor index: {end_idx}. Document has {len(doc.paragraphs)} paragraphs." else: end_idx = None for i in range(start_idx + 1, len(doc.paragraphs)): if doc.paragraphs[i].text.strip() == str(end_anchor).strip(): end_idx = i break if end_idx is None: return f"End anchor '{end_anchor}' not found after start anchor." # Delete all paragraphs between start_idx and end_idx (exclusive) removed_count = 0 for i in range(end_idx - 1, start_idx, -1): p = doc.paragraphs[i]._element p.getparent().remove(p) removed_count += 1 # Insert new paragraphs after the start anchor style_to_use = new_paragraph_style or "Normal" anchor_para = doc.paragraphs[start_idx] current_para = anchor_para for para in new_paragraphs: if isinstance(para, dict): text = para.get("text", "") style = para.get("style", style_to_use) else: text = str(para) style = style_to_use new_para = doc.add_paragraph(text, style=style) current_para._element.addnext(new_para._element) current_para = new_para doc.save(doc_path) return f"Replaced content between anchor {start_anchor} and {end_anchor if end_anchor is not None else 'end of document'} with {len(new_paragraphs)} paragraph(s), removed {removed_count} paragraphs."