Skip to main content
Glama

vaults-hub

M8ven Score npm

A Python MCP server that exposes your Obsidian-style Markdown vaults to MCP clients (e.g. OpenCode).

Keep each project's docs as plain Markdown on disk, and let an agent read and maintain them through a small, predictable tool API — no Obsidian plugins, windows, ports, or API keys. Every change is auto-versioned with local git, so nothing is ever truly lost.

Quickstart

The fastest way — no clone, no venv. Published on npm as vaults-hub:

npx -y vaults-hub

This needs Python 3.10+ on PATH (or VAULTS_HUB_PYTHON set to its path); CI tests 3.10, 3.12 and 3.14. On first run it bootstraps the pinned dependencies from requirements.txt into a cached venv (one-time, ~30s; later runs start instantly); see Configuration for the cache location.

From source (offline/dev alternative) — prereqs are Python 3.10+ (developed/tested on 3.14), a POSIX platform (Linux/macOS — locking uses fcntl), and optionally ripgrep (rg) for faster search (a pure-Python fallback is used when rg is absent):

git clone https://github.com/ishaan-jindal/vaults-hub.git vaults-hub
cd vaults-hub
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python server.py                        # stdio MCP server (no HTTP port)

Vaults live in ~/.vaults by default (each subdir is one vault, e.g. ~/.vaults/MyProject/), auto-created on startup when missing. To use a different location:

export VAULTS_ROOT="$HOME/my-notes"
python server.py --vaults-root "$HOME/my-notes"   # flag wins over env var

Register with OpenCode

Add to your opencode.jsonc (adjust paths to your machine — do not copy any hardcoded home directory). The npx form is recommended:

{
  "mcp": {
    "vaults": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "vaults-hub"],
      // Pick ONE way to point at your vaults (flag wins over env var):
      "environment": {
        "VAULTS_ROOT": "<path-to-your-vaults>"
      }
    }
  }
}

The local-venv form is the offline/dev alternative (replace with the actual paths on your machine):

{
  "mcp": {
    "vaults": {
      "type": "local",
      // Replace with the actual paths on your machine:
      "command": ["<path-to-vaults-hub>/.venv/bin/python", "<path-to-vaults-hub>/server.py"],
      // Pick ONE way to point at your vaults (flag wins over env var):
      "args": ["--vaults-root", "<path-to-your-vaults>"],
      "environment": {
        // ...or via env var instead of "args" above:
        "VAULTS_ROOT": "<path-to-your-vaults>"
      }
    }
  }
}

Related MCP server: obsidian-kb

Usage examples

Vault layout: each project is a directory directly under VAULTS_ROOT containing .md files, e.g. <VAULTS_ROOT>/MyProject/MyProject.md.

With the server registered as vaults:

  • List vaults: call list_vaults → [{"name": "MyProject", "path": "...", "notes": 12}]

  • Read a note: read_note(vault="MyProject", path="MyProject.md") → frontmatter, content, wiki-links, backlinks

  • Write safely: read_note → edit → write_note(..., expected_sha256="<sha from read>") to avoid clobbering concurrent edits

  • Search: search_notes(query="build command", vault="MyProject", before=1, after=1)

  • Recover a note: history(vault="MyProject", path="Notes.md") → pick a sha → restore(vault="MyProject", path="Notes.md", rev="<sha>")

Tools

14 tools (see vaults/server.py for exact descriptions). Read-only tools are marked R, mutating tools M (write_note/append_note/move_note/restore honor expected_sha256 for optimistic concurrency — read first, then pass the sha back; delete_note has no sha guard and delete_vault is gated on confirm instead):

Tool

R/M

What it does

list_vaults

R

List all project vaults with note counts

server_info

R

Server version, Python/platform, git + ripgrep availability, git_enabled, vaults root, vault count

create_vault

M

Create a new vault (created=False when it already exists; idempotent)

delete_vault

M

Delete a whole vault including git history (irreversible; confirm must equal the vault name)

list_notes

R

List dirs/notes under a vault path (recursive=True for flat listing); paginated with offset/limit (default 200, max 500) → total, truncated, next_offset

read_note

R

Read a note: frontmatter, content, wiki-links, backlinks, unresolved links

write_note

M

Create or atomically overwrite a note (expected_sha256 for optimistic concurrency)

append_note

M

Append text to a note (created if missing), atomic write, optional expected_sha256

delete_note

M

Delete a note (missing_ok=True to tolerate absence); lock files are left in place

move_note

M

Move/rename a note (copy+delete, not atomic); errors if src missing or dst exists; honors expected_sha256; refreshes updated:

list_tags

R

Tag counts per vault from cached frontmatter (one vault or all)

search_notes

R

Full-text search of .md notes via ripgrep (or Python fallback) across one vault or all, with before/after context lines; limit 1–200 with a truncated flag

history

R

Version history for a note ([{sha, date, message}]) or whole vault from the local git repo, with a truncated flag

restore

M

Restore a note from a past revision (snapshots dirty state first; recreates deleted notes); echoes the revision as restored_from

Also built in: YAML-frontmatter parsing with auto-refreshed updated: dates, file locking (fcntl), atomic writes via temp-file + rename, backlink/tag indexes with mtime invalidation, and optional debug logging to file.

Tool annotations

Every tool declares all four MCP ToolAnnotations hints explicitly, so hosts that gate on them (OpenAI's tool directory rejects a tool where any hint is missing or non-boolean) accept the whole set:

Hint

Meaning here

Value

readOnlyHint

does not modify the vault

true for the 7 read tools, false for the rest

destructiveHint

may destroy or overwrite existing data

true for write_note, append_note, move_note, delete_note, delete_vault, restore; false elsewhere

idempotentHint

repeat calls add no further effect

true for the 7 read tools and create_vault; false otherwise

openWorldHint

touches entities outside the vaults root

false for every tool — this server is closed-world by construction

The hints are hints, not guarantees: a client must not make trust decisions from them alone. They matter because the stdio writer serializes tool payloads with exclude_none=True, so an unset hint is dropped from tools/list entirely rather than sent as null. smoke_test.py asserts all four are present booleans on all 14 tools, so a new tool cannot silently reintroduce the gap.

Reliability

How the server avoids losing or corrupting notes:

  • Atomic writes. Every note write goes to a temp file in the same directory (fsynced, then os.replace), with the parent directory fsynced afterwards — readers never see a half-written note. Existing file permissions are preserved.

  • Locking. Mutations serialize per note (flock read-modify-write cycles across processes) and git operations serialize per vault, with a consistent lock order everywhere (note lock first, git lock inside it), so concurrent writes and restores cannot deadlock. Read-only history takes no locks and never blocks writers; truncation flags are computed by the core library, not the tool boundary.

  • Optimistic concurrency. write/append/move/restore accept expected_sha256; a stale sha is rejected instead of clobbering someone else's edit. delete_note has no sha guard; delete_vault is instead gated on confirm exactly equaling the vault name.

  • Fail-open versioning. The write itself is the source of truth — a missing git binary or failed commit warns (surfaced as commit_error) but never blocks the write.

  • Search parity. search_notes prefers rg --json and falls back to pure Python when ripgrep is absent; both sides search only .md notes, skip dotfiles, .obsidian/ and symlinks, and ignore .gitignore, so results match whichever backend runs. Regex syntax is the exception: ripgrep uses Rust regex, the fallback Python re, so lookarounds and backreferences are not portable.

  • No lossy rewrites. append_note, move_note and restore refuse content that is not valid UTF-8 instead of replacing bytes, and keep existing CRLF line endings.

  • No surprise frontmatter. Notes without a frontmatter block stay that way; updated: is only refreshed (or inserted) when a block exists.

  • Fresh indexes. Backlink/tag indexes are invalidated by mtime, so external edits are picked up on the next read. Like listings and search, they skip notes in hidden folders such as .obsidian/ and .trash/.

  • Symlink confinement. Symlink targets resolving outside the vault are rejected — a link can never pull reads or writes out of the vault. Escaping wiki-link path targets (e.g. [[../Outside.md]]) are treated as unresolved; list_notes skips escaping symlink entries instead of failing. A vault directory that is itself a symlink is not listed, searched, or counted in list_tags.

Configuration

Variable

Default

Purpose

VAULTS_ROOT

~/.vaults

Root dir; each immediate subdir is one vault

VAULTS_HUB_DEBUG

unset

Set to 1 to enable debug file logging; anything else disables it

VAULTS_HUB_GIT

unset (versioning on)

Set to 0 to disable git versioning; history/restore then return errors

Precedence for the vaults root: --vaults-root <dir> flag > VAULTS_ROOT env var > default ~/.vaults. Whatever wins is auto-created on startup when missing.

Notes:

  • ripgrep is optional. If rg is on PATH, search_notes uses rg --json; otherwise a pure-Python fallback with the same results is used. No configuration needed either way.

  • POSIX-only. File locking uses fcntl, so Windows is not supported.

  • npx launcher. VAULTS_HUB_PYTHON overrides which Python the vaults-hub bin uses (else python3, then python on PATH; must be 3.10+). When that interpreter lacks the pinned dependencies, the bin installs them once into a cached venv under $XDG_CACHE_HOME/vaults-hub (else ~/.cache/vaults-hub), keyed by Python minor version, and reuses it silently while the requirements.txt hash matches.

Versioning

Each vault is a local git repo (one per vault root), maintained automatically:

  • Default-on. The repo is lazily git init -b main on the first mutation; every write/append/delete/move commits path-scoped with a Sha256: trailer (e.g. vaults: write Notes.md). The write itself is the source of truth — a missing git binary or failed commit warns but never blocks the write.

  • Local-only, no push. Versioning never pushes, pulls, or fetches; identity is per-invocation (vaults-hub), never written to gitconfig. Lock/tmp files and .obsidian/ are excluded via $GIT_DIR/info/exclude (no visible .gitignore). A vault already nested inside an external repo is left alone.

  • Opt-out. Set VAULTS_HUB_GIT=0 to disable init/commits; history and restore then return clear errors.

  • history(vault, path?, limit?) lists [{sha, date, message}] (newest first, limit clamped 1–200) plus a truncated flag when more commits exist beyond the page; a deleted note keeps its history, and a path that was never committed returns [] with untracked:true. restore(vault, path, rev, expected_sha256?) writes git show rev:path back to disk atomically (snapshotting dirty state first), echoes the revision as restored_from, and can recreate deleted notes.

Testing

No test framework — one end-to-end smoke test over a temporary stdio server:

source .venv/bin/activate
python smoke_test.py

It creates fixture vaults in a temp dir, exercises all tools (including versioning and its opt-out), and exits non-zero with a traceback on failure.

Architecture (brief)

opencode (MCP client, stdio) <-> vaults/server.py (FastMCP "vaults", 14 tools) <-> ~/.vaults/<project>/*.md
  • vaults/ is the whole server: config.py (vaults root, logging, CLI), notes.py (path validation, UTF-8 checks, fcntl locks, atomic writes, SHA-256 optimistic concurrency, frontmatter/wiki-link helpers, note CRUD, vault creation), indexes.py (in-memory backlink/tag indexes with mtime-based invalidation), search.py (ripgrep + Python-fallback search), versioning.py (per-vault git layer), and server.py (FastMCP app, 14 tools). Root server.py is a thin shim so python server.py keeps working.

  • server.py keeps the event loop responsive: every tool runs its blocking library call in a worker thread via anyio.to_thread. Errors are sanitized at the tool boundary (client-safe ValueErrors pass through; anything else becomes a plain failure notice) while the server log keeps the full traceback; request logging records only vault/path.

  • smoke_test.py spawns server.py over stdio with VAULTS_ROOT pointed at a temp dir.

Limitations

  • Private SDK pin: dependencies are pinned in requirements.txt (anyio==4.15.1, mcp==1.30.0, PyYAML==6.0.3); bump deliberately and re-run python smoke_test.py.

  • Move is copy + delete, not one atomic rename: move_note writes the destination atomically, then unlinks the source — a crash between the two steps can leave both copies behind. A failed move cleans up the partial destination. It also refuses to overwrite an existing destination.

  • Wiki-link resolution is name-based: bare [[Name]] links resolve via a stem index (shortest path wins on collision); only [[path/with/slash]] links resolve as paths. Self-links are excluded from backlinks.

  • POSIX-only (fcntl locking); no Windows support.

  • No authentication: the stdio transport trusts the local client; do not expose vault contents beyond your machine without adding your own access controls.

License

MIT — see LICENSE.

Contributing

See CONTRIBUTING.md for setup, checks, and the PR flow.

Available Tools

14 tools
append_noteA
Destructive

Append text to a note (created if missing) via an atomic write. Optionally pass expected_sha256 to prevent appending to a changed note. Refreshes the frontmatter updated: date (inserted when a frontmatter block exists without one).

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-root-relative note path
textYesText to append
vaultYesVault name
expected_sha256NoSHA-256 from a prior read/write; rejects stale appends

TDQS

A4.2/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false) by disclosing auto-creation on missing notes, atomic write semantics, optimistic-concurrency rejection via expected_sha256, and the frontmatter side effect of refreshing/inserting the `updated:` date. These are exactly the mutation behaviors an agent needs before calling.

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 tight sentences, front-loaded with the core action, then the concurrency guard, then the side effect. No filler and no repetition.

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 no output schema, the description covers creation-on-missing, atomicity, the stale-write guard, and frontmatter side effects. It stops short of saying what a successful call returns or how a sha256 mismatch surfaces, which is a minor remaining 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%, so path/text/vault/expected_sha256 are already documented, and the schema's own text ('rejects stale appends') nearly duplicates the description's sha256 note. Baseline 3 is appropriate since the description adds framing but no new parameter detail.

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 ('Append text to a note') plus the important edge case that the note is created when missing. The append semantics cleanly separate it from write_note/delete_note even without naming a sibling.

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?

Usage is implied by the purpose rather than stated: nothing tells the agent when to prefer append_note over write_note, or when appending is inappropriate. The one conditional it does give ('Optionally pass expected_sha256 to prevent appending to a changed note') is helpful but parameter-level, not tool-level routing.

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

create_vaultA
Idempotent

Create a new vault (one subdirectory of the vaults root). Idempotent: returns created=False when the vault already exists.

ParametersJSON Schema
NameRequiredDescriptionDefault
vaultYesVault name

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false, so the description's restatement of idempotency adds little. However, it does contribute the concrete return behavior 'returns created=False when the vault already exists', which is valuable given there is no output 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?

Two tight clauses, front-loaded with the action and followed immediately by the idempotency/return behavior. No filler sentences.

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 single-parameter, low-complexity tool with full schema coverage and no output schema, the description covers purpose, idempotency, and the key return signal. It omits any naming/permission constraints, but nothing critical for correct invocation 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% (the 'vault' parameter is documented as 'Vault name'), so the schema already carries the burden. The description's note that a vault is a subdirectory of the vaults root adds minor semantic context but no naming rules or constraints, matching the baseline 3.

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 ('Create a new vault') and grounds it with a definition ('one subdirectory of the vaults root'), so an agent understands what is being created. It does not explicitly contrast with siblings like delete_vault or list_vaults, so it lands at clear-but-undifferentiated.

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?

Use is implied by the name and the word 'new', but there is no explicit when-to-use or when-not-to-use guidance and no mention of alternatives (list_vaults, delete_vault). Implied usage only.

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 file. Errors when missing unless missing_ok=True. Lock files are intentionally left in place.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-root-relative note path
vaultYesVault name
missing_okNoReturn success when already absent

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 and readOnlyHint=false, but the description adds genuinely non-obvious behavior: the default error-on-missing contract and the deliberate decision to leave lock files in place after deletion. It stops short of stating irreversibility or any required permission/confirmation, which for a destructive tool would be the remaining gap.

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 short sentences, front-loaded with the action, with zero filler. Each sentence carries a distinct and useful fact (action, error contract, side effect).

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 destructive single-target delete with no output schema, the description covers the action, the failure mode, the opt-out flag, and the notable lock-file side effect. It omits confirmation/permission expectations and recovery options, but nothing critical for correct invocation is missing.

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 schema already documents all three parameters. The description nonetheless adds meaning by expressing missing_ok as 'Errors when missing unless missing_ok=True', which makes the tool's default error behavior explicit in a way the schema's 'Return success when already absent' only implies.

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 ('Delete a note file'), which cleanly separates it from delete_vault and from non-destructive siblings like write_note or move_note. The agent knows exactly what the call does without opening 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 Guidelines3/5

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

Usage is implied by the purpose and the description does give the failure condition ('Errors when missing unless missing_ok=True'), which helps the caller decide how to invoke it. However, there is no explicit when-to-use/when-not guidance or routing to an alternative (e.g. restore, move_note) for a destructive operation.

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

delete_vaultA
Destructive

Delete a whole vault: removes every note, lock file and the git history. Irreversible with no undo in this server; confirm must exactly equal the vault name.

ParametersJSON Schema
NameRequiredDescriptionDefault
vaultYesVault name
confirmYesMust exactly equal the vault name

TDQS

A4.5/5.0
Behavior5/5

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

Annotations declare destructiveHint=true and non-idempotent, but the description goes further by specifying exactly what is destroyed (notes, lock files, git history) and that the action is irreversible with no in-server undo. That is precisely the extra context 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.

Conciseness5/5

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

Two compact sentences: destruction scope first, then the irreversible warning and the confirm requirement. Zero filler and the riskiest information is front-loaded.

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, and none is needed for a delete. The description covers destruction scope, reversibility, and the confirmation guard, which is everything an agent needs to invoke this safely.

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 schema already documents both the vault and confirm parameters, including confirm's exact-match rule. The description repeats the confirm constraint without adding syntax or format 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 (delete), a specific resource (a whole vault), and enumerates the blast radius: every note, lock file, and git history. An agent can distinguish this from the sibling delete_note at a glance.

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?

Clearly frames this as an irreversible last-resort operation with no undo, and states the exact confirm guard required to proceed. It does not explicitly name delete_note or other safer siblings as alternatives, so the when-not guidance is implied rather than spelled out.

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

historyA
Read-onlyIdempotent

Show version history for a note (or the whole vault) from the local git repo: [{sha, date, message}] with a truncated flag when more commits exist beyond limit (clamped 1-200). An untracked path returns an empty list with untracked:true.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
limitNoMax commits (default 50)
vaultYesVault name

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already establish the safe read-only, idempotent, non-destructive profile, and the description adds real value beyond them: the return shape [{sha, date, message}], the 'truncated' flag when commits exceed limit, and the untracked-path edge case returning an empty list. Only minor gaps remain (pagination semantics beyond clamping).

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 dense sentence that front-loads the purpose and then layers return format and edge cases. Every clause carries information, though the run-on structure with parentheticals slightly hurts scannability.

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?

With no output schema, the description correctly fills that gap by describing the returned list structure and the untracked/truncated edge cases. It is nearly complete for a read-only history tool, missing only richer pagination guidance.

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 67%, with path and limit already documented (including min/max). The description largely restates the schema's vault-vs-note semantics and the 1-200 clamp, adding little param meaning beyond it, though it does reinforce the omission behavior.

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 ('Show') and resource ('version history for a note (or the whole vault)') and names the git source, clearly separating it from siblings like read_note or restore. An agent can tell what it does without opening 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 Guidelines3/5

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

It implies when it applies by distinguishing note-level from vault-level history ('or the whole vault', 'omit path'), but it never names an alternative tool or states when not to use it. Usage is inferable rather than explicit guidance.

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

list_notesA
Read-onlyIdempotent

List directories and notes under a vault path (vault-root-relative, '' for root). Pass recursive=True to list all descendant notes flat (dirs=[]). Paginate with offset/limit (default limit 200, max 500); the response carries total (full match count), truncated, and next_offset (None when done).

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoVault-root-relative dir; '' for root
limitNoMax entries (default 200)
vaultYesVault name
offsetNoSkip this many entries
recursiveNoFlat recursive listing (dirs=[])

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds genuinely useful behavior beyond that: the recursive flattening side effect (dirs=[]), default/pagination bounds (limit 200, max 500), and the shape of the response (total, truncated, next_offset).

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 dense sentences ordered purpose → recursion behavior → pagination/return fields, with no filler. Every clause carries operational information and the most important scoping detail is 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?

With no output schema, the description correctly shoulders the burden of explaining returns (total, truncated, next_offset, dirs on recursion), which is the critical piece for a paginated list tool. It omits result ordering/sort behavior, which matters for offset-based pagination, preventing a 5.

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 schema already documents all five parameters ('Vault-root-relative dir', 'Max entries', 'Skip this many entries', 'Flat recursive listing'). The description largely restates these and adds only the interaction between recursive mode and dirs being emptied, so baseline 3 is appropriate.

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?

The description states a specific verb+resource combination ('List directories and notes under a vault path') with explicit scoping ('vault-root-relative, '' for root'), which clearly separates it from search_notes and list_vaults. It stops short of naming a sibling tool, so an agent must infer the browsing-vs-search distinction from the scope wording alone.

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?

Conditional usage is implied through 'Pass recursive=True to list all descendant notes flat (dirs=[])' and the pagination instructions, which tell the agent how to operate the tool. However, it never states when to prefer this over search_notes (e.g., exact browsing vs. query matching) or when not to use it, leaving tool selection to inference.

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

list_tagsA
Read-onlyIdempotent

List tag counts per vault from cached frontmatter. Pass vault for one vault, or omit for all vaults.

ParametersJSON Schema
NameRequiredDescriptionDefault
vaultNoVault name; omit for all vaults

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description adds genuinely useful context by disclosing the data source is 'cached frontmatter', hinting that results may be derived/stale rather than live. It stops short of describing the returned shape or whether counts reflect cached vs current state.

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 with zero filler; the core behavior is front-loaded and the parameter guidance follows immediately.

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 one-optional-parameter read-only tool with no output schema, the description covers purpose, scope, and filtering. It could briefly sketch the return shape (tag→count map) since no output schema exists, but nothing needed to invoke it 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% and the single parameter is already documented as 'Vault name; omit for all vaults'. The description's 'Pass vault for one vault, or omit for all vaults' restates the schema rather than adding format or naming details. 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?

Specific verb ('List') plus a precise resource ('tag counts per vault'), with the data origin ('cached frontmatter') stated. No sibling tool returns tag data, so it is trivially distinguishable from read_note, list_notes, search_notes, etc.

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 clearly describes the two usage modes: pass a vault for a single vault, omit for all vaults. It does not, however, state when to prefer this over search_notes for tag lookups or any exclusion conditions, so it stops short of full alternative routing.

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

list_vaultsA
Read-onlyIdempotent

List all project vaults with their note counts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered without the description. The description adds only that note counts are included; it says nothing about ordering, pagination, or scope limits on 'all', and an output schema already covers the return shape.

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?

A single, front-loaded sentence with the verb first and the payload detail second. Every word earns its place and there is no filler.

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?

With no parameters, full annotation coverage, and an output schema handling return values, the description carries almost no burden and is adequate. It could be marginally better by noting the scope of 'all' (e.g., that it is unimpeded by filters), but nothing essential is missing.

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?

There are zero parameters, so there is no parameter semantics to explain and the baseline is 4. The description does not need to compensate for any coverage gap.

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 (List) and resource (project vaults) plus the payload detail (note counts), so the agent immediately knows what it returns. It is clearly distinct from list_notes and list_tags by resource, though it never names a sibling explicitly.

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?

Usage is implied: a zero-argument listing tool for vaults, so the intent is inferable from the name. However, there is no explicit when-to-use, when-not-to-use, or routing to alternatives such as list_notes when the agent actually wants note-level data.

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/rename a note via copy+delete (not atomic): the destination is written atomically, then the source is unlinked, and a partial destination is cleaned up on failure. Errors if src is missing or dst exists. Honors expected_sha256 against src. Refreshes updated:.

ParametersJSON Schema
NameRequiredDescriptionDefault
vaultYesVault name
dst_pathYesNew note path (must not exist)
src_pathYesExisting note path
expected_sha256NoSHA-256 of src from a prior read; rejects stale moves

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond annotations: disclose non-atomicity, the exact ordering (destination written, then source unlinked), partial-destination cleanup on failure, refusal when src missing or dst exists, and the updated: refresh. These are exactly the behaviors an agent needs for a destructiveHint=true, non-idempotent mutation.

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 with the mechanism and precondition front-loaded and zero filler. Every clause — atomicity caveat, ordering, cleanup, error conditions, hash check, metadata refresh — 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?

With no output schema, the description carries the full burden and does so: success behavior, failure semantics, preconditions, atomicity guarantees, and side effects are all covered, on top of annotations that already flag destructiveness and non-idempotency.

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 baseline is 3, but the description adds real semantic value: expected_sha256 is described as being honored against src to reject stale moves, which clarifies concurrency intent beyond the schema's 'rejects stale moves' phrasing. Syntax-level detail of paths is left to 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 (move/rename) plus the resource (a note) and even discloses the mechanism (copy+delete). An agent can immediately distinguish this from write_note, delete_note, or append_note in the sibling list.

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?

Provides concrete preconditions — errors if src is missing or dst exists — which tells the agent when the call will succeed, but never names alternatives (e.g., did you mean write_note + delete_note?) or states when to prefer this over them. Usage is implied rather than guided.

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

read_noteA
Read-onlyIdempotent

Read a note: frontmatter, content, wiki-links, backlinks, unresolved links.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-root-relative note path
vaultYesVault name

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so safety is covered. The description adds real value by disclosing the returned payload (frontmatter, content, wiki-links, backlinks, unresolved links), which is important given there is no output schema; it omits note-size or truncation behavior.

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 compact sentence that front-loads the verb and resource before enumerating outputs. Every clause earns its place, though it reads as a fragment rather than a structured description.

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 two-parameter read with no output schema, enumerating the returned fields is the key missing piece and it is provided. Nothing about error handling or missing-note behavior, but the core is 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?

With 100% schema description coverage for both parameters (path as vault-root-relative note path, vault as vault name), the schema carries the semantics. The description adds nothing about parameter format or edge cases, so the 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 ('read a note') and enumerates exactly what the read covers: frontmatter, content, wiki-links, backlinks, unresolved links. It does not, however, distinguish itself from siblings like list_notes or search_notes that also surface 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?

There is no statement of when to use this versus list_notes, search_notes, or history — the agent must infer usage from the tool name alone. No prerequisites, no exclusions, no alternative routing.

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

restoreA
Destructive

Restore a note's content from a past revision (git rev, e.g. a history sha); the response echoes the revision as restored_from. Snapshots dirty worktree state first; recreates deleted notes. Honors expected_sha256 against current content.

ParametersJSON Schema
NameRequiredDescriptionDefault
revYesGit revision (e.g. a history sha)
pathYesVault-root-relative note path
vaultYesVault name
expected_sha256NoSHA-256 of current content; rejects stale restores

TDQS

A4.4/5.0
Behavior5/5

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

Annotations already flag destructive and non-idempotent, but the description adds real beyond-annotation behavior: it snapshots dirty worktree state before restoring, recreates deleted notes, enforces expected_sha256 as a stale-restore guard, and reports restored_from in the response. These are non-obvious side effects an agent must know before calling.

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?

Front-loads the core action, then packs side effects into compact clauses. Dense with semicolons but every clause earns its place; only minor trimming possible.

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 destructive, non-idempotent mutation with no output schema, the description covers the safety snapshot, the concurrency guard, deleted-note handling, and the returned restored_from field. An agent has everything needed 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 rev, path, vault, and expected_sha256 are already documented. The description restates the git-rev meaning and the expected_sha256 staleness check without adding syntax or format detail beyond the schema, so 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?

States a specific verb (restore), resource (a note's content), and source (a past revision / git rev). This cleanly separates it from siblings like history (inspect) and write_note (author new content), so an agent can route to it without opening any 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?

Gives clear selecting conditions: it operates on a past revision, and it will recreate deleted notes and snapshot dirty worktree state. However it never names an alternative ('if you only want to view revisions, use history') or states when not to use it, so it stops short of full routing guidance.

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

search_notesA
Read-onlyIdempotent

Search .md note contents with ripgrep across one vault or all vaults. regex=True uses ripgrep's Rust syntax (Python re when ripgrep is absent), so lookarounds and backreferences are not portable. limit is clamped 1-200 and the response carries a truncated flag; before/after (0-10) add context lines. With context each hit keeps text (= match_line) plus before_lines/match_line/after_lines, otherwise only text.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoContext lines after each hit
limitNoMax matches (default 50)
queryYesSearch text (or regex with regex=True)
regexNoTreat query as a regular expression
vaultNoVault name; omit to search all
beforeNoContext lines before each hit
case_sensitiveNoCase-sensitive matching

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/non-destructive, and the description adds substantial behavioral context beyond them: the ripgrep backend with Python re fallback, the regex engine's lack of lookarounds/backreferences, limit clamping and a truncated flag, and the shape of returned hits with and without context. It stops short of full disclosure on error/authorization behavior, hence a 4.

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?

Front-loaded with the core action and scope, then value-dense detail on regex, limits, and output shape. Every sentence carries information, though the result-format sentence is somewhat packed.

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?

With no output schema, the description usefully compensates by describing the returned hit structure (text plus before_lines/match_line/after_lines). Coverage of search semantics, limits, and results is strong, with only minor gaps around error/pagination behavior.

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 schema lacks: the regex engine semantics for regex=True, the fact that limit is clamped (with a truncated signal), and exactly how before/after alter the result structure. This goes beyond the terse schema descriptions.

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 ('Search'), resource ('.md note contents'), mechanism (ripgrep), and scope (one vault or all vaults). This clearly distinguishes it from siblings like list_notes and read_note without needing to name them.

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 scope note ('one vault or all vaults') and the regex portability warning imply appropriate usage, but the description never states when to choose this tool over read_note or list_notes, nor any prerequisite conditions. Usage must be inferred.

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

server_infoA
Read-onlyIdempotent

Report server version, Python/platform, git and ripgrep availability, whether git versioning is enabled, the local vaults root path, and the vault count. This is a local stdio server; the vaults root path is intentionally exposed.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=false, and destructiveHint=false, so the safety profile is covered. The description adds context annotations cannot: it is a local stdio server and the vaults root path is intentionally exposed, which tells an agent about the trust boundary and privacy expectations.

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, no filler. The enumeration is front-loaded immediately after the verb, and the second sentence adds only the non-obvious local/stdio exposure caveat.

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 parameters and no output schema, the description effectively serves as the return-value contract by listing every reported field, so an agent knows exactly what it will get. Nothing needed to invoke or interpret this tool is missing.

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?

There are zero parameters and the schema is an empty object, so there is nothing for the description to disambiguate. The baseline for a no-parameter tool 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?

Names a specific verb ('Report') plus an explicit enumeration of the resources returned: server version, Python/platform, git/ripgrep availability, git versioning state, vaults root path, and vault count. This clearly distinguishes it from siblings like list_vaults (which enumerates vaults) or read_note (which reads content).

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?

Usage is implied by the content: an agent can infer this is for diagnostics/environment introspection before attempting vault operations. However, it never states when to prefer it, nor does it mention siblings (e.g., use list_vaults when you need the vault names rather than a count). Adequate but with a clear gap.

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

write_noteA
Destructive

Create or atomically overwrite a note (vault-root-relative path). Pass sha256 from a prior read/write as expected_sha256 to prevent overwriting a changed note. Refreshes the frontmatter updated: date (inserted when a frontmatter block exists without one); notes without a frontmatter block stay that way.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesVault-root-relative note path
vaultYesVault name
contentYesFull new note content
expected_sha256NoSHA-256 from a prior read/write; rejects stale writes

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, idempotentHint=false, and readOnlyHint=false, so the safety profile is covered. The description adds genuinely non-redundant behavior: it refreshes the frontmatter `updated:` date and intentionally leaves notes without a frontmatter block untouched, plus the stale-write rejection semantics.

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 tight sentences, front-loaded with the core action, followed by concurrency and side-effect details in priority order. No filler or repetition.

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?

No output schema exists, and the description adequately covers the mutation semantics, concurrency control, and frontmatter side effect. Return value expectations and path validation behavior are the only modest gaps for a destructive write 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 description coverage is 100%, so all four parameters are already documented in the schema, including expected_sha256's stale-write purpose. The description restates the sha256 usage but adds no syntax or format detail beyond it, so the 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?

States a specific verb pair ('create or atomically overwrite') and resource ('note'), plus the path convention (vault-root-relative). The 'atomically overwrite' phrasing distinguishes it from the sibling append_note without ambiguity.

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?

Explicitly tells the agent when to pass expected_sha256 (from a prior read/write, to prevent overwriting a changed note), which is actionable usage guidance. It stops short of naming append_note or stating when not to use this tool, so not a 5.

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. 14 tool updatesv0.2.1
    • First observedappend_note
    • First observedcreate_vault
    • First observeddelete_note
    • First observeddelete_vault
    • First observedhistory
    • First observedlist_notes
    • First observedlist_tags
    • First observedlist_vaults
    • First observedmove_note
    • First observedread_note
    • First observedrestore
    • First observedsearch_notes
    • First observedserver_info
    • First observedwrite_note

TDQS

A4.2/5.0

Scored across 14 tools

Disambiguation5/5

Each tool maps to a distinct operation: read/list per entity, create/delete/move notes, git history/restore, and search/tags. Overlaps like write_note vs append_note are clearly distinguished by overwrite semantics, and list_vaults/list_notes/list_tags target different scopes.

Naming Consistency5/5

Consistent verb_noun snake_case throughout (read_note, list_vaults, create_vault, delete_note, move_note, list_tags, search_notes). Single-word tools like history, restore, and server_info are intuitive and fit the pattern.

Tool Count5/5

14 tools is well-scoped for a vault/notes server, covering CRUD, navigation, versioning, and search without redundancy. Every tool earns its place.

Completeness5/5

Full lifecycle coverage: vault create/delete/list, note read/write/append/delete/move/list, git history/restore, tags, search, and server_info. No obvious dead ends for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that provides read and write access to an Obsidian vault by interacting directly with markdown files on disk. Supports searching, listing, reading, creating, editing, and appending notes without requiring any Obsidian plugins.
    1,967 npm
    ISC
  • F
    license
    C
    quality
    D
    maintenance
    Git-backed MCP server for creating and maintaining an Obsidian-style markdown knowledge base with full CRUD, search, and git sync.
    7
    -
  • F
    license
    C
    quality
    C
    maintenance
    MCP server to query and modify an Obsidian vault or any folder of markdown files. It provides search, tag filtering, backlinks, and CRUD operations on notes, with path traversal protection.
    11
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for browsing Obsidian-compatible Markdown vaults, searching notes, viewing backlinks and knowledge graphs, and adding selected content to chat context.
    13 npm
    MIT