insert_section
Add a new section with specified heading and content into a Markdown document at a defined position. Optionally enable auto-saving and backup for secure document management.
Instructions
Insert a new section at a specified location.
The document will be saved after the operation if successful and auto_save is True.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| auto_save | No | ||
| backup | No | ||
| content | Yes | ||
| document_path | Yes | ||
| heading | Yes | ||
| position | Yes | ||
| validation_level | No | NORMAL |
Implementation Reference
- Primary MCP tool handler for 'insert_section'. Registers the tool via @mcp.tool(), defines input schema via parameters and docstring, implements logic by loading document, computing insertion position, and calling SafeMarkdownEditor.insert_section_after via stateless processor.def insert_section(document_path: str, heading: str, content: str, position: int, auto_save: bool = True, backup: bool = True, validation_level: str = "NORMAL") -> Dict[str, Any]: """ Insert a new section at a specified location. The document will be saved after the operation if successful and auto_save is True. """ """ Insert a new section at a specified location. Args: document_path: Path to the Markdown file heading: The section heading/title content: The section content position: Position to insert (0-based index) 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): sections = editor.get_sections() if position == 0 or not sections: if sections: after_section = sections[0] return editor.insert_section_after( after_section=after_section, level=2, title=heading, content=content ) else: # Handle empty document case from .safe_editor_types import EditResult, OperationType return EditResult( success=False, operation=OperationType.INSERT, modified_sections=[], errors=["Cannot insert into empty document"], warnings=[] ) else: if position-1 < len(sections): after_section = sections[position-1] return editor.insert_section_after( after_section=after_section, level=2, title=heading, content=content ) else: from .safe_editor_types import EditResult, OperationType return EditResult( success=False, operation=OperationType.INSERT, modified_sections=[], errors=[f"Position {position} is out of range"], warnings=[] ) 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)
- Core helper function implementing the actual insertion logic: validates params, auto-adjusts level, previews operation, creates transaction, inserts new heading and content lines after target section, re-parses document, returns EditResult with new section reference.def insert_section_after(self, after_section: SectionReference, level: int, title: str, content: str = "", auto_adjust_level: bool = True) -> EditResult: """ Insert new section after specified section. Args: after_section: Reference section for insertion point level: Heading level for new section (1-6) title: Section title (plain text) content: Section content (markdown) auto_adjust_level: Auto-adjust level to maintain hierarchy Returns: EditResult with new section reference in modified_sections """ with self._lock: try: # Validate parameters if not (1 <= level <= 6): return EditResult( success=False, operation=EditOperation.INSERT_SECTION, modified_sections=[], errors=[SafeParseError( message=f"Invalid heading level: {level}. Must be between 1 and 6.", error_code="INVALID_LEVEL", category=ErrorCategory.VALIDATION, suggestions=["Use a heading level between 1 and 6"] )], warnings=[] ) if not title.strip(): return EditResult( success=False, operation=EditOperation.INSERT_SECTION, modified_sections=[], errors=[SafeParseError( message="Section title cannot be empty", error_code="EMPTY_TITLE", category=ErrorCategory.VALIDATION, suggestions=["Provide a non-empty title for the section"] )], warnings=[] ) # Auto-adjust level if requested if auto_adjust_level: # Ensure the new section level makes sense in context child_sections = self.get_child_sections(after_section) if child_sections: # If after_section has children, insert at child level level = max(after_section.level + 1, min(s.level for s in child_sections)) else: # No children, use level one below parent level = min(level, after_section.level + 1) # Preview the operation first preview_result = self.preview_operation( EditOperation.INSERT_SECTION, after_section=after_section, level=level, title=title, content=content ) if not preview_result.success: return preview_result # Create transaction transaction = self._create_transaction([{ 'operation': EditOperation.INSERT_SECTION, 'after_section': after_section, 'level': level, 'title': title, 'content': content, 'auto_adjust_level': auto_adjust_level }]) # Apply the changes lines = self._current_text.split('\n') insert_line = after_section.line_end + 1 # Create new section lines new_section_lines = [ f"{'#' * level} {title}", "", content, "" ] # Insert the new section new_lines = (lines[:insert_line] + new_section_lines + lines[insert_line:]) # Update state self._current_text = '\n'.join(new_lines) self._current_result = self._parser.parse(self._current_text) self._wrapper = ASTWrapper(self._current_result) self._last_modified = datetime.now() self._version += 1 # Add transaction to history self._transaction_history.append(transaction) self._trim_transaction_history() # Find the newly created section updated_sections = self._build_section_references() new_section = None for section in updated_sections: if (section.title == title and section.level == level and section.line_start >= insert_line): new_section = section break return EditResult( success=True, operation=EditOperation.INSERT_SECTION, modified_sections=[new_section] if new_section else [], errors=[], warnings=[], metadata={ 'transaction_id': transaction.transaction_id, 'version': self._version, 'auto_adjusted_level': auto_adjust_level, 'final_level': level } ) except Exception as e: return EditResult( success=False, operation=EditOperation.INSERT_SECTION, modified_sections=[], errors=[SafeParseError( message=f"Insert section operation failed: {str(e)}", error_code="INSERT_ERROR", category=ErrorCategory.SYSTEM )], warnings=[] )
- Enum defining operation types including INSERT_SECTION used throughout the editor for 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"
- src/quantalogic_markdown_mcp/mcp_server.py:617-628 (registration)Internal tool registration dictionary mapping 'insert_section' to its implementation for synchronous tool calls.tools = { "load_document": self._load_document_impl, "list_sections": self._list_sections_impl, "get_section": self._get_section_impl, "insert_section": self._insert_section_impl, "update_section": self._update_section_impl, "delete_section": self._delete_section_impl, "move_section": self._move_section_impl, "get_document": self._get_document_impl, "save_document": self._save_document_impl, "analyze_document": self._analyze_document_impl, }
- Alternative/internal implementation of insert_section logic for synchronous calls, similar to main handler but with different position handling.def _insert_section_impl(self, document_path: str, heading: str, content: str = "", position: Optional[int] = None, auto_save: bool = True, backup: bool = True) -> Dict[str, Any]: """Implementation for insert_section tool.""" def operation(editor): sections = editor.get_sections() # Handle position parameter if position is None or position >= len(sections): # Insert at the end if sections: last_section = sections[-1] return editor.insert_section_after(last_section, 1, heading, content) else: # Document is empty - create a simple document with the new section return {"success": False, "error": "Cannot insert into empty document - use save_document first"} elif position == 0: # Insert at the beginning - insert before first section if sections: # Since we can't insert "before", we need to manipulate this differently # For now, let's insert at level 1 after a dummy section or return error return {"success": False, "error": "Inserting at position 0 not supported - use position >= 1"} else: return {"success": False, "error": "Cannot insert into empty document"} else: # Insert after the section at position-1 after_section = sections[position - 1] level = after_section.level if after_section.level < 6 else 1 return editor.insert_section_after(after_section, level, heading, content) validation_enum = ValidationLevel.NORMAL return self.processor.execute_operation(document_path, operation, auto_save, backup, validation_enum)