SkillAgentSearch skills...

obsidian-mcp-server

Read, write, search, and surgically edit Obsidian vault notes, tags, and frontmatter via MCP. STDIO or Streamable HTTP.

Install / Use

claude mcp add cyanheads -- npx -y github:cyanheads/obsidian-mcp-server

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

89/100

Category

Marketing

Supported Platforms

Claude Code
Claude Desktop

Our assessment of obsidian-mcp-server

obsidian-mcp-server scores 89/100 on our quality scale, 257th of 582 Marketing skills we index (top 45%).

Its MCP Server is 32 KB long, well organised into 35 sections with 6 code examples: a thorough specification that gives an agent plenty to work with.

It has 702 GitHub stars, a meaningful sign that others use it.

Substance
30/30
Structure
20/20
Description
12/15
Adoption
12/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 6 days ago, so obsidian-mcp-server is actively maintained.
  • Our last check on 2026-10-18 found the source still online.
  • It is released under the Apache-2.0 license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.

AI review by kimi-k2.7-code on 2026-09-24. Automated pattern scan on 2026-09-24. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

obsidian-mcp-server compared with similar skills

All 4 of these similar skills score higher than obsidian-mcp-server; compare them before choosing.

SkillScoreStarsUpdatedFormat
obsidian-mcp-server (this skill)by cyanheads897026d agoMCP Server
Agent-Reachby Panniantong100109.3ktodayCLAUDE.md
headroomby headroomlabs-ai10079.0ktodayCLAUDE.md
CowAgentby zhayujie10047.8ktodayCLAUDE.md
Scraplingby D4Vinci10098.3ktodayMCP Server

Frequently asked questions

How do I install obsidian-mcp-server?
Run claude mcp add cyanheads -- npx -y github:cyanheads/obsidian-mcp-server. The install tabs above show the steps for each supported agent.
Which AI agents does obsidian-mcp-server work with?
It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
Is obsidian-mcp-server safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It is Apache-2.0-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is obsidian-mcp-server still maintained?
The repository was last updated 6 days ago, so obsidian-mcp-server is actively maintained.
<div align="center"> <h1>obsidian-mcp-server</h1> <p><b>Read, write, search, and surgically edit Obsidian vault notes, tags, and frontmatter via MCP. STDIO or Streamable HTTP.</b> <div>14 Tools • 3 Resources</div> </p> </div> <div align="center">

Version License Docker MCP SDK npm TypeScript Bun

</div> <div align="center">

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

</div>

Overview

Read, write, search, and surgically edit Obsidian vault notes — sections, frontmatter, tags — over the Local REST API plugin, with folder-scoped read/write permissions built in. Runs as a stdio process or a local Streamable HTTP server.

Tools

| Tool | Description | |:---|:---| | obsidian_get_note | Read a note as raw content, full structured form (content + frontmatter + tags + stat, with optional outgoing links), structural document map, or a single section. | | obsidian_list_notes | List notes and subdirectories under a vault path. Recursive walk (default depth 2, max depth 20; 1000-entry cap) with optional extension and nameRegex filters. | | obsidian_list_tags | List vault tags with usage counts, including hierarchical parents. Ordered by count descending and capped at limit (default 200, max 10000), with the withheld remainder disclosed. Optional nameRegex and minCount narrow the set first. | | obsidian_list_commands | List Obsidian command-palette commands, optionally filtered by nameRegex on display name. Opt-in via OBSIDIAN_ENABLE_COMMANDS=true (paired with obsidian_execute_command). | | obsidian_search_notes | Search the vault by text, JSONLogic, or BM25-ranked Omnisearch (when the plugin is reachable). Results paginate via opaque cursors. | | obsidian_write_note | Create a note, replace a single section in place, or — with overwrite: true — clobber an existing file. Refuses whole-file writes against an existing path by default. | | obsidian_append_to_note | Append content to a note. Without section, creates the file if missing. With section, appends to a specific heading, block, or frontmatter field (file must exist). | | obsidian_patch_note | Surgical append / prepend / replace against a heading, block reference, or frontmatter field. | | obsidian_replace_in_note | Search-replace inside a single note, scoped to the body by default. Literal or regex matching with whole-word, whitespace-flexible, and case-sensitivity options; supports capture-group replacement. | | obsidian_manage_frontmatter | Atomic get / set / delete on a single frontmatter key. | | obsidian_manage_tags | Add, remove, or list tags. Defaults to the frontmatter tags: array; location: 'inline' or 'both' opts into mutating the note body. | | obsidian_delete_note | Permanently delete a note. Always asks the user to confirm first — the call is answered with a confirmation request and retried with the answer. | | obsidian_open_in_ui | Open a file in the Obsidian app UI, with failIfMissing and newLeaf toggles. | | obsidian_execute_command | Execute an Obsidian command-palette command by ID. Opt-in via OBSIDIAN_ENABLE_COMMANDS=true. |

Resources

| Resource | Description | |:---|:---| | obsidian://vault/{+path} | A note in the vault — content, frontmatter, tags, and file metadata. | | obsidian://tags | All tags found across the vault, with usage counts (full snapshot). | | obsidian://status | Server reachability, auth status, plugin/Obsidian version info, and registered API extensions. |

Vault-note and tag data are also reachable via tools — obsidian_get_note for obsidian://vault/{+path}, obsidian_list_tags for obsidian://tags (count-ranked and capped, unlike the resource's raw snapshot). obsidian://status has no tool equivalent. Resources exist for clients that prefer attaching a note or vault snapshot to a conversation.

Capability reference

obsidian_get_note <sub>tool</sub>

  • format: "content" | "full" | "document-map" | "section" selects the projection; full accepts includeLinks: true for outgoing wiki/markdown links (vault-internal only — external URLs are filtered)
  • Addressed by vault path, the active file, or a periodic note (daily / weekly / monthly / quarterly / yearly)
  • Heading sections use Parent::Child syntax and find headings the way the document map does — setext headings (underlined with === or ---) count, # lines inside a list item, HTML block, or fence do not — so every heading path the map lists reads back as itself, over the same span a section write edits; a bare leaf name matching several headings, or a full path that repeats in the note, returns the first match and lists every colliding path in candidates
  • Forgiving path resolution: a case-mismatched path retries against the canonical filename, an ambiguous case match fails with Conflict, and a NotFound carries Did you mean: …? suggestions when near-matches exist
  • Typed errors include note_missing, path_forbidden, no_active_file, periodic_unsupported / periodic_disabled, and path_traversal

obsidian_list_notes <sub>tool</sub>

  • Recursive walk from path (default vault root); depth 1–20 (default 2 = target plus immediate children)
  • Optional extension and nameRegex (≤256 chars, no nested quantifiers) filters; a directory failing nameRegex is skipped without recursing into it
  • Hard cap of 1000 entries per call — excluded.reason: "entry_cap" signals a truncated walk; narrow path or the filters to see the rest
  • Per-directory truncated: true marks entries cut off by the depth limit or by path policy

obsidian_list_tags <sub>tool</sub>

  • Vault-wide tag counts, including hierarchical parents (work/tasks contributes to both work and work/tasks)
  • Ordered by count descending, capped at limit (default 200, max 10000); optional nameRegex and minCount narrow the candidate set before ranking
  • Reports truncated / shown / cap when the limit withheld results
  • Not narrowed by OBSIDIAN_READ_PATHS — tag names (never note contents) can surface from outside the read scope

obsidian_list_commands <sub>tool</sub>

  • Lists Obsidian command-palette IDs and display names; optional nameRegex filters on display name
  • Opt-in via OBSIDIAN_ENABLE_COMMANDS=true — absent from tools/list when unset
  • Discovery partner for obsidian_execute_command

obsidian_search_notes <sub>tool</sub>

  • mode: "text" | "jsonlogic" always; "omnisearch" is added to the schema only when the Omnisearch plugin's HTTP server is reachable at startup (restart to re-probe)
  • text — whitespace-split tokens, all required, each matched case-insensitively as a substring (quotes are literal, so there is no phrase operator), with contextLength-sized context windows (default 100) and an optional pathPrefix; tokens within 2 × contextLength of each other, such as a phrase's words, share one match location; jsonlogic — a JSONLogic tree with var paths into path / content / frontmatter.<key> / tags / stat.{ctime,mtime,size}, plus glob / regexp operators taking [PATTERN, VALUE]; omnisearch — BM25-ranked, quoted phrases, -exclusion, path: / ext: filters, typo tolerance, PDF/OCR via Text Extractor, hard-capped at 50 upstream hits (truncated: true when likely hit)
  • Cursor pagination — omit cursor for page one, pass nextCursor from the prior response; text-mode hits additionally clip to maxMatchesPerHit match locations (default 10), flagged with truncated / totalMatches
  • No dedicated backlinks tool — express "what links here" via jsonlogic: {"regexp": ["\\[\\[Target Note(\\||#|\\]\\])", {"var": "content"}]}

obsidian_write_note <sub>tool</sub>

  • Without section — full-file write; refuses to clobber an existing note unless overwrite: true (file_exists conflict otherwise, naming the surgical-edit tools as the alternative)
  • With section — PATCH-with-replace against a heading/block/frontmatter target, leaving the rest of the file untouched (overwrite is ignored); a bare heading leaf shared by several headings fails with ambiguous_section unless one of them has no parent heading, which the write then targets, and a full heading path that repeats in the note fails the same way
  • Output reports created, plus previousSizeInBytes / currentSizeInBytes on every call to spot an accidental clobber or a mistyped path

obsidian_append_to_note <sub>tool</sub>

  • Without section — appends to an existing file, or creates it with the given content as the whole body (created: true flags the second case)
  • With section — appends to a heading/block/frontmatter target; the file must already exist, and createTargetIfMissing: true brings the section itself into existence. On plugin v5.0 and later, content appended to a heading is separated from the section's existing content by a blank line (except a list item appended to a section that ends in a list and has no sub-headings, which continues that list), and a heading in it must sit below the section's own level (heading_outside_section otherwise)
  • Block-reference targets concatenate with no separator — include a leading newline in content for one
  • previousSizeInBytes / currentSizeInBytes bracket every call for drift detection

obsidian_patch_note <sub>tool</sub>

  • operation: "append" | "prepend" | "replace" against one heading, block reference, or frontmatter field per call; on plugin v5.0 and later, content appended or prepended to a heading is separated from the section's existing content by a blank line (except a list item appended to a section that ends in a list and has no sub-headings, or prepended to one that opens with a list, which continues that list), and a heading in it must sit below the section's own level (heading_outside_section otherwise)
  • Heading targets accept the full Parent::Child path or a bare leaf name; a leaf matching several headings fails with ambiguous_section and lists the candidates, unless one of them has

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars702
CategoryMarketing
Updated6d ago
Forks107

Languages

TypeScript

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions