Skip to main content
Glama

delete_section

Remove specific sections from Markdown documents by ID or heading. The tool automatically saves changes and creates backups for document safety.

Instructions

        Delete a section by ID or heading.
        The document will be saved after the operation if successful and auto_save is True.
        

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
document_pathYes
section_idNo
headingNo
auto_saveNo
backupNo
validation_levelNoNORMAL

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Core handler function that executes the delete_section tool logic: validates the section reference, calculates deletion boundaries, removes the section content, updates the document state, records the transaction for rollback, and returns an EditResult.
    def delete_section(self, section_ref: SectionReference, preserve_subsections: bool = False) -> EditResult:
        """
        Delete a section from the document.
        
        Args:
            section_ref: Reference to section to delete
            preserve_subsections: If True, promote subsections to parent level
            
        Returns:
            EditResult with operation details
        """
        with self._lock:
            try:
                # Validate section exists
                if not self._is_valid_section_reference(section_ref):
                    return EditResult(
                        success=False,
                        operation=EditOperation.DELETE_SECTION,
                        modified_sections=[],
                        errors=[SafeParseError(
                            message=f"Section not found: {section_ref.title}",
                            error_code="SECTION_NOT_FOUND",
                            category=ErrorCategory.VALIDATION,
                            suggestions=["Verify section ID", "Refresh section references"]
                        )],
                        warnings=[]
                    )
                
                # Store rollback data
                rollback_data = self._current_text
                
                # Get current sections
                current_sections = self.get_sections()
                
                # Find section to delete
                target_section = None
                for section in current_sections:
                    if section.id == section_ref.id:
                        target_section = section
                        break
                
                if not target_section:
                    return EditResult(
                        success=False,
                        operation=EditOperation.DELETE_SECTION,
                        modified_sections=[],
                        errors=[SafeParseError(
                            message="Target section not found in current document",
                            error_code="SECTION_NOT_FOUND",
                            category=ErrorCategory.VALIDATION
                        )],
                        warnings=[]
                    )
                
                # Calculate deletion bounds
                lines = self._current_text.split('\n')
                
                # Find next section at same or higher level to determine end bound
                delete_end_line = len(lines)
                for section in current_sections:
                    if (section.line_start > target_section.line_start and 
                        section.level <= target_section.level):
                        delete_end_line = section.line_start - 1
                        break
                
                # Simple deletion - remove entire section and subsections
                new_lines = (lines[:target_section.line_start - 1] + 
                            lines[delete_end_line:])
                
                # Update document
                new_text = '\n'.join(new_lines)
                self._current_text = new_text
                self._current_result = self._parser.parse(new_text)
                self._wrapper = ASTWrapper(self._current_result)
                
                # Record transaction
                operation_dict = {
                    'operation': EditOperation.DELETE_SECTION,
                    'section_id': section_ref.id,
                    'content': "",
                    'preserve_subsections': preserve_subsections,
                    'deleted_title': target_section.title
                }
                
                self._record_transaction([operation_dict], rollback_data)
                
                # Update version
                self._version += 1
                self._last_modified = datetime.now()
                
                return EditResult(
                    success=True,
                    operation=EditOperation.DELETE_SECTION,
                    modified_sections=[section_ref],
                    errors=[],
                    warnings=[],
                    metadata={
                        'preserve_subsections': preserve_subsections,
                        'version': self._version
                    }
                )
                
            except Exception as e:
                return EditResult(
                    success=False,
                    operation=EditOperation.DELETE_SECTION,
                    modified_sections=[],
                    errors=[SafeParseError(
                        message=f"Delete operation failed: {str(e)}",
                        error_code="DELETE_ERROR",
                        category=ErrorCategory.SYSTEM
                    )],
                    warnings=[]
                )
  • MCP tool registration for 'delete_section'. Defines input parameters (document_path, section_id or heading, etc.), resolves the section reference, calls the SafeMarkdownEditor.delete_section handler, and handles stateless execution with auto-save and backup.
    def delete_section(document_path: str, section_id: Optional[str] = None, heading: Optional[str] = None,
                      auto_save: bool = True, backup: bool = True,
                      validation_level: str = "NORMAL") -> Dict[str, Any]:
        """
        Delete a section by ID or heading.
        The document will be saved after the operation if successful and auto_save is True.
        """
        """
        Delete a section by ID or heading.
        
        Args:
            document_path: Path to the Markdown file
            section_id: The section ID to delete (optional)
            heading: The section heading to delete (optional)
            auto_save: Whether to automatically save the document
            backup: Whether to create a backup before saving
            validation_level: Validation strictness - "STRICT", "NORMAL", or "PERMISSIVE"
        """
        def operation(editor):
            if section_id:
                # Find section by ID
                section_ref = editor.get_section_by_id(section_id)
                if not section_ref:
                    from .safe_editor_types import EditResult, OperationType
                    return EditResult(
                        success=False,
                        operation=OperationType.DELETE,
                        modified_sections=[],
                        errors=[f"Section with ID '{section_id}' not found"],
                        warnings=[]
                    )
            elif heading:
                # Find section by heading
                sections = editor.get_sections()
                matching_sections = [s for s in sections if s.title == heading]
                if not matching_sections:
                    from .safe_editor_types import EditResult, OperationType
                    return EditResult(
                        success=False,
                        operation=OperationType.DELETE,
                        modified_sections=[],
                        errors=[f"Section with heading '{heading}' not found"],
                        warnings=[]
                    )
                section_ref = matching_sections[0]
            else:
                from .safe_editor_types import EditResult, OperationType
                return EditResult(
                    success=False,
                    operation=OperationType.DELETE,
                    modified_sections=[],
                    errors=["Either section_id or heading must be provided"],
                    warnings=[]
                )
            
            return editor.delete_section(section_ref, preserve_subsections=False)
        
        validation_map = {"STRICT": ValidationLevel.STRICT, "NORMAL": ValidationLevel.NORMAL, "PERMISSIVE": ValidationLevel.PERMISSIVE}
        validation_enum = validation_map.get(validation_level.upper(), ValidationLevel.NORMAL)
        
        return self.processor.execute_operation(document_path, operation, auto_save, backup, validation_enum)
  • Enum defining EditOperation.DELETE_SECTION used throughout for operation typing and result tracking.
    class EditOperation(Enum):
        """Supported editing operations."""
        INSERT_SECTION = "insert_section"
        UPDATE_SECTION = "update_section"
        DELETE_SECTION = "delete_section"
        MOVE_SECTION = "move_section"
        CHANGE_HEADING_LEVEL = "change_heading_level"
        INSERT_CONTENT = "insert_content"
        DELETE_CONTENT = "delete_content"
        BATCH_OPERATIONS = "batch_operations"
  • Dataclass defining SectionReference type, used as input parameter for delete_section handler.
    @dataclass(frozen=True)
    class SectionReference:
        """Immutable reference to a document section."""
        
        id: str                    # Stable hash-based identifier
        title: str                 # Section heading text
        level: int                 # Heading level (1-6)
        line_start: int           # Starting line number (0-indexed)
        line_end: int             # Ending line number (0-indexed)
        path: List[str]           # Hierarchical path from root
        
        def __hash__(self) -> int:
            """Hash based on immutable properties."""
            return hash((self.id, self.title, self.level, self.line_start))
        
        def __eq__(self, other) -> bool:
            """Equality based on ID and position."""
            return (isinstance(other, SectionReference) and
                    self.id == other.id and
                    self.line_start == other.line_start)
  • Alternative/enhanced MCP tool registration for 'delete_section' in the enhanced server.
    def delete_section(document_path: str, section_id: Optional[str] = None,
                      heading: Optional[str] = None, auto_save: bool = True, backup: bool = True,
                      validation_level: str = "NORMAL") -> Dict[str, Any]:
        """Delete a section (stateless only)."""
        def operation(editor: SafeMarkdownEditor):
            if section_id:
                section = editor.get_section_by_id(section_id)
            elif heading:
                sections = editor.get_sections()
                section = next((s for s in sections if s.title == heading), None)
            else:
                from .safe_editor_types import EditResult
                return EditResult(
                    success=False,
                    operation=EditOperation.DELETE_SECTION,
                    errors=["Either section_id or heading must be provided"]
                )
            if section:
                return editor.delete_section(section, preserve_subsections=False)
            else:
                from .safe_editor_types import EditResult
                return EditResult(
                    success=False,
                    operation=EditOperation.DELETE_SECTION,
                    errors=["Section not found"]
                )
        validation_map = {"STRICT": ValidationLevel.STRICT, "NORMAL": ValidationLevel.NORMAL, "PERMISSIVE": ValidationLevel.PERMISSIVE}
        validation_enum = validation_map.get(validation_level.upper(), ValidationLevel.NORMAL)
        return self.processor.execute_operation(document_path, operation, auto_save, backup, validation_enum)
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions that the document will be saved if auto_save is True, which adds some context, but fails to disclose critical behavioral traits such as whether the deletion is permanent, what happens to nested sections, error conditions, or the impact of the backup and validation_level parameters. This leaves significant gaps for a destructive operation.

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 appropriately sized with two sentences that are front-loaded with the core action. There is no wasted text, but it could be slightly more structured by explicitly listing key parameters or behaviors in a bullet-point format for clarity.

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

Completeness2/5

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

Given the complexity of a destructive operation with 6 parameters, 0% schema description coverage, no annotations, and an output schema (which reduces the need to describe return values), the description is incomplete. It lacks details on parameter semantics, behavioral risks, and usage context, making it insufficient for safe and effective tool invocation.

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

Parameters2/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 by explaining parameters. It only mentions 'ID or heading' and 'auto_save', covering 2 out of 6 parameters (document_path, section_id, heading, auto_save, backup, validation_level). This partial coverage is inadequate, as key parameters like backup and validation_level are left unexplained, failing to add sufficient meaning beyond the schema.

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

Purpose4/5

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

The description clearly states the verb 'Delete' and the resource 'a section by ID or heading', making the purpose unambiguous. However, it doesn't explicitly distinguish this tool from sibling tools like 'move_section' or 'update_section' in terms of destructive nature, which would require a 5.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'move_section' or 'update_section', nor does it mention prerequisites such as needing the document to be loaded first. It only mentions the auto_save condition, which is insufficient for comprehensive usage guidance.

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/quantalogic/quantalogic_markdown_mcp'

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