| searchA | Search vault notes. hybrid (default) fuses semantic + full-text ranks via Reciprocal Rank Fusion — no tuning needed, best for most queries. semantic is concept-only (better for abstract/paraphrased queries). fulltext is literal-token (better when you know the exact phrase exists). Semantic search is chunk-level — results are deduped to one-per-note by default. Set unique: "chunks" to return chunk-level hits with chunkHeading, chunkStartLine, and chunkExcerpt; supported by semantic and hybrid modes. fulltext is note-level only and ignores unique (full-text chunk search is not yet supported). Response is wrapped as {data, context} where context.next_actions suggests the agent's most useful follow-up call (read top hit, explore connections, or retry with broader phrasing on zero hits). |
| read_noteA | Read a note's content. Brief mode (default) returns title + metadata + linked-note titles; full mode returns full content + edge context. Full mode also reports truncated: true when the body exceeded maxContentLength (default 2000 chars) and was sliced. Response is wrapped as {data, context} where context.next_actions suggests follow-ups like creating missing linked notes or exploring outgoing connections. |
| list_notesA | List notes in the vault. Optionally filter by directory prefix or by frontmatter tag. Pass includeStubs: false to exclude unresolved wiki-link targets (nodes with frontmatter._stub: true) and see only real on-disk notes. |
| find_connectionsA | Find notes linked to (from or to) a given note, up to N hops. Optionally return the full subgraph instead of a flat list. Response is wrapped as {data, context} where context.next_actions suggests follow-ups like clustering a dense neighbourhood via detect_themes or tracing a path to the furthest neighbour via find_path_between. Broken-wikilink stub neighbours are excluded by default; pass includeStubs: true to include them. |
| find_path_betweenA | Find link paths between two notes. Returns all simple paths up to maxDepth edges, optionally including their shared neighbors. Broken-wikilink stub nodes are excluded by default — they are degree-1 dead ends in the undirected graph and will block legitimate paths if left in. Pass includeStubs: true to include them. |
| detect_themesA | List auto-detected topic clusters across the vault (served from the community-detection cache). Pass a theme id or label to drill into one cluster. To recompute with a different Louvain resolution, call reindex({ resolution: X }) first — detect_themes itself is a read-only tool. Each returned cluster carries staleMembersFiltered — the number of cached nodeIds that no longer exist in the vault and were dropped on this read. A positive value means the cached community row is lagging; the filter also regenerates summary so it stays consistent with the filtered nodeIds. Broken-wikilink stub targets are excluded by default; pass includeStubs: true to include them. When the overall vault graph has LOW modularity (<0.3), the response includes { warning, modularity } at the envelope top-level — the clusters aren't clearly separable on this graph and may not reflect meaningful themes. |
| rank_notesA | Rank notes by importance: 'influence' (densely-connected hubs), 'bridging' (notes that connect otherwise-separate topic clusters), or both. Credibility guards (I): by default, influence excludes notes with fewer than minIncomingLinks: 2 incoming edges — this filters out random-orphan noise that makes PageRank feel meaningless on personal vaults. Pass minIncomingLinks: 0 to see the unfiltered ranking. Bridging scores are normalized by graph size (divided by n*(n-1)/2) so values compare across vaults of different sizes — a bridging score of 0.5 means the same thing in any vault. Broken-wikilink stub targets are excluded by default; pass includeStubs: true to include them. |
| create_noteA | Create a new note in the vault with a title, body, and optional YAML frontmatter. The new note is indexed immediately so semantic search and graph tools can find it. Auto-injects a title: field into frontmatter matching the note title unless frontmatter already has one. |
| edit_noteA | Modify an existing note. Supports six edit modes: append (add to end; defensively inserts a leading newline if the source didn't end with one), prepend (insert after frontmatter if present, otherwise at file start), replace_window (find a block of text and replace it — optionally fuzzy; fuzzy extends match to consume trailing .?! so the replacement has no doubled punctuation), patch_heading (insert or replace content under a specific heading; headingOp: 'before' | 'after' inserts immediately before/after the heading line — use before on the NEXT heading to append to a section's end; headingOp: 'replace' with scope: 'section' (default) replaces to the next same-or-higher heading or EOF — CAREFUL on the LAST heading, this consumes everything below including content separated by blank lines — pass scope: 'body' to stop at the first blank line after the body; if the target heading text appears MORE THAN ONCE the call throws MultipleMatches listing each occurrence with its line number — pass headingIndex: 0 | 1 | ... (0-indexed, top-to-bottom) to pick one), patch_frontmatter (set a single YAML key; pass value: null to clear — or from XML-stringifying clients use valueJson: 'null' for true null, valueJson: 'true' for a real boolean, valueJson: '42' for a number, valueJson: '["a"]' for an array; valueJson wins over value when both are set), at_line (insert or replace at a 1-indexed line number that counts from file start including frontmatter lines). Pass edits (array) to apply multiple edits atomically — all succeed or none are written. |
| apply_edit_previewA | Apply a previously previewed edit. Pass the previewId returned by edit_note with dryRun: true. Previews expire after 5 minutes. Fails with a descriptive error if the target file changed since the preview was generated — in that case, regenerate the preview and try again. |
| link_notesA | Add a wiki-link from one note to another with a context sentence describing why they're connected. Appends the link to the source note and records the edge in the graph so analytics pick it up. |
| move_noteA | Rename or move a note. Inbound wiki-links in other notes are rewritten in place immediately (bare [[old]], [[old|alias]], ![[old]] embeds, and [[old#heading]]/[[old^block]] suffixes all handled). If the note's frontmatter has a title: field matching the old basename, it's auto-rewritten to the new basename (custom titles and missing titles are left alone). Response includes linksRewritten: { files, occurrences }. |
| delete_noteA | Permanently delete a note. Removes the file from disk AND its index rows (edges, embedding, node). Requires confirm: true to guard against accidents. When the delete removes inbound edges, the response is wrapped in a next_actions envelope suggesting a follow-up rank_notes(method=pagerank, minIncomingLinks=0) to spot newly orphaned notes. |
| reindexA | Re-index the vault: re-embeds notes whose mtime changed, prunes orphan stubs, and re-runs community detection only when something actually changed. Pass resolution to force a Louvain rerun and tune cluster granularity (0.5 = fewer/broader clusters, 2.0 = more/finer); without it, a no-op vault skips Louvain entirely. |
| active_noteA | Return the note currently open in Obsidian, including cursor position and selection. Requires the obsidian-brain companion plugin installed and Obsidian running against the same vault. |
| dataview_queryA | Run a Dataview DQL query against the vault. Requires the obsidian-brain companion plugin v0.2.0+ installed, Obsidian running against the same vault, and the Dataview community plugin enabled. Returns a normalized discriminated-union shape. kind='table' gives {headers, rows}. kind='list' gives {values}. kind='task' gives {items: [{task, text, path, line, tags, children, ...STask fields when task=true}]}. kind='calendar' gives {events: [{date, link, value?}]}. DQL reference: https://blacksmithgu.github.io/obsidian-dataview/queries/structure/. Default 30s timeout (override with timeoutMs). NOTE: timeoutMs only cancels the HTTP wait; Dataview has no cancellation API, so the query keeps running inside Obsidian to completion. Prefer LIMIT N in DQL for open-ended queries. |
| base_queryA | Evaluate an Obsidian Bases .base file and return its rows. Requires the obsidian-brain companion plugin installed, a recent Obsidian (1.10.0+) running against the same vault, and the Bases core plugin enabled (Obsidian → Settings → Core plugins → Bases). Obsidian does not yet expose a public API for headless Bases query execution (Plugin.registerBasesView() is a view-factory hook only). The plugin uses its own YAML parser + a whitelisted expression subset (Path B). See docs/plugin.md#bases for the full supported subset. Supported subset: tree ops (and/or/not), comparisons (==, !=, >, >=, <, <=), leaf boolean (&&, ||, !), file.{name, path, folder, ext, size, mtime, ctime, tags}, file.hasTag("x"), file.inFolder("x"), frontmatter dot-paths. Arithmetic (+, -, *, /, %), method calls other than hasTag/inFolder, function calls (today(), now(), etc.), regex literals, formulas:, summaries:, and this context references all return 400 unsupported_construct errors — they ship in subsequent plugin patches as users hit them. Provide either file (vault-relative path to a .base file) or yaml (inline .base YAML source); view names which view inside the file to execute. Returns { view, rows, total, executedAt } — rows contain {file: {name, path}, ...projected columns}, total is the pre-limit count. Default 30s timeout (override with timeoutMs). Timeout only cancels the HTTP wait; the plugin has no cancellation API, so a running evaluation keeps going inside Obsidian. Prefer a limit: in the view for open-ended queries over large vaults. |
| index_statusA | Report the current state of the vault index: embedder model + dim, count of notes / chunks indexed, chunks skipped during the last reindex (if any), advertised vs discovered max tokens, last reindex reasons, whether a reindex is currently in flight, and the last init error. Read-only — does not mutate anything. |