Skip to main content
Glama
zoeynine

Obsidian Server MCP

by zoeynine

Obsidian Server MCP

English · 简体中文

A lightweight, general Obsidian Server MCP for filesystem and semantic access to a Vault without a running Obsidian Desktop application. Common tools follow the pinned Local REST 5.3.1 contract as closely as the filesystem backend permits.

The current entry is stdio. Synchronization, remote transport/authentication and deployment configuration are external to this implementation. Vault files are the source of truth; the server sees changes once they reach its filesystem.

The supported deployment target is a Linux headless server/VPS. Windows can be used for local development, but is not a supported deployment platform.

Deployment filesystem permissions are authoritative for what the MCP process may read, write or delete. Configure access through the environment's user, group, ACL, mount or container settings. MCP contains no deployment authorization policy. Local tests use disposable fixtures; Linux filesystem and permissions validation remains a separate platform qualification.

Quick start

Install Node.js 22 or newer with npm on Linux. CI checks Node 22 and 24. Download and extract this repository's source archive, or clone its URL from the repository's Code menu. Open a terminal in the project folder:

npm ci
npm run build

Keep development dependencies installed while building; the TypeScript compiler is a development dependency. sharp installs its native image library for the current platform, so install dependencies on each host instead of copying node_modules between Windows and Linux.

Start with an empty example Vault. In Linux bash or sh:

mkdir -p ./example-vault
printf '# Hello\n' > ./example-vault/Hello.md
OBSIDIAN_VAULT_ROOT="$PWD/example-vault" node ./dist/stdio-main.js

For optional local development in Windows PowerShell:

New-Item -ItemType Directory -Force ./example-vault | Out-Null
Set-Content -LiteralPath ./example-vault/Hello.md -Value '# Hello' -Encoding utf8
$env:OBSIDIAN_VAULT_ROOT = (Resolve-Path ./example-vault).Path
node ./dist/stdio-main.js

A running stdio server waits for MCP messages on standard input; it does not open a web page or print a ready banner. Stop this manual check with Ctrl+C, then let your MCP client launch the process itself.

Connect an MCP client

For clients accepting a mcpServers JSON configuration, add this entry and replace the two absolute paths with your project and Vault paths:

{
  "mcpServers": {
    "obsidian-server": {
      "command": "node",
      "args": ["/absolute/path/obsidian-server-mcp/dist/stdio-main.js"],
      "env": {
        "OBSIDIAN_VAULT_ROOT": "/absolute/path/example-vault"
      }
    }
  }
}

For local Windows development, forward-slash paths such as C:/Projects/obsidian-server-mcp/dist/stdio-main.js and C:/Vaults/example-vault work in JSON. If your client does not inherit the terminal's PATH, use the absolute Node executable as command (find it with (Get-Command node).Source in PowerShell or command -v node on Linux). Clients with form-based settings use the same command, argument and environment variable. Launch node directly so the MCP protocol has exclusive use of stdout.

Reconnect the client and discover 13 tools. First call obsidian_help({"topic":"read"}), then vault_list({"path":""}) and vault_read({"path":"Hello.md"}) against the example Vault. A write-capable client can modify files with this server; choose its Vault and filesystem permissions accordingly.

If startup fails, check that npm run build created dist/stdio-main.js, the Vault directory exists, and the client process receives OBSIDIAN_VAULT_ROOT. No API key or Obsidian Desktop plugin is required for this local stdio entry. HTTPS hosting, authentication, synchronization and signed attachment downloads are supplied by a separate deployment adapter. See binary integration for attachment delivery.

Related MCP server: vault-mcp-server

Architecture and compatibility reference

  • src/core owns filesystem, path, exact-byte version, parser, query and mutation semantics.

  • src/transport owns MCP schemas and error/result mapping; it never accesses files directly.

  • Tests use disposable fixtures. No build or check connects to a real Vault.

This project references and adapts contracts and implementation patterns from Obsidian Local REST API by Adam Coddington. The reference is Local REST 5.3.1, peeled commit 17a9cfd9ff5dd0156b694bf9b13ab36c786b29da, not moving main. See the pinned parity tables for source links, operation/scope tables, exact dependency rationale, limits and deliberate differences. This project is distributed under the MIT License. The upstream copyright and complete MIT notice are retained in third-party notices.

Implemented MCP tools

All tools have strict input/output schemas. Text-tool success payloads appear once in structuredContent, with empty content. Attachment payloads appear once in native MCP content, with only metadata in structuredContent. Known failures return compact structured errors and a short text equivalent; unexpected failures reveal no absolute filesystem paths or stacks.

Tool

Behavior

obsidian_help

Topic index when topic is omitted; only the requested usage section otherwise

vault_list

Sorted {files} with directory suffixes; omit path or use "" for the Vault root

vault_read

Whole file or selected heading/block/frontmatter value, with exact-byte version; discover targets with vault_get_document_map

vault_read_binary

Image preview, signed download link or explicit bytes for non-PDF attachments; PDF is unsupported; see obsidian_help topic binary

vault_get_document_map

Nested heading addresses, block IDs and frontmatter keys, including duplicate disambiguators

search_query

JsonLogic over note text, paths and properties, retaining truthy values in {results} within scan/result limits

reference_query

Read-only references to a file/heading/block within explicit source and resolution scopes; matches and uncertainties with source versions

tag_list

Direct tags and nested parents with per-file counts

vault_write

Atomic text create/replace; existing files require ifMatch

vault_append

Atomic append; existing files require ifMatch; missing LF added first as in Local REST

vault_patch

Generic heading/block/frontmatter instruction; always requires ifMatch

vault_move

Move a file; destination suffix and optional allowOverwrite follow Local REST

vault_delete

Recoverable Vault-local trash by default; permanent: true permanently deletes a file

The stdio entry exposes twelve Vault tools plus the static obsidian_help manual. An embedded read-only composition exposes five text/discovery tools plus help, can add the binary reader and reference query, and can omit the mutation store. There are no mutation stubs. search_simple and its unused implementation are removed. Properties use generic patching. Binary upload, copy and Desktop UI tools remain outside this surface.

Properties are edited through vault_patch(targetType=frontmatter); edits preserve unrelated property text/comments, body, BOM and line endings. YAML aliases, anchors, duplicate/complex keys and non-JSON values are refused. Obsidian's Desktop link graph is unavailable and never fabricated. The separate reference query implements the bounded filesystem reference contract. JsonLogic supports coercion, arithmetic, collections, defaults, glob and bounded regexp; it is no longer predicate-only. There is no search database or whole-Vault snapshot.

Operational note: under the current server parser semantics, malformed or unsupported frontmatter in a single note can make whole-Vault search_query and tag_list fail explicitly.

On-demand help

Call obsidian_help({}) for a compact topic index, then, for example, obsidian_help({"topic":"patch"}) for that section alone. Unknown topics return a short error with the same topic index. Help reads no Vault data, makes no network calls and performs no mutations.

The marked sections below are the single source for the bundled help text. Edit them here, run npm run generate:help, and commit the generated module. npm run check:help detects drift; builds also regenerate the module. Runtime help uses those bundled strings, so a deployed package needs no README file.

Finding and reading notes

List the Vault root with vault_list({"path":""}), or omit path. Paths are Vault-relative; / and . are not root aliases.

Whole-file reads return path, content, tags, parsed frontmatter, filesystem stat, and SHA-256 version. Targeted reads return {path,version,result}. vault_get_document_map returns the same version plus heading/block/property addresses, without returning the note body.

maxBytes applies to the entire source document, not the selected target. Targeted reads still read and parse the full source and return its exact-byte version.

To read one section, first call vault_get_document_map({"path":"note.md"}). For ## Setup inside # Guide, pass the full ancestor path to vault_read:

{"path":"note.md","targetType":"heading","target":["Guide","Setup"]}

Copy every heading key from the returned tree unchanged, including any marker used to distinguish repeated headings. Block targets use a reference ID without ^; frontmatter targets use the property name. scope selects part of a target and requires targetType and target; it is not a whole-file field selector.

Targeted heading reads express levels relative to their scope. Use the map or a whole-file read to verify actual nesting after a structural edit.

Reading attachments

vault_read_binary({path, as?: "auto" | "bytes" | "link"}) accepts the same Vault-relative paths and filesystem permissions as text reads. It performs no OCR, upload or Vault mutation. MIME type is inferred from the filename, with application/octet-stream for unknown extensions.

PDF is intentionally unsupported for both reading and delivery. PDF paths (.pdf, case-insensitive) return vault_read_binary.unsupported_pdf in every mode, including bytes, and through MCP resource reads. Use the client's native file upload / attachment feature for PDFs; changing as does not enable them.

  • auto (default): PNG/JPEG/GIF/WebP become a native MCP image preview. The first frame is auto-oriented and resized without enlargement to at most 1568 pixels on either edge. The WebP preview is at most 1 MiB, with a 40-million input-pixel guard, 64 MiB source-byte cap and five-second processing timeout. Metadata marks it as a preview and reports whether only the first frame was returned. The original file is unchanged; use bytes for its exact bytes.

  • auto for other non-PDF files returns a signed HTTPS download link, even for small or empty files. SVG and other image formats also use this path; they are not rasterized. The original bytes travel over HTTPS rather than being embedded in the tool result. The client must fetch the URL to read them.

  • Oversized or unavailable image previews also select a link. as: "link" requests a download link directly, including for raster images.

  • as: "bytes" returns original bytes as a binary resource, with an inclusive 4 MiB hard cap. It never converts, truncates or silently falls back to a link. This is an explicit low-level option for supported non-PDF attachments.

Payload appears once in MCP content (image, embedded resource or resource link); structuredContent contains only delivery metadata. Inline results carry an exact-byte source version. The bytes result's obsidian-vault://attachment/… URI can be re-read through MCP resources with the same 4 MiB cap and version check; it is not a browser/download URL. Resource reads do not enumerate attachments.

Links require a deployment-provided, short-lived HTTPS download URL. Stock stdio has no link provider and returns vault_read_binary.link_unavailable for non-PDF auto downloads, explicit links and image fallbacks. Links must expire within 15 minutes and deliver the original file without a login page. Non-preview auto and explicit link inspect the source without loading or hashing its body, so no content version is claimed. An unversioned link refers to the current file at download time; an image fallback with a source version must deliver those exact bytes or reject a changed file. The download handler must recheck path protection, current read access and the PDF exclusion, including for previously issued links. No automatic retries occur.

Examples:

{"path":"Attachments/diagram.png"}
{"path":"Attachments/archive.zip"}
{"path":"Attachments/archive.zip","as":"bytes"}
{"path":"Attachments/recording.mp4","as":"link"}

Searching notes

search_query can use these fields with JsonLogic var:

Field

Value

path

Vault-relative file path, such as projects/plan.md

content

Complete Markdown text, including frontmatter

tags

Direct frontmatter and inline tags, without # or added parent tags

frontmatter

Parsed properties; use dot notation such as frontmatter.status

stat

ctime and mtime in milliseconds, size in bytes

Optional scope limits the scan to a Vault-relative directory ("" is the root). Both directory and recursive are required when scope is provided: recursive: false scans only direct child files; true includes subdirectories. Omitting scope keeps the recursive whole-Vault Markdown scan.

Budget parameters on search_query and tag_list are optional. Normally omit them to use default limits; set them when you intentionally want custom hard limits. For example, scan only projects/ and its subdirectories for needle, choosing a limit of 50 matches:

{
  "scope": {"directory": "projects", "recursive": true},
  "query": {"in": ["needle", {"var": "content"}]},
  "maxResults": 50
}

Only scope limits which files the server scans. Query path/glob conditions filter returned matches without pruning the scan; glob * also matches nested directories. maxTotalBytes limits scanned bytes, not response size. Exceeding a scan or result limit returns an error instead of partial results. Each match contains filename, version and the query's truthy result value; this example returns true, not a text snippet.

Results also have a fixed 4 MiB output budget, including conservative per-result overhead. Overflow returns search_query.budget_exceeded with budget: "maxOutputBytes"; this budget is not a configurable input parameter.

links, backlinks and unresolvedLinks are unavailable. To find possible references, search content for literal link text, for example {"query":{"in":["[[Note",{"var":"content"}]}}. Inspect candidates with vault_get_document_map and targeted vault_read; a text match does not resolve links and may miss other link spellings or match longer names.

JsonLogic supports comparisons, logic, string/collection/arithmetic operators, plus glob and regexp. Unsafe prototype access and the log operator are rejected. Malformed or unsupported frontmatter in any scanned note fails the query explicitly.

An operator expression has exactly one key. Objects with multiple keys are literal data in JsonLogic; for example, {"a":1,"b":2} is a truthy result for every scanned note, not two conditions. Combine conditions with and or or.

Finding references to a target

reference_query is a separate read-only tool. Specify where to scan Markdown bodies, whether to recurse, and the exact Vault-relative target file:

{
  "scope": {"directory": "projects", "recursive": true},
  "resolutionScope": {"directory": "", "recursive": true},
  "target": {"path": "notes/Design.md"}
}

resolutionScope inventories filenames, including attachments; it does not read every note body. It defaults to scope. Bare wikilinks such as [[Design]] need a recursive root inventory to establish uniqueness among accessible files. A unique candidate in a partial inventory remains unknown; duplicate candidates are ambiguous. Explicit paths to the requested target can resolve outside that inventory. The target is inspected/read even when outside the source scope.

To query a section, use target: {"path":"notes/Design.md","heading":["Overview"]}; for a block, use target: {"path":"notes/Design.md","block":"decision"}. Do not combine heading and block. Heading texts are case-sensitive, plain, consecutive ancestor names; duplicate anchors are ambiguous, not selected by map suffixes.

matches contains confirmed references. uncertain contains ambiguous, unresolved, unsupported or unknown occurrences across the source scope; these may be unrelated to the target and are not inferred backlinks. Each occurrence includes source path/version, raw link, parsed destination when available, zero-based half-open UTF-16 offsets and one-based line/UTF-16 column. target.fileExists describes the file; target.status separately describes the requested file/heading/block. Target Markdown carries its exact-byte version.

Supports ordinary wikilinks and CommonMark inline/reference links, display aliases and embeds. Frontmatter aliases do not add filename candidates. Attachments are checked for existence only; page/time fragments are unsupported, and this does not enable PDF reading. Formatted heading anchors are conservative/unsupported. Frontmatter, code, comments, balanced math, HTML and external URLs are excluded.

Completeness covers only the declared scopes and supported syntax. Incoming links outside the source scope remain unknown; this is not an atomic Vault snapshot. Defaults/hard maxima: entries 20,000/200,000; inventoried files 2,000/10,000; per-file bytes 1/4 MiB; total read bytes 8/32 MiB; returned matches plus uncertainties 1,000/10,000; JSON output 1/4 MiB. Override with maxEntries, maxFiles, maxFileBytes, maxTotalBytes, maxResults, maxOutputBytes. The final target recheck counts toward total read bytes. Parsing also has worker, time and structural limits. Overflow, scan failure or detected namespace/target change fails the call; no partial success, mutation, repair or automatic retry.

Listing tags

tag_list({}) returns tags from Markdown files with a count of files containing each tag. Names omit #; repeated occurrences in one file count once. Nested parents are included: a/b also counts toward a. By contrast, vault_read and search_query expose direct tags without adding parents.

Tags come from frontmatter tags and inline hashtags. Inline recognition may differ from Obsidian Desktop. Budget arguments are optional; normally omit them to use defaults. maxTags counts unique names including parents. Scan or tag limit overflow fails explicitly, without returning a truncated list. Malformed or unsupported frontmatter also fails the scan.

Patching headings and properties

Call vault_get_document_map first to discover exact heading paths and obtain the file's current exact-byte version for ifMatch. The map returns that version without returning the whole note text. Replace <current version> in each example below with the version from the latest map or read of note.md.

Use content for Markdown or label edits, value for frontmatter property values, or destination for heading moves; do not combine these payloads. delete takes no payload. With scope: "marker", supply only the new label, without heading # markers. Conflicts and failures are not automatically retried.

These examples are independent. For a note with # Root, ## A and ## B, replace the content of A while keeping its heading:

{
  "path": "note.md",
  "targetType": "heading",
  "target": ["Root", "A"],
  "operation": "replace",
  "scope": "content",
  "content": "New body.",
  "ifMatch": "<current version>"
}

Set the status property, creating it if missing. Use value, not content; omit createTargetIfMissing when a missing property should be an error:

{
  "path": "note.md",
  "targetType": "frontmatter",
  "target": "status",
  "operation": "replace",
  "value": "ready",
  "createTargetIfMissing": true,
  "ifMatch": "<current version>"
}

When vault_patch targets a heading section, omit within. Heading markers in content are relative to the selected heading and scope, not absolute Markdown levels. within instead selects a body block for a block edit.

Scope and operation

Meaning of content starting with #

content (default), replace / prepend / append

A direct child of the selected heading

markerAndContent, prepend / append

A sibling section before / after the selected section and its descendants

For example, with # Root containing ## A and ## B, insert a new sibling section immediately after A by calling vault_patch with:

{
  "path": "note.md",
  "targetType": "heading",
  "target": ["Root", "A"],
  "operation": "append",
  "scope": "markerAndContent",
  "content": "# Inserted",
  "ifMatch": "<current version>"
}

The stored order is ## A, ## Inserted, ## B. Use prepend to insert before A. With the default content scope, # Inserted would instead become ### Inserted inside A; ## Inserted would become #### Inserted.

destination moves an existing heading section. For example, to move A under B as its last child, use operation: "replace" and scope: "parent" with a fresh version and no content:

{
  "path": "note.md",
  "targetType": "heading",
  "target": ["Root", "A"],
  "operation": "replace",
  "scope": "parent",
  "destination": {"parent": ["Root", "B"], "place": "last"},
  "ifMatch": "<current version>"
}

After a structural patch, check vault_get_document_map for actual nesting or read the whole file with vault_read({"path":"note.md"}) for stored # levels. Targeted heading reads normalize levels relative to the selected scope, so their displayed # counts alone cannot confirm the stored hierarchy.

Writing and appending text

vault_write creates a UTF-8 text file or replaces its whole content. vault_append adds text, creating the file if missing. Both create missing parent directories. Binary file extensions, NUL and malformed text are refused.

For an existing file, obtain its latest version with vault_read or vault_get_document_map and pass it as ifMatch; there is no force bypass. For a new file omit ifMatch. A version conflict means the file changed: reread, reconcile the intended edit, then decide whether to submit a new write. No mutation is automatically retried on conflict or failure.

Append adds LF before the supplied text when an existing file does not end in LF, including an empty existing file. A missing file receives exactly the supplied content. Successful writes return a compact receipt with the new version, not the whole note. A successful receipt with a cleanup warning means the content was saved; inspect the warning instead of blindly appending again.

Paths and file limits

One shared sandbox rejects absolute/traversing/noncanonical paths, symbolic links, escape, reserved Windows names and replacement of the original Vault root. Dot-prefixed components are protected internals; embedders can protect additional internal-state subtrees. Discovery and direct tools use the same policy. These are generic containment and internal-state safeguards. Text access rejects binary extensions, NUL and malformed UTF-8/Unicode, while preserving BOM and original newlines. Reads and mutations default to 4 MiB with a 64 MiB hard cap.

The mutation path is deliberately small:

  1. Serialize the relative path across store instances in this process; safely read existing bytes and require exact-byte ifMatch for existing write/append and all patches. Validate the prepared text before changing files.

  2. Create missing parent directories through the shared sandbox. Write a hidden .obsidian-mcp-<random>.tmp beside the target using exclusive creation. Normal OS creation defaults inherit directory permissions/default ACLs; MCP never calls chown/chmod/setfacl or runs a permissions hook.

  3. Flush the completed temporary file, close it, and revalidate parents, path, temporary identity and the original exact-byte version. No append/patch retry.

  4. Atomically rename over an existing file. For a missing file, atomic hard-link publication refuses a concurrent new destination, then removes the temp name. Node rename has no NOREPLACE flag. No unlink-before-replace or copy fallback.

Temporary files are blocked by the same protected-path policy and omitted from list/search/tag discovery. Failed writes remove their exact temp name after identity checks. Unsafe/failed cleanup is reported; a successful create with a leftover temp returns an explicit saved-note warning, not a misleading failure. Missing parent directories can remain after a failed operation. No startup orphan sweeper, parent-directory fsync, durability modes or permission manager is included. A single file fsync is retained before publication; this is not a power-loss durability guarantee.

New file inodes inherit deployment permissions from the destination directory. MCP does not preserve/reassign per-file ownership or ACLs. Linux validation must verify permission inheritance and allowed/denied operations for the actual process identity and deployment filesystem, including directory permissions that govern rename and deletion. It must also qualify native symlink/race and rename behavior. Windows fixtures and injected faults do not validate POSIX ACLs.

Per-path locks are process-local. Final version checks are optimistic checkpoints, not cross-process filesystem CAS; Sync keeps its own conflict handling. Parent identities are revalidated, but native Node path calls do not lock directories against adversarial renames between syscalls. Directory ownership and access must keep the namespace trusted; the remaining platform behavior is qualified on each deployment's operating system and filesystem.

Stdio requires only OBSIDIAN_VAULT_ROOT; no staging-root or policy-module configuration is needed. Protocol output uses stdout; diagnostics use stderr. Write/append/patch success is a compact message: "OK" receipt with path, exact-byte version, byte count, creation status and any warnings, without echoing the note body.

Moving and deleting files

vault_move takes path, destination and optional allowOverwrite (false by default), returning {message: "OK", oldPath, newPath}. Missing destination parents are created. A trailing / retains the filename; an empty destination moves to the Vault root. Desktop link rewriting and history updates are unavailable, so referring notes are unchanged. Overwrites use atomic rename. Without overwrite permission, atomic hard-link publication refuses a raced-in destination, followed by source unlink. Both names briefly exist; a failed source unlink removes only the newly created link. If safe cleanup fails, the error names both relative paths for inspection. There is no copy fallback or retry.

vault_delete takes path and optional permanent (false by default). Recoverable deletion renames into .trash/<unique-directory>/<filename> on the same filesystem and returns message, path, permanent: false and trashPath. Recovery uses filesystem access to that receipt path; .trash is protected from ordinary MCP tools. permanent: true unlinks the file and returns message, path and permanent: true. Trash failure never falls back to permanent deletion.

Both tools accept an optional SHA-256 ifMatch extension and share the mutation locks and path checks. They can relocate/delete attachments without decoding or transferring their bytes. Version checking is limited to 64 MiB; omitted tokens retain Local REST's operation-on-current-path behavior. Operations on directories and additional hard links are refused; directory deletion could contain protected internal descendants. The exact Desktop differences are recorded in the parity table.

Requirements and checks

Node.js 22 or newer. Install with npm ci; npm run check verifies generated help, typechecks, runs disposable-fixture tests and builds. Individual commands are npm run typecheck, npm test and npm run build. GitHub Actions runs the same check on Linux with Node 22 and 24. For ordinary code changes, run the local check once; there is no required manual OS/Node matrix. Additional Linux checks depend on the affected behavior or release needs. The portable test runner discovers compiled test files explicitly and runs them in separate processes, one file at a time. See contributing for the development workflow.

Pinned parser/JSON/YAML/MIME dependencies are documented in the parity table. sharp is the only additional dependency for bounded raster previews; it does not render PDFs. See binary deployment integration for the provider required by generic downloads and deployment acceptance steps. Tests cover compact transport, targeted reads, frontmatter operations, JsonLogic values and limits, shared path/text policy, concurrency, exact byte versions, temp-file/publication ordering, hidden artifacts, races, cleanup and filesystem error propagation. Binary tests cover PDF rejection across all modes/resources, generic download links, explicit exact-byte transfer, previews, limits, resource versions, link-provider boundaries, and a real stdio child process with the MCP SDK client.

Available Tools

13 tools
obsidian_helpB
Read-onlyIdempotent

Usage manual; omit topic for the topic index.

ParametersJSON Schema
NameRequiredDescriptionDefault
topicNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
textYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds one behavioral trait beyond the annotations: that omitting topic yields a topic index. It discloses nothing about rate limits, output format, or failure modes.

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?

Two short clauses, front-loaded with the tool's identity followed by the parameter instruction; no filler. It is arguably too terse for a help tool, but nothing in it is wasted.

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 only one optional parameter and an output schema present, return-value detail is not required, and the annotations carry the safety profile. Still, the definition gives the agent no sense of what topics are available or what the manual covers, leaving discovery entirely to trial calls.

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 0% for the single parameter, so the description must carry the meaning. It does explain the optionality semantics — omitting topic returns the topic index, implying topic selects a specific entry — but it never says what valid topic values look like or how to discover them, so the compensation is partial.

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 names a specific resource (a usage manual / help documentation), which is clearly distinct from the vault-operation siblings like vault_read and vault_write. It stops short of stating an explicit verb or the scope of the manual, but an agent can identify it as the documentation tool 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 Guidelines3/5

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

Usage is only implied — the agent is expected to infer that this is the tool to call when it needs documentation. The clause 'omit topic for the topic index' does give one concrete invocation instruction, but there is no explicit when-to-use vs alternatives guidance beyond that.

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

reference_queryA
Read-onlyIdempotent

Find references to a file/heading/block within explicit source and resolution scopes. Read-only; returns matches plus uncertainties and exact source versions. Outside-scope incoming links remain unknown. See help topic references.

ParametersJSON Schema
NameRequiredDescriptionDefault
scopeYes
targetYes
maxFilesNo
maxEntriesNo
maxResultsNo
maxFileBytesNo
maxTotalBytesNo
maxOutputBytesNo
resolutionScopeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
scopeYes
targetYes
matchesYes
coverageYes
uncertainYes
resolutionScopeYes

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so safety is covered. The description adds genuinely useful behavioral context beyond that: it returns matches plus uncertainties and exact source versions, and it explicitly warns that outside-scope incoming links remain unknown, which is a completeness limitation an agent must know about.

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?

Three dense sentences, front-loaded with the core action and followed by the return/limitation caveat and a doc pointer. No filler, though 'See help topic references' shifts work to an external document rather than resolving it inline.

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?

The tool is read-only with an output schema, so return values need not be spelled out, and the description still usefully flags uncertainties and version reporting. The gap is the parameter side: with 9 params, nested objects and 0% schema coverage, the undocumented max* limits leave an agent guessing about throttling and truncation 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 0% across 9 parameters, so the description must carry the load. It partially does: 'source and resolution scopes' maps to scope/resolutionScope, and 'file/heading/block' maps to the target object. But the seven max* limit parameters (maxFiles, maxEntries, maxResults, maxFileBytes, maxTotalBytes, maxOutputBytes) get no mention at all, leaving a large documentation 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?

The description names a specific verb and resource ('Find references to a file/heading/block'), which tells an agent this is a backlink/reference lookup rather than a content search. It does not explicitly distinguish itself from the nearest sibling, search_query, leaving the agent to infer the split between 'what links here' and 'find text'.

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 'within explicit source and resolution scopes' and the caveat about outside-scope links, which hints at the scoping model an agent must set up. However, there is no explicit when-to-use-vs-alternatives guidance (e.g. versus search_query), only a pointer to 'help topic references' that defers the decision to external docs.

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

search_queryA
Read-onlyIdempotent

Query Markdown with JsonLogic over path, content, tags, frontmatter and stat. Returns truthy values. Only scope limits the scan; query path/glob conditions only filter results. Overflow errors, never truncation. No link graph.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes
scopeNoOptional scan scope; omit for a recursive whole-Vault scan. directory "" is root; recursive=false scans only direct child files.
maxFilesNoOptional scanned-file cap; omit for defaults.
maxEntriesNoOptional scanned-entry cap; omit for defaults.
maxResultsNoOptional match cap, not truncation; omit for defaults.
maxFileBytesNoOptional per-file byte cap; omit for defaults.
maxTotalBytesNoOptional scanned-byte cap, not response size; omit for defaults.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYes

TDQS

A3.9/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 the safety profile is covered. The description adds real behavioral context beyond that: query results are evaluated for truthy values, only scope limits the scan while path/glob conditions merely filter, and overflow produces errors rather than truncation. That is meaningful semantics the schema and annotations do not 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?

Five short sentences, each carrying a distinct fact, with the core purpose front-loaded. No filler, no repetition of schema or annotation content, and the important overflow-vs-truncation guarantee is stated tersely.

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 complex JsonLogic query tool with an output schema present, the description covers purpose, evaluation semantics, scope behavior, overflow handling, and the link-graph exclusion. The only meaningful gap is the absence of an explicit pointer to reference_query as the alternative for link queries, which would complete the routing picture.

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 86%, so the schema already documents scope, the max* caps, and the query object. The description still adds value by enumerating the queryable domains (path, content, tags, frontmatter, stat) that the bare 'query: object' schema does not reveal, and by clarifying that path conditions inside the query filter rather than limit scanning.

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: query Markdown via JsonLogic over path, content, tags, frontmatter and stat. This clearly identifies what the tool does and its query domain. However, it never names the closest sibling (reference_query) even though the 'No link graph' clause hints at the boundary between them, so differentiation is only implicit.

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?

There is no explicit 'use this when' statement or named alternative. The clause 'No link graph' implicitly steers link-oriented queries toward reference_query, and the scope/path-filter clarification implies when scanning vs filtering applies, but an agent must infer the routing rather than read it.

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

tag_listA
Read-onlyIdempotent

List tags and parent tags with per-file counts; names omit #. Scan/result limits fail explicitly. Inline recognition may differ from Obsidian Desktop.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxTagsNoOptional unique-tag cap including parents; omit for defaults.
maxFilesNoOptional scanned-file cap; omit for defaults.
maxEntriesNoOptional scanned-entry cap; omit for defaults.
maxFileBytesNoOptional per-file byte cap; omit for defaults.
maxTotalBytesNoOptional scanned-byte cap, not response size; omit for defaults.

Output Schema

ParametersJSON Schema
NameRequiredDescription
tagsYes

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/non-destructive, so the bar is lower, yet the description adds real behavioral context: limits 'fail explicitly' (i.e., errors instead of silent truncation) and inline recognition 'may differ from Obsidian Desktop'. Those caveats are not derivable from the annotations or schema.

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?

Three tight clauses, no filler, with the core purpose front-loaded before the two caveats. Nothing redundant is present.

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?

An output schema exists so return values needn't be described, annotations cover the safety profile, and the schema documents all five caps. The description covers the surprising edge cases; only the when-to-use gap keeps it from being fully 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% and every cap parameter is self-documented in the schema, so the baseline of 3 applies. The description adds no syntax or default guidance beyond the schema's 'omit for defaults'.

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 tags and parent tags with per-file counts', and adds a concrete output detail ('names omit #'). It is clearly distinguishable from vault_list and search_query by resource, though it never explicitly contrasts itself with those siblings.

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 description never says when to reach for tag_list versus search_query or vault_list, nor does it state any prerequisites. Usage is only implied by the word 'List'.

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

vault_appendA

Append UTF-8 text; creates missing files. Existing files require ifMatch; missing final LF is added first. Binary/NUL refused; no automatic retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes
ifMatchNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathYes
createdYes
messageYes
versionYes
warningsNo
sizeBytesYes

TDQS

A4.1/5.0
Behavior5/5

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

With annotations only declaring the generic safety flags, the description carries substantial extra load: it discloses upsert semantics, optimistic-concurrency requirements for existing files, a silent side effect (missing final LF is added), input rejection rules (binary/NUL refused), and retry behavior ('no automatic retry'). These are exactly the traits an agent cannot infer from 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?

Four compact clauses, no filler, and the primary action is front-loaded before the caveats. Every clause adds a distinct operational fact, so nothing could be cut without losing information.

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?

An output schema exists, so return values need not be explained, and the description covers creation, concurrency, encoding, and retry behavior. Remaining gaps are minor: no mention of the content size cap enforced by maxLength, no path-format guidance, and no note on permissions or failure modes.

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 0%, so the description must compensate, and it does for two of three params: ifMatch's conditional requirement and content's UTF-8/text-only constraint. It says nothing about the path parameter (format, vault-relative vs absolute), leaving one gap, and the sha256: prefix format is only conveyed by the schema pattern.

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+resource ('Append UTF-8 text') plus upsert behavior ('creates missing files'), which cleanly separates it from vault_write and vault_patch without naming them. Sibling differentiation is implied by the verb rather than stated explicitly, so it falls just short of a 5.

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?

Gives one real conditional rule ('Existing files require ifMatch'), which tells the agent when a parameter becomes mandatory. However, it never says when to choose vault_append over vault_write or vault_patch, nor any preconditions such as vault availability or path scoping, so usage is only partially covered.

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

vault_deleteA
Destructive

Delete a file to recoverable Vault .trash; permanent=true is irreversible. ifMatch checks source. No automatic retry or permanent fallback.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
ifMatchNo
permanentNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

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

Beyond the destructiveHint annotation, it discloses that the default path is recoverable via .trash, that permanent=true is irreversible, that ifMatch guards against source changes, and that there is no automatic retry or permanent fallback. These are exactly the operational traits an agent needs to avoid data loss and to handle retries itself.

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 default (recoverable) behavior before the irreversible flag, with zero filler. Every clause carries distinct operational information.

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?

An output schema exists so return values need no explanation, and annotations cover the safety profile. The description supplies the remaining behavioral essentials, though it omits edge cases such as missing paths or directory handling that a mutation tool could clarify.

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 0% schema description coverage, the description must carry the parameter burden, and it explains the two non-obvious ones: permanent controls irreversibility and ifMatch validates the source. Only 'path' is left undocumented, though its meaning is self-evident from the name.

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 names a specific verb (Delete) and resource (a file in the Vault), and its default semantics ('to recoverable Vault .trash') immediately distinguish it from the read/write/append/patch siblings, which cannot destroy data. An agent can identify this as the sole deletion tool 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 Guidelines3/5

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

The description implies the deletion context and warns that permanent=true is irreversible, but never states when to prefer this tool over alternatives or what prerequisites apply (e.g. whether the file must exist). Usage is inferable rather than explicit, which matches a 3.

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

vault_get_document_mapB
Read-onlyIdempotent

Get heading paths, block IDs, property names and exact-byte version. Copy returned keys unchanged for targeted reads/patches.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
maxBytesNo
maxHeadingsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathYes
blocksYes
versionYes
headingsYes
frontmatterFieldsYes

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so the safety profile is covered. The description does add real value beyond that by introducing the 'exact-byte version' token and warning that returned keys must be copied unchanged. It nonetheless omits truncation behavior despite bounds on maxBytes/maxHeadings, which is a material behavioral 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?

Two sentences, zero filler, with the payload contents front-loaded and the operational caveat second. Nothing is redundant with the schema or annotations.

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?

An output schema exists, so return-value structure need not be explained, and the description rightly focuses on how to consume the result. Still, with three parameters at 0% schema coverage and no note about what happens when maxBytes or maxHeadings are hit, an agent cannot fully predict the call's behavior.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must carry the full burden of explaining path, maxBytes and maxHeadings. It explains none of them: maxBytes and maxHeadings in particular are opaque limit parameters whose truncation semantics are left entirely undefined, and even 'path' is not clarified as a vault-relative path or a folder path.

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 resource and enumerates what the map contains (heading paths, block IDs, property names, version), which is far more informative than the name alone. It hints at its role relative to siblings by pointing to 'targeted reads/patches', though it never names vault_read or vault_patch 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?

'Copy returned keys unchanged for targeted reads/patches' implies a workflow (map first, then targeted read/patch), which is genuinely useful routing guidance. However, it never states when to choose this tool instead of vault_read or the other read siblings, nor any preconditions, so the guidance remains implied rather than explicit.

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

vault_listA
Read-onlyIdempotent

List a Vault directory; omit path or use "" for root. Directory names end in /. Protected/symlink entries are omitted; overflow errors, never truncation.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
maxEntriesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
filesYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and closed-world, so the safety profile is covered. The description adds real behavior beyond that: trailing '/' on directory names, omission of protected/symlink entries, and a failure mode where overflow errors rather than truncates. That error-over-truncation guarantee is exactly the kind of context an agent needs and could not get from 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?

A single tight sentence pair: the core action and root-addressing rule come first, then the behavioral caveats. No filler, no repetition of the schema, and the most decision-relevant constraint (root path) 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 an output schema present, return-shape explanation is unnecessary, and the annotations carry the safety profile. The description adds the filtering rules and the error-not-truncation contract, which is most of what an agent needs; only the maxEntries semantics remain undocumented in prose.

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 0%, so the description has to carry both parameters. It explains path well (omitting it or passing "" selects root), and 'overflow errors, never truncation' indirectly implies maxEntries caps results and errors when exceeded, but maxEntries is never named or bounded in prose. Partial compensation for a coverage gap, hence a mid score.

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 gives a specific verb+resource ('List a Vault directory') and immediately pins down the scope ('omit path or use "" for root'), which is enough for an agent to distinguish it from vault_read, vault_get_document_map, and search_query without opening a schema. It stops short of naming a sibling alternative explicitly, so it falls just below the top mark.

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 tells the agent how to address the root directory ('omit path or use ""'), which is useful invocation guidance, but it never states when to choose vault_list over search_query or tag_list, nor any exclusions or prerequisites. Usage is implied by the name rather than argued.

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

vault_moveA
Destructive

Move a file; no link/history updates. Creates parents; trailing / retains filename. Overwrite requires allowOverwrite. ifMatch checks source only. No retry or cross-filesystem fallback.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
ifMatchNo
destinationYes
allowOverwriteNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
newPathYes
oldPathYes

TDQS

A4.2/5.0
Behavior5/5

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

Goes well beyond the destructive/idempotent annotations, disclosing that links and history are NOT updated, that parent directories are created, that overwrite requires allowOverwrite, that ifMatch validates the source only, and that there is no retry or cross-filesystem fallback. These are exactly the side-effect and failure-mode details an agent needs before a destructive move.

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?

Five dense clauses, each conveying a distinct constraint, with the core action front-loaded and 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?

An output schema exists, so return values need no explanation. For a destructive move tool the description covers side effects, overwrite conditions, precondition checking, and failure behavior, leaving nothing critical unstated.

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 0%, so the description must carry the parameters. It explains allowOverwrite (required for overwriting), ifMatch (validates source only), and destination semantics via the trailing-slash rule; only the plain path/destination roles are left implicit.

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 ('Move a file'), which is immediately distinguishable from read/list siblings. It does not explicitly contrast with vault_write + vault_delete, the plausible alternative, so it stops short of a 5.

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 use case (moving a file) is implied clearly, but there is no explicit when-to-use versus siblings such as delete-then-write, and no preconditions stated beyond the conditional overwrite rule. It gives conditional mechanics rather than selection guidance.

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

vault_patchB
Destructive

Patch a heading/block/property with exact-byte ifMatch from a read/map. Copy map keys unchanged. Heading content uses relative levels. No automatic retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
scopeNo
valueNo
targetYes
withinNo
contentNoHeading target without within: # is a child in content scope, a sibling with markerAndContent prepend/append.
ifMatchYes
operationYes
targetTypeYes
destinationNoHeading move only: operation=replace, scope=parent; omit content.
createTargetIfMissingNo
rejectIfContentPreexistsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathYes
createdYes
messageYes
versionYes
warningsNo
sizeBytesYes

TDQS

B3.3/5.0
Behavior4/5

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

Annotations already declare destructive=true, idempotent=false, readOnly=false, so the safety profile is covered. The description adds genuine value beyond that: the exact-byte ifMatch precondition (optimistic concurrency) and "No automatic retry" — a non-obvious behavioral trait an agent must handle itself. It stops short of describing auth needs or what a failed ifMatch returns.

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?

Four terse sentences, front-loaded with the core action and the ifMatch precondition, with no filler. It is dense but every clause carries information; it is arguably too compressed given the tool's complexity rather than padded.

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

Completeness2/5

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

For a 12-parameter, nested-object, destructive mutation with 17% schema coverage, a four-sentence description is thin. Output schema existing means return values need not be explained, but the mutation semantics, parameter behavior, and sibling routing are largely absent, leaving real gaps an agent would hit.

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

Parameters2/5

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

Schema description coverage is only 17% across 12 parameters with nested objects, so the description must compensate heavily but only touches ifMatch, map-key copying, and heading relative levels. It says nothing about operation, scope, targetType, destination, createTargetIfMissing, or rejectIfContentPreexists, leaving most parameters documented only by their bare enum values.

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 (patch) and concrete resources (heading/block/property), and the ifMatch phrasing signals a conditional partial update distinct from a full write. It is clear on its own but never names or contrasts with siblings like vault_write, vault_append, or vault_move, so an agent must infer the boundary.

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?

"with exact-byte ifMatch from a read/map" implies the prerequisite workflow (obtain the token from vault_read/vault_get_document_map before calling), which is useful implied guidance. However, there is no explicit when-to-use-vs-alternative statement, no when-not guidance, and no routing against the other mutation siblings.

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

vault_readA
Read-onlyIdempotent

Read a Vault text file or target with its version. Discover targets via vault_get_document_map; targeted heading levels are relative. No link graph.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
scopeNoRequires a target; defaults to content.
targetNoPair with targetType. Heading: full map path, e.g. ["Root","Child"]; block: ID without ^; property: key.
maxBytesNo
targetTypeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/openWorld=false, so the safety profile is covered. The description still adds real behavioral context: results carry a version, targeted heading levels are resolved relative to a base, and the read does not traverse a link graph.

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?

Three short clauses, front-loaded with the core action and free of filler. It is terse to the point of leaving some parameter behavior unexplained, but every sentence carries information.

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?

An output schema exists so return values need no explanation, and annotations cover the safety profile. The gaps are the undocumented maxBytes/targetType parameters and the interplay of scope with target, which the description does not clarify.

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 only 40%, with maxBytes and targetType carrying no descriptions at all. The description partially compensates by explaining target discovery and the relative nature of heading targets, but it says nothing about maxBytes truncation or targetType values, leaving half the parameters undocumented in both places.

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 Vault text file or target') and adds scope qualifiers ('with its version', 'No link graph') that separate it from graph-oriented siblings. It does not explicitly contrast with vault_read_binary, but the 'text file' framing implies the distinction.

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?

Points the agent to vault_get_document_map for discovering targets, which is genuine routing guidance. However, it never states when to choose this over vault_read_binary or other read siblings, and gives no prerequisites or exclusions beyond that one pointer.

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

vault_read_binaryA
Read-onlyIdempotent

Read images and non-PDF attachments. auto: raster preview or signed HTTPS download link. bytes: original data up to 4 MiB. PDF is unsupported in every mode; use the client's native file upload/attachments.

ParametersJSON Schema
NameRequiredDescriptionDefault
asNo
pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/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, and the description adds real value beyond them: a 4 MiB cap in bytes mode, a signed HTTPS link in auto mode, and a hard PDF exclusion. It does not mention whether signed links expire or require auth, which is the one notable gap.

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 scope statement, then mode behaviors, then the exclusion. Every clause carries information and there is no filler, though the telegraphic style trades a little readability for density.

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?

An output schema exists, so return values need no explanation. The description covers the supported content types, all three modes at least in outline, the size cap, and the PDF exclusion — enough for correct invocation, with only link-mode details and path semantics left implicit.

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 0%, so the description must carry the parameters. It explains the 'auto' and 'bytes' enum values and implies 'link' via the signed-URL mention, but the third enum value is never described on its own and 'path' is undocumented. Partial compensation for a 2-param tool.

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 and resource ('Read images and non-PDF attachments'), which implicitly scopes it away from the text-reading sibling vault_read. It does not name vault_read explicitly, so the sibling differentiation is inferable rather than stated.

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 states the negative case ('PDF is unsupported in every mode') and routes PDFs to an alternative ('use the client's native file upload/attachments'), and it describes each 'as' mode. It never says when to prefer auto vs bytes vs link, leaving that inference to the agent.

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

vault_writeA
DestructiveIdempotent

Create or replace UTF-8 text. Existing files require ifMatch; no force bypass. Creates parents. Binary/NUL refused; no automatic retry.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes
ifMatchNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathYes
createdYes
messageYes
versionYes
warningsNo
sizeBytesYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint, idempotentHint, and readOnlyHint=false, so the safety profile is covered. The description adds real value beyond them: parent directories are created, binary/NUL content is refused, there is no automatic retry, and no force-override exists for existing files. It stops short of noting permission/auth requirements or rate limits.

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?

Four terse clauses, front-loaded with the core action before constraints. Every sentence carries a distinct behavioral fact with 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?

An output schema exists, so return values need not be described. For a mutating tool the description covers the crucial mechanics (ifMatch gating, parent creation, refusal rules, retry behavior), leaving only path semantics and content limits unaddressed.

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 0%, so the description must carry the load. It meaningfully explains ifMatch's purpose (required for existing files, no force bypass), but says nothing about path format constraints or the content size limit that the schema enforces. It compensates for one of three parameters only.

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+resource ('Create or replace UTF-8 text'), which is far more precise than the bare name vault_write. It implicitly differentiates from siblings vault_append/vault_patch by emphasizing replace semantics, though it never names them 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?

It gives a conditional rule ('Existing files require ifMatch; no force bypass') which implies when the tool is applicable, but never states when to choose it over vault_append or vault_patch, nor what happens on a first-time create vs overwrite beyond the ifMatch hint. Usage is implied rather than explicit.

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. 1 tool update
    • Changedsearch_query1 field changed
      • addedInput schema / properties / scope
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Optional scan scope; omit for a recursive whole-Vault scan. directory \"\" is root; recursive=false scans only direct child files.",
        +  "properties": {
        +    "directory": {
        +      "type": "string"
        +    },
        +    "recursive": {
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "directory",
        +    "recursive"
        +  ],
        +  "type": "object"
        +}
  2. 13 tool updatesv0.1.0
    • First observedobsidian_help
    • First observedreference_query
    • First observedsearch_query
    • First observedtag_list
    • First observedvault_append
    • First observedvault_delete
    • First observedvault_get_document_map
    • First observedvault_list
    • First observedvault_move
    • First observedvault_patch
    • First observedvault_read
    • First observedvault_read_binary
    • First observedvault_write

TDQS

A3.7/5.0

Scored across 13 tools

Disambiguation4/5

The vault_* tools carve out distinct operations (read vs write vs append vs patch vs move vs delete), and search_query vs reference_query serve different purposes. Minor overlap between vault_read/vault_get_document_map and vault_read vs vault_read_binary could cause slight confusion, but descriptions clarify.

Naming Consistency3/5

The vault_* family is consistently verb-suffixed (vault_list, vault_read, vault_write), but other tools mix conventions (search_query, reference_query, tag_list, obsidian_help). Readable overall but not a single predictable pattern.

Tool Count5/5

13 tools is well-scoped for an Obsidian vault server, covering the essential file, query, tag, and reference operations without bloat.

Completeness4/5

Strong lifecycle coverage: read, write, append, patch, move, delete, list, search, references, tags, and document mapping. Notable gap is no binary write (only vault_read_binary) and no copy operation, but these are minor workarounds.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers