obsidian-mcp-pro
You can use obsidian-mcp-pro as an MCP server to give AI assistants structured access to an Obsidian vault for reading, writing, searching, linking, and analyzing notes and assets.
Search and read notes: full-text search, frontmatter search, tag search, recent notes, vault stats, alias resolution, daily notes, and fragments by section, block ID, or line range.
Write and organize: create notes, append/prepend content, update frontmatter, create daily notes from templates, move/rename with link rewrites, and delete to trash or permanently with optional reference cleanup.
Make surgical edits: update or insert into sections, list headings, regex/literal replace with match guards, and edit
^blockcontent while preserving anchors.Manage tags: list tag counts, find notes by tag, and rename tags vault-wide, including nested tags and frontmatter arrays.
Analyze links and graph structure: get backlinks, outlinks, orphan notes, broken links, and traverse graph neighbors up to 3 hops.
Work with Obsidian canvases: list/read
.canvasfiles, add text/file/link/group nodes, and add edges between nodes.Query Obsidian Bases: list/read
.basefiles and run supported filter DSL queries against the vault.Handle attachments: list non-note files, find unused attachments, and retrieve image/audio/binary bytes with size caps.
Use semantic search: index the vault for embeddings with explicit confirmation, search by meaning, and find notes similar to a source note.
Use MCP resources and prompts: read notes/tags/daily content by URI and run prompts for daily review, weekly rollup, stale-note discovery, action-item extraction, and MOC building.
Allows for structured manipulation of Markdown documents within the vault, including parsing and updating frontmatter properties, as well as appending or prepending content to existing files.
Provides comprehensive access to Obsidian vaults, enabling AI agents to search notes, read and write content with frontmatter support, manage tags, analyze backlinks and outlinks, and traverse the link graph.
obsidian-mcp-pro
The most feature-complete MCP server for Obsidian vaults.
ā Please star us on GitHub, it helps us reach more users!
š Support this project. obsidian-mcp-pro is free and open-source. If it saves you time, consider becoming a patron for ongoing support, or tipping on Ko-fi for a one-time thanks. Patrons get release notes early, priority on bug reports, and (optionally) their name in the README.
Give AI assistants deep, structured access to your Obsidian knowledge base. Read, write, search, tag, analyze links, traverse graphs, manipulate canvases, query Bases, edit by heading or block reference, run semantic search, and pull binary attachments. All through the Model Context Protocol.
41 tools, 5 prompts, 3 resources. Every tool ships with rich descriptions, typed schemas, human-readable titles, and safety annotations (readOnlyHint, destructiveHint, idempotentHint) so your agent picks the right tool, passes the right arguments, and handles results correctly. The original 23 tools earned an average 4.40/5 score and all-A grades on Glama's quality index; the 18 newer ones follow the same authoring conventions documented in docs/TOOL_AUTHORING.md.
Contents
Related MCP server: Vault Cortex Obsidian MCP Server
Features
Read & Search
Focus-ranked full-text search across all vault notes, with query-centered snippets (cached: re-runs only re-read changed files)
Read individual notes whole, or as a fragment by heading path, block id, or line range
List and filter notes by folder, date, or pattern
Search by frontmatter fields and values
Retrieve daily notes automatically using the vault's configured filename format
get_recent_notesorders by mtime;get_vault_statsreports counts, words, tag coverage;resolve_aliastranslates a display name to a real note path
Write & Modify
Create new notes with frontmatter and content
Append or prepend content to existing notes
Update frontmatter properties programmatically (merge: unlisted keys are preserved)
Move and rename notes (rewrites every wikilink, markdown link, and canvas reference across the vault by default)
Delete notes safely; moved to the vault's
.trashfolder by default, with an optional permanent flag and elicitation-based confirmationSurgical edits by heading:
update_section,insert_at_section,list_sections, plus single-notereplace_in_note(regex with match-count guard) andedit_blockfor paragraphs tagged with^id
Tags
Build and query a complete tag index (incremental: cached across runs)
Search notes by single or multiple tags
rename_tagrewrites both inline#tagoccurrences and frontmattertags:arrays vault-wide; hierarchical mode also rebases nested sub-tags (project/alphafollowsproject)
Links & Graph
Get backlinks (what links to a note)
Get outlinks (what a note links to)
Find orphan notes with no inbound or outbound links
Detect broken links pointing to non-existent notes
Traverse graph neighbors to a configurable depth
Canvas
Read
.canvasfiles with full node and edge dataAdd new nodes (text, file, link, group) to canvases
Add edges between canvas nodes
List all canvases in the vault
Bases (Obsidian 1.10+)
list_basesenumerates.basefilesread_basereturns the parsed YAML (filters, properties, views)query_baseruns the filter DSL against the vault and returns matching notes; supportstaggedWith(),file.hasTag(),file.inFolder(), comparison operators, andand/or/notcombinators. Unsupported filters warn and fail closed instead of broadening results.
Attachments
list_attachmentsenumerates every non-md/canvas/base file with a per-extension count summaryfind_unused_attachmentsflags assets no note references via embeds or markdown links; optional reclaimable-bytes reportget_attachmentreturns image / audio / blob bytes inline as MCP content blocks (5 MB default cap, 50 MB hard cap)
Semantic Search (optional, Ollama or OpenAI)
index_vaultchunks each note (heading-aware), embeds via the configured provider, persists vectors to<vault>/.obsidian/cache/, and incrementally re-embeds only changed notesBecause indexing sends readable note chunks to the configured embedding provider,
index_vaultrequiresconfirm: "send-vault-text-to-embedding-provider"on each callsearch_semanticranks notes by cosine similarity against an embedded queryfind_similar_notesreuses an existing note's embeddings, with source-topic anchoring, to surface neighbors without a live API callStored snippets are returned only while the current note content hash still matches the indexed text; stale chunks are pruned on search
MCP Resources
obsidian://note/{path}reads any note by its vault-relative pathobsidian://tagsretrieves the full tag index as JSONobsidian://dailygets today's daily note content
MCP Prompts
The server exposes five starter prompts that clients (Claude Desktop, Cursor) surface in their slash-command palette:
daily-reviewwalks today's daily note, surfaces unchecked tasks, and proposes follow-upsweekly-rollupaggregates the last seven daily notes into themes / decisions / open tasksfind-stale-noteslocates untouched notes and clusters them as orphaned vs. broken-linked vs. still-linkedextract-action-itemspulls all- [ ] ā¦lines from a note (or every note matching a tag) into a checklistbuild-mocgenerates a Map of Content (MOC) for a tag or folder
Operational features
Folder-scoped permissions:
OBSIDIAN_READ_PATHS/OBSIDIAN_WRITE_PATHSallowlists gate every tool at the path-resolution choke pointIn-memory note cache speeds repeated vault scans within a running process without persisting note bodies to disk
Progress notifications (
notifications/progress) onrename_tag,find_unused_attachments, andindex_vaultwhen the client subscribes via_meta.progressTokenHard bulk-write latches require
confirmPathfor defaultmove_notereference rewrites,confirmTagfor non-dry-runrename_tag, andconfirm=truefor permanent deletion; clients with elicitation support also get typed prompts
Quick Start
npx installs the latest published npm release. This README follows the source
branch and may describe merged changes that have not been published. See the
4.1.0 release notes for verified publication and
consumer dependency requirements.
Using Obsidian? There's also an Obsidian plugin that runs this server inside the app with a ribbon toggle and settings UI ā no config-file editing. Recommended for most users.
One-Command Install (Claude Desktop / Cursor)
npx -y obsidian-mcp-pro installThis merges an entry into your claude_desktop_config.json (or ~/.cursor/mcp.json with --client=cursor), backs up the previous file, and prints next steps. Works on macOS, Windows, and Linux.
Pin a specific vault:
npx -y obsidian-mcp-pro install --vault /path/to/your/vaultManual Claude Desktop Config
Add this to your Claude Desktop configuration file (claude_desktop_config.json):
{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": ["-y", "obsidian-mcp-pro"]
}
}
}If you have multiple vaults, specify which one:
{
"mcpServers": {
"obsidian": {
"command": "npx",
"args": ["-y", "obsidian-mcp-pro"],
"env": {
"OBSIDIAN_VAULT_PATH": "/path/to/your/vault"
}
}
}
}Claude Code
claude mcp add obsidian-mcp-pro -- npx -y obsidian-mcp-proHTTP Transport (Remote Clients, Cursor, ChatGPT, Web)
MCP_HTTP_TOKEN=your-secret npx -y obsidian-mcp-pro --transport=http --port=3333Endpoint: http://127.0.0.1:3333/mcp (Streamable HTTP). HTTP transport requires a bearer token:
MCP_HTTP_TOKEN=your-secret npx -y obsidian-mcp-pro --transport=httpThe HTTP server binds to 127.0.0.1 by default with DNS rebinding protection enabled.
IPv6 bind literals use canonical URL spelling and brackets in returned and logged URLs and the derived Host allowlist entry. For example, host: "::1" returns http://[::1]:port/mcp, and host: "::ffff:127.0.0.1" uses [::ffff:7f00:1]; handle.host remains the original bind address. Explicit allowedHosts entries retain their exact configured spelling.
Scoped IPv6 bind addresses such as fe80::1%eth0 are unsupported by the HTTP URL parser and reject before the server starts listening.
Startup always requires MCP_HTTP_TOKEN, including loopback-only local servers. The old --token flag was removed because command-line secrets can be exposed through OS process listings.
The following embedding option is available in core 4.1.0 and newer. When embedding the library, set
allowedHosts to accept additional destination
addresses, such as the hostname forwarded by an HTTPS reverse proxy:
import { buildMcpServer, startHttpServer } from "obsidian-mcp-pro";
const vaultPath = process.env.OBSIDIAN_VAULT_PATH!;
const server = await startHttpServer({
host: "127.0.0.1",
port: 3333,
bearerToken: process.env.MCP_HTTP_TOKEN!,
allowedHosts: ["vault.example.com", "192.0.2.10:3333"],
buildMcpServer: () => buildMcpServer(vaultPath),
installSignalHandlers: false,
});
// On application shutdown:
await server.stop();startHttpServer() resolves after the socket starts listening. Validation errors,
invalid listen arguments, and bind failures such as EADDRINUSE reject its Promise,
so an embedder can catch the error and retry. These startup failures create no
session sweeper or signal handlers. A successful handle supports repeated stop()
calls.
Entries match the HTTP
Hostheader exactly and case-sensitively, including a port when present. Usevault.example.com:443if the proxy forwards that value instead ofvault.example.com. IPv6 must keep brackets ([::1]:port). There is no IDN / punycode normalization. Do not include schemes, paths, or wildcards;"*"is rejected at startup (it is not a wildcard).Configured entries extend the bound-address and loopback defaults. Omitting
allowedHostsor passing[]preserves the defaults.The server copies and validates the list at startup. Restart it to apply configuration changes. Listen-time logs include the effective Host allowlist (never the bearer token).
/healthand/versionskip Host validation (pre-existing)./mcprejects a disallowed Host with 403 and a warn log, including when the bearer is valid.This controls destination addresses, not client identity. Bearer authentication and Origin validation still apply; DNS-rebinding protection remains enabled.
This is an embedding API option, not a CLI flag.
The Role API below is available in core 4.1.0 and newer. HTTP embedders can assign each token a named Role containing an explicit Tool list. Roles filter tool, resource, and prompt discovery and calls. Permission changes close affected sessions immediately. See HTTP Roles for configuration, legacy-token migration, audit events, and the remaining plugin integration work.
Never bind --host=0.0.0.0 directly to the public internet. Doing so exposes your entire Obsidian vault to anyone who can reach the port. The server refuses HTTP startup without a bearer token, but if you need remote access:
Put the server behind a reverse proxy (nginx, Caddy, Cloudflare Tunnel) that terminates TLS, and
Set
MCP_HTTP_TOKEN, andRestrict
--allow-originto the specific origins you trust, andSet
--rate-limitto cap request volume per IP.
For local-only setups (same machine / VPN / SSH tunnel), keep the default 127.0.0.1 bind.
Additional hardening flags:
Flag | Purpose |
| Restrict CORS to an allowlist (e.g. |
| Cap requests per minute per client IP. |
Operational endpoints (no auth required):
Endpoint | Returns |
|
|
|
|
Structured logging is controlled by LOG_LEVEL (debug/info/warn/error/silent, default info) and LOG_FORMAT (text/json, default text). All logs go to stderr so the stdio transport on stdout is never polluted, with absolute paths, vault-relative path fields, secret-bearing URLs, and control characters redacted before write.
Usage
Once installed, the server exposes 41 tools, 5 prompts, and 3 resources to whichever MCP client you configured. Below is a transcript of a Claude Desktop conversation showing what day-to-day use looks like.
You: Find notes tagged
#projectI touched this week, then summarize the status of each and append today's date under a "Last reviewed" heading in each one.
Claude picks the right tools in order, with no guidance beyond the prompt:
š§ search_by_tag(tag="project", includeContent=false)
ā 7 notes: "Atlas/overview.md", "Atlas/milestones.md", "Beacon/spec.md", ...
š§ list_notes(folder="Atlas", limit=100)
ā filters to recent modifications via get_note stats
š§ get_note(path="Atlas/overview.md")
ā reads content + frontmatter + tags
š§ get_note(path="Atlas/milestones.md")
ā ...
š§ append_to_note(
path="Atlas/overview.md",
content="\n## Last reviewed\n2026-04-21 ā on track; waiting on design review."
)
ā ok
š§ append_to_note(
path="Atlas/milestones.md",
content="\n## Last reviewed\n2026-04-21 ā Q2 milestone at risk, see spec.md."
)
ā okClaude: I reviewed 7 project notes tagged
#project. Atlas is on track pending design review; the Q2 milestone is at risk ā details inmilestones.md. Beacon's spec is complete but has 3 open questions in the frontmatter. I appended a "Last reviewed" section to each.
Other things the tool set lets agents do without hand-holding:
Research a topic across the vault.
search_notesāget_outlinksāget_graph_neighborswalks the graph todepth=2and surfaces related notes the user may have forgotten.Clean up dangling references after a rename.
move_noteāfind_broken_linksreturns every wikilink that now points nowhere, with source note and line number.Maintain a daily log.
get_daily_notereads today's note (using the vault's configured date format) andappend_to_noteadds the new entry ā daily-note plugin config is honored, no manual date formatting.Canvas editing.
read_canvasā agent reasons about the node graph āadd_canvas_node+add_canvas_edgelays out new ideas on an existing board.
With updateLinks=true, move_note also preserves self-links and outgoing targets inside the moved note. Explicit relative Markdown links and embeds retain their original targets after a folder change. Move link behavior describes resolution and partial failures.
Tool descriptions + typed schemas + safety hints (readOnlyHint, destructiveHint) are what make this work reliably ā the agent knows delete_note is destructive and asks first, knows search_notes is free to call speculatively, and knows the expected shape of every argument.
Configuration
The server locates your vault using the following priority:
Priority | Method | Description |
1 |
| Environment variable with the absolute path to your vault |
2 |
| Environment variable to select a vault by folder name when multiple vaults exist |
3 | Auto-detection | Reads Obsidian's global config ( |
Auto-detection works on macOS, Windows, and Linux by reading the platform-specific Obsidian configuration directory.
Environment Variables
Every setting is optional unless noted. The sections below explain the grouped ones in depth.
Variable | Purpose | Default |
| Absolute path to the vault (highest-priority vault selector). | auto-detect |
| Select a vault by folder name when several exist. | first valid vault |
| Comma/colon list of folders read tools may access (see Folder-Scoped Permissions). | unrestricted |
| Same shape, for mutating tools. | unrestricted |
| Set | enabled |
| Semantic-search provider, e.g. | unset (disabled) |
| Embedding model name for the chosen provider. | provider default |
| Override the embedding endpoint base URL. | provider default |
| API key for the embedding provider. | falls back to |
| Used as the embedding key when | unset |
| Bearer token required by the HTTP transport (see HTTP Transport). | unset |
| Logger verbosity: |
|
| Log output format: |
|
Daily-Note Filename Format
get_daily_note, create_daily_note, and the obsidian://daily resource render the note path using your vault's .obsidian/daily-notes.json format string. Moment.js-style tokens are supported:
Token | Example | Token | Example | |
|
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
|
|
|
| |
| renders the bracket contents verbatim, e.g. |
Unrecognized tokens pass through unchanged. Local time is used (matching Obsidian's rendering).
Folder-Scoped Permissions
Restrict the tools' read/write surface to specific folders without exposing the rest of the vault:
Env var | Purpose |
| Comma- or colon-separated list of folders that read tools may access. Unset means unrestricted. Use |
| Same shape, but for mutations (create / append / update / delete / move / surgical edits). |
Read and write are independent, so an audit account can be read-only on most of the vault but write-only to a Drafts/ folder. Moving a note requires read access to the source and write access to the destination, because the move carries the source content into its new folder. Surgical edits (replace_in_note, update_section, insert_at_section, and edit_block) require read access to the target plus write access because they inspect existing content before writing. In-vault symlinks are checked against their real target before the allowlist decision is finalized. The startup log line and --help advertise the active scope. The allowlist is enforced at a single path-resolution choke point so every tool inherits it.
append_to_note, prepend_to_note, and update_frontmatter can modify write-only notes without granting retrieval access. Their internal read preserves existing content. Invalid YAML errors report a fixed category and a one-based line and column in the note, without source excerpts or parser-provided reasons. Oversized frontmatter errors report the size limit. These errors leave the note unchanged and do not include existing note text in responses or logs.
Caches
The note-content cache is in-memory only. It speeds repeated vault-wide scans
inside the running process, but it does not persist note bodies or absolute paths to
disk. Any legacy <vault>/.obsidian/cache/mcp-pro-index-cache.json snapshot is
ignored and removed on first cache use.
Batch reads reuse content only when the validated file's size, mtime, ctime, device, and inode match the cached signature at the same requested path. A size change or replacement therefore invalidates an entry even when mtime is restored. Filesystems can reuse identities or preserve metadata, and a file can change after validation. This signature is not content validation. Direct point reads remain uncached; use a direct read and validate the bytes when exact content freshness is required.
Semantic embeddings live under <vault>/.obsidian/cache/:
File | Purpose |
| Persisted embeddings for semantic search (only present once |
The embedding cache is vault-local, excluded from vault scans (.obsidian/ is pruned), and can be deleted at any time. Persistence can be turned off with OBSIDIAN_CACHE_DISABLED=1.
Semantic Search Provider
The semantic-search tools (index_vault, search_semantic, find_similar_notes) need an embedding provider. Configure via env:
Env var | Default | Notes |
|
|
|
|
| Provider-specific model identifier. |
|
| Base URL without credentials, query strings, or fragments. |
|
| Required for hosted providers. |
For local Ollama: install Ollama, then ollama pull nomic-embed-text. The semantic tools register even when no provider is configured, so they're discoverable; calls return a configuration hint until set up.
index_vault sends readable note chunks to that provider. Calls must include:
{ "confirm": "send-vault-text-to-embedding-provider" }This latch is per call so scripted index refreshes have to keep the privacy decision visible.
Observability
Logs stream to stderr as either plain text (default) or single-line JSON, controlled by LOG_LEVEL (debug/info/warn/error/silent) and LOG_FORMAT (text/json). Local stderr and MCP-forwarded log payloads both redact absolute paths, vault-relative path fields, secret-bearing URLs, and control characters.
The server also declares the MCP logging capability, so every log line is forwarded to the connected client as a notifications/message frame alongside tool responses. Clients that honor logging/setLevel can filter server-side logs at runtime without restarting. Claude Desktop surfaces these in its MCP DevTools pane; most other clients currently ignore them, so this is useful primarily for self-hosters and tooling authors.
Security
Tool calls over HTTP and stdio are limited to 16 object keys and array entries, counted recursively before validation. The largest current tool takes eight scalar fields. String length does not consume this element budget, so existing content and frontmatter string limits still apply. Over-budget calls return a tool error before dispatch. HTTP requests also remain subject to the 4 MiB body cap, including JSON framing and escaping; schema-valid text may need smaller chunks. See the dependency security review for the budget rationale and separate transport limits.
Vault boundary ā every tool and resource routes through a single path resolver that rejects
..traversal, null-byte injection, and symlinks pointing outside the vault (ancestor-realpath check). On Windows it also rejects reserved device names, alternate data stream syntax, and trailing-dot/space filename aliases.Note/file boundary ā note read and edit surfaces only target
.mdfiles; attachments, Canvas files, and Bases stay on their dedicated tools with their own caps and parsers.Full-note cap ā full
.mdnote reads and read-modify-write helpers refuse notes over 5 MiB before materializing them;get_noteline fragments still stream from large notes for targeted inspection.Excluded directories ā
.obsidian,.git, and.trashare pruned at traversal time and denied on both requested paths and canonical targets. File symlinks and directory aliases into these directories are denied, including nested occurrences. Public note reads, including read-modify-write operations, require canonical file targets ending in.md. Directory aliases remain valid for folder operations even when their names end in.md. Reads through aliases to permitted note targets remain supported. Internal reads of configuration and cache files use a separate vault-boundary check.HTTP transport ā requires a bearer token at startup and binds to
127.0.0.1by default with DNS rebinding protection (host-header allowlist)./mcprequests must sendAuthorization: Bearer <secret>, compared in constant time. Malformed request URL or Host data is rejected before routing.Attachment safety ā executable extensions are blocked, SVGs are returned as
text/plain, and active text formats such as HTML/XML/CSS are served withtext/plainresource metadata.Canvas link safety ā Canvas link nodes added through the server accept only absolute
http://andhttps://URLs, preventing local file and application-protocol links from being persisted by tool calls.Regex edit safety ā
replace_in_noteexecutes compilation, counting, and replacement in a terminable worker with a 1,000 ms deadline that includes worker startup. It retains input caps and early pattern rejection, limits output to 5 MiB of UTF-8, and leaves the note unchanged on timeout or worker failure. Literal mode uses the same worker while preserving literal dollar tokens. See Bounded note replacement.Error and log sanitization ā filesystem error messages are stripped of absolute host paths before being returned to MCP clients, local stderr and MCP-forwarded logs redact paths and secret-bearing URLs, ASCII control bytes and Unicode bidi controls are escaped in displayed values, and note-derived duplicate-alias text is not copied into graph warnings. Uncaught HTTP errors respond with a generic
Internal server errorbody while server logs keep sanitized diagnostics.Untrusted vault text boundaries ā tool outputs that include note bodies, read, search result, semantic result, semantic index failure, write rewrite-warning, link-graph, attachment, Base, and Canvas path summaries, attachment extension summaries, search snippets, semantic snippets and heading paths, tag lists, tag search result paths and previews, tag rename skipped-note rows, frontmatter values, Base data, wikilink targets in link-analysis output, SVG attachment text, section headings, Canvas node identities, colors, previews, edge endpoints, and edge labels, or backlink context wrap those vault-authored portions in
[BEGIN UNTRUSTED VAULT CONTENT: ...]/[END UNTRUSTED VAULT CONTENT: ...]markers before they enter an MCP client's model context. Note and daily resources use the same visible boundaries for markdown bodies and carry_meta["obsidian-mcp-pro/contentTrust"] = "untrusted-vault-content".YAML parser boundaries ā Obsidian properties are parsed only from
---YAML delimiter lines; non-YAML gray-matter language blocks stay as body text, oversized frontmatter is skipped on reads and refused for metadata updates, and note/Base YAML containing anchors or aliases is not parsed.Semantic index freshness ā
search_semanticandfind_similar_notesre-check current note content hashes before returning stored snippets or source-note embeddings, pruning stale cache entries instead of surfacing old note text.Semantic indexing confirmation ā
index_vaultrefuses to read and embed vault notes unless the call includesconfirm: "send-vault-text-to-embedding-provider", making provider-bound note transfer explicit.Bulk-write confirmations ā
move_notereference rewrites requireconfirmPathto match the destination path, and non-dry-runrename_tagrequiresconfirmTagto match the new tag. Clients that support MCP elicitation are also asked to re-type the destination path or new tag before the rewrite runs.Interactive confirmation failures ā permanent deletion, link-rewriting moves, and tag renames abort if an attempted form confirmation fails, times out, or is cancelled. A late response cannot authorize a cancelled tool request. Clients without form elicitation, including URL-only clients, use the required caller-supplied
confirm,confirmPath, orconfirmTaglatch as the explicit noninteractive fallback. See Destructive confirmation policy.Atomic writes ā every note write (
create_note,append,prepend,update_frontmatter, canvas mutations) stages content to a sibling temp file then renames onto the target, so a crash or kill mid-write never leaves a truncated file. Per-path locks serialize cooperating callers in this process. Note transforms, appends, and prepends also reject observed external changes before replacement. This is optimistic conflict detection with a remaining check-to-rename window. See Note update conflicts. Existing POSIX file modes survive replacement; new notes use0666 & ~umask, and staging starts without group or other access. See File permissions for the policy and platform limits. Theinstallsubcommand uses the same staging pattern and keeps a backup of the previous config.Rate limiting + CORS allowlist ā optional
--rate-limitcaps per-IP request volume;--allow-originrestricts browser-facing CORS and refuses*unless bearer auth is enabled./healthand/versionstay reachable under load for monitoring.Request timeout ā HTTP POST requests are capped at 2 minutes of wall-clock time. Long-lived SSE GET streams are exempt so idle clients aren't reaped.
Process supervision ā
uncaughtExceptionexits cleanly so systemd/Docker/npx supervisors can restart;unhandledRejectionlogs but doesn't kill the process.
Wikilink Resolution
[[Target]] resolves in the same order Obsidian does:
Exact relative-path match (case-insensitive).
Path-suffix match (e.g.
[[projects/foo]]pickswork/projects/foo.md).Basename match. When multiple notes share a basename, the one that shares the deepest directory prefix with the linking note wins; ties break on shortest overall path.
Frontmatter
aliasesā[[Display Name]]resolves to a note whose frontmatter declares that alias.aliases,Aliases, andALIASESare all recognized.
Tag extraction is similarly case-tolerant: tags, Tags, TAGS, tag, and Tag frontmatter keys are all read.
Tool Reference
Read
Tool | Description | Key Parameters |
| Focus-ranked full-text search with query-centered snippets (cached) |
|
| Read a note whole, or by |
|
| List notes in the vault or a folder |
|
| Get today's (or a specific date's) daily note |
|
| Find notes by frontmatter property values with case-insensitive key/value matching |
|
| Notes sorted by mtime; optional ISO-or-relative |
|
| Vault counts, bytes, words, tag coverage, most-recent note |
|
| Translate frontmatter alias (or basename) to note path |
|
Write
Tool | Description | Key Parameters |
| Create a new note with content and frontmatter |
|
| Append content to an existing note |
|
| Prepend content after frontmatter |
|
| Update frontmatter properties on a note |
|
| Create today's daily note from template |
|
| Move or rename a note; rewrites references across the vault |
|
| Delete a note (trash by default); optional elicitation on permanent |
|
Section-level edits
Tool | Description | Key Parameters |
| Replace the body under a heading path (heading kept) |
|
| Insert at |
|
| Return the heading outline of a note as an indented tree |
|
| Find/replace within one note (literal or regex, with match-count guard) |
|
| Replace content of a paragraph tagged |
|
Tags
Tool | Description | Key Parameters |
| Get all tags and their usage counts |
|
| Find all notes with a specific tag |
|
| Rewrite inline + frontmatter occurrences vault-wide; hierarchical |
|
Links & graph
Tool | Description | Key Parameters |
| Get all notes that link to a given note |
|
| Get all links from a given note |
|
| Find notes with no links in or out |
|
| Detect links pointing to non-existent notes |
|
| Get notes connected within N link hops |
|
Canvas
Tool | Description | Key Parameters |
| List all | (none) |
| Read a bounded |
|
| Add a node to a canvas |
|
| Add an edge between two canvas nodes |
|
Bases
Tool | Description | Key Parameters |
| Enumerate | (none) |
| Parse a Base file (filters, properties, views) |
|
| Run a Base's filter DSL against the vault; unsupported filters warn and fail closed |
|
Attachments
Tool | Description | Key Parameters |
| Enumerate every non-md/canvas/base file |
|
| Attachments not referenced via embeds or markdown links |
|
| Return image / audio / blob content (5 MB default cap) |
|
Semantic search
Tool | Description | Key Parameters |
| Build / refresh the embedding index (incremental, progress events) |
|
| Cosine search the embedding index for a natural-language query |
|
| Surface notes most similar to a source note, anchored to its opening topic (no live API call) |
|
MCP Resources
Resources provide a URI-based way to access vault data:
Resource URI | Description |
| Read any note by its vault-relative path |
| Full tag index with file lists (JSON) |
| Today's daily note content |
Troubleshooting
Tools Don't Show Up in Claude Desktop
MCP clients only re-read their config on startup. After editing claude_desktop_config.json (or running npx obsidian-mcp-pro install), fully quit Claude Desktop (āQ on macOS, tray ā Quit on Windows) and relaunch. Hot-reloading the window is not enough.
"No Obsidian vault configured" on Startup
The server couldn't locate a vault. Resolution order is:
OBSIDIAN_VAULT_PATHenv var (absolute path) ā always wins if set. An invalid selection fails startup instead of falling back to another vault.OBSIDIAN_VAULT_NAMEenv var ā picks a named vault from Obsidian's global config.Auto-detection ā reads
obsidian.json(platform-specific) and uses the first valid vault found.
Fastest fix: set OBSIDIAN_VAULT_PATH in the env block of your MCP client's config. Auto-detection fails when Obsidian has never been launched, obsidian.json is missing/corrupt, or all registered vaults resolve to paths that no longer exist.
Both startup and install --vault require an accessible vault directory containing an accessible .obsidian directory. An ordinary folder or a file named .obsidian does not qualify. Correct an invalid explicit path, or unset OBSIDIAN_VAULT_PATH to enable auto-detection.
"Path traversal detected" Error on Tool Calls
All tool paths must be vault-relative (e.g. notes/hello.md), never absolute (/Users/me/vault/notes/hello.md) or containing ... The agent normally gets this right ā if you see this error, check whether a custom instruction is asking it to use absolute paths.
HTTP Transport Returns 401 Unauthorized
The server was started with MCP_HTTP_TOKEN but the client isn't sending a matching Authorization: Bearer <secret> header. Verify the token value and that the header is present ā comparison is case-sensitive and constant-time.
HTTP Transport Returns 429 Too Many Requests
--rate-limit=<n> is set and the client exceeded N requests in the last 60 seconds from that IP. Either raise the limit, drop it, or wait 60 seconds. /health and /version are exempt if you need to check liveness under load.
Daily-Note Path Is Wrong or Unresolved
The server reads .obsidian/daily-notes.json from the vault for the filename format and folder. If that file doesn't exist (the Daily Notes core plugin has never been configured), the server falls back to YYYY-MM-DD.md in the vault root. Configure the plugin once inside Obsidian and the server picks it up automatically.
npx obsidian-mcp-pro Silently Exits With Code 0
This was a bug in versions < 1.4.1 where the npx-symlinked CLI entry failed to detect itself as the entrypoint. Upgrade: npx -y obsidian-mcp-pro@latest install.
Windows: "EPERM: operation not permitted" During Writes
The server retries these transparently (Windows holds stricter file-sharing locks than POSIX) ā if you still see the error, it usually means antivirus or a sync client (OneDrive, Dropbox) is holding the file. Exclude the vault folder from real-time antivirus scanning, or pause the sync client during heavy agent sessions.
Development
# Clone the repository
git clone https://github.com/rps321321/obsidian-mcp-pro.git
cd obsidian-mcp-pro
# Install dependencies
npm install
# Build
npm run build
# Run the full local maintenance gate
npm run verify
# Run in development (watch mode)
npm run dev
# Start the server locally
OBSIDIAN_VAULT_PATH=/path/to/vault npm startGitHub Actions workflows are manual-only in this repository. Use npm run verify as the required local gate before merging or publishing.
Commits run a local Husky hook that rejects maintainer-only paths, formats staged
files, then runs the type-checker and test suite. Run npm ci after cloning to
install the hook.
Project Structure
src/
index.ts # Server entry, CLI parser, resource + prompt registration
config.ts # Vault detection, daily-notes config loader
http-server.ts # Streamable HTTP transport, Bearer auth, session TTL
install.ts # `install` subcommand (Claude Desktop / Cursor)
types.ts # Shared TypeScript interfaces
lib/
vault.ts # Core vault ops (read, search, list, per-file locks,
# symlink boundary, canvas + base + attachment round-trip)
permissions.ts # OBSIDIAN_READ_PATHS / OBSIDIAN_WRITE_PATHS allowlist
markdown.ts # Frontmatter, wikilinks, tags, alias-aware resolver
sections.ts # Heading parser, block-id parser, section bounds
tag-rewriter.ts # Vault-wide tag rewriting (inline + frontmatter)
link-rewriter.ts # Plan/apply edit pipeline used by move + delete
bases.ts # Bases YAML parser + filter DSL evaluator
chunker.ts # Heading-aware chunking for embeddings
embedding-providers.ts# Ollama + OpenAI providers
embedding-store.ts # Persistent vector index, cosine search
index-cache.ts # file-signature content cache (in-memory)
progress.ts # MCP progress-notification helper
mime.ts # extension -> MIME map for attachments
dates.ts # Moment-style date format for daily-note filenames
errors.ts # sanitizeError: strips absolute paths from fs errors
concurrency.ts # Bounded-concurrency fan-out helper
logger.ts # Leveled stderr logger (text + JSON modes)
tools/
read.ts # search, get, list, daily, frontmatter, recent, stats, alias
write.ts # create, append, prepend, update_frontmatter, move, delete
sections.ts # update_section, insert_at_section, list_sections,
# replace_in_note, edit_block
tags.ts # get_tags, search_by_tag, rename_tag
links.ts # backlinks, outlinks, orphans, broken, graph_neighbors
canvas.ts # list, read, add_node, add_edge
bases.ts # list_bases, read_base, query_base
attachments.ts # list_attachments, find_unused_attachments, get_attachment
semantic.ts # index_vault, search_semantic, find_similar_notes
prompts.ts # daily-review, weekly-rollup, find-stale-notes,
# extract-action-items, build-moc
__tests__/
vault.test.ts markdown.test.ts tools.test.ts
security.test.ts http-server.test.ts semantics.test.ts
logger.test.ts sections.test.ts tag-rewriter.test.ts
bases.test.ts permissions.test.ts index-cache.test.ts
chunker.test.ts embedding-store.test.ts errors.test.ts
link-rewriter.test.ts
handlers/
read.test.ts write.test.ts tags.test.ts
links.test.ts canvas.test.ts attachments.test.ts
semantic.test.ts harness.tsTesting
npm testRun node scripts/check-packed-consumer.mjs to build, pack and install the core into a fresh consumer, then exercise its installed CLI, library and HTTP sessions against a temporary vault. See installed package acceptance for platform coverage and limits.
The suite covers vault operations, concurrent writes, Markdown parsing, link and
tag rewriting, attachment classification, semantic search and embedding
persistence, cache freshness, HTTP transport, and security regressions. Handler
tests exercise tools through a real MCP client/server pair via
InMemoryTransport. See CI runs
for results tied to a commit; the badge above reports the master workflow state.
npm run lint # eslint v9 + typescript-eslint v8 (flat config)
npm run lint:fix # auto-fixWhat's New
v1.8.2 rolls in a deeper-dive audit pass on top of 1.8.1:
rename_tagand other vault-wide bulk writers now hold the same rewrite lock asmove_note/delete_note. Closes a cross-tool TOCTOU where running tag-rename concurrently with a move could surface "content changed during move" failures and leave stale links.applyRewritesretries failed edits via content search. When bytes shift between plan and apply (Obsidian sync, text editor, concurrent tool), the apply step now finds the uniqueexpectedsubstring at its new position and splices there. If ambiguous or missing, the failure is still surfaced rather than corrupting the file.planMoveRewritesandplanDeleteRewritesnow read each note exactly once. The previous two-pass implementation doubled I/O on rename / delete operations across large vaults.CommonMark fenced-code indentation now matches the spec. Lines with more than 3 leading spaces no longer falsely close a fenced block (and don't expose subsequent content to wikilink rewriting).
/healthno longer leaks the live session count when a Bearer token is configured. Status + version stay public for monitoring;sessionsis dropped in authenticated deployments. In 4.0.0 and later, HTTP always starts with bearer auth, so the field stays hidden.constantTimeEqualis now fully length-safe (pads both inputs to a fixed width before comparing), and the regex / parser hardening list also closed:resolveWikilinkproximity tie-break for path-suffix matches, escaped]in markdown link labels, control- character validation onrunInstall.vaultName, backup-path hint on install write failure, andmapConcurrentreturn-value usage in the canvas planner.npm auditclean. Resolved 4 moderate-severity advisories in transitive devDependencies. Production deps were already clean.
v1.8.1 was a security and correctness patch on top of 1.8.0:
CRITICAL: permission allowlist bypass via
..segments closed. v1.8.0 evaluatedOBSIDIAN_READ_PATHS/OBSIDIAN_WRITE_PATHSagainst the raw user-supplied path beforepath.resolvecollapsed... An input likeAllowed/../OtherFolder/note.mdslipped past the prefix check.assertAllowednow collapses..viapath.posix.normalizeand rejects any path that climbs above its starting point. Six regression tests cover the bypass classes.HIGH: HTTP timeout on every embedding-provider fetch (
AbortSignal.timeout(30s)), TOCTOU race inrename_tagclosed by moving the rewrite insideupdateNote's transform, andsearch_semantic/find_similar_notesnow invalidate stale vectors when the active provider/model differs from what produced the index.MEDIUM: depth guard on Bases filter recursion,
updateNoteskips the disk write when the transform returns unchanged content (no more spurious mtime bumps on no-op tools), and embedding-provider error bodies are truncated to 200 chars before being interpolated into thrown errors.LOW: empty
acceptelicitation responses are now cancellations, not errors, and the in-memory mtime cache snapshot orders by content length so small entries fill the budget first.
v1.8.0 was the largest feature drop since v1.0:
Surgical edits by heading and block id.
update_section,insert_at_section,list_sections,replace_in_note,edit_block, plus fragment retrieval modes onget_note(section,block,lines).Bases support.
list_bases,read_base,query_basefor Obsidian's database-view files. First filesystem-only MCP server to ship native Bases.Semantic search.
index_vault,search_semantic,find_similar_notesbacked by Ollama (default) or OpenAI. Persistent vector index with content-hash incremental updates.Attachments.
list_attachments,find_unused_attachments,get_attachment(returns image / audio / blob bytes inline).Tag renames vault-wide.
rename_tagrewrites both inline#tagand frontmattertags:(hierarchical mode rebases nested sub-tags).Folder-scoped permissions.
OBSIDIAN_READ_PATHS/OBSIDIAN_WRITE_PATHSallowlists.In-memory note cache. Vault-wide scans (
get_tags,search_notes,search_by_tag) reuse note content when its file signature matches, without persisting note bodies to disk.Quick wins.
get_recent_notes,get_vault_stats,resolve_alias.MCP prompts.
daily-review,weekly-rollup,find-stale-notes,extract-action-items,build-moc.Progress notifications on
rename_tag,find_unused_attachments,index_vault.Bulk-write confirmation latches on
delete_note(permanent: true),move_notereference rewrites, and non-dry-runrename_tag, plus elicitation prompts for clients that support them.eslint wired up with typescript-eslint flat config;
npm run lintandlint:fix.
v1.7.0 ā delete_note reference handling:
delete_notecan strip references vault-wide whenpermanent: trueis paired withremoveReferences: true. Wikilinks fall back to alias-or-basename, markdown links fall back to visible text, embeds drop entirely, fragments are discarded. Trash-mode (default) leaves references intact since trashed files stay recoverable.Concurrent-safe rewrites ā
move_note(withupdateLinks: true) anddelete_note(withremoveReferences: true) serialize per vault, removing the partial-failure mode for parallel rewrite-bearing operations.
v1.6.0 ā Obsidian-parity link maintenance:
move_noterewrites references across the vault by default, matching Obsidian's "Automatically update internal links" behavior. Wikilinks (with aliases / fragments preserved), markdown links, and canvasnodes[].filefields all follow the moved file. Output form is preserved when possible.TOCTOU correctness ā every edit's pre-edit content is verified before splicing, so a parallel
write_notebetween plan and apply is surfaced infailedReferrersrather than corrupting referrers silently.Control-char injection defense ā
sanitizeErrorand the newescapeControlCharsstrip newlines/control bytes from any caller-controlled string before it reaches LLM context. Closes a prompt-injection vector via attacker-named filenames.
Full version history in CHANGELOG.md.
License
MIT
Contributing
Contributions welcome! Please open an issue first to discuss what you'd like to change. Pull requests without a corresponding issue may be closed.
If you're adding or editing a tool, read docs/TOOL_AUTHORING.md first ā it documents the description, schema, and annotation conventions that keep every tool at A-grade quality.
Acknowledgments
Vault-wide link rewriting on
move_note(#3, #4) and thesanitizeErrordefense-in-depth hardening contributed by @brentkearney.
For the full list of everyone who's contributed, see the contributors page.
Available Tools
41 toolsadd_canvas_edgeAdd Canvas EdgeA
Create a directed edge connecting two existing canvas nodes. Both fromNode and toNode must already exist on the canvas (use read_canvas to list node ids, or capture the id returned by add_canvas_node). Optional fromSide/toSide control which face of each node the edge anchors to. Returns the generated edge UUID.
| Name | Required | Description | Default |
|---|---|---|---|
| label | No | Optional text label rendered on the edge | |
| toNode | Yes | UUID of the target (destination) node - must already exist on the canvas | |
| toSide | No | Face of the target node the edge arrives at (default: auto-chosen by Obsidian) | |
| fromNode | Yes | UUID of the source (origin) node - must already exist on the canvas | |
| fromSide | No | Face of the source node the edge leaves from (default: auto-chosen by Obsidian) | |
| canvasPath | Yes | Relative path from vault root to the target .canvas file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a non-read-only, non-destructive, non-idempotent mutation. The description adds useful behavioral context by specifying that both nodes must already exist and that the tool returns the generated edge UUID.
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 three tight sentences, front-loading the core action and prerequisites before optional details and return value. There is no wasted language.
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 no output schema, the description compensates by stating that the generated edge UUID is returned. Combined with the prerequisites and 100% schema coverage, an agent has enough information to invoke the 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?
The schema has 100% description coverage, so the schema already explains all six parameters. The description adds prerequisite meaning for fromNode/toNode and clarifies fromSide/toSide, but does not add much for label or canvasPath beyond what the schema provides.
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 action and resource: creating a directed edge between two existing canvas nodes. It clearly distinguishes this from sibling tools like add_canvas_node and read_canvas by focusing on edge creation and node prerequisites.
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 gives clear contextual guidance: both node IDs must already exist, and it names read_canvas and add_canvas_node as ways to obtain them. It does not explicitly describe when not to use the tool, but the usage context is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_canvas_nodeAdd Canvas NodeA
Add a new node to an Obsidian canvas and persist the updated file. Supports four node types: 'text' (markdown block), 'file' (embedded vault note reference), 'link' (external URL), and 'group' (labeled container). Returns the generated node UUID, needed to connect nodes via add_canvas_edge. When neither x nor y is supplied, the new node is auto-positioned at (50 * existing_count, 50 * existing_count) to avoid stacking multiple defaulted nodes at the origin. Supplying an explicit x or y always overrides this stagger.
| Name | Required | Description | Default |
|---|---|---|---|
| x | No | X coordinate on the canvas. When omitted (and y is also omitted) the node is auto-staggered to avoid origin pile-up; an explicit value always wins. | |
| y | No | Y coordinate on the canvas. When omitted (and x is also omitted) the node is auto-staggered to avoid origin pile-up; an explicit value always wins. | |
| type | Yes | Node kind: 'text' = markdown block, 'file' = vault note reference, 'link' = external URL, 'group' = labeled container | |
| color | No | Color: '1'-'6' for Obsidian's preset palette (red/orange/yellow/green/cyan/purple), or a hex code like '#ff5555' | |
| width | No | Node width in pixels (default: 250, max: 10000) | |
| height | No | Node height in pixels (default: 60, max: 10000) | |
| content | Yes | Interpretation depends on type: text body for 'text', relative note path for 'file', URL for 'link', display label for 'group' | |
| canvasPath | Yes | Relative path from vault root to the target .canvas file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the safety profile is covered. The description adds real value beyond that: it discloses the persistence side effect ('persist the updated file'), the return value, and a non-obvious positioning heuristic that prevents origin stacking. It doesn't say what happens on invalid canvas paths or whether concurrent writes clobber, keeping it at 4.
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?
Front-loaded with the action and node types, then return value, then the positioning rule. Four sentences all earning their place, though the auto-position explanation is somewhat verbose and partially duplicates the schema wording.
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 an 8-parameter mutation tool with no output schema, the description covers the action, node-type branching, side effects, return value, and the key defaulting rule. An agent has everything needed to invoke it correctly and chain to add_canvas_edge.
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 100%, so every parameter is already documented, including the auto-stagger behavior on x/y and content interpretation per type. The description largely restates that schema content at the aggregate level rather than adding new syntax or format detail. Baseline 3 is appropriate since the schema does the heavy lifting.
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 ('Add a new node to an Obsidian canvas') and enumerates the four node types with their semantics. It is clearly distinguished from the siblings read_canvas and add_canvas_edge, the latter of which is explicitly named as the follow-up consumer of the returned UUID.
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 clear operational context: the returned UUID is 'needed to connect nodes via add_canvas_edge', which routes the agent to the correct next tool. It also states explicitly when auto-positioning applies and that explicit coordinates win. It does not state exclusions (e.g. prefer read_canvas first to inspect existing nodes), so it falls short of a full usage contract.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
append_to_noteAppend to NoteA
Append text to the end of an existing note without altering prior content. By default, inserts a leading newline if the file does not already end in one, so appended content starts on its own line. Use for log entries, running lists, or adding new sections. Fails if the note does not exist ā use create_note to make a new note first.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the target note (e.g., 'journal/2026-04-15.md'). Extension optional. | |
| content | Yes | Markdown text to append to the end of the note. A leading newline is auto-inserted when the file does not already end in one. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavior beyond the annotations: the auto-inserted leading newline (a side effect on the file), the guarantee that prior content is preserved, and the fail-when-missing error mode. The safety profile (non-destructive, non-idempotent) is already carried by the hints, and the description doesn't explain what repeated appends accumulate to or what is returned, so it is strong but not exhaustive.
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 short sentences, each doing distinct work: core semantics, default newline behavior, then use cases and the failure/alternative. The critical non-destructive guarantee is front-loaded rather than buried.
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 two-parameter append tool with full schema coverage and safety annotations, this covers the essentials: what changes, what doesn't, the default newline, and the not-found failure. The only gap is that, with no output schema, it never says what the call returns (e.g., bytes written, resulting length), which an agent verifying the append might need.
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 both parameters are documented with examples and length limits, so the schema does the heavy lifting and the baseline of 3 applies. The description's newline note merely restates what the 'content' schema field already says; it adds no new path or content 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?
States a specific verb and resource ('append text to the end of an existing note') and immediately pins down the distinguishing semantics: prior content is untouched. It also names the sibling it is often confused with ('use create_note to make a new note first'), so an agent can separate append semantics from creation.
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 concrete use cases (log entries, running lists, new sections) and the failure precondition with a redirect to create_note. It does not, however, distinguish against the other mutating siblings it most overlaps with ā prepend_to_note, insert_at_section, update_section, replace_in_note ā leaving that routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_daily_noteCreate Daily NoteA
Create a daily note for today (or a specific date) in the vault's configured daily-note folder using its configured filename format. Optionally seed the note from a template file with Obsidian-style placeholder substitution: {{date}} and {{title}} ā the formatted date; {{time}} ā local HH:mm; {{date:FORMAT}} / {{time:FORMAT}} ā custom moment-style format. Fails if the daily note already exists.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Target date in YYYY-MM-DD format (defaults to today). Determines filename and {{date}} substitution. | |
| content | No | Initial markdown body for the daily note. Ignored if templatePath is provided. | |
| templatePath | No | Relative path to a template note. Its content is copied into the new daily note with Obsidian-style placeholders substituted: {{date}}/{{title}} ā formatted date, {{time}} ā local HH:mm, and {{date:FORMAT}}/{{time:FORMAT}} ā custom moment-style format. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the mutating, non-idempotent, non-destructive, closed-world profile, and the description adds substantive behavior: config-driven path/filename, template placeholder substitution semantics, and the failure condition when the note already exists. These are the non-obvious traits an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences, front-loaded with the operation and scope, and the failure condition is included where it matters. The placeholder enumeration is somewhat long and partly duplicates the schema, but it earns its place as the core behavioral nuance.
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?
No output schema exists, yet the description never states what the tool returns (e.g., created note path/content) or whether parent folders are auto-created. For a creation tool with zero required params, the core behavior is covered but the return contract is a notable gap.
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 100%, so the schema already documents date, content, and templatePath in depth. The description largely restates the placeholder rules already present in the templatePath schema description, adding little beyond the structured fields.
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+resource: creating a daily note in the vault's configured daily-note folder using its configured filename format. This clearly distinguishes it from the generic create_note and from get_daily_note by its config-driven placement, template seeding, and existence-failure behavior.
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 a clear context for use (today or a specific date, optional template) and surfaces the important 'fails if the note already exists' constraint, which implicitly steers the agent to check first. It does not explicitly name create_note or get_daily_note as alternatives, so no 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.
create_noteCreate NoteA
Create a new markdown note at the given path with body content and optional YAML frontmatter. Fails (does not overwrite) if a note already exists at that path ā use append_to_note, prepend_to_note, or update_frontmatter for existing notes. Missing directories are created automatically, and a .md extension is appended if omitted.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root, e.g., 'folder/note.md' or 'note' (.md added automatically) | |
| content | Yes | Markdown body content for the note (rendered below the frontmatter block if any) | |
| frontmatter | No | JSON object string of frontmatter key-value pairs (e.g., '{"status":"draft","tags":["idea"]}'). Rendered as YAML at the top of the note. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=false. The description adds valuable context beyond annotations: it fails rather than overwrites on conflict, creates missing directories automatically, and appends .md if omitted. This clarifies failure behavior and side effects, though it doesn't mention permissions or return values.
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 sentences, front-loaded with the core action, then failure behavior and alternatives, then automatic side effects. No wasted words, each sentence adds specific value.
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?
Given the complexity of a create operation with 3 parameters at 100% schema coverage and no output schema, the description covers usage, failure modes, and automatic behaviors completely. Nothing essential for correct invocation is missing.
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 100%, so the input schema already documents all three parameters (path, content, frontmatter) with examples and constraints. The description adds no additional parameter-level semantics beyond what the schema provides. Baseline 3 is appropriate.
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 (Create) and resource (markdown note at given path) with body and optional frontmatter. Explicitly distinguishes from sibling tools for existing notes (append_to_note, prepend_to_note, update_frontmatter).
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?
Clearly states when to use this tool (creating new notes) and when not to (existing notes), naming alternative tools for those cases. Provides explicit prerequisites like automatic directory creation and .md extension handling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_noteDelete NoteADestructive
Delete a note. By default the file is moved to the vault's .trash folder (recoverable inside Obsidian); pass permanent=true to unlink it from disk immediately. When permanent=true, you can additionally pass removeReferences=true to strip wikilinks and markdown links to the deleted file across the vault (embeds are removed entirely; plain links fall back to their visible text). References are never rewritten when the file moves to .trash, since trashed files are recoverable.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the note to delete (e.g., 'archive/old.md'). Extension optional. | |
| confirm | No | Safety latch: must be set to true when permanent=true to confirm the caller intends irreversible deletion. Ignored when permanent=false (trash deletes are recoverable). If permanent=true and confirm is not true, the tool returns an error without deleting. | |
| permanent | No | If true, delete the file permanently from disk; if false (default), move it to the vault's .trash folder so it can be recovered. | |
| removeReferences | No | If true (and permanent=true), strip wikilinks and markdown links pointing at the deleted file across the vault. Embeds are removed entirely; plain links fall back to their visible text (alias if present, else the deleted file's basename). Ignored when permanent=false. Default false ā opt in explicitly because the rewrite is irreversible. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds the crucial nuance that the default action is recoverable via the vault's .trash, and that the truly irreversible path requires an explicit flag. It further discloses the side effects of removeReferences (embeds deleted entirely, plain links degraded to visible text or basename) ā behavior an agent cannot infer from annotations alone.
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 sentences, front-loaded with the action, then the default behavior, then the opt-in escalation path. Nothing is repeated and every sentence carries a decision-relevant 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?
For a destructive, four-parameter tool with no output schema, the description covers recoverability, irreversibility, and side effects of the reference-rewrite option, while the confirm safety latch is fully documented in the schema. An agent has everything needed to call it safely.
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 100%, and the schema's per-parameter text already explains permanent, confirm, and even the embed/link fallback semantics of removeReferences. The description largely restates that content rather than adding syntax, formats, or edge cases beyond it, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Delete a note") and immediately scopes it into two distinct modes (trash-by-default vs. permanent unlink). No sibling tool in the list performs note deletion, so an agent can route here unambiguously without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit conditions for the optional behaviors: pass permanent=true only for immediate on-disk unlink, and removeReferences=true only in combination with permanent=true, with the rationale ("opt in explicitly because the rewrite is irreversible"). It also states the negative case (references are never rewritten when trashing). It stops short of naming an alternative tool (e.g. move_note) for relocating rather than deleting, which keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_blockEdit BlockADestructiveIdempotent
Replace the content of a block tagged with ^id. The trailing ^id anchor is preserved on the last line of the new content so existing transclusions (![[note#^id]]) keep working. Use to update a single paragraph or list item that other notes reference.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note. | |
| block | Yes | Block id with or without the leading `^` (e.g. `myid` or `^myid`). | |
| newContent | Yes | Replacement content. The `^id` anchor is appended automatically. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds genuinely useful behavior beyond the annotations: the `^id` anchor is re-appended to the last line so existing `![[note#^id]]` transclusions keep working, which is the key side effect an agent must anticipate. Annotations already cover destructiveness and idempotency, so this extra context is what pushes it above baseline.
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 short sentences, front-loaded with the core action, followed by the non-obvious anchor-preservation behavior and then the use case. No redundancy or filler.
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?
All three parameters are documented in the schema, annotations cover safety profile, and the description covers the most critical behavior (anchor/transclusion preservation). It omits error behavior (e.g. what happens if the block id is not found), which is a minor but real gap.
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 100% and the schema already documents the `^`-optional block id and the automatic anchor append for `newContent`. The description adds no syntax or edge-case detail (e.g. multi-line content behavior) beyond what the schema provides, so baseline 3 applies.
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 ('Replace the content of a block tagged with `^id`') and scopes it to anchored blocks, which separates it from sibling tools like `update_section` or `replace_in_note`. It does not name those siblings explicitly, so the differentiation is inferred from the resource qualifier rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The final sentence gives a clear use case: 'update a single paragraph or list item that other notes reference', implying this is the right tool when transclusions must survive. No explicit when-not guidance or named alternatives are given, keeping it out of 5 territory.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_broken_linksFind Broken LinksARead-onlyIdempotent
Scan notes for wikilinks ([[target]]) whose target does not resolve to any existing note in the vault. Returns a per-source report grouping each note with its broken link text and line numbers, plus a total count. Use after renaming, moving, or deleting notes to catch dangling references. Resolution uses the whole vault even when scanning a single folder, so only truly unresolvable links are reported.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | Restrict the scan to notes within this folder (resolution still uses the entire vault). Omit to scan every note. | |
| maxResults | No | Maximum broken link entries to show (1-1000, default: 200). Grouped by source note. Remaining matches are summarized. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a read-only, idempotent, closed-world operation. The description adds meaningful behavioral details beyond annotations: per-source grouping, broken link text and line numbers, total count, and the whole-vault resolution rule even when scanning a folder.
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 front-loaded with the core purpose and then adds return format and usage timing without waste. Every sentence contributes useful information for invoking or interpreting the tool.
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?
There is no output schema, but the description sufficiently explains the return structure: a per-source report with broken link text, line numbers, and a total count. Together with the annotated safety profile and fully described parameters, it is complete enough for correct use.
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 100%, so both folder and maxResults are already well documented. The description reinforces the whole-vault resolution behavior for folder scanning but does not add syntax or constraints beyond what the schema provides, making the baseline 3 appropriate.
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: scanning notes for wikilinks whose targets do not resolve to existing notes. It also distinguishes the behavior from related tools by explaining that resolution uses the whole vault and that only truly unresolvable links are reported.
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 gives a clear usage situation: after renaming, moving, or deleting notes to catch dangling references. It does not explicitly name alternatives such as get_outlinks or find_orphans, nor does it state when not to use this tool, so it falls short of full alternative guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_orphansFind Orphan NotesARead-onlyIdempotent
Identify disconnected notes in the vault's link graph, classified into three groups: fully isolated (no links in or out), no-backlinks (nothing links to them), and no-outlinks (they link to nothing). Returns counts per category and an example list per category, capped by maxResults. Use to surface abandoned notes, missing hub pages, or candidates for archiving.
| Name | Required | Description | Default |
|---|---|---|---|
| maxResults | No | Maximum total note paths to list across all categories (1-1000, default: 200). Full counts are always reported regardless. | |
| includeOutlinksCheck | No | If true (default), also report notes with no outgoing links; if false, only report fully-isolated notes and notes with no backlinks. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, closed-world, so the safety profile is covered. The description adds real behavioral context the annotations cannot: the three-way classification scheme and the return shape (counts per category plus capped example lists).
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?
Front-loads the core purpose, then the category definitions, then usage guidance, in three tight sentences. Every sentence carries distinct information with no repetition of name or title.
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 read-only, two-param tool with a fully documented schema, the description covers purpose, categories, return shape, and usage. Minor gap: it does not clarify interaction between includeOutlinksCheck=false and the reported categories beyond the schema text, but nothing essential is missing.
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 both parameters are fully described there, including the maxResults cap and the includeOutlinksCheck toggle. The description only echoes the maxResults cap ('capped by maxResults') without new syntax or edge-case detail, so baseline 3 applies.
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 (identify disconnected notes in the link graph) and enumerates the three sub-categories precisely. An agent can distinguish this from get_backlinks, get_outlinks, and find_broken_links without inspecting other 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?
Explicitly names the use cases: surfacing abandoned notes, missing hub pages, or archiving candidates. However, it never states when to prefer a sibling tool (e.g., get_backlinks for a single note) or any exclusions, leaving routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_similar_notesFind Similar NotesARead-onlyIdempotent
Given a note path, return the K most semantically similar notes from the index (excluding the source note). Uses the source note's existing chunk embeddings and anchors the source query to chunks aligned with the note's opening topic ā no live API call to the embedding provider, so this is fast and free. Run index_vault first to populate embeddings for both the source and the candidates.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the source note, e.g. 'projects/atlas.md'. | |
| limit | No | Maximum number of similar notes to return (1-100, default: 10). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavior beyond annotations: results exclude the source note, the tool reuses cached chunk embeddings rather than making a live API call, and is therefore 'fast and free.' That discloses cost/latency and an index-staleness dependency the annotations do not cover. It stops short of saying what happens when the index is missing or stale (error vs. empty result).
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 front-loaded sentences with no filler; the core behavior comes first and the prerequisite last. The middle sentence about chunk embeddings and opening-topic anchoring is somewhat implementation-heavy but does explain why results are cheap and how they are ranked.
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?
No output schema exists, yet the description never says what a result looks like ā paths only, paths plus similarity scores, snippets? For a ranked-retrieval tool that omission is a meaningful gap, though the input side and behavioral context are otherwise well covered.
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%, so both parameters are already documented in-schema with types, ranges, and defaults. The description maps 'note path' to path and 'K' to limit but adds no syntax, ranking, or scoring detail. Baseline 3 is appropriate when the schema carries the parameter burden.
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 scope: 'Given a note path, return the K most semantically similar notes from the index (excluding the source note).' The note-to-note input form distinguishes it operationally from query-based siblings like search_semantic and search_notes, and the exclusion rule removes ambiguity about the result set.
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 explicit prerequisite ā 'Run index_vault first to populate embeddings for both the source and the candidates' ā which tells the agent the ordering constraint. It does not explicitly name when to prefer search_semantic (query string) over this tool, leaving the alternative to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_unused_attachmentsFind Unused AttachmentsARead-onlyIdempotent
Locate attachments that no note references ā neither via ![[file]] embeds nor [text](file) markdown links. Useful for vault hygiene before archiving or before running a sync. Pair the output with delete operations from your shell, since this tool deliberately doesn't unlink files.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of unused-attachment paths to return (1-10000, default: 200). Total counts are still reported. | |
| includeBytes | No | If true, also stat each unused attachment and report total reclaimable bytes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false. The description adds key behavioral context beyond that: it deliberately does not unlink files and must be paired with external delete operations, which prevents destructive assumptions.
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 three focused sentences with zero waste. The core purpose is front-loaded, followed by use cases and the important non-destructive behavioral caveat.
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 description is complete enough to call the tool correctly: it defines unused attachments, explains the intended workflow, and clarifies that deletion is external. It does not describe the return shape in detail, but the schema covers both parameters and no output schema exists.
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 100%, so both limit and includeBytes are already documented in the schema. The description adds no additional parameter semantics, so the baseline score of 3 is appropriate.
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: 'Locate attachments that no note references.' It also defines 'unused' precisely via two reference forms, which distinguishes this from sibling list_attachments, get_attachment, and find_broken_links.
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 gives clear usage contexts ('vault hygiene before archiving or before running a sync') and explicitly routes deletion to shell operations rather than this tool. It lacks explicit when-not-to-use guidance, but the practical workflow is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_attachmentGet AttachmentARead-onlyIdempotent
Read an attachment file and return its bytes to the client. Images come back as image content blocks (rendered inline by Claude / Cursor), audio as audio blocks, everything else as a base64 resource block with a vault:// URI. Caps at 5 MB by default to keep token usage sane; raise via maxBytes up to 50 MB. The attachment must be inside the vault ā markdown notes (.md), canvases (.canvas), and Bases (.base) are deliberately rejected so callers don't accidentally pull text-format files through this binary path; use get_note / read_canvas / read_base instead.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the attachment, e.g. 'assets/diagram.png'. | |
| maxBytes | No | Maximum file size to fetch in bytes (default: 5,242,880, hard cap: 52,428,800). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnly/idempotent annotations by disclosing the return shape per media type (image blocks, audio blocks, base64 resource with vault:// URI), the 5 MB default and 50 MB hard ceiling, and the vault-containment restriction. These are exactly the traits that determine token cost and whether a call will fail.
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 dense sentences, front-loaded with the return behavior, then limits, then constraints, then sibling routing. No sentence is filler; each carries either behavioral or routing 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 no output schema, the description fully carries the burden of describing return values by content type, plus size limits and path restrictions. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds rationale the schema lacks: maxBytes exists to keep token usage sane and can be raised to 50 MB, and path must resolve inside the vault. It stops short of any path-format examples, though the schema supplies one.
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 an attachment file and return its bytes') and immediately distinguishes itself from the text-format siblings get_note / read_canvas / read_base. An agent can identify the tool and its domain without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes callers: text-format files (.md, .canvas, .base) are rejected here and must go through get_note / read_canvas / read_base instead. It also gives the condition for raising the size cap via maxBytes, so both the when-to-use and when-not-to-use cases are covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_backlinksGet BacklinksARead-onlyIdempotent
List all notes that contain a wikilink pointing to the target note. Each result includes the source note path, line number, and the surrounding line text for context. Use to understand which notes reference a topic, or to assess the impact of renaming or deleting a note. Accepts paths with or without .md extension; falls back to basename matching if exact match fails.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Target note path relative to vault root (e.g., 'folder/note.md' or 'note'). Extension optional. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is covered. The description adds valuable behavioral detail beyond annotations: result contents (source path, line number, surrounding text) and a fallback matching strategy ('falls back to basename matching if exact match fails'). It does not mention pagination or ordering, but the added context is substantial.
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 four sentences, front-loads the core purpose, and each sentence contributes useful information: result fields, use cases, and path handling. There is little waste, though the use-case sentence could arguably be slightly tightened.
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 no output schema, the description appropriately explains the return shape (source note path, line number, surrounding text). Combined with annotations covering safety and idempotency, it gives an agent enough to call the tool correctly. Minor gaps like result ordering or pagination are not critical for a read-only list tool.
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 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema by explaining that paths are accepted with or without the .md extension and that basename matching is used as a fallback. This clarifies runtime behavior for the single path parameter, which the schema does not specify.
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: 'List all notes that contain a wikilink pointing to the target note.' It precisely defines the direction of the relationship, distinguishing this from the sibling get_outlinks tool without needing to name it. An agent can confidently identify this as the inbound-link lookup.
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 gives clear use cases: 'Use to understand which notes reference a topic, or to assess the impact of renaming or deleting a note.' This provides strong context for when to call the tool. However, it does not explicitly mention alternatives such as get_outlinks for outgoing links or find_broken_links for broken links, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_daily_noteGet Daily NoteARead-onlyIdempotent
Read the daily note for today or for a specific date, resolved via the vault's configured daily-note folder and filename format. Returns the note path, parsed frontmatter (as a labeled header block), and body. Errors if no daily note exists for that date ā use create_daily_note to create one.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Target date in YYYY-MM-DD format (defaults to today's local date) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations (which already declare readOnly/idempotent/openWorld=false) by disclosing the resolution mechanism, the return shape (path, parsed frontmatter as a labeled header block, body), and the error condition when no note exists. That is substantive behavioral context an agent cannot infer from the flags.
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 sentences, front-loaded with the action and scope, then resolution mechanics, then error handling. Every sentence carries information the agent needs; nothing is restated from the name or schema.
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?
There is no output schema, but the description covers the return contents (path, frontmatter, body) and the failure mode, so an agent knows what to expect on both success and error. Nothing material is missing for a single optional-parameter read tool.
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 already documents YYYY-MM-DD format and the local-today default, so the baseline is 3. The description adds value by explaining how the date is interpreted (resolved through the vault's configured folder/filename format) rather than being a raw path lookup.
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 the daily note) plus scope (today or a specific date), and immediately distinguishes it from the generic get_note by explaining that the path is resolved via the vault's daily-note folder and filename format. An agent can tell this apart from get_note and create_daily_note without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the fallback: 'Errors if no daily note exists for that date ā use create_daily_note to create one.' That is real when-to-use-something-else guidance. It doesn't explicitly contrast against get_note for the read case, but the resolution semantics imply the distinction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_graph_neighborsGet Graph NeighborsARead-onlyIdempotent
Traverse the wikilink graph outward from a starting note and return every note reachable within N hops, grouped by depth level with an indented tree visualization. Each neighbor is tagged with its hop distance and direction (inbound = reached via backlink, outbound = reached via outlink). Use to explore a topic cluster, map a note's local neighborhood, or find related notes beyond direct links. Accepts paths with or without .md extension.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Starting note path relative to vault root (e.g., 'projects/alpha.md'). Extension optional; falls back to basename match. | |
| depth | No | Maximum link-hops to traverse from the start note (1-3, default: 1). Higher values explore exponentially more notes. | |
| direction | No | Traversal direction: 'outbound' follows outlinks the start note points to, 'inbound' follows backlinks pointing at the start note, 'both' follows either (default) | both |
| maxResults | No | Maximum neighbor notes to return (1-1000, default: 200). Traversal stops early when this cap is reached and a truncation notice is appended. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld=false, so safety is covered; the description adds genuine behavioral detail beyond them ā results are grouped by depth into an indented tree and each neighbor carries hop distance and direction. It does not discuss cost or the truncation behavior of maxResults (that lives only in the schema), keeping it from 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?
Front-loaded with the core traversal semantics, then return format, then use cases, then the path note ā four tight sentences. The final sentence about .md extension mildly duplicates the schema, a small redundancy rather than waste.
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?
There is no output schema, so describing the returned structure (depth-grouped tree with hop tags) is exactly what's needed and it is present. Nothing essential is missing, though a word on truncation or graph-size limits would round it out.
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 100%, so depth/direction/maxResults are already fully documented. The description reinforces path extension flexibility, but that same fact is in the schema, so it adds little beyond restating structured data ā baseline 3 applies.
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 ('traverse the wikilink graph outward') plus the resource (notes reachable within N hops) and the return shape. It also implicitly distinguishes itself from the direct-link siblings by promising neighbors 'beyond direct links', so get_backlinks/get_outlinks are clearly not substitutes.
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?
Names three concrete use cases (explore a topic cluster, map a local neighborhood, find related notes beyond direct links), which is clear usage context. It stops short of explicit when-not guidance or naming get_backlinks/get_outlinks as the bounded alternative, so it is strong but not complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_noteGet NoteARead-onlyIdempotent
Read a note in full or as a fragment. With no fragment options, returns parsed frontmatter (as a labeled header), a flat list of inline #tags, and the body. With section, returns just the body under that heading (path-form like 'Tasks/Today' is supported). With block, returns the paragraph or block tagged ^id. With lines, returns the inclusive 1-indexed line range. Fragment modes skip the frontmatter/tag header and return raw text ā use them to keep token usage tight on long notes.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the note (e.g., 'folder/note.md'). Extension required. | |
| block | No | Block id (without the leading `^`). Returns just the paragraph or block tagged with that id. | |
| lines | No | Line range, 1-indexed and inclusive (e.g., '10-25' or '42'). Returns just those lines. | |
| section | No | Heading path (e.g., 'Tasks' or 'Project A/Status'). Returns just that section's body. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/closed-world, and the description adds real value on the return shape: parsed frontmatter as a labeled header, a flat inline tag list, and body; fragment modes skip the header and return raw text. It does not describe failure behavior (missing note, nonexistent section or block id), which is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the default behavior, then one clause per mode, ending with a practical recommendation about token usage. Dense but every sentence earns its place; slightly long in its enumeration.
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?
No output schema exists, and the description does carry that burden by explaining exactly what each mode returns. For a read-only, four-parameter tool with full schema coverage that is nearly sufficient; error/edge-case behavior is the only missing piece.
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%, so baseline is 3, but the description adds semantic detail beyond the schema: section supports path-form headings ('Tasks/Today'), block targets the paragraph tagged with that id, and lines are inclusive 1-indexed. These clarify how parameters compose with the output modes, not just their types.
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 note') and immediately enumerates the four retrieval modes. It is clearly separable from siblings like search_notes, list_notes, and read_base without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Each mode is tied to a condition ('With section...', 'With block...', 'With lines...') and it explicitly recommends fragment modes for token efficiency on long notes. It lacks an explicit exclusion against sibling tools (e.g., use search_notes to locate a note first), so not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_outlinksGet OutlinksARead-onlyIdempotent
List every outgoing wikilink from a note, partitioned into valid links (resolve to an existing note), broken links (target not found), and file embeds (![[...]]). Returns the raw link text and resolved paths. Use to audit a note's references, detect broken links, or follow downstream dependencies.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Source note path relative to vault root (e.g., 'folder/note.md'). Extension optional. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/closed-world, so safety is covered; the description adds genuinely new behavior by disclosing the three-way result partitioning and that raw link text plus resolved paths are returned. It says nothing about ordering, limits, or whether nested/transcluded links are followed.
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 tight sentences: the first front-loads the operation and the exact result shape, the second front-loads the use cases. No redundant restatement of the title or annotations.
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?
No output schema exists, and the description compensates well by describing the partition and returned fields; safety comes from annotations and the single param is fully covered by the schema. Minor gaps remain on edge behavior (missing source note, link ordering, non-wikilink URLs).
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 100% schema description coverage on a single 'path' parameter, the schema carries the semantics (vault-relative path, extension optional). The description adds no further meaning about how path is interpreted or what happens if the note does not exist ā baseline 3 applies.
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 ('List') and resource ('every outgoing wikilink from a note') and even describes the output partitioning into valid/broken/embeds. The word 'outgoing' implicitly separates it from get_backlinks, but the overlap with find_broken_links (also named as a use case here) is never resolved.
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 three concrete use cases (audit references, detect broken links, follow downstream dependencies), which is clear context for invocation. It stops short of exclusions or naming alternatives such as find_broken_links or get_backlinks when those would be the better choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recent_notesGet Recent NotesARead-onlyIdempotent
List notes ordered by most-recently-modified first. Optional since filter accepts an ISO date (e.g. '2026-04-01') or a relative span ('7d', '24h', '2w'); only notes modified at or after that time are returned. Use to surface what you've been working on, build a 'what changed this week' digest, or pick targets for review.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of notes to return (1-1000, default: 20). | |
| since | No | Filter to notes modified at or after this point. Accepts ISO 8601 (YYYY-MM-DD or full timestamp) or a relative span like '7d', '24h', '2w'. | |
| folder | No | Restrict to notes within this folder (relative to vault root). Omit to scan the entire vault. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and closed-world, so the safety profile is covered; the description adds the default sort order and the inclusive 'modified at or after' filter semantics. It says nothing about what a returned note contains or how limit interacts with result ordering, leaving gaps the annotations don't fill.
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 sentences, front-loaded with the single most important fact (recency ordering) and then the filter syntax, then use cases. The final clause ('pick targets for review') is slightly filler but does reinforce intent.
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?
No output schema exists, so the description carries the burden of describing return shape, and it never says whether notes come back as titles, paths, or full content ā a real gap for a listing tool. Filtering and ordering are adequately covered.
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 100% and the description largely restates the `since` documentation, including the same relative-span examples ('7d', '24h', '2w'). `limit` and `folder` are not mentioned at all, so the description adds essentially no parameter meaning beyond 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 plus the ordering guarantee ("List notes ordered by most-recently-modified first"), which meaningfully separates it from the unordered list_notes / search_notes siblings. It does not explicitly name or contrast with those siblings, so an agent still has to infer the boundary.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives three concrete usage contexts (surfacing recent work, a 'what changed this week' digest, picking review targets), which is stronger than implied usage. It offers no exclusions or 'use X instead whenā¦' routing, so the choice against search_notes or list_notes remains unstated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_vault_statsGet Vault StatsARead-onlyIdempotent
Return a quick health snapshot of the vault: note count, total bytes, total words, unique tag count, untagged-note count, and the most-recently-modified note. Useful for dashboards and 'is this vault healthy?' checks. Reads through the mtime cache so repeat calls are cheap.
| Name | Required | Description | Default |
|---|---|---|---|
| folder | No | Restrict stats to this folder (relative to vault root). Omit for whole-vault stats. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-openWorld, so safety is covered. The description adds genuinely new behavioral context beyond them: reads flow through the mtime cache, so repeated calls are cheap ā a performance trait an agent can plan around. It also implicitly discloses the return shape by listing the metrics, which matters since there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences: what it returns, when to use it, and the cost profile. The key content (the metric list) is front-loaded and no sentence is filler.
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 one optional parameter, rich read-only annotations, and no output schema, the description does exactly the extra work needed by enumerating the returned fields and noting cache behavior. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single 'folder' parameter is fully documented in the schema, including the omit-for-whole-vault semantics. The description adds nothing on top of that, so the baseline 3 applies.
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 ('Return a quick health snapshot of the vault') and then enumerates the exact metrics returned, so the tool is unmistakable. It never names a sibling to contrast against, which keeps it out of 5 territory, but the metric list does the disambiguating work implicitly.
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 usage context ('useful for dashboards and is-this-vault-healthy checks'), which tells the agent when this is the right call. It offers no explicit exclusions or alternatives among siblings like read_base or query_base, 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.
index_vaultIndex Vault for Semantic SearchAIdempotent
Build or refresh the embedding index used by search_semantic and find_similar_notes. Splits readable notes into heading-aware chunks, sends those chunks to the configured embedding provider (Ollama by default, OpenAI optional), and persists the index to <vault>/.obsidian/cache/mcp-pro-embeddings.json. Requires confirm: "send-vault-text-to-embedding-provider" so callers explicitly acknowledge that vault text will leave this tool boundary. Incremental: notes whose content hash matches the prior pass are skipped. Use force: true to re-embed everything (e.g., after switching models). Emits progress notifications when the client subscribes.
| Name | Required | Description | Default |
|---|---|---|---|
| force | No | If true, re-embed every note even if its content hash matches the cached one. | |
| folder | No | Restrict the indexing pass to this folder. Notes outside the folder are left untouched. | |
| confirm | No | Required safety latch. Set exactly to "send-vault-text-to-embedding-provider" to acknowledge that readable note chunks will be sent to the configured embedding provider. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations: discloses the exact cache file written, that vault text is sent to an external embedding provider, the required `confirm` safety latch for data leaving the tool boundary, hash-based skipping behavior, and progress notifications. These details let an agent reason about privacy, cost, and idempotency.
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?
Front-loads the core purpose, then layers in privacy, persistence, incrementality, and progress behavior. Sentences are dense with useful facts rather than filler, though the description is longer than strictly necessary for an expert agent.
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?
Covers the important risks for a complex indexing tool: external data transmission, required confirmation, cache location, incremental behavior, and force re-embedding. It does not cover failure modes or the role of the `folder` scoping parameter, but the annotations and schema fill in the remaining structure.
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%, so the schema already documents all three parameters thoroughly. The description reinforces the purpose of `confirm` and gives an example for `force`, but the `folder` parameter is not mentioned and no syntax or format details are added beyond 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 ('Build or refresh the embedding index') and explicitly names the sibling tools that consume it (`search_semantic` and `find_similar_notes`). An agent can immediately distinguish this maintenance operation from the search tools themselves.
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 clear context: it is the index-builder behind the semantic search siblings, is incremental by design, and `force: true` is for re-embedding after switching models. It does not state explicit when-not-to-use conditions or concurrency caveats, but the intended usage is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
insert_at_sectionInsert at SectionA
Insert content into a specific section without replacing it. position controls where: 'before' inserts above the heading, 'after-heading' inserts immediately under the heading line (at the top of the section body), 'append' inserts at the end of the section's body just before the next heading. Use to add a new bullet or paragraph without rewriting the section.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note. | |
| content | Yes | Content to insert. A trailing newline is normalized. | |
| section | Yes | Heading path identifying the section. | |
| position | No | Insert before the heading line, immediately after the heading, or at the end of the section body. | append |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare non-destructive, non-readonly and non-idempotent behavior, so the safety profile is covered. The description adds that content is inserted without replacement, which is useful context, but says nothing about failure modes (missing section) or repeated-insert behavior that the non-idempotent hint implies.
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?
Front-loads the core action, then the position semantics, then the use case. Every sentence contributes and there is no redundancy.
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?
No output schema exists, but the description covers action, positioning, and use context adequately. It omits what happens when the section is not found, a minor gap for an insertion tool.
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%, so baseline is 3, but the description meaningfully elaborates the `position` enum in plain terms ('above the heading', 'top of the section body', 'just before the next heading'), adding clarity beyond the schema's own enum descriptions.
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 ('Insert content into a specific section') and immediately clarifies it does not replace the section, distinguishing it from update_section and append_to_note in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use to add a new bullet or paragraph without rewriting the section' gives a clear use context and implicitly contrasts with update_section. It does not explicitly name an alternative tool or exclusions, keeping it just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_attachmentsList AttachmentsARead-onlyIdempotent
Enumerate every non-markdown file in the vault ā images, PDFs, audio/video clips, anything pasted in beyond notes/canvases/Bases. Returns a sorted list of relative paths plus a per-extension count summary. Use to audit assets, find duplicates by name, or pick targets for find_unused_attachments.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of attachment paths to return (1-10000, default: 200). Total counts are still reported. | |
| extension | No | Restrict to one extension (e.g., 'png' or '.png'). Omit for every attachment. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/closed-world, so the bar is lower; the description still adds real value by disclosing the return shape (sorted relative paths plus per-extension count summary) and the non-markdown filter scope. It does not discuss ordering key or behavior in very large vaults, keeping it at 4.
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 sentences, zero filler: scope first, return value second, usage third. Each sentence carries distinct information 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?
With no output schema, the description steps in to describe the return payload (sorted relative paths + per-extension counts), which is the main gap it needed to cover for a two-param read tool. Minor omissions like path root semantics and pagination interplay are handled by the schema.
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% ā both 'limit' (including that counts are still reported when truncated) and 'extension' (with/without dot) are fully documented in the schema. The description adds no parameter-level detail beyond that, so baseline 3 applies.
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 ('Enumerate') plus precisely delimited resource ('every non-markdown file in the vault ā images, PDFs, audio/video clips'), explicitly excluding notes/canvases/Bases. That exclusion is what separates it from list_notes and read_canvas 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 three concrete use cases (audit assets, find duplicates by name, pick targets for find_unused_attachments) and explicitly hands off to a sibling for the follow-up action. It lacks an explicit 'use get_attachment instead if you want to read one file' exclusion, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_basesList BasesARead-onlyIdempotent
Enumerate every Obsidian Bases (.base) file in the vault. Bases are YAML-defined database views over notes (filters, properties, table/calendar/kanban views). Returns a sorted list of relative paths plus the total count. Pair with read_base or query_base.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint. The description adds behavioral details: returns sorted list, relative paths, and count. It does not contradict 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?
Three sentences, each adding unique value: enumerates, defines bases, describes output, suggests next steps. No wasted words, 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 no parameters and no output schema, the description fully explains the tool's operation and output. It is self-contained and sufficient for an agent to use 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?
The tool has no parameters, and schema coverage is 100%. The description does not need to add parameter details, and the baseline score for 0 params is 4.
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 explicitly states it enumerates every .base file in the vault, defines what a base is, and specifies the output (sorted relative paths and count). It clearly distinguishes the tool's purpose from siblings by focusing specifically on .base files.
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 advises pairing with read_base or query_base, indicating a typical workflow. While it doesn't explicitly contrast with sibling list tools like list_notes or list_attachments, the context and tool name make its usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_canvasesList CanvasesARead-onlyIdempotent
Enumerate every Obsidian canvas file (.canvas) anywhere in the vault, returning a numbered list of relative paths and the total count. Takes no parameters ā scans the entire vault. Use to discover available canvases before calling read_canvas, add_canvas_node, or add_canvas_edge.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=false. The description adds that it scans entire vault and takes no parameters, but no new behavioral traits beyond 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?
Two sentences, efficient, front-loaded with key information, no waste.
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?
Given no parameters and no output schema, the description is complete: it specifies scope, return type, and usage context.
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?
No parameters, baseline 4 per guidelines. The description correctly states 'Takes no parameters'.
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 clearly states it enumerates Obsidian canvas files, returns a numbered list of relative paths and total count, and distinguishes from sibling tools by noting it scans the entire vault and takes no parameters.
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?
Explicitly says to use to discover available canvases before calling read_canvas, add_canvas_node, or add_canvas_edge, providing clear context and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_notesList NotesARead-onlyIdempotent
Enumerate every markdown note in the vault (or a single folder), returning a sorted list of relative paths along with the total count. Truncates output to limit entries but still reports the total. Use to browse vault structure, build a file picker, or enumerate targets for batch processing.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of note paths to return (1-10000, default: 50). The full total count is still reported separately. | |
| folder | No | Folder relative to vault root to restrict the listing (omit to list the entire vault) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, closed-world behavior, so the bar is lower; the description still adds real value by disclosing sort order and, importantly, that output is truncated at `limit` while the total count is still reported. The one gap is that no offset/pagination cursor exists, so truncated results cannot be resumed ā that limitation is implied but not spelled out.
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 tight sentences: the first covers scope and return shape, the second covers truncation semantics and intended uses. The most decision-relevant fact (what it enumerates) is front-loaded, and nothing is padding.
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 no output schema, the description carries the burden of describing return values and does so (sorted relative paths, total count). For a two-parameter, zero-required listing tool with full annotation coverage, nothing an agent needs to call it correctly is missing.
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%, so both parameters are fully documented in the schema, including the 1-10000 range, default of 50, and the note that the total is still reported. The description's mentions of `limit` and folder scoping essentially restate the schema, so baseline 3 applies.
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 (enumerate), resource (markdown notes), scope (whole vault or one folder), and even the return shape (sorted relative paths plus total count). This is clearly distinguishable from siblings like search_notes or get_note, which retrieve by query or by identity rather than enumerating the vault.
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 three concrete use cases: browsing vault structure, building a file picker, and enumerating targets for batch processing. It stops short of naming an alternative and the condition that selects it (e.g., 'for query-based retrieval use search_notes instead'), so it is clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sectionsList SectionsARead-onlyIdempotent
List all headings in a note as a tree of paths (with depth). Useful for discovering valid section arguments before calling get_note, update_section, or insert_at_section.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, so safety is covered; the description adds the output shape (tree of paths with depth) that annotations cannot convey. It omits edge behavior such as what happens for a missing path or a note with no headings.
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 sentences, zero waste, with the core capability front-loaded and the usage hint following immediately.
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 no output schema, the description adequately covers the return shape (tree of paths with depth) and the tool's role in the workflow. Only minor gaps remain around error or empty-result behavior for a nonexistent path.
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 the single `path` parameter is documented there as a vault-relative note path. The description's 'in a note' reinforces the target but adds no syntax or format detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (headings in a note) and even specifies the return shape: a tree of paths with depth. This is clearly distinguishable from siblings like get_note or list_notes.
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?
Explicitly frames the tool as a discovery step before calling get_note, update_section, or insert_at_section, naming the exact alternatives and the condition that selects them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tagsList All TagsARead-onlyIdempotent
Enumerate every unique tag used across the vault along with the number of notes each tag appears in. Detects tags from both inline #hashtags and YAML frontmatter, normalizes them case-insensitively, and returns a sorted list plus the total unique tag count. Use to build a tag cloud, pick categories, audit taxonomy, or discover available tags before calling search_by_tag.
| Name | Required | Description | Default |
|---|---|---|---|
| sortBy | No | Sort order: 'count' = by usage count descending (most-used first, default), 'name' = alphabetical by tag name | count |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, closed-world), yet the description still adds substantive behavior: tags come from both inline #hashtags and YAML frontmatter, names are case-normalized, and the result includes a total unique count. It does not mention edge cases (empty vault, duplicate tag spellings after normalization), which keeps it from 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?
Two sentences, front-loaded with the core action and return content, followed by usage routing. No filler and nothing repeated from the title or schema.
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 no output schema, the description carries the burden of describing return values and does so (sorted list plus total unique tag count), and it explains tag sourcing and normalization. Minor gaps remain around empty-result behavior and sort defaults, but nothing an agent needs in order to call it correctly is missing.
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 the single enum parameter is fully documented in the schema, so the schema does the heavy lifting. The description's reference to 'a sorted list' hints at ordering but does not explain the count-vs-name sort choice, so it adds little beyond the schema ā the baseline 3 applies.
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 ('Enumerate every unique tag used across the vault') plus what is returned ('the number of notes each tag appears in'). It also distinguishes itself from the sibling search_by_tag by positioning itself as the discovery step before tag-based search.
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?
Names concrete use cases (tag cloud, category picking, taxonomy audit) and explicitly routes the agent to search_by_tag for the follow-up step. The complementary relationship with the sibling is unambiguous, so an agent can pick this tool without inspecting either schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_noteMove/Rename NoteADestructive
Move or rename a note within the vault, preserving its full content. Parent folders at the destination are created as needed. By default, wikilinks and file references are updated, matching Obsidian's "Automatically update internal links" behavior; this rewrite requires confirmPath to match the destination path after .md normalization. Pass updateLinks: false to skip the rewrite scan (faster on large vaults; pair with find_broken_links if you need to audit afterward). A .md extension is added automatically if omitted from either path.
| Name | Required | Description | Default |
|---|---|---|---|
| newPath | Yes | Destination relative path from vault root (e.g., 'projects/idea.md'). Creates intermediate folders as needed. | |
| oldPath | Yes | Current relative path of the note from vault root (e.g., 'inbox/idea.md') | |
| confirmPath | No | Required when updateLinks is true: re-type the destination path after .md normalization to confirm vault-wide reference rewriting. | |
| updateLinks | No | If true (default), update every wikilink, markdown link, and canvas node reference across the vault to point at the new path. Set false to skip the rewrite pass. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses substantial behavior beyond the annotations: parent folders are created, internal links are rewritten by default, confirmPath must match the normalized destination, updateLinks:false skips the rewrite scan, and .md extensions are auto-added. These are meaningful side effects for a destructive mutation tool, and the description does not contradict the destructiveHint annotation.
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 front-loaded with the core action and follows with the most important behavioral details in a compact sequence. Every sentence adds operational value, including folder creation, link rewriting, confirmPath requirements, and the updateLinks tradeoff.
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 destructive move/rename tool with full schema coverage and no output schema, the description covers the main behavioral concerns: link rewriting, folder creation, confirmPath, extension normalization, and an audit alternative. It omits what happens if the destination already exists, such as overwrite or collision behavior, which is important for a destructive move 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 coverage is 100%, so the baseline is 3, but the description adds valuable meaning beyond the schema: confirmPath must match the destination after .md normalization, updateLinks:false is faster on large vaults, and the agent may pair it with find_broken_links afterward. It also notes that .md extensions are added automatically if omitted, which the schema does not explicitly state for either path.
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 and resource: 'Move or rename a note within the vault, preserving its full content.' This is unambiguous and inherently distinct from sibling operations such as create_note, delete_note, or update_section. An agent can identify exactly what the tool does without reading the 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?
Usage guidance is implied by 'Move or rename a note', and the description gives useful guidance for the updateLinks option, including pairing with find_broken_links for audits. However, it does not explicitly state when to use move_note versus alternatives or when not to use it, so selection guidance remains implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
prepend_to_notePrepend to NoteA
Insert content at the top of an existing note's body, immediately after the YAML frontmatter block if one is present (so metadata stays at the top of the file). Use for adding new items to the front of a running list, pinning context, or inserting TL;DR sections. Fails if the note does not exist.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the target note (e.g., 'notes/log.md'). Extension optional. | |
| content | Yes | Markdown text to insert at the top of the body, after any frontmatter |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the safety profile is covered. The description contributes the non-obvious behaviors: frontmatter is preserved at the top and the call errors when the note is missing. It does not state whether repeated calls duplicate content (relevant given idempotentHint=false) or whether the vault index is updated.
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 short sentences, front-loaded with the operation and its placement rule, followed by use cases and the failure condition. No redundancy or filler.
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 two-parameter mutation tool with full annotation coverage and no output schema, this covers placement, when to use it, and the failure mode. It could go further on idempotency/duplication behavior given idempotentHint=false, but nothing needed to invoke it correctly is absent.
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 the schema already documents both path and content, including the 'after any frontmatter' wording the description repeats. The description adds no format, size, or encoding detail beyond the schema, so the baseline 3 applies.
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 ('Insert content at the top of an existing note's body') plus the placement rule relative to YAML frontmatter, which is the exact semantic that separates it from append_to_note and insert_at_section. An agent can identify the operation without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete use cases (prepending to a running list, pinning context, TL;DR sections) and a precondition ('Fails if the note does not exist'). It stops short of naming the sibling alternatives append_to_note or insert_at_section that an agent should consider instead when the target position differs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_baseQuery BaseARead-onlyIdempotent
Run a Base file's filters against the vault and return matching note paths. Optionally pick a named view to apply that view's filters and ordering on top of the base-level filters. Supported filter syntax (subset of Obsidian's full DSL): chained methods file.hasTag("tag"), file.hasProperty("key"), file.inFolder("path"), file.linksTo("target"), file.name.contains("x")/.startsWith/.endsWith/.equals, plus .isEmpty/.isNotEmpty on any value; legacy function form taggedWith(file, "tag"); comparisons key == "val", key != x, key contains x, >=, <=, >, <; combinators and:, or:, not:. Recognized file properties: file.name, file.basename, file.folder, file.ext, file.path, file.size, file.ctime, file.mtime, file.tags, file.properties, file.links, file.embeds, file.backlinks. Unsupported clauses are reported as warnings and treated as no-match.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the .base file. | |
| view | No | Optional view name (or view type) to apply on top of the base-level filters. | |
| limit | No | Maximum number of matching notes to return (1-1000, default: 100). | |
| includeFrontmatter | No | If true, include each row's frontmatter in the output. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, closed-world), so extra credit goes to the substantive disclosure that unsupported clauses are reported as warnings and treated as no-match ā a non-obvious failure mode that would otherwise cause an agent to silently misread an empty result as 'no matches exist'. It does not, however, say where those warnings appear in the response or whether results are truncated when `limit` is 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 purpose is front-loaded correctly in the first two sentences. However, roughly two-thirds of the text is an exhaustive enumeration of filter DSL syntax, and there is no filter parameter in the schema ā the filters live inside the .base file ā so this bulk does not help the agent construct a call. It is organized and scannable, but it is reference material occupying a tool description.
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 read-only query tool with four fully documented parameters, the description covers what it does, the optional view layering, and partial return semantics (note paths, plus warnings). The main gap, given there is no output schema, is the response shape: where warnings surface and whether truncation at `limit` is signalled.
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 100%, so the baseline is 3; the description earns more by explaining that `view` applies both the view's filters AND its ordering on top of base-level filters ā semantics the schema's one-liner does not convey. `limit` and `includeFrontmatter` are left entirely to the schema, which is acceptable given full coverage.
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 opening sentence gives a specific verb and resource: run a Base file's filters against the vault and return matching note paths. That distinguishes it from read_base (which returns the file itself) and from search_notes, though the description never names those siblings explicitly, so the differentiation is inferable rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence clarifies an optional mode (apply a named view on top of base-level filters), which tells the agent when to supply `view`. However, there is no guidance on when to prefer this tool over read_base, search_notes, or search_by_frontmatter, and no stated prerequisites for what a valid .base file is.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_baseRead BaseARead-onlyIdempotent
Return the parsed contents of a Base file: filters, properties, view definitions, and any unrecognized fields. Use to discover what queries a Base supports before calling query_base.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the .base file. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=false, so safety is covered. The description adds valuable context beyond that: what the return payload contains, including unrecognized fields, which prepares the agent for pass-through data. It doesn't mention failure modes for missing/invalid files, but with annotations carrying the safety profile this is solid.
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 sentences, front-loaded with the return payload, followed by the routing hint. Zero wasted words.
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?
No output schema exists, so the description carries return-value disclosure and does so by enumerating the parsed sections. Complete enough for a single-param read tool, though it could note error behavior for malformed or missing .base files.
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?
Only one parameter at 100% schema coverage, so the schema fully documents 'path' including pattern and length constraints. The description adds no syntax or path-format guidance beyond what structured fields already provide, making the baseline 3 correct.
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+resource ('Return the parsed contents of a Base file') with enumerated contents (filters, properties, view definitions, unrecognized fields). It also implicitly distinguishes itself from query_base via the recommended sequencing, so an agent can tell it apart from 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?
Explicitly states when to use it ('Use to discover what queries a Base supports') and names the downstream alternative (query_base). Clear context, but no explicit when-not conditions or mention of list_bases as an alternative for discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_canvasRead CanvasARead-onlyIdempotent
Read an Obsidian canvas file (.canvas, JSON format) and return a bounded human-readable summary of its structure: total node/edge counts, up to 200 nodes with id/type/position/size/content preview, and up to 200 edges with source/target node ids plus optional label. Use to inspect or navigate a canvas before calling add_canvas_node or add_canvas_edge.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the .canvas file (e.g., 'boards/roadmap.canvas') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so safety is covered. The description adds valuable behavior beyond that: it is a bounded summary with hard caps (up to 200 nodes, up to 200 edges) and content is 'preview' rather than full, which tells the agent to expect truncation. That truncation disclosure is the kind of trait annotations cannot 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?
A single dense sentence that front-loads the core action and file format, then enumerates the returned payload. Every clause earns its place (counts, caps, field lists, workflow guidance), though the enumeration is lengthy enough to read as a spec rather than a quick summary.
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?
No output schema exists, so the description must carry return-value semantics ā and it does: counts, capped node/edge lists, exact fields included, and the 'content preview' caveat. Combined with full annotation coverage and a fully documented single parameter, an agent has everything needed to call and interpret it 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?
There is a single required 'path' parameter, and schema coverage is 100% with an example and .canvas pattern constraint. The description adds no syntax or format detail beyond the schema, so this is the baseline-3 case where structured data does the heavy lifting.
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 (Read) and resource (Obsidian .canvas file) and precisely describes the returned structure: counts, capped nodes with id/type/position/size/content preview, and edges with source/target. This is clearly differentiated from mutation siblings like add_canvas_node/add_canvas_edge by naming them as downstream consumers.
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 explicit context: 'Use to inspect or navigate a canvas before calling add_canvas_node or add_canvas_edge.' This ties usage to a workflow and names alternatives. It lacks an explicit when-not statement, but the intended occasion is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rename_tagRename TagADestructive
Rename a tag everywhere it appears across the vault, in both inline #tags and frontmatter tags: fields. Non-dry-run rewrites require confirmTag to match the new tag name. With hierarchical: true (default), nested tags also rebase: renaming project to client also renames project/alpha ā client/alpha. With dryRun: true, returns the planned counts without writing. Strip the leading # from oldName/newName ā they're tag names, not tag tokens.
| Name | Required | Description | Default |
|---|---|---|---|
| dryRun | No | If true, count matches without modifying any notes. | |
| newName | Yes | New tag name (without leading #), e.g. 'client'. | |
| oldName | Yes | Existing tag name (without leading #), e.g. 'project'. | |
| confirmTag | No | Required when dryRun is false: re-type the new tag name to confirm vault-wide tag rewriting. | |
| hierarchical | No | Also rename nested sub-tags (default: true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses vault-wide rewriting scope, both inline and frontmatter targets, the confirmation guard, hierarchical rebasing behavior with an example, and the dry-run read-only mode. This is substantial behavioral context for a destructive mutation 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?
The description is dense and front-loaded, moving from scope to confirmation requirement, hierarchical behavior, dry-run behavior, and tag-name formatting. Every sentence adds actionable information without waste.
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 destructive 5-parameter mutation tool with no output schema, the description covers the critical safety mechanism, dry-run alternative, hierarchical default, and naming format. An agent has enough context to invoke it correctly and safely.
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%, so the baseline is 3, but the description adds useful meaning: confirmTag must match the new tag name, hierarchical rebasing is illustrated with project/alpha ā client/alpha, and oldName/newName should omit the leading #. It goes beyond the schema descriptions, though some details are still schema-owned.
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, 'Rename a tag', and clarifies vault-wide scope across inline #tags and frontmatter tags:. It is clearly distinct from sibling tag-listing/searching tools.
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 explains key usage conditions: non-dry-run rewrites require confirmTag, dryRun returns planned counts without writing, and hierarchical defaults to true. No sibling alternative is named, but no direct rename alternative exists in the sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_in_noteReplace in NoteADestructive
Search-and-replace within a single note. Supports literal strings or regex patterns. With expectedCount, the operation refuses to commit unless that many matches are present, guarding against accidental over-replacement when an LLM drafts a pattern that's too broad. Returns the count of replacements made.
| Name | Required | Description | Default |
|---|---|---|---|
| find | Yes | Literal string (default) or regex pattern to match. | |
| path | Yes | Vault-relative path to the note. | |
| flags | No | Regex flags (e.g., 'gi'). Defaults to 'g' so all matches are replaced. | |
| regex | No | Treat `find` as a JavaScript regex (multi-line, case-sensitive by default). | |
| replace | Yes | Replacement text. With `regex: true`, supports $1, $2 backreferences. | |
| expectedCount | No | If set, abort unless exactly this many matches are found. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so safety profile is carried by structured data. The description adds real value beyond that: it discloses the fail-closed abort behavior with `expectedCount`, and states that the tool returns a replacement count ā behavior an agent could not infer from 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?
Three sentences, each doing distinct work: core operation, mode support, safety guard plus return value. Front-loaded with the verb and resource, with no filler or restatement of the name.
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 6-parameter destructive mutation with full schema coverage and rich annotations, the description covers the operation, modes, guard, and return value. Minor gaps remain ā e.g. behavior on zero matches, or what happens if `path` doesn't exist ā but nothing critical to correct invocation is missing.
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%, so baseline is 3. The description goes beyond the schema by explaining the *rationale* for `expectedCount` ('guarding against accidental over-replacement when an LLM drafts a pattern that's too broad') and by framing the literal-vs-regex tradeoff, which clarifies the interaction between `find` and `regex` better than the schema's per-field notes.
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 combination ('Search-and-replace within a single note') that immediately distinguishes it from sibling mutation tools like update_section, edit_block, or append_to_note. It also names the two modes of operation (literal strings vs regex) in the same breath.
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?
Explains the purpose of `expectedCount` as a guard against over-broad patterns, which is genuinely useful usage guidance. However, it never explicitly states when to prefer this over update_section or edit_block, nor any when-not conditions, so the agent must infer routing from sibling names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_aliasResolve AliasARead-onlyIdempotent
Find every note whose frontmatter aliases: field contains the given name (case-insensitive). With includeBasename: true, also matches notes whose filename (without .md) equals the name ā Obsidian's resolution fallback when no alias matches. Use to translate a human-friendly title like 'My Project' into the actual note path before calling get_note.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Alias or display name to resolve, e.g. 'My Project'. | |
| includeBasename | No | If true (default), also match notes whose filename (without extension) equals `name`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, idempotentHint, openWorldHint=false), yet the description adds real behavior: matching is case-insensitive, includeBasename mirrors Obsidian's own resolution fallback, and 'every note' signals multiple results are possible. It omits what the result looks like (paths vs. note objects), which with no output schema is the remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero waste, front-loaded with the core matching rule and followed by the option and the recommended workflow. Every clause carries 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?
For a two-parameter, read-only lookup with full schema coverage and annotations, this covers purpose, option semantics, and workflow. The one missing piece is return shape (list of matching paths, ordering), which matters given there is no output schema.
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%, so baseline is 3, but the description adds meaning beyond the schema: case-insensitivity is not documented in the schema, and the 'Obsidian's resolution fallback when no alias matches' framing explains why includeBasename defaults to true and when it fires.
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 ('Find every note whose frontmatter aliases: field contains the given name') plus matching semantics (case-insensitive). This is clearly distinct from siblings like search_notes or search_by_frontmatter, which search content or other fields.
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 explicit usage context: 'Use to translate a human-friendly title like My Project into the actual note path before calling get_note,' which names the downstream tool. It stops short of stating when not to use it (e.g., when the path is already known, or when a content search is needed), so a 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_frontmatterSearch by FrontmatterARead-onlyIdempotent
Find notes whose YAML frontmatter contains a given property/value pair. Property names and values are matched case-insensitively; for array-valued properties, a match is declared if any element matches. Returns matching note paths with their full frontmatter. Use to filter notes by metadata like status, type, or tags stored in frontmatter.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | Value to match against the property (case-insensitive; matches any array element) | |
| folder | No | Restrict search to this folder relative to the vault root (omit to search entire vault) | |
| property | Yes | Frontmatter key to look up, case-insensitively (e.g., 'status', 'type', 'author') | |
| maxResults | No | Maximum number of matching notes to return (1-500, default: 50) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, and closed-world behavior. The description adds useful matching semantics beyond annotations: case-insensitive matching, array-element matching, and that results include note paths with full frontmatter.
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 three efficient sentences and front-loads the core matching behavior. Every sentence contributes useful information without repetition.
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 simple read-only search tool with full schema coverage and annotations covering safety, the description is complete enough. It explains matching rules and return content, which is especially important because there is no output schema.
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 100%, so every parameter is already documented in the schema. The description reinforces property/value matching semantics but adds no details for folder or maxResults beyond what the schema provides.
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: find notes by YAML frontmatter property/value pair. It is clear what the tool does, but it does not explicitly distinguish itself from the sibling search_by_tag, especially since it mentions tags stored in frontmatter.
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 gives clear usage context: filter notes by metadata like status, type, or tags. However, it does not explicitly say when to prefer search_by_tag or search_notes, nor does it state exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_by_tagSearch by TagARead-onlyIdempotent
Find all notes tagged with a specific tag, including nested sub-tags (searching 'project' matches both #project and #project/alpha). Detects tags from both inline #hashtags and YAML frontmatter. Returns matching note paths with optional content previews. Use to collect notes belonging to a topic, area, or workflow stage.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | Tag to search for, with or without # prefix (e.g., 'project' or '#project'). Matches nested tags like 'project/alpha'. | |
| maxResults | No | Maximum number of matching notes to return (1-1000, default: 100) | |
| includeContent | No | If true, include the first 200 characters of each matching note as a preview (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, closed-world behavior, so the safety profile is covered. The description adds real value on top: prefix optionality implied by matching 'project' vs '#project', sub-tag recursion, dual tag sources, and the return shape (paths plus optional previews).
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 sentences, front-loaded with the core matching rule followed by edge-case behavior and then usage intent. No filler and nothing 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?
With no output schema, the description correctly states it returns matching note paths with optional content previews, and annotations cover safety. Ordering and pagination beyond maxResults are unaddressed, which is a minor gap for a search tool.
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 100%, including the default for maxResults and the 200-char preview detail, so the schema carries parameter meaning. The description reinforces tag format and nested matching but adds little beyond what the schema already documents; 3 is the baseline.
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 (find) plus resource (notes tagged with a tag) and goes further by explaining the matching mechanism: nested sub-tags, inline hashtags, and YAML frontmatter. This distinguishes it operationally from full-text search_notes and search_by_frontmatter even without naming them.
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?
'Use to collect notes belonging to a topic, area, or workflow stage' gives an implied usage context, but there is no explicit when-not guidance and no alternatives (e.g., search_by_frontmatter or search_notes) are named for the agent to route between.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_notesSearch NotesARead-onlyIdempotent
Full-text search across all notes in the vault. Ranks literal matches with title/path focus and repeated-line dampening, then returns matching note paths grouped with the line numbers and query-centered snippet content of each matching line. Use to locate notes containing a phrase, keyword, or code fragment; pair with get_note to retrieve full bodies.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Literal search string matched against note body text (not regex) | |
| folder | No | Restrict search to this folder relative to the vault root (omit to search entire vault) | |
| maxResults | No | Maximum number of matching notes to return (1-500, default: 20) | |
| caseSensitive | No | If true, match case exactly; otherwise case-insensitive (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, closed-world), and the description adds real behavioral content: ranking signals (title/path focus, repeated-line dampening) and the shape of results (paths grouped with line numbers and query-centered snippets). It omits truncation/empty-result behavior and how the maxResults cap interacts with ranking.
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 front-loaded sentences with no filler: what it does, how results come back, when to use it. The ranking sentence is dense but earns its place by explaining result ordering.
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 no output schema, the description carries the return-value burden and does describe result structure (grouped paths, line numbers, snippets). Missing is what happens with zero matches, result cap/truncation, and whether ordering vs. maxResults is deterministic.
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 100%, so every parameter is already documented, and the description only echoes the 'literal, not regex' point already in the schema. It adds nothing on folder scoping, case sensitivity, or result limits. Baseline 3 for a fully described 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+resource ('full-text search across all notes') and pins the matching model as literal/full-text, which implicitly separates it from search_semantic, search_by_tag, and search_by_frontmatter. An agent can pick this tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context ('locate notes containing a phrase, keyword, or code fragment') and a follow-up path ('pair with get_note to retrieve full bodies'). It never explicitly excludes or names the sibling alternatives (search_semantic, search_by_frontmatter), so routing between them is left partly to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_semanticSemantic SearchARead-onlyIdempotent
Search notes by meaning rather than keywords. Embeds the query with the configured provider, scores every chunk in the persisted index by cosine similarity, ranks one result per note using the best chunk plus a small top-chunk focus signal, and returns the best chunk as the snippet source. Run index_vault first to populate the index ā this tool does not auto-index because the user should know they're paying the embedding cost. Pair with get_note to retrieve full bodies after picking a hit.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of notes to return (1-100, default: 10). | |
| query | Yes | Natural-language description of what you're looking for, e.g. 'notes about onboarding new hires'. | |
| folder | No | Restrict the search to a folder relative to the vault root. | |
| includeSnippet | No | If true (default), include a short snippet of the matching chunk under each hit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld, and the description adds genuinely useful context: the index is persisted, no implicit re-indexing happens, and the embedding cost is deliberate. It does not cover failure modes such as an empty or stale index, which is the main residual behavioral gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the key constraint are front-loaded, and every sentence carries information. The scoring-internals clause ('cosine similarity', 'top-chunk focus signal') is slightly more implementation detail than an agent needs to select or call the tool.
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 no output schema, the description still tells the agent what a result is (one per note, best chunk as snippet), the indexing prerequisite, and the natural next step. Nothing needed to call it correctly is missing.
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%, so the baseline is 3; the description earns extra by clarifying that ranking yields one result per note (so 'limit' counts notes, not chunks) and that the snippet comes from the best chunk. It still says nothing extra about 'folder' scope beyond 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 ('Search notes by meaning rather than keywords') and immediately contrasts with the keyword sibling search_notes, so the agent can pick correctly without opening a schema. The ranking model (best chunk per note) further pins down what comes back.
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?
Explicit prerequisites and follow-ups: run index_vault first, no auto-indexing because of embedding cost, and pair with get_note for full bodies. Together with the 'by meaning rather than keywords' framing, the when-to-use vs search_notes is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_frontmatterUpdate FrontmatterADestructiveIdempotent
Merge new key-value pairs into a note's YAML frontmatter, preserving any keys not mentioned and leaving the body content untouched. Keys in the payload overwrite existing values. Creates a frontmatter block if the note has none. Returns a count of properties written. Use to set status fields, tags arrays, or other metadata without rewriting the body.
Note: The YAML block is regenerated on each update ā comments, custom quoting, multi-line scalar style, blank lines, and key ordering inside the block are normalized. Key presence and values are preserved; formatting is not.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Relative path from vault root to the note (e.g., 'projects/alpha.md'). Extension optional. | |
| properties | Yes | JSON object string of frontmatter keys to set, e.g., '{"status":"done","priority":1,"tags":["review"]}'. Existing keys not in the payload are preserved. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing merge-vs-overwrite semantics, creation of a block when absent, and ā critically ā that the YAML block is regenerated so comments, quoting, multi-line style, blank lines, and key ordering are normalized. This explains exactly what the destructiveHint=true means in practice, which is the single most decision-relevant fact here.
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?
Core behavior is front-loaded in the first two sentences, with the formatting-loss caveat isolated in a clearly marked note. Every sentence carries distinct information; nothing is redundant with the name or title.
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 two-parameter mutation tool with no output schema, the description covers the mutation semantics, the preservation guarantee, the destructive side effect, and the return value (a count of properties written). Nothing an agent needs to invoke it safely is missing.
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%, so the baseline is 3; the description still adds value by clarifying that payload keys overwrite while unmentioned keys persist, and that the properties argument is a payload rather than a path. It does not add format or edge-case detail (e.g., null values to delete a key) beyond 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 (merge) and resource (YAML frontmatter of a note), and immediately delimits scope: body content untouched, keys not mentioned preserved. This clearly separates it from siblings like update_section, replace_in_note, and append_to_note, which act on body content rather than metadata.
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 a concrete usage context ("Use to set status fields, tags arrays, or other metadata without rewriting the body"), which gives the agent a clear selection criterion against body-editing siblings. It does not, however, name specific alternatives or state when not to use it (e.g., removing keys, which this tool apparently cannot do).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_sectionUpdate SectionADestructiveIdempotent
Replace the body of a specific section (everything between a heading and the next heading at any level). The heading line itself is preserved. section is a heading path: 'Tasks', 'Project A/Status', etc. - case-insensitive and whitespace-tolerant. Use this instead of rewriting the whole file when you only need to update one section.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Vault-relative path to the note (e.g., 'folder/note.md'). Extension required. | |
| newBody | Yes | Replacement body content. The heading line itself is kept intact. | |
| section | Yes | Heading path identifying the section to replace (e.g., 'Tasks' or 'Daily/Today'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false. The description adds real value on top: it defines precisely what is destroyed (the body span between headings) and what survives (the heading line itself), which is exactly the context an agent needs before an overwrite. It does not cover error behavior when the section is absent or any confirmation/undo semantics.
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 sentences, each earning its place: what is replaced, what is preserved, how to specify the section, and why not to use the alternative. The core destructive scope is front-loaded in the first sentence.
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 three-parameter destructive mutation with annotations and no output schema, this covers scope, parameter format, and the main alternative. Minor gap: no indication of what happens if the heading path doesn't resolve to an existing section, which matters for an overwrite tool.
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%, so the schema already documents all three parameters, making 3 the baseline. The description does add one useful detail beyond the schema: 'section' paths are case-insensitive and whitespace-tolerant, plus concrete path examples. The newBody explanation largely restates the schema's own note that the heading line is kept intact.
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 ('Replace the body of a specific section') and pins down the exact boundary: everything between a heading and the next heading at any level, with the heading line preserved. It clearly separates itself from whole-file rewriting but does not name closer siblings such as insert_at_section or replace_in_note, leaving the agent to infer the difference.
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?
Explicitly says when to use it: 'Use this instead of rewriting the whole file when you only need to update one section.' That gives a clear selection rule against full-file rewrite. It stops short of stating the inverse conditions (e.g., to add content use append_to_note/insert_at_section, or what to do when the section is missing).
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.
39 tool updates
v4.1.1- Changed
add_canvas_edge1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
add_canvas_node1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
append_to_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
create_daily_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
create_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
delete_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
edit_block2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / newContent / maxLengthAdded value: +1000000
- Changed
find_broken_links1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
find_orphans1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
find_similar_notes1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
find_unused_attachments1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_attachment1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_backlinks1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_daily_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_graph_neighbors1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_outlinks1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_recent_notes1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_vault_stats1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
index_vault2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / confirmAdded value: +{ + "const": "send-vault-text-to-embedding-provider", + "description": "Required safety latch. Set exactly to \"send-vault-text-to-embedding-provider\" to acknowledge that readable note chunks will be sent to the configured embedding provider.", + "type": "string" +}
- Changed
insert_at_section2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / content / maxLengthAdded value: +1000000
- Changed
list_attachments1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
list_notes1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
list_sections1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
list_tags1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
move_note2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / confirmPathAdded value: +{ + "description": "Required when updateLinks is true: re-type the destination path after .md normalization to confirm vault-wide reference rewriting.", + "maxLength": 500, + "type": "string" +}
- Changed
prepend_to_note1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
query_base2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / path / patternAdded value: +"\\.base$"
- Changed
read_base2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / path / patternAdded value: +"\\.base$"
- Changed
read_canvas1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
rename_tag4 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / confirmTagAdded value: +{ + "description": "Required when dryRun is false: re-type the new tag name to confirm vault-wide tag rewriting.", + "maxLength": 200, + "type": "string" +} - removed
Input schema / properties / newName / patternRemoved value: -"^[^#\\s/][^\\s]*$" - removed
Input schema / properties / oldName / patternRemoved value: -"^[^#\\s/][^\\s]*$"
- Changed
replace_in_note4 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / expectedCount / maximumAdded value: +9007199254740991 - added
Input schema / properties / find / maxLengthAdded value: +4096 - added
Input schema / properties / replace / maxLengthAdded value: +1000000
- Changed
resolve_alias1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
search_by_frontmatter2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / property / descriptionPrevious value: -"Frontmatter key to look up (e.g., 'status', 'type', 'author')"New value: +"Frontmatter key to look up, case-insensitively (e.g., 'status', 'type', 'author')"
- Changed
search_by_tag1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
search_notes1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
search_semantic1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
update_frontmatter1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
update_section2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / newBody / maxLengthAdded value: +1000000
41 tool updates
v2.0.0- Added
add_canvas_edge - Added
add_canvas_node - Added
append_to_note - Added
create_daily_note - Added
create_note - Added
delete_note - Added
edit_block - Added
find_broken_links - Added
find_orphans - Added
find_similar_notes - Added
find_unused_attachments - Added
get_attachment - Added
get_backlinks - Added
get_daily_note - Added
get_graph_neighbors - Added
get_note - Added
get_outlinks - Added
get_recent_notes - Added
get_vault_stats - Added
index_vault - Added
insert_at_section - Added
list_attachments - Added
list_bases - Added
list_canvases - Added
list_notes - Added
list_sections - Added
list_tags - Added
move_note - Added
prepend_to_note - Added
query_base - Added
read_base - Added
read_canvas - Added
rename_tag - Added
replace_in_note - Added
resolve_alias - Added
search_by_frontmatter - Added
search_by_tag - Added
search_notes - Added
search_semantic - Added
update_frontmatter - Added
update_section
41 tool updates
v1.9.0- Removed
add_canvas_edge - Removed
add_canvas_node - Removed
append_to_note - Removed
create_daily_note - Removed
create_note - Removed
delete_note - Removed
edit_block - Removed
find_broken_links - Removed
find_orphans - Removed
find_similar_notes - Removed
find_unused_attachments - Removed
get_attachment - Removed
get_backlinks - Removed
get_daily_note - Removed
get_graph_neighbors - Removed
get_note - Removed
get_outlinks - Removed
get_recent_notes - Removed
get_tags - Removed
get_vault_stats - Removed
index_vault - Removed
insert_at_section - Removed
list_attachments - Removed
list_bases - Removed
list_canvases - Removed
list_notes - Removed
list_sections - Removed
move_note - Removed
prepend_to_note - Removed
query_base - Removed
read_base - Removed
read_canvas - Removed
rename_tag - Removed
replace_in_note - Removed
resolve_alias - Removed
search_by_frontmatter - Removed
search_by_tag - Removed
search_notes - Removed
search_semantic - Removed
update_frontmatter - Removed
update_section
19 tool updates
v1.8.0- Added
edit_block - Added
find_similar_notes - Added
find_unused_attachments - Added
get_attachment - Changed
get_note3 fields changed- added
Input schema / properties / blockAdded value: +{ + "description": "Block id (without the leading `^`). Returns just the paragraph or block tagged with that id.", + "type": "string" +} - added
Input schema / properties / linesAdded value: +{ + "description": "Line range, 1-indexed and inclusive (e.g., '10-25' or '42'). Returns just those lines.", + "pattern": "^\\d+(-\\d+)?$", + "type": "string" +} - added
Input schema / properties / sectionAdded value: +{ + "description": "Heading path (e.g., 'Tasks' or 'Project A/Status'). Returns just that section's body.", + "type": "string" +}
- Added
get_recent_notes - Added
get_vault_stats - Added
index_vault - Added
insert_at_section - Added
list_attachments - Added
list_bases - Added
list_sections - Added
query_base - Added
read_base - Added
rename_tag - Added
replace_in_note - Added
resolve_alias - Added
search_semantic - Added
update_section
3 tool updates
v1.4.0- Added
get_graph_neighbors - Added
get_tags - Added
search_by_tag
3 tool updates
v1.5.3- Removed
get_graph_neighbors - Removed
get_tags - Removed
search_by_tag
1 tool update
v1.5.0- Added
get_graph_neighbors
TDQS
Scored across 41 tools
Most tools target a clearly distinct resource+action (read_base vs query_base, get_backlinks vs get_outlinks, list_tags vs search_by_tag), and descriptions explicitly cross-reference when to use which. The one genuinely crowded area is content mutation ā append_to_note, prepend_to_note, update_section, insert_at_section, edit_block, and replace_in_note all write into a note ā plus four separate search modalities (search_notes, search_semantic, search_by_frontmatter, search_by_tag), which are well-described but still require careful reading to pick correctly.
Every name is snake_case and verb-led with a clear object (get_note, list_canvases, find_broken_links, add_canvas_edge, search_by_tag). Family prefixes (list_*, get_*, find_*, search_*, create_*, add_*, *_canvas_*) form a predictable and readable taxonomy with no camelCase or casing drift.
41 tools is well past the point where an agent can hold the surface in view comfortably, and several clusters (six note-mutation tools, four search tools, three attachment tools) could be consolidated behind parameters. The domains are genuinely broad (notes, sections, blocks, tags, links, graph, canvas, Bases, attachments, embeddings), so it is not arbitrary bloat ā but the selection cost on every turn is real.
Note lifecycle is essentially full (create/read/append/prepend/move/delete, frontmatter, sections, blocks, regex replace) and tags, links, graph traversal, Bases, attachments, and semantic search all have coherent mini-surfaces. Gaps are around the peripheral formats: canvas support is add-only (no node/edge update or deletion, no canvas creation), Bases are read/query-only, and there is no attachment deletion tool ā the description even defers that to the shell.
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.
Nifty's MCP server ā exposes tasks, projects, messages, and files as tools for AI agents.
Serve a folder of Markdown notes as an MCP server: hybrid search, reading, and sourced answers.
Related MCP Servers
- AlicenseBqualityDmaintenanceLocal-first MCP server for Obsidian vaults with 66 tools for reading, writing, searching, and managing notes, tasks, graphs, and more. Works without Obsidian running and requires no plugins.66MIT
- AlicenseAqualityAmaintenanceStandalone MCP server for Obsidian vaults - hybrid search (FTS5 + vector + cross-encoder reranking), images and PDFs in agent-readable form, Kanban-aware tasks (Tasks-plugin + Dataview formats), structured memory with topic recall, fine-grained read/write tools for optimal token efficiency, and link graph support. Run locally, self-host, or one-click deploy for remote access. OAuth 2.1.1033207 npm31MIT
- AlicenseNot gradedqualityAmaintenanceMCP server for Obsidian that exposes tools for reading/writing notes, managing frontmatter and tags, querying Tasks, semantic search, and interacting with Obsidian Bases, with shared local caching and support for various runtime modes.40Apache 2.0
- AlicenseBqualityDmaintenanceA comprehensive MCP server for Obsidian with 45 tools across hybrid filesystem-native and API-based architectures, enabling note management, backlinks, tag management, and analytics.638MIT