Obsidian Server MCP
A lightweight stdio MCP server for filesystem and semantic access to an Obsidian Vault without Obsidian Desktop running (Linux headless deployment target).
Browse and read notes: list directories, read whole files or targeted headings/blocks/frontmatter values, and map a note's headings, block IDs and properties with exact-byte versions.
Search: run JsonLogic queries over note paths, content, tags, frontmatter and stat; list tags with per-file counts (direct and nested parents).
Find references: query read-only wikilink/Markdown references to a file, heading or block within explicit source and resolution scopes, with matches vs. uncertainties.
Read attachments: get images/previews or non-PDF attachments as native bytes or signed HTTPS download links (PDF unsupported).
Write and edit notes: create/replace whole files, append text, replace a unique literal string, and patch headings, blocks or frontmatter properties; all existing-file edits require an exact-byte version token (
ifMatch).Organize files: move files (with optional overwrite) and delete to recoverable Vault-local trash or permanently.
Get help: an
obsidian_helpmanual with topic index, guides (read, write, search, tags, references, patch, paths, binary, files) and per-tool usage.Safety/limits: sandboxed Vault-relative paths, protected/symlinked entries blocked, explicit scan/result caps that error rather than truncate, atomic writes, and no automatic retries.
Provides filesystem-based access to an Obsidian vault, enabling listing, reading, searching, tagging, writing, appending, patching, moving, and deleting notes and attachments, with document maps, frontmatter/property edits, exact-byte version checks, and reference queries.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Obsidian Server MCPsearch my vault for meeting notes and show their headings"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Obsidian Server MCP
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 buildKeep 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.jsFor 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.jsA 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 14 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/coreowns filesystem, path, exact-byte version, parser, query and mutation semantics.src/transportowns 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
Default 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. Business failures return
isError: true and a single JSON text block containing error.code, error.message
and optional error.details. They omit structuredContent so the error body is not
validated against the success output schema. Unexpected failures reveal no absolute
filesystem paths or stacks.
Tool | Behavior |
| Topic index when |
| Sorted |
| Whole file or selected heading/block/frontmatter value, with exact-byte version; discover targets with |
| Image preview, signed download link or explicit bytes for non-PDF attachments; PDF is unsupported; see |
| Nested heading addresses, block IDs and frontmatter keys, including duplicate disambiguators |
| JsonLogic over note text, paths and properties, retaining truthy values in |
| Read-only references to a file/heading/block within explicit source and resolution scopes; matches and uncertainties with source versions |
| Direct tags and nested parents with per-file counts |
| Atomic text create/replace; existing files require |
| Atomic append; existing files require |
| Generic heading/block/frontmatter instruction; requires |
| Atomic literal replacement of one unique exact string in an existing text file; requires |
| Move a file; destination suffix and optional |
| Recoverable Vault-local trash by default; |
The stdio entry exposes thirteen 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.
Optional text-only reading
An embedding host can select a tool profile for each server instance:
Profile | Reading and navigation tools |
|
|
|
|
Each alias shares its original tool's strict input schema, use case, limits,
path policy, error mapping and version semantics. In the text profile, all tools
omit both outputSchema and structuredContent; successful payloads are still
validated internally. Ordinary data, help and mutation receipts use compact JSON
in one text block. Business errors retain isError: true and their existing
payloads. Chinese characters are emitted directly.
vault_read_text presents whole-file reads in two text blocks: the first contains
all metadata (path, version, versionGuard, tags, frontmatter, stat) plus
textField: "content"; the second is the original content string. Heading/block
reads also use two blocks: {path,version,versionGuard,textField:"result"} and the reader's
unchanged result string. Empty text remains an empty second block. No trimming,
unescaping, newline conversion or code fences are applied. Frontmatter target
reads retain single-block {path,version,versionGuard,result} JSON for every value type,
including strings. Heading/block reads retain their existing semantic behavior,
including relative heading levels; use a whole-file read for exact replacement.
A full composition has 14 tools in either profile. The text profile replaces the four original names rather than adding duplicate choices. The other ten names and all operation semantics are shared. The standard profile's output formats remain unchanged; the standard stdio entry uses that default profile. Every client discovering an endpoint sees that endpoint's selected tool list.
A host serving clients with different presentation needs can select fixed options by endpoint while sharing the same Vault dependencies and mutation store:
const standardServer = createVaultMcpServer(dependencies);
const textServer = createVaultMcpServer(dependencies, {
toolProfile: "text",
});Use separate MCP server/transport instances for the endpoints. Register options are local to each instance; the standard instance neither lists nor accepts calls to the four aliases, and the text instance does not expose their four original names. The host owns HTTP routing, authentication and resource discovery; these options do not create routes or separate Vault permissions. Use the same loaded core module and shared store to retain in-process write coordination. No client-side hiding is needed. Binary delivery in the text profile places metadata JSON in the first text block, followed by the unchanged native image, embedded resource or resource link; attachment bytes are never serialized into the metadata. Reference queries use compact JSON like other data tools. Help and recovery instructions refer to the selected profile's available tool names; stable error codes are unchanged.
For existing hosts, enableTextRead: true remains supported: with the default
profile it adds only vault_read_text, giving a full composition 15 tools, and
retains the original single-block JSON reading contract.
The text profile already includes that tool and never registers it twice.
On-demand help
Call obsidian_help({}) for a compact index with Guides and Tools.
Guides explain cross-tool workflows; Tools lists the names actually exposed by
this endpoint. Ask for obsidian_help({"topic":"search_query"}) for one tool's
contract and examples, or obsidian_help({"topic":"search"}) for its workflow.
All canonical names and the four text-profile names have manuals, including
obsidian_help itself. A known manual does not enable an unavailable tool;
its opening notice identifies that situation and any registered counterpart.
Unknown topics return a recoverable error with this endpoint's index. Help
reads no Vault data, makes no network calls and performs no mutations.
The marked guides below and the canonical tool manual are
the documentation sources. Text aliases reuse canonical tool content and add
only presentation notes; they do not maintain separate contracts. Edit these
sources, run npm run generate:help, and commit the generated module.
npm run check:help detects drift; builds also regenerate it. Runtime help uses
bundled strings, so a deployed package needs neither Markdown source file.
Finding and reading notes
Start with vault_list to discover paths. For a known note, use
vault_get_document_map when you need reliable heading paths, block IDs or
property names, then copy its keys unchanged to a targeted vault_read.
Use a whole-file read for full context or an exact source slice for replacement.
Targeted heading levels are relative; inspect the whole file or map to verify
stored nesting after a structural change.
Both map and read return the full exact-byte version and a 16-hex
versionGuard. Copy either version into ifMatch or versionGuard into
ifMatchGuard for later mutations, never both. The short guard has lower
collision strength; see guide write. A read is not a lock on the note.
If a write reports a conflict, reread and reconcile before another attempt.
maxBytes admits the entire source document, even for a small target; narrowing
the target does not bypass file-size limits or frontmatter parsing.
Ask for tool topics vault_list, vault_get_document_map and vault_read
for limits, targeted-read examples and size-error recovery. For attachments use
guide binary; for selecting notes use search; for edits use write.
Reading attachments
Use vault_read_binary for images and non-PDF attachments. Its default
auto mode selects a bounded native raster preview or a short-lived protected
HTTPS resource link for another file type. Choose bytes only when the client
needs exact bytes within its transfer cap, or link when it needs a download.
Generic download delivery requires the embedding host's link provider.
PDF is intentionally unsupported in every mode, including resource reads. Use the client's native file upload or attachment feature for PDFs. This tool does not perform OCR or document extraction. Preview metadata identifies a derived image; it is not evidence that the original bytes were transferred.
Ask for tool topic vault_read_binary for exact limits, delivery metadata,
examples and link-unavailable recovery. Guide paths applies to attachments
as well as notes.
Searching notes
Choose search_query for content/property conditions, tag_list for tag
inventory, or reference_query for bounded link resolution. A literal content
match can find link-shaped text but does not establish a backlink. Inspect
selected notes with vault_get_document_map and targeted or full vault_read.
JsonLogic evaluates an expression against each Markdown note. An operator has
one key; combine conditions with and or or. The returned value is the
expression's truthy result, which may be a boolean or data rather than a snippet.
Use scope to choose the scan before adding predicates. A path/glob predicate
filters matches without reducing scan work; maxTotalBytes counts scanned
bytes, not response size. Scan and result overflow fail without partial success;
the fixed output cap reports search_query.budget_exceeded.
Ask for tool topic search_query for fields, operators, limits and runnable
content/frontmatter/compound examples. Guide tags explains aggregation;
references explains source and resolution coverage.
Finding references to a target
Use reference_query when spelling alone cannot decide whether a link points
to a particular file, heading or block. Choose a source scope for Markdown
bodies and a resolutionScope for the filename inventory used to resolve links.
The inventory defaults to the source scope. A recursive root inventory can
establish uniqueness for a bare wikilink; a partial inventory cannot prove it.
Treat confirmed matches separately from uncertain occurrences. Uncertain
links may be unrelated to the requested target. Completeness describes only the
declared scopes and supported syntax: incoming links outside the source scope
remain unknown. This is neither a persisted link graph nor an atomic Vault
snapshot. The tool performs no repair or mutation.
Ask for tool topic reference_query for target syntax, locators, limits and
examples. Use guide search for literal candidate discovery and read to
inspect a matched source with its exact version.
Listing tags
Choose tag_list to discover tag names and how many Markdown files contain
each tag. It counts repeated occurrences in a file once and aggregates nested
parents: a note with a/b contributes to both a/b and a.
By contrast, vault_read and search_query expose only direct tags.
Use search_query when you need the matching notes or property conditions.
Tags come from frontmatter and inline hashtags. Inline recognition can differ from Obsidian Desktop. Scan/tag limits and malformed or unsupported frontmatter fail explicitly, so an error is not evidence of an empty inventory.
Ask for tool topic tag_list for its limits and result example, or
search_query for filtering by direct tags.
Patching headings and properties
Use vault_get_document_map to discover an exact semantic target and its
version, then vault_patch to edit that heading, block or property with
ifMatch or ifMatchGuard. Choose a scope before writing content: a section body, its marker,
the whole section or a move of its parent relationship have different effects.
within: 0 selects the first direct body block when child sections should be
retained; choose the appropriate index for another body block.
Heading content uses relative levels. In the default content scope, input
# becomes a child of the selected heading. With markerAndContent
prepend/append it is relative to the target's actual parent; skipped levels
can change nesting. Whole-subtree replacement with children fails with
vault_semantic.subtree_confirmation_required unless explicitly allowed with
allowSubtreeReplacement: true as well as a current ifMatch or ifMatchGuard.
Choose typed value for a frontmatter property and destination for a
heading move. For a literal exact source edit use vault_replace_text; for
literal Markdown at the file end consider vault_append.
After a structural edit, check the map or whole-file vault_read: targeted
heading reads normalize displayed levels and cannot by themselves prove nesting.
Ask for tool topic vault_patch for scope/payload combinations, subtree
recovery and runnable examples. Guide write compares the mutation tools.
Writing, appending and replacing text
Choose the operation that matches the intended change:
vault_write: create a text file or replace its entire content.vault_append: add literal text at the end, creating a missing file.vault_replace_text: replace one unique literal slice from a whole-file read.vault_patch: edit a semantic heading, body block or typed property.
For an existing file, read with vault_read or vault_get_document_map and
copy the returned versionGuard unchanged into ifMatchGuard. Alternatively,
pass the full version as ifMatch; its strict exact-match contract is unchanged.
Supply exactly one: both together fail with vault_mutation.conflicting_preconditions,
even when they agree. Exact replacement needs the original slice and token from
the same whole-file read. Create with write/append without either token only
when the path is missing. A token for a missing file cannot create it.
versionGuard is exactly 16 lowercase hex characters: the first 64 bits of
the same file-byte SHA-256, returned by the server so callers need not slice
or count characters. It has no session, cache, lease, expiry or authorization
meaning. Wrong or stale values conflict; malformed guards are refused. On any
conflict, reread and reconcile rather than copying a token from an error or
automatically retrying. This is content-based, so restoring identical bytes
restores both tokens; neither token tracks intervening edit history.
The short guard is a convenience for non-adversarial edits, not full SHA-256
collision resistance. A random unequal pair collides with probability about
2^-64; birthday collisions become plausible around 2^32 distinct versions.
Use full ifMatch when stronger collision resistance is needed. After the
initial check, the server pins the full SHA-256 for in-flight revalidation,
retaining the existing per-path locking and atomic publication limits.
Successful read/map/search/reference results and text-write receipts include
versionGuard wherever they include version. Binary results include both
only when complete original bytes were read; download-only links need not
have either. Move/delete receipts, directory listings and tag counts gain no
token. Both profiles use the same rules; text reads put the guard in metadata.
Successful receipts report both saved tokens and before/after UTF-8 byte sizes. They establish that bytes were committed, not that the edit fulfilled its intent or preserved Markdown structure. Inspect content or a map when that matters. A saved-note cleanup warning means the write succeeded; do not append again.
Ask for each tool's own topic for its contract and examples. Guide patch
covers structured editing, paths covers shared path/text limits and files
covers moving or deleting files.
Paths and file limits
All tool paths are untrusted Vault-relative paths. The shared sandbox rejects absolute, traversing and noncanonical paths, symbolic-link traversal, escape, reserved Windows names and replacement of the original Vault root. Dot-prefixed components and host-configured internal subtrees are protected; discovery omits them and direct access refuses them. The empty string means root only for inputs that explicitly support it, such as listing and scan directories.
Text operations reject binary extensions, NUL and malformed UTF-8/Unicode while preserving BOM and original newlines. Read and mutation text sizes default to 4 MiB with a 64 MiB hard cap. Each tool also has its own entry, scan or result limits; a smaller returned target does not waive whole-source admission.
Deployment filesystem permissions remain authoritative. These safeguards are not a client authorization policy or a cross-process filesystem lock. Ask for the relevant tool topic for its parameter limits and actionable errors.
The mutation path is deliberately small:
Serialize the relative path across store instances in this process; safely read existing bytes and require
ifMatchorifMatchGuardfor existing write/append and every patch/exact replacement. Validate the prepared text before changing files.Create missing parent directories through the shared sandbox. Write a hidden
.obsidian-mcp-<random>.tmpbeside 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.Flush the completed temporary file, close it, and revalidate parents, path, temporary identity and the original exact-byte version. No automatic mutation retry.
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/exact-replacement success is a compact message: "OK"
receipt with path, exact-byte version, versionGuard, beforeSizeBytes, final sizeBytes,
created and any warnings. Exact replacement adds replacementCount: 1;
the note body is not echoed.
Moving and deleting files
Use vault_move to relocate a file and vault_delete to delete one.
Neither operation updates incoming links or Obsidian Desktop history.
If link impact matters, inspect it with reference_query within declared
scopes before the move; outside-scope incoming links remain unknown.
Move overwrites require allowOverwrite. Delete defaults to recoverable
Vault-local trash; permanent: true is irreversible. Both accept an optional
ifMatch or ifMatchGuard for the source, never both (see guide write).
Omitting both acts on the current path;
on move it never protects the destination's version. Directories and files
with additional hard links are refused.
Neither tool automatically retries. Trash failure does not fall back to permanent deletion, and move has no cross-filesystem copy fallback. Recovery from trash requires filesystem access to the receipt's protected trash path.
Ask for tool topics vault_move and vault_delete for destination syntax,
receipts, recovery and examples. Guide paths describes shared containment.
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
14 toolsobsidian_helpBRead-onlyIdempotent
Usage manual; omit topic for the topic index.
| Name | Required | Description | Default |
|---|---|---|---|
| topic | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| text | Yes |
TDQS
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.
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.
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.
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.
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.
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_queryARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes | ||
| target | Yes | ||
| maxFiles | No | ||
| maxEntries | No | ||
| maxResults | No | ||
| maxFileBytes | No | ||
| maxTotalBytes | No | ||
| maxOutputBytes | No | ||
| resolutionScope | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| scope | Yes | |
| target | Yes | |
| matches | Yes | |
| coverage | Yes | |
| uncertain | Yes | |
| resolutionScope | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent safety profile, so the description earns credit for adding beyond them: it discloses that results include 'uncertainties and exact source versions' and that out-of-scope links are silently omitted—non-obvious behaviors an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the core operation front-loaded, the key limitation second, and a pointer to help last. Nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape needn't be explained, and annotations cover safety. But for a 9-parameter tool with nested scopes and 0% schema coverage, the description leaves the limit parameters and their interaction with results unexplained, a real gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% across 9 parameters, including nested objects. The description maps the conceptual source/resolution scope and target dimensions, but the six max* limit parameters and the recursive flags are never explained, leaving most of the schema meaning undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb ('Find references') plus resource ('file/heading/block') and the scoping model make the operation unambiguous. It does not explicitly contrast with siblings like search_query, but the 'references' framing distinguishes it well enough.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The caveat 'Outside-scope incoming links remain unknown' implies when results are incomplete, and 'See help topic references' routes to more detail. However, it never states when to prefer this over search_query or other siblings, leaving usage largely inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_queryARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| scope | No | Optional scan scope; omit for a recursive whole-Vault scan. directory "" is root; recursive=false scans only direct child files. | |
| maxFiles | No | Optional scanned-file cap; omit for defaults. | |
| maxEntries | No | Optional scanned-entry cap; omit for defaults. | |
| maxResults | No | Optional match cap, not truncation; omit for defaults. | |
| maxFileBytes | No | Optional per-file byte cap; omit for defaults. | |
| maxTotalBytes | No | Optional scanned-byte cap, not response size; omit for defaults. |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description earns credit for adding real behavior: truthy-value returns, overflow-errors-instead-of-truncation, and the scan-vs-filter distinction. The explicit 'never truncation' guarantee is exactly the kind of failure-mode disclosure an agent needs before setting caps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each carrying a distinct fact (fields, return semantics, scan-vs-filter, overflow behavior), with the core purpose front-loaded. No filler and no repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be described, and the scan/error semantics are well covered for a 7-parameter tool. The gap is the query DSL itself: no mention of which JsonLogic operators or field names are valid, which is the hardest part of invoking this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 86%, so the baseline is 3; the description pushes above it by explaining that scope is the sole scan driver and that result caps are not truncation, which clarifies the intent behind maxResults and maxFiles. It still says nothing about the JsonLogic object shape required by the sole required parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Query Markdown') plus the mechanism and queryable fields (path, content, tags, frontmatter, stat), which lets an agent tell it apart from vault_list, tag_list and reference_query. The trailing 'No link graph' explicitly carves out the graph-query sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides one important usage rule -- that only scope limits the scan while path/glob conditions merely filter results -- which shapes how an agent should build a query. However, it never names an alternative tool or states when to prefer vault_list/tag_list over this one; the 'No link graph' clause is the only implied exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tag_listARead-onlyIdempotent
List tags and parent tags with per-file counts; names omit #. Scan/result limits fail explicitly. Inline recognition may differ from Obsidian Desktop.
| Name | Required | Description | Default |
|---|---|---|---|
| maxTags | No | Optional unique-tag cap including parents; omit for defaults. | |
| maxFiles | No | Optional scanned-file cap; omit for defaults. | |
| maxEntries | No | Optional scanned-entry cap; omit for defaults. | |
| maxFileBytes | No | Optional per-file byte cap; omit for defaults. | |
| maxTotalBytes | No | Optional scanned-byte cap, not response size; omit for defaults. |
Output Schema
| Name | Required | Description |
|---|---|---|
| tags | Yes |
TDQS
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.
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.
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.
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.
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.
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 or ifMatchGuard (copy versionGuard); missing final LF is added first. Binary/NUL refused; no automatic retry.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| ifMatch | No | ||
| ifMatchGuard | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| created | Yes | |
| message | Yes | |
| version | Yes | |
| warnings | No | |
| sizeBytes | Yes | |
| versionGuard | Yes | |
| beforeSizeBytes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses create-on-miss behavior, mandatory optimistic concurrency on existing files, the LF normalization side effect, binary/NUL rejection, and the absence of automatic retry. These are exactly the mutation traits an agent needs and annotations alone don't convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences with the primary action and create-on-miss behavior front-loaded, then constraints. No filler; each clause carries a distinct operational fact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and the mutation semantics are well covered. The remaining gap is the missing pointer to where ifMatchGuard/versionGuard values come from (presumably vault_read) and what failure looks like when the precondition fails.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 clarifies the conditional requirement on ifMatch/ifMatchGuard ('copy versionGuard'), but leaves the sha256 format of ifMatch, the 64MiB content cap, and where a guard token is obtained unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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') and adds a key scope fact — missing files are created. The append semantics are self-evidently distinct from siblings like vault_write, vault_patch, and vault_replace_text, though no sibling is named.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives real conditions ('Existing files require ifMatch or ifMatchGuard') but frames them as parameter requirements rather than when-to-use-this-vs-alternatives guidance. An agent still must infer that vault_write is the overwrite path and vault_patch the edit path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_deleteADestructive
Delete a file to recoverable Vault .trash; permanent=true is irreversible. ifMatch or ifMatchGuard (copy versionGuard) checks source. No automatic retry or permanent fallback.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| ifMatch | No | ||
| permanent | No | ||
| ifMatchGuard | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, but the description adds substantive context they don't convey: deletion lands in .trash and is recoverable, permanent=true is irreversible, and there is no automatic retry or fallback to permanent deletion. Permissions/auth requirements are still unstated, keeping it below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with the recoverability default front-loaded and the irreversible case immediately following — no filler. Slight penalty for telegraphic phrasing ('ifMatch or ifMatchGuard (copy versionGuard)') that reads as notes rather than explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 the description covers the key danger profile for a destructive mutation plus the no-retry caveat. Missing pieces are path resolution semantics and any permission requirements, which matter for a delete operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 parameter meaning. It explains permanent and gestures at ifMatch/ifMatchGuard as source checks, but the phrase 'copy versionGuard' is cryptic and the two conditional parameters are never clearly distinguished (full sha256 digest vs 16-hex guard), and 'path' is left entirely implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete a file') plus the immediate destination semantics ('recoverable Vault .trash'), and clarifies the permanent-mode variant. No sibling tool in the list performs deletion, so the agent can distinguish it without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear conditional guidance: default behavior is recoverable, set permanent=true only when irreversibility is acceptable, and use ifMatch/ifMatchGuard to guard against concurrent modification. It does not explicitly name alternatives (e.g., vault_move as a non-destructive option), so it stops short of full when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_get_document_mapBRead-onlyIdempotent
Get heading paths, block IDs, property names, version and versionGuard. Copy returned keys unchanged for targeted reads/patches.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| maxBytes | No | ||
| maxHeadings | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| blocks | Yes | |
| version | Yes | |
| headings | Yes | |
| versionGuard | Yes | |
| frontmatterFields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, and closed-world behavior. The description adds useful detail about what the map contains and that its keys are intended to be reused unchanged, but it does not explain truncation behavior, limits, or what happens when maxBytes/maxHeadings are hit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with no filler, and the primary purpose is front-loaded before the key-reuse instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema covers return values, and annotations cover safety, but the 0%-described parameters are a significant gap for a tool whose maxBytes and maxHeadings settings affect what the map contains. The description does not compensate for that missing parameter semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, with three parameters (path, maxBytes, maxHeadings) and no descriptions in the schema. The description does not mention any parameter, so an agent gets no guidance on what the limits mean or how they affect the returned map.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb ('Get') and lists concrete returned artifacts: heading paths, block IDs, property names, version, and versionGuard. This clearly distinguishes it from a plain document read, though it does not explicitly name sibling tools or contrast itself with vault_read/vault_list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It implies the tool is used before targeted reads/patches by saying to copy returned keys unchanged. However, it does not name the alternative tools or state when not to use this map, leaving the routing decision partially implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_listARead-onlyIdempotent
List a Vault directory; omit path or use "" for root. Directory names end in /. Protected/symlink entries are omitted; overflow errors, never truncation.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| maxEntries | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| files | Yes |
TDQS
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.
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.
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.
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.
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.
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_moveADestructive
Move a file; no link/history updates. Creates parents; trailing / retains filename. Overwrite requires allowOverwrite. ifMatch or ifMatchGuard (copy versionGuard) checks source only. No retry or cross-filesystem fallback.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| ifMatch | No | ||
| destination | Yes | ||
| ifMatchGuard | No | ||
| allowOverwrite | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | |
| newPath | Yes | |
| oldPath | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already flagging destructiveHint=true, the description adds substantial non-redundant behavior: parent auto-creation, trailing-slash filename retention, the overwrite flag requirement, the fact that ifMatch/ifMatchGuard validate the source only, and the absence of retry or cross-filesystem fallback. These are exactly the operational caveats 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is tightly packed with semicolon-delimited clauses and leads with the core action, so no sentence is filler. The telegraphic style is dense but each clause conveys distinct operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the destructive/non-idempotent safety profile and an output schema handling return values, the description fills the important behavioral gaps (parents, overwrite, precondition scope, no fallback). It is nearly complete, missing only explicit guidance on failure behavior when overwrite is not permitted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden and does so well: it explains destination trailing-slash semantics, allowOverwrite's role, and that ifMatch vs ifMatchGuard are source-only precondition checks (with a note that ifMatchGuard mirrors copy's versionGuard). Only 'path' is left unelaborated, which is reasonable given its obviousness.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Move a file') and immediately scopes it ('no link/history updates'), which distinguishes it from copy-style or link-maintaining operations among the siblings. It stops short of naming a sibling outright, but the scope statement makes the tool's identity unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied through conditional rules ('Overwrite requires allowOverwrite') rather than explicit when-to-use versus alternatives. It never states when an agent should pick vault_move over vault_write or vault_delete, so the agent must infer selection from the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_patchCDestructive
Patch a heading/block/property with ifMatch or ifMatchGuard (copy versionGuard) from a read/map. Copy map keys unchanged. Heading content without within: # is one level below the target for content (default), or the target's actual parent for markerAndContent prepend/append. No automatic retry.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| scope | No | ||
| value | No | ||
| target | Yes | ||
| within | No | ||
| content | No | ||
| ifMatch | No | ||
| operation | Yes | ||
| targetType | Yes | ||
| destination | No | Heading move only: operation=replace, scope=parent; omit content. | |
| ifMatchGuard | No | ||
| createTargetIfMissing | No | ||
| allowSubtreeReplacement | No | Explicitly allow heading content/whole-section replace to remove child sections; the version precondition still applies. | |
| rejectIfContentPreexists | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| created | Yes | |
| message | Yes | |
| version | Yes | |
| warnings | No | |
| sizeBytes | Yes | |
| versionGuard | Yes | |
| beforeSizeBytes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true, idempotentHint=false, and openWorldHint=false. The description adds useful context that a version precondition (ifMatch/ifMatchGuard) must be copied from a read/map and that no automatic retry occurs, but omits conflict/error behavior and permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is short, but structured as a dense run-on of cryptic clauses like 'Copy map keys unchanged' and 'markerAndContent prepend/append' that are not interpretable without additional context. The core verb/resource is front-loaded, but the rest is hard to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex mutation tool with 14 parameters, nested objects, and very low schema coverage, the description does not explain most parameter semantics, prerequisites for obtaining the version guard, or error/conflict behavior. An output schema exists, so return values needn't be covered, but the input-side gaps are large.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 14% across 14 parameters, so the description must compensate, but it only touches ifMatch, ifMatchGuard, within, and some scope semantics. Most parameters (path, target, targetType, operation, value, content, destination, createTargetIfMissing, allowSubtreeReplacement, rejectIfContentPreexists) get no explanatory help.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
It states a verb ('Patch') and resource types (heading/block/property), but 'property' does not match the schema's targetType enum (heading/block/frontmatter), and the phrasing is cryptic. It does not clearly distinguish itself from siblings such as vault_replace_text, vault_append, or vault_write.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus vault_replace_text or vault_write. Only oblique hints exist ('from a read/map', 'No automatic retry') without a clear decision rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_readARead-onlyIdempotent
Read a Vault text file or target with version and versionGuard. Discover targets via vault_get_document_map; targeted heading levels are relative. No link graph.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| scope | No | Requires a target; defaults to content. | |
| target | No | Pair with targetType. Heading: full map path, e.g. ["Root","Child"]; block: ID without ^; property: key. | |
| maxBytes | No | ||
| targetType | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, idempotent and non-destructive behavior, so the description only needs to add beyond that. "No link graph" is a useful disclosure about what is not returned, and "targeted heading levels are relative" clarifies resolution semantics, but the mention of "version and versionGuard" is confusing since no such parameters exist in the schema, and nothing is said about maxBytes 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very short and front-loaded, which is good, but the phrase "with version and versionGuard" consumes limited space on parameters that don't exist in the schema, creating noise in an otherwise tight definition. The remaining clauses each carry real information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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 explanation is rightly absent. However, for a 5-parameter read tool the description does not address maxBytes/truncation, the content-vs-marker scope behavior, or clarify the phantom version parameter, leaving gaps an agent must guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 40%, but the schema itself already documents scope ("Requires a target; defaults to content") and target formats. The description adds the useful note that heading levels are relative and points to vault_get_document_map for building target paths, yet leaves maxBytes and the interaction between target/targetType and scope largely unexplained, and references a version parameter that isn't in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 a scope exclusion ("No link graph"). The word "text" implicitly separates it from vault_read_binary, but the contrast is never made explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an actionable routing hint: "Discover targets via vault_get_document_map," which tells the agent how to obtain the target value this tool requires. It lacks an explicit when-not statement (e.g. when to prefer vault_read_binary or search_query), so it stops short of full alternative coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_read_binaryARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| as | No | ||
| path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false. The description adds useful behavior beyond annotations: the 4 MiB limit for bytes mode, the preview-or-link behavior of auto mode, and the PDF exclusion.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, front-loaded, and every sentence carries operational value: supported file type, mode behavior, size limit, and PDF exclusion. There is no wasted text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema exists, so return values need not be explained, and annotations cover safety traits. However, with zero schema parameter descriptions, the missing link mode and unexplained path parameter leave the definition only partially complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must fully explain the parameters. It describes auto and bytes modes, but omits the link enum value entirely, and it does not explain the required path parameter. This leaves a significant gap in mode selection semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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. It clearly excludes PDFs, but it does not explicitly distinguish this tool from sibling vault_read for text files. The purpose is still clear and actionable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use this tool versus native file handling, especially by stating that PDFs are unsupported in every mode. It also explains the auto and bytes modes, though it does not explicitly route text reads to vault_read.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_replace_textADestructive
Replace one unique, case-sensitive literal match in an existing UTF-8 file. Copy exact oldText from a whole-file vault_read; copy version as ifMatch or versionGuard as ifMatchGuard. Empty newText deletes. No automatic retry.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| ifMatch | No | ||
| newText | Yes | ||
| oldText | Yes | ||
| ifMatchGuard | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| created | Yes | |
| message | Yes | |
| version | Yes | |
| warnings | No | |
| sizeBytes | Yes | |
| versionGuard | Yes | |
| beforeSizeBytes | Yes | |
| replacementCount | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false; the description adds real context beyond them: the match must be unique and case-sensitive, empty newText deletes the match, and there is no automatic retry on conflict. It does not say what error surfaces when the match is missing or non-unique, which is the remaining gap for a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, zero filler, with the core operation and its uniqueness constraint front-loaded before the workflow notes. Every sentence adds a distinct fact an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, and the description covers the match semantics, guard parameters, delete-by-empty-newText, and retry behavior. The only meaningful omission is failure-mode detail for a non-unique or absent match on a destructive edit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description carries the burden and largely succeeds: oldText must be an exact literal from vault_read, newText may be empty to delete, and both ifMatch and ifMatchGuard are explained as version-carrying guards. Only 'path' is left unstated, which is self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with the exact matching semantics: 'Replace one unique, case-sensitive literal match in an existing UTF-8 file.' The uniqueness and case-sensitivity constraints implicitly separate it from vault_patch, vault_write and vault_append, so an agent can pick it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the required workflow upfront: copy exact oldText from a whole-file vault_read, and carry version into ifMatch or versionGuard into ifMatchGuard. 'No automatic retry' tells the caller it must handle failure. It stops short of naming when to use vault_patch or vault_append instead, so no explicit exclusion is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
vault_writeADestructiveIdempotent
Create or replace UTF-8 text. Existing files require ifMatch or ifMatchGuard (copy versionGuard). Creates parents. Binary/NUL refused; no automatic retry.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| ifMatch | No | ||
| ifMatchGuard | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | Yes | |
| created | Yes | |
| message | Yes | |
| version | Yes | |
| warnings | No | |
| sizeBytes | Yes | |
| versionGuard | Yes | |
| beforeSizeBytes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint and idempotentHint, but the description adds genuinely new behavioral facts: parent directories are created automatically, binary/NUL content is refused, and there is no automatic retry after a failure, which matters for an agent retry strategy. The overwrite-guard requirement on existing files is also disclosed. It stops short of stating permission/auth requirements or what happens on a failed guard mismatch, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely front-loaded: capability first, then preconditions, then side effects and failure behavior. Every clause carries information, with no filler. The telegraphic style ('copy versionGuard', 'Binary/NUL refused') trades some readability for density, which keeps it slightly below a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Since an output schema exists, return values need not be described, and the annotations carry the safety profile. Given those, the description covers the key gaps an agent needs: parents auto-created, overwrite guard requirement, content-type limits, and no retry. Residual ambiguity about how to obtain versionGuard and about path format is minor but present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 explains the otherwise opaque ifMatch/ifMatchGuard parameters in terms of purpose (required to overwrite existing files) and even hints at the source ('copy versionGuard'), which is real added value. But path and content semantics, and the accepted sha256 format versus 16-hex guard format, are left entirely to the schema's regex patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair and resource: 'Create or replace UTF-8 text', which implicitly separates it from sibling tools like vault_append and vault_patch that modify rather than replace full content. It never names those siblings explicitly, so a reader must infer the boundary from the verbs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The precondition 'Existing files require ifMatch or ifMatchGuard' gives clear context for overwrites, which implies when this tool succeeds versus fails. However, there is no explicit guidance on when to choose vault_write over vault_append, vault_patch, or vault_replace_text, so the selection logic is inferred from the description rather than stated.
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.
11 tool updates
v0.2.0- Changed
reference_query9 fields changed- added
Output schema / properties / matches / items / properties / source / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / properties / matches / items / properties / source / requiredPrevious value: -[ - "path", - "version" -]New value: +[ + "path", + "version", + "versionGuard" +] - removed
Output schema / properties / target / additionalPropertiesRemoved value: -false - added
Output schema / properties / target / anyOfAdded value: +[ + { + "additionalProperties": false, + "properties": { + "block": { + "pattern": "^[a-zA-Z0-9-]+$", + "type": "string" + }, + "fileExists": { + "type": "boolean" + }, + "heading": { + "items": { + "maxLength": 1024, + "minLength": 1, + "type": "string" + }, + "maxItems": 32, + "minItems": 1, + "type": "array" + }, + "path": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "status": { + "enum": [ + "resolved", + "ambiguous", + "unresolved", + "unsupported", + "unknown" + ], + "type": "string" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + } + }, + "required": [ + "path", + "fileExists", + "status", + "reason", + "version", + "versionGuard" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "block": { + "pattern": "^[a-zA-Z0-9-]+$", + "type": "string" + }, + "fileExists": { + "type": "boolean" + }, + "heading": { + "items": { + "maxLength": 1024, + "minLength": 1, + "type": "string" + }, + "maxItems": 32, + "minItems": 1, + "type": "array" + }, + "path": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "status": { + "enum": [ + "resolved", + "ambiguous", + "unresolved", + "unsupported", + "unknown" + ], + "type": "string" + } + }, + "required": [ + "path", + "fileExists", + "status", + "reason" + ], + "type": "object" + } +] - removed
Output schema / properties / target / propertiesRemoved value: -{ - "block": { - "pattern": "^[a-zA-Z0-9-]+$", - "type": "string" - }, - "fileExists": { - "type": "boolean" - }, - "heading": { - "items": { - "maxLength": 1024, - "minLength": 1, - "type": "string" - }, - "maxItems": 32, - "minItems": 1, - "type": "array" - }, - "path": { - "type": "string" - }, - "reason": { - "type": "string" - }, - "status": { - "enum": [ - "resolved", - "ambiguous", - "unresolved", - "unsupported", - "unknown" - ], - "type": "string" - }, - "version": { - "type": "string" - } -} - removed
Output schema / properties / target / requiredRemoved value: -[ - "path", - "fileExists", - "status", - "reason" -] - removed
Output schema / properties / target / typeRemoved value: -"object" - added
Output schema / properties / uncertain / items / properties / source / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / properties / uncertain / items / properties / source / requiredPrevious value: -[ - "path", - "version" -]New value: +[ + "path", + "version", + "versionGuard" +]
- Changed
search_query2 fields changed- added
Output schema / properties / results / items / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / properties / results / items / requiredPrevious value: -[ - "filename", - "version", - "result" -]New value: +[ + "filename", + "version", + "versionGuard", + "result" +]
- Changed
vault_append4 fields changed- added
Input schema / properties / ifMatchGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - added
Output schema / properties / beforeSizeBytesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "message", - "path", - "version", - "sizeBytes", - "created" -]New value: +[ + "message", + "path", + "version", + "versionGuard", + "beforeSizeBytes", + "sizeBytes", + "created" +]
- Changed
vault_delete1 field changed- added
Input schema / properties / ifMatchGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +}
- Changed
vault_get_document_map2 fields changed- added
Output schema / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "path", - "version", - "headings", - "blocks", - "frontmatterFields" -]New value: +[ + "path", + "version", + "versionGuard", + "headings", + "blocks", + "frontmatterFields" +]
- Changed
vault_move1 field changed- added
Input schema / properties / ifMatchGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +}
- Changed
vault_patch7 fields changed- added
Input schema / properties / allowSubtreeReplacementAdded value: +{ + "description": "Explicitly allow heading content/whole-section replace to remove child sections; the version precondition still applies.", + "type": "boolean" +} - removed
Input schema / properties / content / descriptionRemoved value: -"Heading target without within: # is a child in content scope, a sibling with markerAndContent prepend/append." - added
Input schema / properties / ifMatchGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Input schema / requiredPrevious value: -[ - "path", - "targetType", - "target", - "operation", - "ifMatch" -]New value: +[ + "path", + "targetType", + "target", + "operation" +] - added
Output schema / properties / beforeSizeBytesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "message", - "path", - "version", - "sizeBytes", - "created" -]New value: +[ + "message", + "path", + "version", + "versionGuard", + "beforeSizeBytes", + "sizeBytes", + "created" +]
- Changed
vault_read1 field changed- changed
Output schema / anyOfPrevious value: -[ - { - "additionalProperties": false, - "properties": { - "content": { - "type": "string" - }, - "frontmatter": { - "additionalProperties": { - "$ref": "#/$defs/__schema0" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "path": { - "type": "string" - }, - "stat": { - "additionalProperties": false, - "properties": { - "ctime": { - "type": "number" - }, - "mtime": { - "type": "number" - }, - "size": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - } - }, - "required": [ - "ctime", - "mtime", - "size" - ], - "type": "object" - }, - "tags": { - "items": { - "type": "string" - }, - "type": "array" - }, - "version": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - } - }, - "required": [ - "path", - "version", - "content", - "tags", - "frontmatter", - "stat" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "path": { - "type": "string" - }, - "result": { - "$ref": "#/$defs/__schema1" - }, - "version": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - } - }, - "required": [ - "path", - "version", - "result" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "properties": { + "content": { + "type": "string" + }, + "frontmatter": { + "additionalProperties": { + "$ref": "#/$defs/__schema0" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "path": { + "type": "string" + }, + "stat": { + "additionalProperties": false, + "properties": { + "ctime": { + "type": "number" + }, + "mtime": { + "type": "number" + }, + "size": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + } + }, + "required": [ + "ctime", + "mtime", + "size" + ], + "type": "object" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + } + }, + "required": [ + "path", + "version", + "versionGuard", + "content", + "tags", + "frontmatter", + "stat" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "path": { + "type": "string" + }, + "result": { + "$ref": "#/$defs/__schema1" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + } + }, + "required": [ + "path", + "version", + "versionGuard", + "result" + ], + "type": "object" + } +]
- Changed
vault_read_binary2 fields changed- added
Output schema / anyOfAdded value: +[ + { + "additionalProperties": false, + "properties": { + "delivery": { + "const": "image", + "type": "string" + }, + "firstFrameOnly": { + "type": "boolean" + }, + "height": { + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "outputMimeType": { + "const": "image/webp", + "type": "string" + }, + "outputSizeBytes": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "path": { + "type": "string" + }, + "preview": { + "const": true, + "type": "boolean" + }, + "sizeBytes": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + }, + "width": { + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + } + }, + "required": [ + "path", + "mimeType", + "sizeBytes", + "version", + "versionGuard", + "delivery", + "outputMimeType", + "outputSizeBytes", + "width", + "height", + "preview", + "firstFrameOnly" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "delivery": { + "const": "bytes", + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sizeBytes": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "uri": { + "type": "string" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + } + }, + "required": [ + "path", + "mimeType", + "sizeBytes", + "version", + "versionGuard", + "delivery", + "uri" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "delivery": { + "const": "link", + "type": "string" + }, + "expiresAt": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "path": { + "type": "string" + }, + "reason": { + "enum": [ + "requested", + "download", + "too_large", + "image_preview_unavailable" + ], + "type": "string" + }, + "sizeBytes": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "uri": { + "type": "string" + }, + "version": { + "pattern": "^sha256:[0-9a-f]{64}$", + "type": "string" + }, + "versionGuard": { + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" + } + }, + "required": [ + "path", + "mimeType", + "sizeBytes", + "delivery", + "uri", + "expiresAt", + "reason", + "version", + "versionGuard" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "delivery": { + "const": "link", + "type": "string" + }, + "expiresAt": { + "type": "string" + }, + "mimeType": { + "type": "string" + }, + "path": { + "type": "string" + }, + "reason": { + "enum": [ + "requested", + "download", + "too_large", + "image_preview_unavailable" + ], + "type": "string" + }, + "sizeBytes": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "uri": { + "type": "string" + } + }, + "required": [ + "path", + "mimeType", + "sizeBytes", + "delivery", + "uri", + "expiresAt", + "reason" + ], + "type": "object" + } +] - removed
Output schema / oneOfRemoved value: -[ - { - "additionalProperties": false, - "properties": { - "delivery": { - "const": "image", - "type": "string" - }, - "firstFrameOnly": { - "type": "boolean" - }, - "height": { - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - }, - "mimeType": { - "type": "string" - }, - "outputMimeType": { - "const": "image/webp", - "type": "string" - }, - "outputSizeBytes": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "path": { - "type": "string" - }, - "preview": { - "const": true, - "type": "boolean" - }, - "sizeBytes": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "version": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - }, - "width": { - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - } - }, - "required": [ - "path", - "mimeType", - "sizeBytes", - "version", - "delivery", - "outputMimeType", - "outputSizeBytes", - "width", - "height", - "preview", - "firstFrameOnly" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "delivery": { - "const": "bytes", - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "path": { - "type": "string" - }, - "sizeBytes": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "uri": { - "type": "string" - }, - "version": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - } - }, - "required": [ - "path", - "mimeType", - "sizeBytes", - "version", - "delivery", - "uri" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "delivery": { - "const": "link", - "type": "string" - }, - "expiresAt": { - "type": "string" - }, - "mimeType": { - "type": "string" - }, - "path": { - "type": "string" - }, - "reason": { - "enum": [ - "requested", - "download", - "too_large", - "image_preview_unavailable" - ], - "type": "string" - }, - "sizeBytes": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "uri": { - "type": "string" - }, - "version": { - "pattern": "^sha256:[0-9a-f]{64}$", - "type": "string" - } - }, - "required": [ - "path", - "mimeType", - "sizeBytes", - "delivery", - "uri", - "expiresAt", - "reason" - ], - "type": "object" - } -]
- Added
vault_replace_text - Changed
vault_write4 fields changed- added
Input schema / properties / ifMatchGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - added
Output schema / properties / beforeSizeBytesAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / versionGuardAdded value: +{ + "maxLength": 16, + "minLength": 16, + "pattern": "^[0-9a-f]{16}$", + "type": "string" +} - changed
Output schema / requiredPrevious value: -[ - "message", - "path", - "version", - "sizeBytes", - "created" -]New value: +[ + "message", + "path", + "version", + "versionGuard", + "beforeSizeBytes", + "sizeBytes", + "created" +]
1 tool update
- Changed
search_query1 field changed- added
Input schema / properties / scopeAdded 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" +}
13 tool updates
v0.1.0- First observed
obsidian_help - First observed
reference_query - First observed
search_query - First observed
tag_list - First observed
vault_append - First observed
vault_delete - First observed
vault_get_document_map - First observed
vault_list - First observed
vault_move - First observed
vault_patch - First observed
vault_read - First observed
vault_read_binary - First observed
vault_write
TDQS
Scored across 14 tools
Most tools target distinct resources or operations, and the descriptions clarify boundaries between read, write, append, patch, replace, move, and delete. The main possible confusion is among the several text-modification tools, especially vault_patch vs vault_replace_text and vault_write vs vault_append, but the stated preconditions and scopes help distinguish them.
The set is overwhelmingly snake_case and follows a resource-oriented pattern such as vault_read, vault_write, vault_move, and tag_list. Minor deviations like obsidian_help and the longer vault_get_document_map are readable and do not meaningfully hinder selection.
At 14 tools, the server is well-scoped for Obsidian vault management, covering listing, reading, searching, writing, patching, moving, deleting, references, tags, and help. Each tool appears to serve a distinct vault workflow rather than bloating the surface.
Core vault text workflows are well covered: CRUD-like file operations, targeted reads/patches, document maps, search, references, tags, and binary reads. Minor gaps remain around binary/attachment writing, explicit directory operations, copy operations, and PDF handling, but most agent workflows can proceed without dead ends.
Maintenance
Related MCP Connectors
Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.
MCP-native open-source Notion alternative: read & write pages, databases and kanban boards.
Search, read, and safely update Markdown notes in your connected Phasoric knowledge vaults.
Notes and memory assistant: one Markdown vault that Claude, ChatGPT and any MCP client can share.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server for managing an Obsidian vault with CAS-based write, note listing, reading, writing, patching, and searching via ripgrep.77 npmMIT
- FlicenseCqualityDmaintenanceMCP 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-
- AlicenseAqualityBmaintenanceEnables MCP clients to safely read, search, create, edit, delete, and move notes in an Obsidian vault, with automatic link repair and reversible deletes.103,805 npmMIT
- FlicenseNot gradedqualityCmaintenanceEnables MCP clients to search, read, list, and append to markdown notes in a local Obsidian vault or folder of .md files.-