Skip to main content
Glama
pmmvr

Obsidian MCP Server

by pmmvr

browse_vault_structure

Explore and navigate Obsidian vault directories to view folder structures, optionally including files and recursively listing nested contents for comprehensive organization.

Instructions

Browse vault directory structure.

Args:
    path: Path to browse from (defaults to vault root)
    include_files: Include files in listing (default: False, folders only)
    recursive: List nested contents recursively

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
include_filesNo
pathNo
recursiveNo

Implementation Reference

  • The primary MCP tool handler for 'browse_vault_structure', decorated with @mcp.tool(). Cleans input path, delegates to client.browse_vault(), separates directories and files, and returns a structured dictionary response with success/error handling.
    @mcp.tool(
        annotations={
            "title": "Browse Obsidian Vault Structure",
            "readOnlyHint": True,
            "openWorldHint": False
        }
    )
    async def browse_vault_structure(path: str = "", include_files: bool = False, recursive: bool = False) -> Dict[str, Any]:
        """
        Browse vault directory structure.
        
        Args:
            path: Path to browse from (defaults to vault root)
            include_files: Include files in listing (default: False, folders only)
            recursive: List nested contents recursively
        """
        try:
            # Remove leading/trailing quotes and whitespace 
            clean_path = path.strip().strip('"\'')
            items = await client.browse_vault(clean_path, include_files, recursive)
            
            directories = [item for item in items if item.endswith('/')]
            files = [item for item in items if not item.endswith('/')]
            
            return {
                "success": True,
                "path": clean_path,
                "include_files": include_files,
                "recursive": recursive,
                "directories": directories,
                "files": files if include_files else [],
                "total_directories": len(directories),
                "total_files": len(files) if include_files else 0,
                "total_items": len(items)
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"Failed to browse vault structure for path '{path}': {str(e)}",
                "path": path,
                "include_files": include_files,
                "recursive": recursive,
                "directories": [],
                "files": [],
                "total_directories": 0,
                "total_files": 0,
                "total_items": 0
            }
  • Supporting helper method in ObsidianClient that implements the vault browsing logic, handling both shallow (non-recursive) and deep recursive traversal using list_directory(), with file inclusion filter and max_depth safety limit.
    async def browse_vault(self, base_path: str = "", include_files: bool = False, recursive: bool = False, max_depth: int = 10) -> List[str]:
        """Browse vault structure with flexible filtering options."""
        if not recursive:
            all_items = await self.list_directory(base_path)
            if not include_files:
                # Filter to only show directories (items ending with '/')
                return [item for item in all_items if item.endswith('/')]
            return all_items
        
        all_items = []
        
        async def _recursive_list(current_path: str, depth: int):
            if depth > max_depth:
                return
                
            try:
                items = await self.list_directory(current_path)
                for item in items:
                    if current_path:
                        full_path = f"{current_path}/{item}"
                    else:
                        full_path = item
                    
                    # Apply file filtering
                    if include_files or item.endswith('/'):
                        all_items.append(full_path)
                    
                    # If it's a directory, recurse into it
                    if item.endswith('/'):
                        await _recursive_list(full_path.rstrip('/'), depth + 1)
            except Exception:
                # Skip directories we can't access
                pass
        
        await _recursive_list(base_path, 0)
        return all_items
  • Low-level helper in ObsidianClient to list contents of a vault directory/path via Obsidian API endpoint.
    async def list_directory(self, path: str = "") -> List[str]:
        if path:
            # Just URL encode the path and try it directly
            encoded_path = quote(path, safe='/')
            endpoint = f"/vault/{encoded_path}/"
        else:
            endpoint = "/vault/"
        
        result = await self._request("GET", endpoint)
        return result.get("files", [])
Install Server

Other Tools

Related 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/pmmvr/obsidian-api-mcp-server'

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