Skip to main content
Glama
Obsidian MCP (pgvector + Ollama, self-hosted)

Obsidian MCP (pgvector + Ollama, self-hosted)

by maxkuminov

Delete note

delete_note
Destructive

Delete a note from an Obsidian vault, moving it to .trash by default or unlinking it permanently, with an optional hash check to prevent deleting changed content.

Instructions

Delete a note from the vault. Requires write permission — a readwrite API key, or an OAuth token carrying the readwrite scope.

By default this is a soft-delete: the file is moved to .trash/<YYYYMMDD-HHMMSS>-<basename>-<8 hex> inside the vault root, by a single non-replacing rename, so an existing trash entry is never overwritten and two deletes in the same second land on distinct names. The indexer skips dot-prefixed directories, so search and embeddings drop the note automatically on the next reindex pass (≤ 5 minutes). Soft-deleted files accumulate in .trash/ — emptying that directory is the user's responsibility.

A vault filesystem that cannot perform that non-replacing rename into .trash/ makes the soft delete refuse with an error naming the limitation rather than fall back to a rename that could overwrite; pass permanent=True to unlink instead.

With permanent=True, the file is unlinked directly with no recovery path inside this server. Existing backups are the rollback story.

A path whose final component is a symlink is refused, naming its target, so a delete never removes a note other than the one named; symlinked folders inside the vault work normally.

Dangling backlinks left behind by a delete are surfaced via get_backlinks and find_orphans. See get_vault_guide for context.

expected_hash — binding a write to the bytes you read. Optional by default — omitted, the delete proceeds against whatever is on disk — unless the deployment requires it, when an omitted hash is refused precondition_required. Pass the content_hash a read returned, verbatim and canonical (sha256:<64 lowercase hex>), and the call is refused with nothing written if the file changed in between. It is always the whole file's hash, never a hash of the text you received. expected_hash covers your read through this call's preflight read. The delete acts through the pinned parent directory but does not compare the bytes again: an in-place edit after that comparison can still be deleted. Every refusal the server raises ends with one machine-readable MCP-REFUSAL {"code":…} line (an undeclared or mistyped argument is rejected by protocol validation before the tool runs and carries no such line) — stale_precondition (with the file's current hash, ready to resend), concurrent_write, no_incumbent, malformed_precondition, precondition_unavailable, precondition_required — and each states what resolves it.

It applies in both modes, and the comparison runs before the .trash rename and before the unlink, so a refused delete leaves the note where it was and creates no trash entry. A successful delete reports no content_hash: nothing remains to hash.

Args: path: Vault-relative path to the note. permanent: If True, unlink instead of soft-deleting. expected_hash: The note's content_hash as you last read it. Refuses the delete, changing nothing, if the note has changed since.

Input Schema

NameRequiredDescriptionDefault
pathYes
permanentNo
expected_hashNo

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.8.2
    • addedInput schema / additionalProperties
      Added value: +false
  2. Changed1 schema field changedv0.8.1
    • addedInput schema / properties / expected_hash
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Expected Hash"
      +}
  3. First observed

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true, but the description adds far more: the exact .trash naming scheme, atomic rename semantics, the indexer's ≤5-minute drop, the irreversibility of permanent=True, symlink refusal, and the full list of MCP-REFUSAL codes with what resolves each. This is context structured fields cannot carry.

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

Conciseness3/5

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

Front-loaded with purpose and permissions, but the expected_hash section sprawls across three paragraphs with repeated restatements ('It applies in both modes' revisiting the preflight comparison) and a long refusal-code list. Content is useful but the prose is bloated for what is a three-argument tool.

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

Completeness5/5

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

Covers modes, permissions, failure semantics, and precondition behavior, and correctly omits return-value details since an output schema exists (noting only that a successful delete reports no content_hash). 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.

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden — and it does: path is vault-relative, permanent defaults to soft-delete vs unlink, and expected_hash is documented with its exact canonical format (sha256:<64 lowercase hex>), whole-file scope, default-omitted behavior, and deployment override to precondition_required.

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

Purpose5/5

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

States a specific verb and resource ('Delete a note from the vault') and immediately scopes it with permission requirements and the soft-vs-permanent distinction. Although it never names the sibling delete_file explicitly, the symlink-scoping paragraph makes clear this operates on named notes only, which differentiates it sufficiently.

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

Usage Guidelines4/5

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

Gives explicit conditions for optional arguments: pass permanent=True when the filesystem cannot do the non-replacing rename, and expected_hash when the deployment requires preconditions. It also points at get_backlinks, find_orphans, and get_vault_guide for follow-up. It does not state when to prefer this over the delete_file sibling, 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.