obsidian_patch_file
Modify Obsidian notes by inserting content relative to headings, block references, or frontmatter fields using append, prepend, or replace operations.
Instructions
Insert content into an existing note relative to a heading, block reference, or frontmatter field.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Content to insert | |
| filepath | Yes | Path to the file (relative to vault root) | |
| operation | Yes | Operation to perform (append, prepend, or replace) | |
| target | Yes | Target identifier (heading path, block reference, or frontmatter field) | |
| target_type | Yes | Type of target to patch |
Implementation Reference
- PatchContentToolHandler: Main implementation of the obsidian_patch_file tool, providing schema via get_tool_description and execution logic via run_tool which delegates to api.patch_content.class PatchContentToolHandler(ToolHandler): def __init__(self): super().__init__(TOOL_PATCH_CONTENT) def get_tool_description(self): return Tool( name=self.name, description="Insert content into an existing note relative to a heading, block reference, or frontmatter field.", inputSchema={ "type": "object", "properties": { "filepath": { "type": "string", "description": "Path to the file (relative to vault root)", "format": "path" }, "operation": { "type": "string", "description": "Operation to perform (append, prepend, or replace)", "enum": ["append", "prepend", "replace"] }, "target_type": { "type": "string", "description": "Type of target to patch", "enum": ["heading", "block", "frontmatter"] }, "target": { "type": "string", "description": "Target identifier (heading path, block reference, or frontmatter field)" }, "content": { "type": "string", "description": "Content to insert" } }, "required": ["filepath", "operation", "target_type", "target", "content"] } ) def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: if not all(k in args for k in ["filepath", "operation", "target_type", "target", "content"]): raise RuntimeError("filepath, operation, target_type, target and content arguments required") api.patch_content( args.get("filepath", ""), args.get("operation", ""), args.get("target_type", ""), args.get("target", ""), args.get("content", "") ) return [ TextContent( type="text", text=f"Successfully patched content in {args['filepath']}" ) ]
- src/mcp_obsidian_advanced/server.py:26-43 (registration)TOOL_MAPPING dictionary registers 'obsidian_patch_file' (TOOL_PATCH_CONTENT) with PatchContentToolHandler class, used by register_tools() to instantiate and add handlers to the MCP server.TOOL_MAPPING = { tools.TOOL_LIST_FILES_IN_DIR: tools.ListFilesInDirToolHandler, tools.TOOL_SIMPLE_SEARCH: tools.SearchToolHandler, tools.TOOL_PATCH_CONTENT: tools.PatchContentToolHandler, tools.TOOL_PUT_CONTENT: tools.PutContentToolHandler, tools.TOOL_APPEND_CONTENT: tools.AppendContentToolHandler, tools.TOOL_DELETE_FILE: tools.DeleteFileToolHandler, tools.TOOL_COMPLEX_SEARCH: tools.ComplexSearchToolHandler, tools.TOOL_BATCH_GET_FILES: tools.BatchGetFilesToolHandler, tools.TOOL_PERIODIC_NOTES: tools.PeriodicNotesToolHandler, tools.TOOL_RECENT_PERIODIC_NOTES: tools.RecentPeriodicNotesToolHandler, tools.TOOL_RECENT_CHANGES: tools.RecentChangesToolHandler, tools.TOOL_UNDERSTAND_VAULT: tools.UnderstandVaultToolHandler, tools.TOOL_GET_ACTIVE_NOTE: tools.GetActiveNoteToolHandler, tools.TOOL_OPEN_FILES: tools.OpenFilesToolHandler, tools.TOOL_LIST_COMMANDS: tools.ListCommandsToolHandler, tools.TOOL_EXECUTE_COMMANDS: tools.ExecuteCommandsToolHandler, }
- Obsidian.patch_content method: Performs the core HTTP PATCH request to the Obsidian API endpoint /vault/{filepath} with custom headers for operation, target_type, and target to insert content.def patch_content(self, filepath: str, operation: str, target_type: str, target: str, content: str) -> Any: url = f"{self.get_base_url()}/vault/{filepath}" headers = self._get_headers() | { 'Content-Type': 'text/markdown', 'Operation': operation, 'Target-Type': target_type, 'Target': urllib.parse.quote(target) } def call_fn(): response = requests.patch(url, headers=headers, data=content, verify=self.verify_ssl, timeout=self.timeout) response.raise_for_status() return None return self._safe_call(call_fn)