Skip to main content
Glama
GongRzhe

Office Word MCP Server

insert_numbered_list_near_text

Add bulleted or numbered lists before or after specific paragraphs in Word documents by text or index position.

Instructions

Insert a bulleted or numbered list before or after the target paragraph. Specify by text or paragraph index. Args: filename (str), target_text (str, optional), list_items (list of str), position ('before' or 'after'), target_paragraph_index (int, optional), bullet_type ('bullet' for bullets or 'number' for numbered lists, default: 'bullet').

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filenameYes
target_textNo
list_itemsNo
positionNoafter
target_paragraph_indexNo
bullet_typeNobullet

Implementation Reference

  • MCP tool registration using @mcp.tool() decorator. Delegates to the content_tools handler.
    @mcp.tool()
    def insert_numbered_list_near_text(filename: str, target_text: str = None, list_items: list = None, position: str = 'after', target_paragraph_index: int = None, bullet_type: str = 'bullet'):
        """Insert a bulleted or numbered list before or after the target paragraph. Specify by text or paragraph index. Args: filename (str), target_text (str, optional), list_items (list of str), position ('before' or 'after'), target_paragraph_index (int, optional), bullet_type ('bullet' for bullets or 'number' for numbered lists, default: 'bullet')."""
        return content_tools.insert_numbered_list_near_text_tool(filename, target_text, list_items, position, target_paragraph_index, bullet_type)
  • Async handler function in content_tools that invokes the core implementation from document_utils.
    async def insert_numbered_list_near_text_tool(filename: str, target_text: str = None, list_items: list = None, position: str = 'after', target_paragraph_index: int = None, bullet_type: str = 'bullet') -> str:
        """Insert a bulleted or numbered list before or after the target paragraph. Specify by text or paragraph index."""
        return insert_numbered_list_near_text(filename, target_text, list_items, position, target_paragraph_index, bullet_type)
  • Core implementation of the tool logic: finds target paragraph, creates list paragraphs, applies bullet/numbering via XML manipulation, inserts near target.
    def insert_numbered_list_near_text(doc_path: str, target_text: str = None, list_items: list = None, position: str = 'after', target_paragraph_index: int = None, bullet_type: str = 'bullet') -> str:
        """
        Insert a bulleted or numbered list before or after the target paragraph. Specify by text or paragraph index. Skips TOC paragraphs in text search.
        Args:
            doc_path: Path to the Word document
            target_text: Text to search for in paragraphs (optional if using index)
            list_items: List of strings, each as a list item
            position: 'before' or 'after' (default: 'after')
            target_paragraph_index: Optional paragraph index to use as anchor
            bullet_type: 'bullet' for bullets (•), 'number' for numbers (1,2,3) (default: 'bullet')
        Returns:
            Status message
        """
        import os
        from docx import Document
        if not os.path.exists(doc_path):
            return f"Document {doc_path} does not exist"
        try:
            doc = Document(doc_path)
            found = False
            para = None
            if target_paragraph_index is not None:
                if target_paragraph_index < 0 or target_paragraph_index >= len(doc.paragraphs):
                    return f"Invalid target_paragraph_index: {target_paragraph_index}. Document has {len(doc.paragraphs)} paragraphs."
                para = doc.paragraphs[target_paragraph_index]
                found = True
            else:
                for i, p in enumerate(doc.paragraphs):
                    # Skip TOC paragraphs
                    if p.style and p.style.name.lower().startswith("toc"):
                        continue
                    if target_text and target_text in p.text:
                        para = p
                        found = True
                        break
            if not found or para is None:
                return f"Target paragraph not found (by index or text). (TOC paragraphs are skipped in text search)"
            # Save anchor index before insertion
            if target_paragraph_index is not None:
                anchor_index = target_paragraph_index
            else:
                anchor_index = None
                for i, p in enumerate(doc.paragraphs):
                    if p is para:
                        anchor_index = i
                        break
            # Determine numbering ID based on bullet_type
            num_id = 1 if bullet_type == 'bullet' else 2
    
            # Use ListParagraph style for proper list formatting
            style_name = None
            for candidate in ['List Paragraph', 'ListParagraph', 'Normal']:
                try:
                    _ = doc.styles[candidate]
                    style_name = candidate
                    break
                except KeyError:
                    continue
            if not style_name:
                style_name = None  # fallback to default
    
            new_paras = []
            for item in (list_items or []):
                p = doc.add_paragraph(item, style=style_name)
                # Add bullet numbering XML - this is the fix!
                add_bullet_numbering(p, num_id=num_id, level=0)
                new_paras.append(p)
            # Move the new paragraphs to the correct position
            for p in reversed(new_paras):
                if position == 'before':
                    para._element.addprevious(p._element)
                else:
                    para._element.addnext(p._element)
            doc.save(doc_path)
            list_type = "bulleted" if bullet_type == 'bullet' else "numbered"
            if anchor_index is not None:
                return f"{list_type.capitalize()} list with {len(new_paras)} items inserted {position} paragraph (index {anchor_index})."
            else:
                return f"{list_type.capitalize()} list with {len(new_paras)} items inserted {position} the target paragraph."
        except Exception as e:
            return f"Failed to insert numbered list: {str(e)}"
  • Helper function to add bullet or numbering formatting to paragraphs using direct XML manipulation.
    def add_bullet_numbering(paragraph, num_id=1, level=0):
        """
        Add bullet/numbering XML to a paragraph.
    
        Args:
            paragraph: python-docx Paragraph object
            num_id: Numbering definition ID (1=bullets, 2=numbers, etc.)
            level: Indentation level (0=first level, 1=second level, etc.)
    
        Returns:
            The modified paragraph
        """
        # Get or create paragraph properties
        pPr = paragraph._element.get_or_add_pPr()
    
        # Remove existing numPr if any (to avoid duplicates)
        existing_numPr = pPr.find(qn('w:numPr'))
        if existing_numPr is not None:
            pPr.remove(existing_numPr)
    
        # Create numbering properties element
        numPr = OxmlElement('w:numPr')
    
        # Set indentation level
        ilvl = OxmlElement('w:ilvl')
        ilvl.set(qn('w:val'), str(level))
        numPr.append(ilvl)
    
        # Set numbering definition ID
        numId = OxmlElement('w:numId')
        numId.set(qn('w:val'), str(num_id))
        numPr.append(numId)
    
        # Add to paragraph properties
        pPr.append(numPr)
    
        return paragraph

Latest Blog Posts

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/GongRzhe/Office-Word-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server