List Bases
list_basesEnumerate all .base files in the vault to get sorted relative paths and total count, enabling efficient management of YAML-defined database views.
Instructions
Enumerate every Obsidian Bases (.base) file in the vault. Bases are YAML-defined database views over notes (filters, properties, table/calendar/kanban views). Returns a sorted list of relative paths plus the total count. Pair with read_base or query_base.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/bases.ts:31-41 (handler)The handler function for the 'list_bases' tool. It calls listBaseFiles(vaultPath), formats the result (sorted list of relative paths and count), and returns it as text. Error handling logs failures and returns an error result.
async () => { try { const bases = await listBaseFiles(vaultPath); if (bases.length === 0) return textResult("No .base files in this vault."); const lines = [`Found ${bases.length} Base file(s):`, "", ...bases]; return textResult(lines.join("\n")); } catch (err) { log.error("list_bases failed", { tool: "list_bases", err: err as Error }); return errorResult(`Error listing bases: ${sanitizeError(err)}`); } }, - src/tools/bases.ts:17-42 (registration)The registerBaseTools function registers the 'list_bases' tool on the McpServer with its schema (inputSchema: {}), description, and annotations (readOnlyHint, idempotentHint).
export function registerBaseTools(server: McpServer, vaultPath: string): void { server.registerTool( "list_bases", { title: "List Bases", description: "Enumerate every Obsidian Bases (`.base`) file in the vault. Bases are YAML-defined database views over notes (filters, properties, table/calendar/kanban views). Returns a sorted list of relative paths plus the total count. Pair with read_base or query_base.", annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false, }, inputSchema: {}, }, async () => { try { const bases = await listBaseFiles(vaultPath); if (bases.length === 0) return textResult("No .base files in this vault."); const lines = [`Found ${bases.length} Base file(s):`, "", ...bases]; return textResult(lines.join("\n")); } catch (err) { log.error("list_bases failed", { tool: "list_bases", err: err as Error }); return errorResult(`Error listing bases: ${sanitizeError(err)}`); } }, ); - src/tools/bases.ts:19-28 (registration)The input schema for 'list_bases' – an empty object ({}), meaning no arguments are required.
"list_bases", { title: "List Bases", description: "Enumerate every Obsidian Bases (`.base`) file in the vault. Bases are YAML-defined database views over notes (filters, properties, table/calendar/kanban views). Returns a sorted list of relative paths plus the total count. Pair with read_base or query_base.", annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false, }, - src/lib/vault.ts:792-802 (helper)The listBaseFiles helper function walks the vault directory tree for .base files using walkVault(), then filters out excluded directories and returns a sorted array of relative paths.
export async function listBaseFiles( vaultPath: string, ): Promise<string[]> { const entries = await walkVault(await getRealVaultRoot(vaultPath), [".base"]); const out: string[] = []; for (const rel of entries) { if (isExcluded(rel)) continue; out.push(rel); } return out.sort(); } - src/lib/vault.ts:142-177 (helper)The walkVault helper function recursively walks the vault directory, filtering by file extension (here '.base') and excluding .obsidian/.trash/.git directories.
async function walkVault( baseDir: string, extensions: string[], ): Promise<string[]> { const results: string[] = []; const exts = extensions.map((e) => e.toLowerCase()); async function walk(dir: string, relPrefix: string): Promise<void> { let entries: import("fs").Dirent[]; try { entries = await fs.readdir(dir, { withFileTypes: true }); } catch (err) { if ((err as NodeJS.ErrnoException).code === "ENOENT") return; throw err; } for (const entry of entries) { const name = entry.name; if (entry.isDirectory()) { // Prune excluded directory names at ANY depth. Obsidian's own // subfolders aside, nested `.git`/`.obsidian`/`.trash` directories // should never be surfaced to clients. if (EXCLUDED_SET.has(name.toLowerCase())) continue; const nextPrefix = relPrefix === "" ? name : `${relPrefix}/${name}`; await walk(path.join(dir, name), nextPrefix); } else if (entry.isFile()) { const lower = name.toLowerCase(); if (!exts.some((ext) => lower.endsWith(ext))) continue; const relPath = relPrefix === "" ? name : `${relPrefix}/${name}`; results.push(relPath); } } } await walk(baseDir, ""); return results; }