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
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions the action ('Insert') and parameters but lacks behavioral details such as whether this modifies the document in place, requires specific permissions, handles errors (e.g., if target text isn't found), or what the output looks like. It doesn't contradict annotations, but it's insufficient for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in two sentences: the first states the purpose and key parameters, and the second lists all args with brief explanations. It's front-loaded with the main action, though it could be slightly more polished (e.g., avoiding 'Args:' in the description text).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 6 parameters with 0% schema coverage and no annotations or output schema, the description does well on parameters but lacks behavioral context for a mutation tool. It's complete enough for basic usage but misses details like error handling or output format, leaving gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate fully. It clearly explains all 6 parameters: 'filename' (the document), 'target_text' or 'target_paragraph_index' (how to locate the paragraph), 'list_items' (content), 'position' (placement), and 'bullet_type' (formatting). This adds essential meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Insert a bulleted or numbered list'), the resource ('target paragraph'), and the scope ('before or after'). It distinguishes itself from siblings like 'add_paragraph' or 'insert_line_or_paragraph_near_text' by focusing specifically on lists with formatting options.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by mentioning 'Specify by text or paragraph index' and the positional options, but it doesn't explicitly state when to use this tool versus alternatives like 'add_paragraph' for plain text or other list-insertion tools if they existed. No exclusions or prerequisites are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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