Skip to main content
Glama
aliasunder

Vault Cortex Obsidian MCP Server

Patch Note

vault_patch_note
Destructive

Surgical edits to a markdown note — append, prepend, replace, or insert content by heading. Frontmatter values are preserved; YAML formatting may be normalized to block style on first edit.

Instructions

Surgical edits to a markdown note — append, prepend, replace, or insert content by heading. Frontmatter values are preserved; YAML formatting may be normalized to block style on first edit.

Example: vault_patch_note({ path: "Projects/plan.md", operation: "append", heading: "Open questions", content: "- Which region hosts the backup?" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "replace", heading: "Status", content: "On track for launch.\n" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "insert_before", heading: "Phase 2", content: "## Phase 1\nDone.\n" }) Example: vault_patch_note({ path: "Notes/Plan.md", operation: "prepend", content: "> [!info] Draft\n> Not reviewed yet.\n" })

When to use: Modifying part of an existing note without overwriting the entire body. Prefer vault_write_note for creating new notes, or full rewrites (with overwrite: true). Prefer vault_replace_in_note for in-place text changes (typos, renaming) that stay in the same location. Prefer vault_insert_at_anchor for inserting next to a specific line inside a section. Prefer vault_replace_span for replacing a run of lines inside a section. Prefer vault_delete_span for removing lines. Prefer vault_update_properties for changing frontmatter properties. Prefer vault_create_task for adding a task. Prefer vault_update_task for completing or moving a task in one write.

Operations:

  • append: add content at end of section (or end of file if no heading)

  • prepend: add content after heading line (or at the top of the body, below frontmatter, if no heading — how you add a leading callout). To start a new section above the note's current first heading, use insert_before on that heading, not a no-heading prepend.

  • replace: replace section body (requires heading)

  • insert_before: insert content above the heading line (requires heading)

Heading-targeted ops keep the matched heading and write content verbatim. No separator is added around the content — end it with a newline to leave a blank line after the inserted block.

Limitation: A no-heading prepend inserts at body line 0. If the note has content above its first heading and your content starts with a heading, the pre-existing content becomes the new section's body. The write still succeeds.

Section boundaries: a section spans from its heading to the next heading of the same or higher level (or EOF), so it includes its child headings. Empty headings ("##" with no text) act as boundaries but cannot be targeted — edit their content via vault_replace_in_note instead.

Editing a leading callout: read it via vault_read_note(outline: true), then vault_replace_in_note the old block for the new one (a no-heading prepend would stack a second callout above it).

Errors:

  • "note not found" — path does not exist; check vault_list_notes for valid paths

  • "path must end in …" — add the .md extension

  • "heading not found" — no heading matches the text; error lists available headings

  • "ambiguous heading" — multiple headings match; use heading_level to disambiguate, or use vault_replace_in_note to target by text content when headings share the same level

  • "operation … requires a heading target" — pass heading, or use append or prepend to edit the file body

  • "heading cannot be empty" — heading is whitespace only; pass the heading's text

  • "content begins with the heading … which would duplicate it" — content's first line repeats the target heading; omit it

  • "section … has N child headings …" — the target section contains child headings that replace would destroy; pass include_children: true to confirm, or target the child heading directly

  • "absolute path blocked" / "path traversal blocked" / "hidden path blocked" — use a vault-relative path with no hidden (dot-prefixed) file or folder in it

  • "concurrent write in progress" — another write to this note is in flight; re-read the note and retry

  • "content contains a control character" — content includes a non-printable control byte; remove it before writing

  • "properties block …" — the note's properties block can't be read, or a rewrite would lose it; the error says how to repair it

  • "the note would open with a properties block …" — the edit would leave --- lines at the top of a note with no properties, around text that can't be kept as properties; the error says how to avoid it

Obsidian syntax: Content is Obsidian Flavored Markdown (no escaping applied). Watch for: #word = tag, [[ = wikilink, %% = comment block. Inserting heading-level content (## New Section) changes the note's structure — future heading-targeted ops may resolve differently. Table rows: send only the data row ("| cell1 | cell2 |"), not the header or separator — duplicating them splits the table.

Returns: Confirmation message — "Applied to → ", where target is the matched heading (e.g. "## Active") or "file body" for a no-heading append/prepend. A no-heading prepend that nested existing content under an inserted heading adds a sentence naming the content's size and the call that would have avoided it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesVault-relative path to the note, including the ".md" extension (e.g. "TASKS.md", "Projects/plan.md"). Use the exact letter case.
contentYesMarkdown content to insert.
headingNoTarget heading text (case-sensitive exact match). Omit for a file-level append or prepend.
operationYesappend | prepend | replace | insert_before.
heading_levelNoHeading level (1-6) for disambiguation when multiple headings share the same text
include_childrenNoWhen true, allows replace to overwrite a section that contains child headings.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv0.54.13
    • changedInput schema / properties / content / description
      Previous value: -"Markdown content to insert. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."New value: +"Markdown content to insert."
    • changedInput schema / properties / include_children / description
      Previous value: -"When true, allows replace to overwrite a section that contains child headings. Without this, replace errors if children exist — preventing silent data loss."New value: +"When true, allows replace to overwrite a section that contains child headings."
  2. Changed3 schema fields changedv0.54.9
    • changedInput schema / properties / content / description
      Previous value: -"Markdown content to insert, written verbatim with no separator added — end it with a newline to leave a blank line after the inserted block. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."New value: +"Markdown content to insert. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."
    • changedInput schema / properties / heading / description
      Previous value: -"Target heading text (case-sensitive exact match). Required for replace and insert_before. Optional for append/prepend (omit for file-level operation)."New value: +"Target heading text (case-sensitive exact match). Omit for a file-level append or prepend."
    • changedInput schema / properties / operation / description
      Previous value: -"append | prepend | replace | insert_before. replace and insert_before require a heading; append and prepend work with or without one."New value: +"append | prepend | replace | insert_before."
  3. Changed1 schema field changedv0.54.7
    • changedInput schema / properties / path / description
      Previous value: -"Vault-relative path to the note, including the \".md\" extension (e.g. \"TASKS.md\", \"Projects/plan.md\")"New value: +"Vault-relative path to the note, including the \".md\" extension (e.g. \"TASKS.md\", \"Projects/plan.md\"). Use the exact letter case."
  4. Changed1 schema field changedv0.41.2
    • changedInput schema / properties / content / description
      Previous value: -"Markdown content to insert. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."New value: +"Markdown content to insert, written verbatim with no separator added — end it with a newline to leave a blank line after the inserted block. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."
  5. Changed1 schema field changedv0.37.1
    • addedInput schema / properties / include_children
      Added value: +{
      +  "description": "When true, allows replace to overwrite a section that contains child headings. Without this, replace errors if children exist — preventing silent data loss.",
      +  "type": "boolean"
      +}
  6. Changed1 schema field changedv0.23.10
    • changedInput schema / properties / path / description
      Previous value: -"Vault-relative path to the note (e.g. \"TASKS.md\", \"Projects/plan.md\")"New value: +"Vault-relative path to the note, including the \".md\" extension (e.g. \"TASKS.md\", \"Projects/plan.md\")"
  7. Changed3 schema fields changedv0.23.5
    • changedInput schema / properties / content / description
      Previous value: -"Content to insert or replace with"New value: +"Markdown content to insert. Must not begin with the target heading text (it would duplicate the heading, which is kept automatically)."
    • changedInput schema / properties / operation / description
      Previous value: -"Patch operation to apply"New value: +"append | prepend | replace | insert_before. replace and insert_before require a heading; append and prepend work with or without one."
    • changedInput schema / properties / path / description
      Previous value: -"Vault-relative path to the note"New value: +"Vault-relative path to the note (e.g. \"TASKS.md\", \"Projects/plan.md\")"
  8. Changed1 schema field changedv0.22.1
    • addedInput schema / properties / content / minLength
      Added value: +1
  9. Changed1 schema field changedv0.19.2
    • addedInput schema / properties / heading / minLength
      Added value: +1
  10. Added

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already flag the mutation profile (destructiveHint=true, idempotentHint=false), and the description goes well past them: frontmatter preservation with YAML block-style normalization on first edit, section-boundary rules, the no-heading prepend nesting limitation, concurrency/control-character errors, and the full error catalogue. Nothing about the tool's destructive blast radius is left implicit.

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

Conciseness4/5

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

Well front-loaded (purpose → routing → operations → limitations → errors) and mostly earns its length given six parameters and subtle section semantics. It is, however, redundant in places: the leading-callout advice appears in the prepend bullet, again in the limitation paragraph, and a third time under 'Editing a leading callout', and the error list is long enough to blur into reference documentation.

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?

Despite having no output schema, the description documents the return string format including the no-heading-prepend caveat sentence, and covers the edge cases (empty headings, child-heading destruction, frontmatter blocks) an agent must handle to call this correctly. Complete for the tool's complexity.

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 coverage is already 100%, but the description adds genuine meaning: per-operation semantics (append vs prepend vs replace vs insert_before), what include_children guards against, how heading_level disambiguates, that content is written verbatim with no separator, and table-row guidance for content. The four examples make parameter usage concrete.

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?

Opens with a specific verb+resource+scope: 'Surgical edits to a markdown note — append, prepend, replace, or insert content by heading.' It immediately distinguishes itself from the many sibling write tools via the 'When to use' routing paragraph, so an agent can pick it without opening any schema.

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

Usage Guidelines5/5

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

Explicit when-to-use plus a named alternative for nearly every adjacent case (vault_write_note for creates/rewrites, vault_replace_in_note for in-place edits, vault_insert_at_anchor, vault_replace_span, vault_delete_span, vault_update_properties, vault_create_task, vault_update_task). This is the strongest possible routing guidance.

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