Skip to main content
Glama

Seekstone

obsidian-mcp-server (#1 by downloads)

REST-proxy servers

Local REST API plugin

Not needed

Required

Required

Obsidian app running

Not needed — works with Obsidian closed

Required

Required

Search payload @ 10k notes

2.0 KB

47 KB

up to 95 MB

Warm search latency @ 10k notes

5.2 ms

732 ms (~141× slower)

up to 1,550 ms

Structured frontmatter queries

Built-in (query_notes) — property/date/size predicates, answers in a few hundred bytes

JSONLogic via REST

Varies

Same queries, same committed vaults, 20 runs each, one machine. In-process adapters were re-run on the fixture-v2 vault in September 2026; the REST-proxy rows (rest, obsidian-mcp-server, mcp-obsidian) plus obsidian-mcp and obsidian-mcp-pro are June 2026 captures on fixture v1 — per-row provenance in benchmarks.json, the generated source of truth every number here is checked against in CI — full results across eight servers and three vault sizes below, fully reproducible from the harness.



What is Seekstone?

Seekstone is an Obsidian MCP server — it gives Claude (and any Model Context Protocol client) direct read and write access to your Obsidian vault. No Obsidian app needs to be open, no plugins are required, and nothing leaves your machine.

It reads your vault directly from disk rather than routing through the Obsidian Local REST API plugin, and holds a warm full-text index in-process. The practical difference is twofold:

  • Speed. Keyword searches return in single-digit milliseconds warm and semantic searches in ~26 ms — up to ~514× faster than every other Obsidian MCP server we benchmarked, because there's no subprocess to spawn and no HTTP round-trip per query.

  • Context. A broad search that returns tens of megabytes and millions of tokens via a REST-proxy server returns ~2 KB via Seekstone — up to a ~47,000× reduction that only widens as your vault grows.

Search comes in three modes: ranked full-text search (fuzzy and prefix matching), optional local semantic search (meaning-based, via a small on-device embedding model — opt-in, offline at runtime after a one-time ~30 MB model download), and structured metadata queries — query_notes filters by frontmatter properties (status, due, type, …), tags, folder, modified time, and size, answering questions like "which draft notes changed this week?" in a few hundred bytes instead of a search-and-read loop.

Claude can search and read your entire note library, in milliseconds, without burning most of its context window on a single tool call.

Published on npm as seekstone — install with npx -y seekstone. (Previously also published as obsidian-mcp-seekstone; that alias is deprecated but existing installs keep working.)


Related MCP server: mcp-obsidian-ek

Why Seekstone? The numbers.

Most Obsidian MCP servers return full note content for every search hit. On a broad query that's megabytes of text your LLM has to process — most of it irrelevant, all of it burning context window.

Seekstone returns short ranked excerpts instead (~120 characters by default, tunable per query). We benchmarked Seekstone against 7 other Obsidian MCP servers — 8 servers total — across three vault sizes — 1,000 / 5,000 / 10,000 notes (20 runs each). Every number below is fully reproducible: the vaults are committed to this repo (generated from the public-domain 1911 Encyclopædia Britannica), so you can clone it and run the exact same benchmark yourself.

The point of testing three sizes is that this is where the architectures diverge — a real vault only grows.

Search payload — bytes returned per query (context tax; lower is better)

Server

Architecture

1k notes

5k notes

10k notes

🥇 Seekstone

in-process index

1.6 KB

1.8 KB

2.0 KB

mcpvault

fs-direct subprocess

1.7 KB

1.9 KB

2.2 KB

obsidian-mcp-rs

fs-direct, per-query scan

5.4 KB

5.8 KB

6.2 KB

obsidian-tc

SQLite platform

4.6 KB

6.8 KB

7.2 KB

obsidian-mcp-server

REST API

55 KB

47 KB

47 KB

obsidian-mcp-pro

fs-direct subprocess

25 KB

84 KB

114 KB

obsidian-mcp

fs-direct subprocess

18 KB

105 KB

201 KB

mcp-obsidian

REST API

9.8 MB

45 MB

95 MB

Seekstone stays flat (~2 KB) no matter how big your vault gets, because it always returns ranked excerpts — and it's now the smallest payload of every server tested, edging out mcpvault at all three sizes. The REST-proxy servers return full note content for every match, so they grow with the vault — mcp-obsidian hits 95 MB at 10k notes, and a single broad query (the capital of) averaged 370.9 MB / 97.8 million tokens per call across 20 runs. At 10k notes that's a ~47,000× context-tax difference.

Search latency — warm mean, ms (lower is better)

Server

1k notes

5k notes

10k notes

vs Seekstone @10k

🥇 Seekstone

1.0

2.7

5.2

—

obsidian-mcp-rs

5.8

18

35

~7× slower

obsidian-mcp-pro

46

213

430

~83× slower

obsidian-mcp-server

82

356

732

~141× slower

obsidian-mcp

82

405

811

~156× slower

mcpvault

89

436

897

~173× slower

mcp-obsidian

164

740

1,550

~299× slower

obsidian-tc

263

1,253

2,667

~514× slower

Every competitor spawns a subprocess or makes HTTP round-trips per query, and most do work that scales with vault size. Seekstone holds a warm in-process index — no IPC, no network — so keyword search stays in single-digit milliseconds even at 10,000 notes (the shipped semantic pipeline — embed, scan, MaxSim rerank — lands at ~26 ms). And the gap widens with scale: from 1k → 10k notes the competitors slow down 5–10×, while Seekstone barely moves. Even the fastest alternative — obsidian-mcp-rs, which re-scans the vault on every query — is ~7× slower warm at 10k notes with 3× the payload, and the REST-proxy generation runs ~110–300× slower.

Seekstone is the only server in our benchmark set that delivers both ~2 KB payloads and single-digit-ms keyword latency at every vault size — and, as far as we know, the only Obsidian MCP server with published, reproducible benchmarks. The harness, the synthetic vaults, and the full results are open source: see benchmark-scaling.md and the harness. Clone, run, verify.


Install

Choose the method that suits you best.

Using an AI agent? Paste this prompt

If you use Claude Code, Cursor, or another coding agent, you don't need to follow any instructions yourself — paste this prompt and the agent does the install:

Install the seekstone MCP server for this editor. Run npx -y seekstone init --client code --write (use desktop, cursor, or vscode for other clients). It auto-detects my Obsidian vault; if it lists several, ask me which one and re-run with --vault "<path>". Relay any errors to me, then tell me to restart this session so the seekstone tools load.

seekstone init is fully non-interactive — with --write it validates the vault and patches the client config in one shot (Claude Code via claude mcp add, other clients via an additive JSON patch with a timestamped backup).

Option 1 — One-click (Claude Desktop, no terminal needed)

  1. Download seekstone.mcpb (direct link, always the latest release)

  2. Open it with Claude Desktop — double-click in Finder, or right-click → Open With → Claude Desktop

  3. Pick your Obsidian vault folder when prompted

You'll know it worked when seekstone appears in Claude's toolbar. No JSON editing, no terminal, no Node.js required.

Want semantic search? Grab seekstone-semantic.mcpb instead — same server with the local embedding model shipped inside the bundle (~28 MB bigger), so meaning-based search works out of the box: still no terminal, and nothing is downloaded at runtime.

Open Terminal (macOS: Cmd+Space, type "Terminal", press Enter) and run:

npx -y seekstone init

You'll know it worked when Seekstone appears in Claude's toolbar under the plug icon.

Seekstone reads Obsidian's own vault registry to detect your vault, validates it, and either prints the config block to paste or patches Claude Desktop directly:

# Auto-detect vault, print config to paste
npx -y seekstone init

# Auto-detect vault, patch Claude Desktop in place (with backup)
npx -y seekstone init --write

# Specify vault explicitly if you have multiple
npx -y seekstone init --vault "/path/to/vault"

# Auto-configure Claude Code in one step (auto-detects vault, runs claude mcp add)
npx -y seekstone init --client code --write

# Or just print the Claude Code command without running it
npx -y seekstone init --client code

Option 3 — Manual config (Claude Desktop)

Add to claude_desktop_config.json (Settings → Developer → Edit Config):

{
  "mcpServers": {
    "seekstone": {
      "command": "npx",
      "args": ["-y", "seekstone"],
      "env": { "SEEKSTONE_VAULT": "/absolute/path/to/your/vault" }
    }
  }
}

Option 4 — Claude Code

Auto-detects your vault and configures Claude Code in one command:

npx -y seekstone init --client code --write

Or manually, if you prefer to specify the vault path explicitly:

claude mcp add seekstone --env SEEKSTONE_VAULT=/absolute/path/to/your/vault -- npx -y seekstone

Option 5 — Cursor

One-click: — then set SEEKSTONE_VAULT to your vault's absolute path in Cursor's MCP settings (the link installs a placeholder).

Or let the CLI auto-detect your vault and patch ~/.cursor/mcp.json (with a backup):

npx -y seekstone init --client cursor --write

Or add the block manually to ~/.cursor/mcp.json (global) or <project>/.cursor/mcp.json (per-project):

{
  "mcpServers": {
    "seekstone": {
      "command": "npx",
      "args": ["-y", "seekstone"],
      "env": { "SEEKSTONE_VAULT": "/absolute/path/to/your/vault" }
    }
  }
}

Option 6 — VS Code

One-click: — then set SEEKSTONE_VAULT to your vault's absolute path when VS Code opens the server config (the link installs a placeholder).

Or let the CLI auto-detect your vault and write the workspace config (.vscode/mcp.json in the current directory):

npx -y seekstone init --client vscode --write

Or add it from the terminal:

code --add-mcp '{"name":"seekstone","command":"npx","args":["-y","seekstone"],"env":{"SEEKSTONE_VAULT":"/absolute/path/to/your/vault"}}'

Or add the block manually to .vscode/mcp.json (workspace) or via Command Palette → MCP: Open User Configuration (user-global). Note VS Code's two quirks: the top-level key is servers (not mcpServers), and "type": "stdio" is required:

{
  "servers": {
    "seekstone": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "seekstone"],
      "env": { "SEEKSTONE_VAULT": "/absolute/path/to/your/vault" }
    }
  }
}

Requires VS Code 1.102+; seekstone appears in Copilot Chat's Agent mode tools picker.

Other MCP clients (Windsurf, Cline, …)

Seekstone is a standard MCP stdio server — any MCP client can run it. Use the same JSON block as above in your client's MCP config (command: npx, args: ["-y", "seekstone"], env SEEKSTONE_VAULT).


After installing, restart the client. On startup Seekstone walks the vault, builds an in-memory full-text index (a few seconds for thousands of notes), and keeps it live as you edit. The 23 tools below are then available to Claude.

Requires Node.js ≥ 22 for the CLI options. The one-click .mcpb bundle has no external requirements.

If Seekstone saves you context, consider ⭐ starring the repo — it helps others find it.


What can Claude do with your vault?

Once Seekstone is connected, you can ask Claude things like:

  • "Search my notes for everything about [topic] and give me a summary" — uses search, returns ranked excerpts, not full files

  • "Find all notes tagged #project and list their titles" — uses list_notes with a tag filter

  • "Read just the 'Decisions' section of my [project] note" — uses read_note with a section selector, so only that slice enters context

  • "What links to my [topic] note, and what does it link out to?" — uses get_backlinks and get_links to walk your graph

  • "Append today's standup notes to my daily note" — uses append_periodic_note, resolving the daily-note path from your vault config (Obsidian doesn't need to be open)

  • "Fix every occurrence of the old project name in this note" — uses replace_in_note, with a dry-run preview before it writes

  • "Add a summary section to the bottom of [note]" — uses append_note, never touches frontmatter

  • "Move all notes in /inbox to /archive/[year]" — uses move_note

  • "Update the status field in this note's frontmatter to 'done'" — uses patch_frontmatter, preserves key order and quote style

  • "Create a new meeting note for today with a standard template" — uses create_note

Claude never sees your full vault at once — it searches and reads selectively, so even large vaults (10k+ notes) stay within context budget.


Tools

Read

Tool

Description

search

Full-text search. Returns ranked excerpts (default ~120 chars, tunable via excerptLength), not full notes. Fuzzy and prefix matching; with SEEKSTONE_SEMANTIC=1, mode: "semantic"/"hybrid" searches by meaning via a local embedding model (nothing leaves your machine).

query_notes

Structured metadata query. Filter by frontmatter key/value predicates (eq, ne, contains, exists, missing, gt/gte/lt/lte), tag, folder, modified time, and size; sort and select the fields you need. Returns compact rows (path + title by default), not note content.

context_pack

Answer-ready context for a natural-language question in one call, hard-capped at a byte budget (default 2 KB): ranked excerpts, linked neighbor notes with one-line summaries, and follow-up source paths — replaces a search → read → get_backlinks round-trip loop. Scopable by folder/tag and takes the same mode as search.

read_note

Read the full content of a note by vault-relative path. Supports returning a single section, block, or line range.

read_notes

Read up to 20 notes (or sections, blocks, line ranges) in one call under a total byte budget (default 16 KB). Over budget, each note is cut to a fair share and marked truncated; one bad path returns its own error without failing the batch.

list_notes

List notes, optionally filtered by folder prefix or tag.

list_tags

List all tags in the vault sorted by usage count (or alphabetically).

outline_note

Return a note's heading and block structure without its full content — cheap navigation before a targeted read.

get_backlinks

Find all notes that link to a given note.

get_links

List all outgoing wikilinks and markdown links from a note.

resolve_note

Turn a note name, path, or frontmatter alias into its canonical vault path(s) — with provenance per match, all candidates when ambiguous, and did-you-mean suggestions when nothing matches.

get_periodic_note

Read today's (or any date's) daily, weekly, monthly, quarterly, or yearly note — path resolved from your vault config, no Obsidian required.

list_writes

Recent writes from the journal — seq, timestamp, tool, touched paths, and whether each is still undoable. Metadata only, never note content.

Write

Tool

Description

create_note

Create a note (optional frontmatter + body); parent directories are created automatically.

delete_note

Move a note to the vault's .trash/ folder (Obsidian-compatible, restorable). Pass permanent: true to skip the trash — the write journal still lets undo_write restore it.

move_note

Move or rename a note — wikilinks and markdown links in other notes that point at it are rewritten so nothing breaks (rewriteLinks: false to opt out); destination directories are created automatically.

rename_heading

Rename a heading in a note — every [[note#heading]] wikilink and embed across the vault is rewritten so references keep working (aliases preserved, fenced code blocks left alone).

append_note

Append text to a note body without touching frontmatter.

patch_frontmatter

Set, update, or delete frontmatter keys without reordering existing keys or changing quote style.

patch_note

Append, prepend, or replace text at a heading or block reference (createIfMissing to add the section) — frontmatter untouched.

replace_in_note

Find and replace text in the note body — literal or regex, case sensitivity, whole-word matching, optional limit (replaces all occurrences by default), and a dry-run preview.

append_periodic_note

Append to today's periodic note, creating it from a template if it doesn't yet exist.

undo_write

Revert a journaled write: every file it touched goes back to its byte-identical pre-write state (a multi-file move or heading rename is restored whole; a delete is restored even if it was permanent). Defaults to the most recent write; refuses with undo_conflict if a file changed since, unless force: true. The undo is itself journaled — undo_write({ seq }) on the undo entry redoes it.

Every write tool (append_note, patch_note, patch_frontmatter, replace_in_note, rename_heading, move_note, delete_note, append_periodic_note, and create_note with overwrite: true) supports optional compare-and-swap: pass the contentHash you got from read_note as prevHash and the call fails cleanly if the note changed underneath you — no silently discarded concurrent edit, no moving or deleting content you haven't seen. Every mutating result returns the new contentHash, so chained edits need no re-reads.

Every write is reversible. Before any write tool changes a byte, it journals the pre-image of every file it is about to touch under <vault>/.seekstone/history/ — content-addressed (identical states are stored once) and fsync'd before the vault write commits. list_writes shows the journal; undo_write restores byte-identically: a multi-file move_note or rename_heading is restored whole (the note and every link rewrite), and a delete_note comes back even if it was permanent. An undo after an external edit is refused with a structured undo_conflict unless you pass force: true — and even then the clobbered state is journaled first, so nothing is ever lost. Undo is itself journaled: repeated default undos walk backwards through the history, and undo_write({ seq }) on an undo entry redoes it. .seekstone/ is excluded from indexing and search like .trash/; add it to your vault's .gitignore. This complements git and Obsidian's File Recovery rather than replacing them — it is the recovery path the agent can drive.

Every write leaves a receipt. Set SEEKSTONE_AUDIT_FILE and every write-tool call — successful or refused — appends one JSON line: tool, vault-relative paths, sha-256 before/after, outcome (ok, hash_conflict, undo_conflict, policy_denied, error), and op metadata such as replacement counts or the .trash/ destination — never note content, frontmatter values, or search queries, so the file is safe to attach to a bug report.

{"v":1,"ts":"2026-08-29T21:02:11.042Z","tool":"replace_in_note","outcome":"ok","durationMs":1.8,"seq":42,"files":[{"path":"notes/a.md","hashBefore":"3f9c…","hashAfter":"b71e…"}],"path":"notes/a.md","replacements":3}

The hashes are the same contentHash values read_note returns, so any record can be checked against the vault; seq is the journal entry the call committed, so a row indexes straight into list_writes / undo_write. Records are appended and fsync'd after the vault write commits, the file rotates to <file>.1 past SEEKSTONE_AUDIT_MAX_SIZE, an unwritable audit path fails boot, and a failed append reports the call as a structured audit_failed error rather than a clean success. A few jq recipes:

jq -r '[.tool, .outcome] | @tsv' audit.jsonl | sort | uniq -c            # session summary by tool + outcome
jq -c 'select(.files[]?.path == "notes/a.md")' audit.jsonl              # history of one note
jq -c 'select(.ts > "2026-08-29T21:00:00Z" and .outcome == "ok")' audit.jsonl   # what changed since a timestamp

Fast and complete. Seekstone is the only Obsidian MCP server in our benchmark set to expose list_tags, outline_note, get_backlinks, and get_links as first-class tools. Four more capabilities set it apart:

  • Local semantic search, fully in-process. With SEEKSTONE_SEMANTIC=1, search and context_pack gain mode: "semantic" and "hybrid" — meaning-based retrieval through a small on-device embedding model (one-time npx -y seekstone fetch-model download, or the seekstone-semantic.mcpb bundle which ships the model inside; the running server never touches the network), with a MaxSim late-interaction rerank on top since 0.17.0. On our committed 10k-note benchmark vault (150-query golden set, fixture v2), the default model — measured end-to-end through the real search tool — scores 83.3% overall hit@5, 86.7% on the held-out split (vs 34.7% for keyword search alone) at ~26 ms warm p50, and the opt-in potion-retrieval-32M model (SEEKSTONE_SEMANTIC_MODEL; ~129 MB) reaches 86.7% overall hit@5, 86.7% held-out at ~55 ms. No other server we benchmarked ships offline, zero-native-dependency embeddings — and we measured the alternatives head-to-head on the same golden set, same run, committed dev/holdout split (committed comparison, read-out in COMPETITORS-SHA-322): obsidian-tc's plain Ollama-backed semantic search edges us on the held-out split (90.0% vs our 86.7%) at 169 ms/query and a 30-minute index vs our ~28 s, and its GraphRAG mode scores highest of anything we benchmarked (95.0% held-out), paying for it with seconds-per-query latency (2.9 s p50, 4.2 s p95 — against our 26–55 ms), ~8× the payload (16 KB vs ~2 KB per query), and a second server (Ollama + a 137M-parameter model) you must install and run. We pre-registered a gate to claim the #1 spot (GATE-V2-SHA-316, run on fixture v1) and missed it — that verdict is published with the same prominence a win would have been; no new gate ran on v2, and the same clauses recompute to the same miss. obsidian-mcp-pro could not index the 10k-note vault at all (its JSON vector store exceeds JavaScript's string limit after ~17 minutes of embedding). Pick your trade — the numbers are all committed.

  • Periodic notes, filesystem-direct. get_periodic_note and append_periodic_note resolve daily, weekly, monthly, quarterly, and yearly note paths by reading your vault's own config (.obsidian/daily-notes.json and the Periodic Notes plugin) — with Obsidian closed. Every REST-based server can only do this while the app is running.

  • Byte-identical frontmatter, guaranteed. patch_frontmatter edits YAML in place — preserving key order, quote style, and comments — and write-safety is proven byte-for-byte by the test harness. No other server we surveyed makes this guarantee.

  • Zero coupling. No Obsidian app, no Local REST API plugin, no plugin-version drift. Just your files on disk.


Configuration

Variable

Required

Description

SEEKSTONE_VAULT

Yes

Absolute path to your Obsidian vault.

SEEKSTONE_LOG_LEVEL

No

error | warn | info (default) | debug.

SEEKSTONE_LOG_FILE

No

Absolute path; when set, JSON-line logs are appended here (size-rotated).

SEEKSTONE_LOG_MAX_SIZE

No

Log-rotation threshold for SEEKSTONE_LOG_FILE (e.g. 10mb; default 5 MB).

SEEKSTONE_WATCH_POLL

No

Set to 1 to stat-poll for changes instead of native OS events — slower but reliable on network drives, WSL, and some containers.

SEEKSTONE_WATCH_POLL_INTERVAL

No

Stat-poll interval in ms (default 10000). Only used with SEEKSTONE_WATCH_POLL=1. Lower = faster pickup of external edits, higher CPU; raise it on slow network/9p mounts.

SEEKSTONE_READ_ONLY

No

Set to 1 to run read-only: the 10 write tools are unregistered from the tool list entirely (and rejected if called anyway), so the session provably cannot modify your vault.

SEEKSTONE_WRITE_PATHS

No

Comma-separated vault-relative globs (e.g. journal/**,inbox/*.md). Writes are permitted only under matching paths; the rest of the vault stays read-only.

SEEKSTONE_HISTORY

No

Set to 0 to disable the write journal (default on). With it on, every write tool stores the pre-image of each file it touches under <vault>/.seekstone/history/ so undo_write can restore it byte-for-byte.

SEEKSTONE_HISTORY_MAX_SIZE

No

Cap on stored pre-images (e.g. 100mb; default 50 MB). Oldest entries are evicted first and then show undoable: false in list_writes — never silently.

SEEKSTONE_HISTORY_MAX_ENTRIES

No

Cap on journal entries (default 1000); the oldest are dropped past it.

SEEKSTONE_AUDIT_FILE

No

Absolute path; off unless set. Appends one JSON-line audit record per write-tool call — ok or refused — with the tool, paths, sha-256 before/after, outcome, and op metadata. Never note content.

SEEKSTONE_AUDIT_MAX_SIZE

No

Rotate the audit file to <file>.1 past this size (e.g. 10mb; default 10 MB).

SEEKSTONE_SEMANTIC

No

Set to 1 to enable semantic search (search and context_pack gain mode: "semantic" and "hybrid"). Requires the local embedding model — download it once with npx -y seekstone fetch-model; the running server never touches the network. The seekstone-semantic.mcpb bundle sets this automatically and ships the model inside.

SEEKSTONE_SEMANTIC_MODEL

No

Which local model to load: potion-base-8M (default, ~30 MB, 256-dim) or potion-retrieval-32M (~129 MB, 512-dim — more accurate on description-style queries at roughly 2× the query latency). Fetch it first with npx -y seekstone fetch-model --model potion-retrieval-32M.

SEEKSTONE_MODEL_PATH

No

Directory holding the Model2Vec embedding model (default: where fetch-model puts the selected model, under the cache dir).

SEEKSTONE_CACHE_DIR

No

Cache root for the downloaded model and per-vault embedding caches (default ~/.cache/seekstone).

SEEKSTONE_BUNDLED_MODEL_DIR

No

Set by the seekstone-semantic.mcpb bundle's manifest — points at the sharded model files shipped inside the extension, which the server reassembles into the model directory at boot (disk-only, verified against the pinned SHA-256 hashes). Not usually set by hand.

SEEKSTONE_INSTRUCTIONS

No

Path to a file whose contents become the MCP server's instructions string (surfaced to clients alongside the tool list). A relative path resolves against the vault root. Read once at boot, trimmed, capped at 16 KB (truncated with a warning past that). Missing, unreadable, or empty after trim means no instructions — never a boot failure.


How it works

Seekstone walks the vault with fast-glob, parses each note's frontmatter (byte-aware, so writes can prove the frontmatter region is byte-identical pre- and post-write), and builds a MiniSearch full-text index in memory. Search returns short ranked excerpts rather than whole notes — that excerpt-not-document design is where the context-tax win comes from. A cross-platform file watcher (chokidar) keeps the index current as you edit in Obsidian.

Writes are conservative by design: append_note never touches frontmatter, and patch_frontmatter edits the YAML document in place rather than re-serializing it, preserving key order, quote style, and comments.

It's built to stay up. Seekstone is tested on macOS, Linux, and Windows in CI on every commit, its write tools are hardened against pathological (ReDoS) inputs, and a stray unhandled rejection is logged rather than crashed on — so your long-lived MCP session keeps its warm index instead of dropping out mid-conversation.

For a layer-by-layer tour of the codebase — packages, the server's internals, the end-to-end request flow, and the measurement harness — see docs/ARCHITECTURE.md.


Security & privacy

Seekstone reads — and, via the write tools, modifies — files under SEEKSTONE_VAULT on your local disk. The running server makes no network calls and sends no telemetry (the one network path in the package is the explicit npx -y seekstone fetch-model subcommand — a SHA-256-verified, one-time download of the optional semantic-search model that exits before serving starts; the seekstone-semantic.mcpb bundle skips even that by shipping the model inside and reassembling it from disk at boot, verified against the same pinned hashes). Logs are metadata-only by default (note contents only appear at debug level). Nothing is written outside the vault except an optional log file you configure and, with SEEKSTONE_SEMANTIC=1, the per-vault embedding cache under ~/.cache/seekstone (derived vectors of your notes — never sent anywhere).

The Write-Safety Contract

Giving an AI write access to your notes deserves more than "trust us." Seekstone ships a named, tested contract — docs/WRITE-SAFETY.md — of ten guarantees, each linked to the code that enforces it and the test that proves it, verified byte-by-byte by the harness safety suite in CI on every commit and release: zero network, vault sandbox, byte-identical frontmatter on body edits, atomic writes (no torn files), creates never clobber, recoverable deletes (.trash/), optional compare-and-swap on every write tool, configurable write scoping / read-only mode, a write journal that makes every write reversible (undo_write), and a hash-verifiable audit log — every write call leaves a receipt. The same suite runs headlessly against other FS-direct servers — the comparison table is in the contract.


Frequently asked questions

Does the Obsidian app need to be running? No. Seekstone reads the vault folder directly from disk. Obsidian can be open or closed.

Do I need the Local REST API plugin? No. Seekstone bypasses it entirely — that's the source of the up-to-47,000× payload reduction. No plugins are required.

Which AI clients does it support? Any client that supports the Model Context Protocol (MCP) over stdio — Claude Desktop, Claude Code, Cursor, Windsurf, Continue, and others.

Is it safe to use on my vault? Seekstone never modifies files except when you explicitly invoke one of its write tools (the ten in the table above — create_note, append_note, patch_note, patch_frontmatter, replace_in_note, move_note, rename_heading, delete_note, append_periodic_note, undo_write). Every one of them journals the pre-image of each file it touches first, so undo_write can put it back byte-for-byte — see the write-journal note above — and with SEEKSTONE_AUDIT_FILE set, every write call leaves a hash-verifiable audit record (refused attempts included). The running server makes no network requests (semantic search's model is fetched once, out-of-band, by the explicit fetch-model subcommand). The vault path is sandboxed — no tool can read or write outside it. And you can tighten it further: SEEKSTONE_READ_ONLY=1 removes the write tools from the session entirely, and SEEKSTONE_WRITE_PATHS restricts writes to the folders you allow (say, only journal/**). Both are enforced at the dispatch layer, not per-tool, so no tool can forget the check.

Does it work on Windows? Yes. Seekstone is tested on macOS, Linux, and Windows in CI on every commit.

Does search handle typos? Yes, small ones. Keyword search allows one typo per word of 3–7 letters and two for words of 8 or more, so benchamrk still finds "benchmark". One- and two-letter words must match exactly, and swapping two letters counts as two typos. It also matches word prefixes: kuber finds "Kubernetes". The tag filter on search, context_pack, query_notes, and list_notes works like Obsidian's: it ignores case and includes nested tags, so project matches #Project/alpha. A tag no note has returns an unknown_tag error listing the closest existing tags.

What Obsidian vault sizes does it handle? Seekstone has been profiled against vaults with thousands of notes. On the committed 10,000-note benchmark vault, the cold index build takes tens of seconds and process RSS lands under ~100 MB; typical personal vaults index in a few seconds. Semantic mode embeds in the background after boot (~30 s at 10k notes, then cached per-vault so restarts reload in well under a second).

How does seekstone init find my vault automatically? It reads Obsidian's own vault registry (obsidian.json) — the same file Obsidian uses to track your known vaults. If you have one vault, it's selected automatically. If you have multiple, it lists them and asks you to pick with --vault.

What is the .mcpb file? An MCP Bundle — a self-contained zip with the server and its manifest. To install: double-click in Finder (or right-click → Open With → Claude Desktop), pick your vault, and you're done. No terminal or Node.js required. Two variants ship with every release: seekstone.mcpb (standard) and seekstone-semantic.mcpb (same server with the local embedding model inside, semantic search on out of the box).


Contributing & development

Contributions welcome. See CONTRIBUTING.md for guidelines, or jump straight in:

npm install                                          # install all workspace deps
npm test                                             # run all tests
npm run lint                                         # biome check
npm run build -w seekstone                           # tsup → dist/
npm run build:mcpb                                   # build seekstone.mcpb bundle

npx vitest run packages/server/src/tools/search.test.ts  # single test file
npx vitest run -t 'parses a typical frontmatter'         # single test by name
npx tsc -p packages/server/tsconfig.json --noEmit        # typecheck

Repository layout

Package

Purpose

packages/server

The published seekstone MCP server (23 tools, stdio, MiniSearch index, chokidar watcher).

packages/core

Shared vault primitives — walk, frontmatter parser, link/tag extractor, outline, percentiles, pmap, and the Model2Vec embedder. Bundled into the server build.

packages/harness

Profiler + benchmark + write-safety harness (REST vs filesystem) that produced the payload numbers above. Dev-only; not published.

The server has a real build (tsup → dist/) and is published to npm. The harness is run from source via tsx. Releases are automated — see docs/RELEASING.md.

The measurement harness

The harness exists to reproduce the benchmark numbers that motivated the filesystem-direct design. The default reproduction path (fs/seekstone backends against the committed synthetic vault) needs nothing extra; only the REST-backed backends (rest, mcp-obsidian, obsidian-mcp-server) need Obsidian running with the Local REST API plugin.

export SEEKSTONE_VAULT="/absolute/path/to/your/vault"

npx tsx packages/harness/src/cli.ts profile --vault "$SEEKSTONE_VAULT"
npx tsx packages/harness/src/cli.ts bench \
  --queries packages/harness/queries/default.json \
  --stats reports/vault-stats.json
npx tsx packages/harness/src/cli.ts safety --vault "$SEEKSTONE_VAULT"

Harness env vars: SEEKSTONE_REST_API_KEY (from the Local REST API plugin) and SEEKSTONE_REST_URL (defaults to https://127.0.0.1:27124).


Support

Seekstone is free and open source. If it saves you context (and money), you can buy me a coffee.


License

MIT © Shaq Mughal

Available Tools

22 tools
append_noteA

Append text to a note body without touching the frontmatter. Safe for meeting notes, daily logs, and append-only workflows.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path to the note.
contentYesText to append.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate it's a write operation (readOnlyHint=false) and non-destructive (destructiveHint=false). The description adds valuable behavioral detail: it preserves frontmatter and is safe for 'append-only workflows,' which provides context beyond the annotations. No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences with no filler. The core purpose is stated first, and the additional safety/use-case context is provided in a second sentence. Every phrase adds value, making it appropriately sized and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple append operation with three parameters, the description covers the key points: it appends, preserves frontmatter, and indicates safe workflows. However, it does not mention error behaviors (e.g., what happens if the path doesn't exist) or whether it creates a note if missing. Given the low complexity and existing annotations, this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (path, content, prevHash) already documented in the schema. The description does not add any additional parameter-specific semantics, so it remains at the baseline score of 3 given the complete schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'Append text to a note body without touching the frontmatter.' This is a specific verb (append) and resource (note body), and it explicitly distinguishes itself from other mutation tools by mentioning the frontmatter preservation, which differentiates it from patch_note or replace_in_note.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when the tool is appropriate ('Safe for meeting notes, daily logs, and append-only workflows'), but does not explicitly mention when NOT to use it or point to alternative tools. It implies usage scenarios but lacks explicit exclusions or sibling comparisons, leaving the agent to infer the boundary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

append_periodic_noteA

Append text to a periodic note (daily, weekly, monthly, quarterly, or yearly). Preserves existing frontmatter exactly. Creates the note first (from template if configured) when createIfMissing is true (default).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoISO date string (YYYY-MM-DD). Defaults to today when omitted.
periodNoPeriod type. Default: daily.
contentYesText to append to the note body.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
createIfMissingNoCreate the note if it does not exist before appending. Default true.

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With all annotations false, the description carries the full behavioral burden. It adds genuinely useful guarantees ('Preserves existing frontmatter exactly') and creation-flow detail ('from template if configured'), which go beyond the raw annotations. However, it omits the most salient risk of an append operation — non-idempotency (duplicate calls duplicate content) — even though the prevHash parameter hints at concurrency concerns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero filler. The primary action leads, the scoping list follows, and the creation behavior closes. Every clause serves a distinct purpose with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a moderate-complexity tool with 5 simple params and no output schema, the description covers the essentials well. Gaps remain: no mention of timezone handling for date-boundary behavior (critical for 'today' defaults), no duplicate-append warning, and no interaction with prevHash conflict recovery. These are real but not fatal omissions for an append operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, establishing a baseline of 3. The description adds value by clarifying the createIfMissing parameter's effect ('Creates the note first (from template if configured)') and confirming its default, which is not fully obvious from the schema text alone. This is a small but genuine increment over baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description leads with a specific verb+resource: 'Append text to a periodic note' and immediately scopes it to '(daily, weekly, monthly, quarterly, or yearly)'. This clearly differentiates it from sibling 'append_note' (regular notes) and 'get_periodic_note' (read path) without needing to inspect either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'periodic note' qualifier implies the tool's niche, and the description notes the conditional creation behavior when createIfMissing is true. However, it never explicitly points to an alternative (e.g., 'use append_note for regular notes') or states when not to use this tool, despite siblings like append_note and patch_note existing. Usage context is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

context_packA
Read-only

Assemble everything needed to ANSWER a natural-language question in one call, under a strict byte budget (default 2048): ranked excerpts, linked neighbor notes (backlinks/outlinks) with one-line summaries, and follow-up source paths. Retrieval is lexical by default: for a question phrased in words the note itself may not use, pass mode "hybrid" or "semantic", and scope with folder/tag exactly as in search. Use search to locate notes and query_notes for metadata filters; use context_pack when you want answer-ready context without multiple round-trips. Empty excerpts with confidence "none" or "low" means the vault lacks coverage — do not infer content; with folder or tag set, "none" can also mean the filter excluded every match, which totalMatches distinguishes.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoRestrict to notes with this tag. # optional, case-insensitive; nested child tags match ("project" matches project/alpha).
modeNolexical = keyword search (default). semantic = meaning-based over local embeddings (needs SEEKSTONE_SEMANTIC=1 and a fetched model). hybrid = exact-title lookups go lexical, everything else semantic.
queryYesNatural-language question or topic.
folderNoRestrict to a vault-relative folder prefix.
budgetBytesNoHard cap on response JSON bytes (256–16384, default 2048).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint=false, and the description adds substantial behavior beyond them: a hard byte budget with default, lexical-by-default retrieval, backlink/outlink expansion, and the important failure semantics (empty excerpts with confidence 'none'/'low' means no vault coverage; with folder/tag set, 'none' can mean the filter excluded everything, distinguishable via totalMatches). That is exactly the kind of edge-case disclosure annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Content is front-loaded — the core purpose leads, routing guidance follows, and failure semantics come last. The sentences are long and information-dense, bordering on run-on, but nearly every clause carries distinct operational value rather than repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and discharges it, describing the shape of results and the confidence/totalMatches signals that disambiguate empty responses. For a read-only, five-parameter retrieval tool this is complete enough to call correctly without opening the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real value beyond the schema: it explains the motivation for choosing hybrid/semantic mode and clarifies that folder/tag scoping works 'exactly as in search'. It does not, however, add syntax or precedence detail for budgetBytes or folder beyond what the schema states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource ('Assemble everything needed to ANSWER a natural-language question in one call') and enumerates the concrete outputs (ranked excerpts, neighbor notes with summaries, follow-up source paths). It is immediately distinguishable from search and query_notes, which are named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing: 'Use search to locate notes and query_notes for metadata filters; use context_pack when you want answer-ready context without multiple round-trips.' It also tells the agent when to switch modes ('for a question phrased in words the note itself may not use, pass mode hybrid or semantic'), covering both when-to-use and when-to-use-an-alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_noteA
Destructive

Create a new note at a vault-relative path. Optionally sets frontmatter and body content. Parent directories are created automatically. Fails if the note already exists unless overwrite is true (prevHash may guard the overwrite).

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path, e.g. "Daily Notes/2026-06-01.md".
contentNoBody content for the note.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
overwriteNoOverwrite an existing note. Defaults to false.
frontmatterNoFrontmatter key-value pairs.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint:true annotation, the description discloses three concrete behaviors: automatic parent-directory creation, the fail-on-existing-note rule, and the prevHash compare-and-swap guard that can gate the overwrite. These are non-obvious side effects and failure modes the annotations alone do not convey. The description is consistent with readOnlyHint:false and destructiveHint:true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the core action first, then the optional parameters, then the critical existence-failure and CAS-guard behavior. No filler and no repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 5-parameter destructive write with no output schema, the description covers creation, optional fields, directory auto-creation, the existence failure mode, and the overwrite/CAS guard. The one notable gap is the return contract on success — the CAS workflow implied by prevHash would benefit from knowing whether the note's contentHash is returned — but the invocation semantics are fully specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter (path, content, prevHash, overwrite, frontmatter) is already documented in the input schema. The description's only added semantic is the coupling between prevHash and overwrite ('prevHash may guard the overwrite'), a small increment over the schema's per-parameter text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence 'Create a new note at a vault-relative path' names a specific verb, resource, and scope qualifier. This cleanly distinguishes it from sibling mutators like append_note, patch_note, replace_in_note, and move_note, which all act on existing notes, and from delete_note.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The fail-if-exists clause ('Fails if the note already exists unless overwrite is true') gives the agent a clear condition for choosing the overwrite path. However, it does not explicitly route to alternatives — e.g., checking existence with list_notes first or selecting patch_note/append_note for modifying an existing note — so cross-tool selection is left implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_noteA
Destructive

Delete a note. By default it is moved to the vault .trash/ folder (recoverable by moving it back); pass permanent: true to remove it outright.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path of the note to delete.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since — so you never delete content you have not seen.
permanentNoPermanently remove instead of moving to .trash/. Defaults to false.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description reveals critical behavior: the default action is non-permanent (trash) and reversible, and only permanent deletion requires an explicit flag. It also discloses recoverability. This transparency is essential for an agent deciding whether to call this tool and mitigates risk, going well beyond what the annotation already provides.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact at two sentences, with the action verb first and the most important behavioral nuance immediately following. Every word contributes value, and the sentence structure flows from the core action to the key conditional. No fluff or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with three parameters and one required field, the description covers the essential behavior (delete, default trash, permanent override) and confirms reversibility. It does not mention error handling for missing paths or concurrency, but given the schema and annotations, the definition is complete for an agent to call it correctly. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents all three parameters with 100% coverage, so the description needn't add parameter details. The description's mention of 'pass permanent: true' restates the schema without adding new meaning. This meets the baseline of 3 but does not elevate it further.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Delete a note', which is a specific verb and resource, and immediately clarifies the default trash behavior and the permanent deletion option. This distinguishes it from siblings like move_note or patch_note, which are about modifying instead of removing. The tool's purpose is unambiguous and immediately scoped.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on how deletion works by default (to trash) and how to override it, which implicitly tells the agent when this tool is appropriate. However, it does not explicitly mention alternatives like move_note or state when NOT to use it (e.g., for reorganization). This is a slight gap in otherwise clear guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_periodic_noteA

Get the path and existence status of a periodic note (daily, weekly, monthly, quarterly, or yearly) for a given date. Reads folder/format config from .obsidian/daily-notes.json (daily) or the periodic-notes plugin data.json. Optionally creates the note from the configured template if it is missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoISO date string (YYYY-MM-DD). Defaults to today when omitted.
periodNoPeriod type. Default: daily.
createIfMissingNoCreate the note from the configured template if it does not exist. Default false.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false and destructiveHint=false, so the description correctly adds that the tool may create a note when createIfMissing is true – a behavioral detail beyond the annotations. It also discloses the config file locations (.obsidian/daily-notes.json and plugin data.json). No contradictions. However, it does not describe the exact return shape or failure modes, which are minor gaps given the side‑effect disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The primary purpose ('Get the path and existence status') is front‑loaded, followed by config sources and the optional creation behavior. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Since there is no output schema, the description conveys that the return includes 'path and existence status', and it explains the config‑reading logic and optional creation. This is sufficient for an agent to call correctly. It lacks explicit error cases or what happens after creation (e.g., returns path or just status), but the core information is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Parameter schema coverage is 100% – all three parameters (date, period, createIfMissing) already have descriptions in the schema, including defaults. The description adds no new semantic meaning beyond restating the defaults ('Defaults to today', 'Default: daily', 'Default false') which are already present. Baseline 3 applies because the schema carries the weight.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get the path and existence status of a periodic note' and enumerates the period types (daily, weekly, monthly, quarterly, yearly). This clearly distinguishes it from sibling tools like create_note or append_periodic_note, even though it never names them. The purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does and mentions the optional creation side‑effect, but never explicitly states when to use this tool versus a sibling like create_note or append_periodic_note. It gives context (reads config from specific files) but no when‑to‑use or when‑not‑to‑use guidance, leaving the agent to infer suitability.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_notesC
Read-only

List notes, optionally filtered by folder prefix or tag.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoFilter by tag. # optional, case-insensitive; nested child tags match ("project" matches project/alpha).
limitNoMax results (1–500, default 100).
folderNoVault-relative folder prefix.

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, covering the safety profile. The description adds nothing beyond that – no ordering, return format, or pagination behavior – so it contributes no behavioral value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single efficient sentence with the primary action front-loaded and no waste. It is appropriately sized, though its brevity leaves the gaps noted above unfilled.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with no output schema and fully documented parameters, the description covers the essentials. It is adequate but should do more to distinguish this listing tool from its query/search siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so tag, limit (default 100, range 1–500), and folder are all documented in the schema. The description only gestures at folder/tag filtering and omits limit, adding no syntax or format detail. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List notes") plus its filter scope, so an agent knows what it does. However, it does not differentiate from overlapping siblings like search, query_notes, or read_notes, so it falls short of the top band.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase "optionally filtered by folder prefix or tag" hints at usage but gives no when-to-use, when-not, or named alternatives. An agent choosing between this and query_notes/search gets no routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_tagsA
Read-only

List all tags in the vault with usage counts. Supports substring filtering, minimum count threshold, and sort order. Nested tags (e.g. area/work) include a parent field.

ParametersJSON Schema
NameRequiredDescriptionDefault
sortNoSort by usage count descending (default) or alphabetically.
patternNoSubstring filter on tag name. Example: "work" matches "work" and "area/work".
minCountNoOnly return tags used in at least this many notes.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already signals a safe read operation. The description adds useful behavioral details—that all tags are returned, filtering behaviors, and that nested tags include a parent field—which goes beyond the annotation's minimal information.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences deliver the purpose, options, and a notable output feature with zero redundancy. Front-loaded with the primary action and immediately informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with no output schema, the description covers the return contents (usage counts, parent field for nested tags) and behavioral parameters fully. No gaps are apparent for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers all parameters with descriptions (100% coverage), so the description adds no significant new meaning about inputs. It merely reiterates what the schema already specifies, meeting the baseline but not exceeding it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Describes a specific action ('List all tags in the vault') with clear scope and distinguishes itself from siblings by focusing solely on tags. The mention of usage counts and nested tags further specifies the tool's unique function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While it doesn't explicitly contrast with alternatives, there is no other tag-listing tool among siblings, making the purpose self-evident. It provides clear context but omits explicit exclusions or when-to-use guidance beyond its self-description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_writesA
Read-only

List recent writes from the journal — every write tool records the pre-image of each file it touches, so any of them can be reverted with undo_write. Returns compact metadata rows (seq, timestamp, tool, paths, undoable), never note content.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoOnly entries that touched this vault-relative path.
limitNoMax entries to return, newest first (1–200, default 20).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only, and the description reinforces that by promising metadata rows and explicitly stating 'never note content.' It adds value beyond the annotation by disclosing the exact fields returned (seq, timestamp, tool, paths, undoable) and explaining the pre-image journaling mechanism that makes undo_write possible.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences front-load the main purpose, then add the key behavioral constraint and output shape. Every sentence earns its place, and there is no redundant repetition of the tool name or schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description explicitly lists the returned fields and their nature, so an agent knows what response to expect. Combined with full schema coverage for optional parameters, this is complete enough for a low-complexity list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with both path and limit already described in the input schema. The tool description does not need to repeat parameter details; it adds context about the journal concept but no additional parameter-level semantics. Baseline 3 is appropriate because the schema carries the parameter documentation burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('List recent writes') and the resource ('the journal'), making the tool's purpose immediately obvious. It also distinguishes this from content-focused tools by explicitly noting it returns metadata and never note content, which separates it from siblings like list_notes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: this tool is for reviewing write operations and identifying entries that can be reverted with undo_write. It does not explicitly say 'use this instead of list_notes' or list exclusions, but the connection to undo_write and the metadata-rows framing gives enough context for an agent to choose it appropriately.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

move_noteA
Destructive

Move or rename a note to a new vault-relative path, rewriting wikilinks and markdown links in other notes that point at it so nothing breaks (links inside fenced code blocks are left alone). Parent directories at the destination are created automatically. Fails if the destination already exists unless overwrite is true.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesVault-relative destination path.
fromYesVault-relative source path.
prevHashNoOptional compare-and-swap guard on the source note: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
overwriteNoOverwrite destination if it exists. Defaults to false.
rewriteLinksNoRewrite references in other notes to follow the move. Defaults to true; pass false to move the file only.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses concrete behavioral traits: it rewrites wikilinks and markdown links in other notes while leaving fenced code blocks untouched, auto-creates parent directories, and fails if the destination exists unless overwrite is true. This is rich, actionable context that goes well beyond the annotation and helps an agent anticipate side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the primary purpose, followed by critical behaviors (link rewriting, directory creation, overwrite failure). No filler — every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with 5 parameters and no output schema, the description covers the main side effects (link rewriting, directory creation, failure conditions) and explains the overwrite and rewriteLinks parameters behaviorally. The prevHash guard is documented in the schema but not in the description; however, the agent can infer it from the parameter description. Given the complexity, this is complete enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter already has a clear meaning. The description adds context around rewriteLinks (rewriting links in other notes) and overwrite (failure behavior) but does not add new information for from, to, or prevHash beyond the schema. It sits at the baseline of 3 because the schema carries the parameter explanation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Move or rename a note to a new vault-relative path' — a clear verb, resource, and target location. It explicitly describes the link-rewriting side effect, distinguishing it from destructive delete_note and heading-renaming rename_heading.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly conveys when to use the tool (moving/renaming notes) and details the overwrite and link-rewriting behavior. It does not explicitly name alternative tools, but the purpose is unambiguous given the sibling list; this falls short of a perfect 5 that requires explicit when-not/alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

outline_noteA
Read-only

Return a note's structure — heading tree with offsets, block-reference anchors, and frontmatter key list — without returning any prose. Use this before section reads or patches to discover what sections exist at a fraction of the cost of reading the full note.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path to the note.
includeSizesNoInclude per-section character length in each heading entry. Default false.
includeBlocksNoInclude block-reference anchors (^id). Default true.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds meaningful behavioral context: it returns only structural data (headings, offsets, anchors, frontmatter keys) and explicitly excludes prose. It also signals a performance advantage ('fraction of the cost'), which is not in the annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero wasted words. The most critical information (what it returns and what it excludes) is front-loaded, and the usage guidance is packed efficiently into the second sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers the return value (heading tree, offsets, anchors, frontmatter keys), the exclusions (no prose), and the usage context (before reads/patches). With only 3 well-documented parameters and read-only annotations, nothing essential is missing for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description doesn't add extra semantics to the parameters beyond what the schema already states, but it does clarify the overall output context (e.g., 'frontmatter key list' implies what includeFrontmatter might do). No compensation needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Return') with a precise resource ('a note's structure') and enumerates the components (heading tree, offsets, block-reference anchors, frontmatter key list). It clearly distinguishes from siblings like read_note by explicitly saying 'without returning any prose,' so an agent knows exactly what it gets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance: 'Use this before section reads or patches to discover what sections exist at a fraction of the cost of reading the full note.' This tells the agent the ideal scenario and why it's preferable to full reads, effectively excluding alternatives like read_note.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

patch_frontmatterA
DestructiveIdempotent

Set, update, or delete frontmatter keys without reordering existing keys or changing quote style. Pass null as a value to delete a key.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path to the note.
patchYesKey-value pairs to set. Null value removes the key.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses important behavioral traits: it preserves key ordering and quote style, and explicitly explains that null values delete keys. These details go beyond the annotations (readOnlyHint=false, destructiveHint=true), which only indicate mutation and destructiveness. It adds useful context without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that states the core action, key guarantees, and deletion semantics. No filler or repetition; every clause adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the essential behavior, deletion semantics, and safety guarantees. It does not mention error cases like hash_conflict, but those are captured in the schema. It also omits prerequisites (e.g., note must exist), but given the simple tool and existing schema, the description is near-complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all three parameters. The description repeats the null-deletion behavior for the patch parameter, which is also stated in the schema, and adds no new semantic information beyond what is structured. Thus baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: setting, updating, and deleting frontmatter keys. It specifies the resource (frontmatter keys) and includes a concrete behavioral guarantee (preserving key order and quote style), which distinguishes it from sibling tools like patch_note that modify note content.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives such as patch_note or replace_in_note. The description gives no context on selection criteria, exclusions, or comparative advantages beyond the formatting guarantee.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

patch_noteA
Destructive

Surgically edit a section of a note — targeted by heading or block reference — without rewriting the whole file. Operations: append (add after section), prepend (add after heading line), replace (swap section content). Frontmatter is never touched.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path to the note.
targetYesExactly one of: { heading: "Section Title" } or { block: "block-id" } (without the ^ prefix).
contentYesContent to insert or replace with.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
operationYesappend: insert after section content. prepend: insert after heading line. replace: swap section content.
createIfMissingNoIf the heading target is not found, append a new heading (level 2) + content. Only valid for heading targets. Default false.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, so the mutation nature is known. The description adds valuable behavioral context beyond annotations: edits are surgical and localized ('without rewriting the whole file'), and frontmatter is never touched. This meaningfully clarifies the blast radius of a destructive operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. It front-loads the core purpose and operation model, then adds a key safety guarantee. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with rich schema coverage and annotations, the description covers the essential behavior: targeted section editing, operation types, and frontmatter safety. It could mention failure behavior for missing targets, but the schema already covers createIfMissing and prevHash behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all six parameters thoroughly. The description restates operation semantics in prose but does not add meaning beyond the schema, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Surgically edit'), a resource ('a section of a note'), and a precise targeting mechanism ('targeted by heading or block reference'). It also distinguishes itself from sibling tools by noting 'without rewriting the whole file' and 'Frontmatter is never touched'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when this tool is appropriate: surgical section edits with append, prepend, or replace operations, and explicitly excludes frontmatter. It does not name sibling alternatives like patch_frontmatter or append_note, but the scope and exclusion are enough to guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_notesA
Read-only

Structured metadata query — filter notes by frontmatter key/value predicates, tag, folder, modified time, and size. Returns compact rows (path + title by default; opt into more via select), not note content. Use this instead of search when filtering by properties rather than text.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoRestrict to notes with this tag. # optional, case-insensitive; nested child tags match ("project" matches project/alpha).
sortNoSort field (default path).
limitNoMax results (1–500, default 100).
orderNoSort order (default asc).
whereNoFrontmatter predicates — all must match (AND).
folderNoRestrict to a vault-relative folder prefix.
selectNoExtra fields per hit: frontmatter keys, or "mtime", "size", "tags". Default returns only path + title.
maxSizeBytesNoOnly notes at most this many bytes.
minSizeBytesNoOnly notes at least this many bytes.
modifiedAfterNoOnly notes modified at or after this ISO 8601 date/time.
modifiedBeforeNoOnly notes modified before this ISO 8601 date/time.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and openWorldHint=false, so safety is already covered. The description adds real context beyond them: the return shape (compact rows, path + title by default, more only via select) and the negative statement that note content is not returned. It does not discuss pagination or result-count limits beyond what the schema's limit already says.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, zero padding, front-loaded with what it queries and immediately followed by what it returns and when to prefer it. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description must explain return values, and it does precisely: compact path+title rows by default, expanded via select, no note content. Combined with 100% schema coverage and read-only annotations, nothing needed to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with per-parameter docs including operator semantics and tag nesting, so the schema carries the load and the baseline is 3. The description only restates the filter categories and hints at select, adding no format or syntax detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (structured metadata query over notes) and enumerates the filter axes: frontmatter predicates, tag, folder, modified time, size. It also names the sibling it is not (search) and the axis that separates them, so an agent can disambiguate without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says "Use this instead of search when filtering by properties rather than text," naming both the alternative and the selecting condition. That is exactly the when-to-use/when-not guidance a routing decision needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_noteA
Read-only

Read a note or a span of it — by heading section, block reference, or line range. Returns structured JSON with the content, bytes returned, total note size, and a contentHash to pass as prevHash to edit tools for compare-and-swap. Use search or outline_note first to find the right path and section names.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path, e.g. "Daily Notes/2026-05-29.md".
blockNoReturn only the line anchored by this block id (^ prefix optional).
linesNoReturn only this line range (1-indexed, inclusive).
sectionNoReturn only this heading section (heading text, # prefix optional). First match wins.
includeFrontmatterNoPrepend frontmatter to section/block span results. Default false for spans.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses the exact JSON return shape (content, bytes returned, total note size, contentHash) and the hash's purpose for compare-and-swap with edit tools. This behavioral context is not captured in annotations and is valuable for the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences: first states the operation and modes, second the return value, third the usage context. It is front-loaded with the core purpose and contains zero wasted words, making it efficiently structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, a nested object, and no output schema, the description covers the return structure, the purpose of contentHash, and the prerequisite discovery steps. An agent has everything needed to call the tool correctly and understand its output without ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully describes all five parameters (100% coverage), so the description adds no extra parameter meaning. The mention of block reference and line range merely echoes schema descriptions; no new semantics are introduced, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (read) and resource (note or span), enumerates three selection modes (heading section, block reference, line range), and distinguishes it from siblings like outline_note and search by its read-only content-return focus. The purpose is unambiguous and the description clearly differentiates the tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells the agent to use search or outline_note first to find the path and section names, and explains the contentHash is to pass as prevHash to edit tools for compare-and-swap. This provides clear when-to-use guidance and ordering, effectively routing the agent to the correct prerequisite tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_notesA
Read-only

Read up to 20 notes (or spans of them) in one call instead of repeated read_note calls, e.g. the top hits from search, query_notes, list_notes, or get_backlinks. Each item takes the same options as read_note and returns the same fields, in request order. budgetBytes (default 16384) caps the total note text: when the notes exceed it, each is cut to a fair share, marked truncated: true, and keeps noteBytes, so read the rest with read_note. A failing item (missing path, unknown section) returns its own error without failing the batch. contentHash is always the whole file's hash, usable as prevHash.

ParametersJSON Schema
NameRequiredDescriptionDefault
itemsYesNotes to read, 1–20. Same options as read_note.
budgetBytesNoCap on total note text returned across all items, in UTF-8 bytes (256–65536, default 16384).

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnlyHint/openWorldHint annotations: it discloses budgetBytes truncation semantics (fair-share cut, truncated: true, noteBytes retained for continuation), per-item error isolation ('a failing item returns its own error without failing the batch'), and that contentHash is always the whole-file hash usable as prevHash. These are non-obvious behaviors an agent could not derive from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then batching rationale, then budget/truncation behavior, then error isolation and contentHash. Four dense sentences with no filler; each one carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description compensates by describing the return contract (same fields as read_note, in request order, truncated flag, noteBytes, contentHash). Combined with rich budget/error semantics, an agent has everything needed to call it correctly and handle partial results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: the default value and unit of budgetBytes, its truncation behavior, and the cross-item semantics ('each item takes the same options as read_note'). It does not restate the per-field span options, which the schema already handles well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource with explicit batch scope: 'Read up to 20 notes (or spans of them) in one call instead of repeated read_note calls.' This immediately distinguishes it from the sibling read_note by cardinality and by naming the upstream tools whose output feeds it (search, query_notes, list_notes, get_backlinks).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names when to use it (bulk-fetching top hits from search/query_notes/list_notes/get_backlinks) and routes the agent to the alternative for follow-up ('read the rest with read_note'). Both the when and the fallback path are stated, not inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_headingA
Destructive

Rename a heading in a note and rewrite every [[note#heading]] wikilink and embed across the vault so references keep working — aliases preserved, fenced code blocks left alone. Served from the warm backlink index, no vault scan. Heading matching is case-insensitive; with duplicate headings the first match wins, mirroring Obsidian link resolution.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path of the note containing the heading.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
newHeadingYesNew heading text, without # markers. Must not contain newlines, "[", "]", "|", or "#".
oldHeadingYesCurrent heading text, without # markers. Case-insensitive; first match wins.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite having annotations, it adds valuable context about case-insensitivity, first-match-wins on duplicates, and skipping code blocks. It doesn't contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences pack a lot of precise information: what it does, how it works (warm backlink index), and key edge-case behaviors. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a rename operation, it covers the mutation, the link rewriting, the index source, and important resolution semantics. It could elaborate on return values, but the description is comprehensive for typical usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the schema already documents each parameter. The description adds value by explaining the exact behavior of heading matching and what happens with the prevHash guard.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it renames a heading and rewrites links and embeds across the vault, which distinguishes it from simple rename or edit tools. It mentions specific behavioral nuances like alias preservation and ignoring fenced code blocks.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies this tool is for renaming headings specifically, not for other edits, and mentions how it handles duplicate headings. It doesn't explicitly mention alternative tools, but the context is clear for when to use this over a generic edit tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

replace_in_noteA
Destructive

Find and replace text within a note body. Supports literal and regex search, case sensitivity, whole-word matching, and a replacement limit. Frontmatter is never touched. Use dryRun to preview matches before writing.

ParametersJSON Schema
NameRequiredDescriptionDefault
findYesText or pattern to find.
pathYesVault-relative path to the note.
limitNoMaximum number of replacements. Omit to replace all.
regexNoTreat find as a regular expression. Default false.
dryRunNoIf true, report matches without writing. Default false.
replaceYesReplacement text. Supports $1, $2, … backreferences in regex mode.
prevHashNoOptional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.
wholeWordNoMatch whole words only (\b boundary). Default false.
caseSensitiveNoCase-sensitive matching. Default false.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and readOnlyHint=false, so the write nature is known. The description adds valuable behavioral context beyond that: it clarifies that frontmatter is never affected (scope of mutation) and recommends dryRun for previewing. It does not discuss failure modes like hash_conflict, but the schema documents that, and the bar is lower given the annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff. The core purpose is front-loaded, and the supporting details (feature list, frontmatter exclusion, dryRun tip) follow in a logical order. Every sentence earns its place, and nothing is redundant with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 9 parameters and no output schema, the description could do more to explain return values or error conditions. It does not mention what the tool returns on success (e.g., count of replacements, updated content) or how it reports failures like hash_conflict or note-not-found. The schema and annotations cover some aspects, but the lack of output guidance leaves a gap for a mutation tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all 9 parameters are individually documented. The description adds only a high-level summary of capabilities ('Supports literal and regex search, case sensitivity, whole-word matching, and a replacement limit') and a tip about dryRun, but this does not meaningfully augment the schema, which already explains each parameter's semantics. Thus, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the resource and action: 'Find and replace text within a note body.' It goes beyond a simple verb by listing supported features (literal/regex, case sensitivity, whole-word, limit) and explicitly excludes frontmatter, which distinguishes it from sibling tools like patch_frontmatter or append_note. An agent can immediately understand what it does without needing to inspect the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: it is for body text replacement, and explicitly states 'Frontmatter is never touched,' which serves as a when-not-to-use boundary. It also advises using dryRun to preview before writing, which is a concrete usage tip. However, it does not name any alternative sibling tools, so it stops short of a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

undo_writeA
Destructive

Revert a journaled write: restores every file it touched to its byte-identical pre-write state (a multi-file move or heading rename is restored whole; a delete is restored even if it was permanent). Defaults to the most recent undoable write. Refuses with undo_conflict if a file changed since that write, unless force: true. The undo is itself journaled — undo it to redo.

ParametersJSON Schema
NameRequiredDescriptionDefault
seqNoJournal entry to revert (from list_writes). Defaults to the most recent undoable write.
forceNoRestore even if a file changed after the journaled write; the clobbered state is journaled first so nothing is lost. Defaults to false.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, and the description adds substantial behavioral detail beyond that: byte-identical restoration, whole-operation restoration for multi-file changes, handling of permanent deletes, the undo_conflict guard, the effect of force, and the fact that the undo is itself journaled and can be undone to redo. This is exemplary disclosure of side effects and edge cases.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence carries necessary information, and key facts are front-loaded: what the tool does, how it handles tricky cases, then defaults and conflict behavior. Despite covering complex semantics, the description remains compact and well-ordered with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that there is no output schema, the description still tells the agent everything needed to invoke the tool correctly: default target, failure mode, force escape hatch, permanent-delete restoration, and redo possibility. The reference to list_writes in the schema completes the workflow context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description reinforces the schema's default behavior for seq and explains the force semantics, but it does not add significantly new parameter-level information beyond what the input schema already provides. The description's added value is mostly behavioral, not parameter-specific.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Revert a journaled write' and precisely defines the effect ('restores every file it touched to its byte-identical pre-write state'). It also distinguishes the tool's scope by giving concrete examples like multi-file moves, heading renames, and permanent deletes, leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational guidance: it defaults to the most recent undoable write, explains the undo_conflict refusal condition, and clarifies how force:true changes the behavior. While it does not explicitly state 'use list_writes to find a seq,' the schema parameter references list_writes, and there is no competing sibling tool for undo operations, so the context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.3.26
    • Changedcontext_pack1 field changed
      • changedInput schema / properties / tag / description
        Previous value: -"Restrict to notes with this tag."New value: +"Restrict to notes with this tag. # optional, case-insensitive; nested child tags match (\"project\" matches project/alpha)."
    • Changedlist_notes1 field changed
      • changedInput schema / properties / tag / description
        Previous value: -"Filter by tag (# prefix optional)."New value: +"Filter by tag. # optional, case-insensitive; nested child tags match (\"project\" matches project/alpha)."
    • Changedquery_notes1 field changed
      • changedInput schema / properties / tag / description
        Previous value: -"Restrict to notes with this tag (# optional)."New value: +"Restrict to notes with this tag. # optional, case-insensitive; nested child tags match (\"project\" matches project/alpha)."
    • Addedread_notes
    • Changedsearch1 field changed
      • changedInput schema / properties / tag / description
        Previous value: -"Restrict to notes with this tag."New value: +"Restrict to notes with this tag. # optional, case-insensitive; nested child tags match (\"project\" matches project/alpha)."
  2. 3 tool updatesv0.3.25
    • Changedcontext_pack3 fields changed
      • addedInput schema / properties / folder
        Added value: +{
        +  "description": "Restrict to a vault-relative folder prefix.",
        +  "type": "string"
        +}
      • addedInput schema / properties / mode
        Added value: +{
        +  "description": "lexical = keyword search (default). semantic = meaning-based over local embeddings (needs SEEKSTONE_SEMANTIC=1 and a fetched model). hybrid = exact-title lookups go lexical, everything else semantic.",
        +  "enum": [
        +    "lexical",
        +    "semantic",
        +    "hybrid"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / tag
        Added value: +{
        +  "description": "Restrict to notes with this tag.",
        +  "type": "string"
        +}
    • Changedpatch_note2 fields changed
      • addedInput schema / properties / target / anyOf
        Added value: +[
        +  {
        +    "properties": {
        +      "heading": {
        +        "description": "Heading text (without # markers).",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "heading"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "block": {
        +        "description": "Block reference ID (without the ^ prefix).",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "block"
        +    ],
        +    "type": "object"
        +  }
        +]
      • removedInput schema / properties / target / type
        Removed value: -"object"
    • Changedquery_notes1 field changed
      • addedInput schema / properties / where / items / properties / value / type
        Added value: +[
        +  "string",
        +  "number",
        +  "boolean"
        +]
  3. 2 tool updatesv0.3.22
    • Addedlist_writes
    • Addedundo_write
  4. 1 tool updatev0.3.19
    • Changedsearch1 field changed
      • addedInput schema / properties / excerptLength
        Added value: +{
        +  "description": "Max characters of match context per hit (20–2000, default 120).",
        +  "type": "number"
        +}
  5. 3 tool updatesv0.3.18
    • Changeddelete_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since — so you never delete content you have not seen.",
        +  "type": "string"
        +}
    • Changedmove_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard on the source note: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changedsearch1 field changed
      • addedInput schema / properties / mode
        Added value: +{
        +  "description": "lexical = keyword search (default). semantic = meaning-based search (requires SEEKSTONE_SEMANTIC=1). hybrid = exact-title lookups go lexical, everything else semantic.",
        +  "enum": [
        +    "lexical",
        +    "semantic",
        +    "hybrid"
        +  ],
        +  "type": "string"
        +}
  6. 2 tool updatesv0.3.17
    • Addedcontext_pack
    • Addedrename_heading
  7. 7 tool updatesv0.3.16
    • Changedappend_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changedappend_periodic_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changedcreate_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changeddelete_note1 field changed
      • addedInput schema / properties / permanent
        Added value: +{
        +  "description": "Permanently remove instead of moving to .trash/. Defaults to false.",
        +  "type": "boolean"
        +}
    • Changedpatch_frontmatter1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changedpatch_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
    • Changedreplace_in_note1 field changed
      • addedInput schema / properties / prevHash
        Added value: +{
        +  "description": "Optional compare-and-swap guard: the contentHash from a prior read. Fails with hash_conflict if the note changed since.",
        +  "type": "string"
        +}
  8. 1 tool updatev0.3.15
    • Changedmove_note1 field changed
      • addedInput schema / properties / rewriteLinks
        Added value: +{
        +  "description": "Rewrite references in other notes to follow the move. Defaults to true; pass false to move the file only.",
        +  "type": "boolean"
        +}
  9. 1 tool updatev0.3.13
    • Addedquery_notes
  10. 2 tool updatesv0.3.8
    • Addedappend_periodic_note
    • Addedget_periodic_note
  11. 1 tool updatev0.3.7
    • Addedreplace_in_note

TDQS

A3.9/5.0

Scored across 22 tools

Disambiguation4/5

Most tools target distinct resources/actions and descriptions explicitly disambiguate tricky pairs (search vs query_notes vs context_pack; read_note vs read_notes). Minor overlap exists around append_note vs patch_note (both append) and the periodic-note variants vs their generic counterparts, but descriptions draw clear boundaries.

Naming Consistency4/5

Nearly all names follow a consistent snake_case verb_noun pattern (get_backlinks, create_note, patch_frontmatter, undo_write). A few deviations like 'search' (bare verb) and 'context_pack' (noun-oriented) slightly break the pattern but remain readable and predictable.

Tool Count4/5

22 tools is on the heavier side, but for a full-featured Obsidian vault server spanning search, metadata, links, headings, frontmatter, periodic notes, and a write journal, each tool earns its place with little redundancy.

Completeness5/5

The surface covers the full lifecycle: create/read/list/delete/move, structured and semantic search, metadata queries, tags, backlinks/outlinks, section/frontmatter/heading patching, periodic notes, and journaled undo/redo. No obvious dead ends for the note-management domain.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

Appeared in Searches