obsidian_open_files
Open multiple files in Obsidian vault simultaneously to view content in separate tabs for efficient reference and editing.
Instructions
Open one or more files in the vault in a new leaf.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filepaths | Yes | List of file paths to open |
Implementation Reference
- The OpenFilesToolHandler class provides the core implementation of the 'obsidian_open_files' tool. It defines the tool schema and the run_tool method that iterates over the provided filepaths and calls the Obsidian API to open each file in a new leaf, handling errors and returning appropriate responses.class OpenFilesToolHandler(ToolHandler): def __init__(self): super().__init__(TOOL_OPEN_FILES) def get_tool_description(self): return Tool( name=self.name, description="Open one or more files in the vault in a new leaf.", inputSchema={ "type": "object", "properties": { "filepaths": { "type": "array", "items": { "type": "string", "description": "Path to a file (relative to your vault root)", "format": "path" }, "description": "List of file paths to open" }, }, "required": ["filepaths"] } ) def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: filepaths = args.get("filepaths") if not filepaths: raise ValueError("One or more filepaths are required") successful_opens = [] failed_opens = [] for file in filepaths: try: api.open_file(file) successful_opens.append(file) except Exception as e: failed_opens.append((file, str(e))) if failed_opens: error_messages = [f"Failed to open '{file}': {error}" for file, error in failed_opens] if successful_opens: return [ TextContent( type="text", text=f"Opened {len(successful_opens)} file(s) successfully. Errors: {'; '.join(error_messages)}" ) ] else: raise ValueError(f"Failed to open any files: {'; '.join(error_messages)}") return [ TextContent( type="text", text="File(s) opened successfully!" ) ]
- src/mcp_obsidian_advanced/server.py:26-43 (registration)TOOL_MAPPING dictionary registers 'obsidian_open_files' (via tools.TOOL_OPEN_FILES) to the OpenFilesToolHandler class. This mapping is used in register_tools() to instantiate and add the handler 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, }
- The Obsidian API client's open_file method makes a POST request to '/open/{filepath}' to open the specified file in Obsidian, which is called by the tool handler.def open_file(self, filepath: str) -> Any: """Open a file in the vault. Args: filepath: Path to the file to open (relative to vault root) Returns: None on success. Opens the file in the default editor in a new leaf. """ url = f"{self.get_base_url()}/open/{filepath}" def call_fn(): response = requests.post(url, headers=self._get_headers(), verify=self.verify_ssl, timeout=self.timeout) response.raise_for_status() return None return self._safe_call(call_fn)
- src/mcp_obsidian_advanced/server.py:95-108 (registration)register_tools function instantiates handlers from TOOL_MAPPING (including OpenFilesToolHandler for obsidian_open_files) and registers them with the MCP server via add_tool_handler.def register_tools(): """Register the selected tools with the server.""" tools_to_include = parse_include_tools() registered_count = 0 for tool_name in tools_to_include: if tool_name in TOOL_MAPPING: handler_class = TOOL_MAPPING[tool_name] handler_instance = handler_class() add_tool_handler(handler_instance) registered_count += 1 logger.debug(f"Registered tool: {tool_name}") logger.info(f"Successfully registered {registered_count} tools")
- Constant defining the tool name 'obsidian_open_files' used throughout for registration and handler initialization.TOOL_OPEN_FILES = "obsidian_open_files"