by cyanheads
Read, write, search, and surgically edit Obsidian vault notes, tags, and frontmatter via MCP. STDIO or Streamable HTTP.
# Add to your Claude Code skills
git clone https://github.com/cyanheads/obsidian-mcp-serverGuides for using ai agents skills like obsidian-mcp-server.
Last scanned: 10/5/2026
{
"issues": [
{
"file": "AGENTS.md",
"line": 38,
"type": "secret-exfiltration",
"message": "Instruction appears to send credentials/secrets to an external endpoint",
"severity": "medium"
},
{
"file": "CLAUDE.md",
"line": 38,
"type": "secret-exfiltration",
"message": "Instruction appears to send credentials/secrets to an external endpoint",
"severity": "medium"
}
],
"status": "PASSED",
"scannedAt": "2026-10-05T11:12:26.975Z",
"npmAuditRan": false,
"pipAuditRan": true,
"promptInjectionRan": true
}See how obsidian-mcp-server compares with popular alternatives.
obsidian-mcp-server is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by cyanheads. Read, write, search, and surgically edit Obsidian vault notes, tags, and frontmatter via MCP. STDIO or Streamable HTTP. It has 691 GitHub stars.
Yes. obsidian-mcp-server passed SkillsLLM's automated security scan — a dependency vulnerability audit plus prompt-injection heuristics — with no high-severity issues. You can read the full report in the Security Report section on this page.
Clone the repository with "git clone https://github.com/cyanheads/obsidian-mcp-server" and add it to your Claude Code skills directory (see the Installation section above).
obsidian-mcp-server is primarily written in TypeScript. It is open-source under cyanheads on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh obsidian-mcp-server against similar tools.
No comments yet. Be the first to share your thoughts!
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
Obsidian vault notes over the Local REST API plugin. Read, search, and write notes, edit single headings, blocks, and frontmatter fields in place, and manage tags, with folder-scoped read/write permissions built in. Runs as a stdio process or a local Streamable HTTP server.
| Tool | Description |
|---|---|
obsidian_get_note |
Read a note as raw content, full structured form, document map, or a single section |
obsidian_list_notes |
List notes and folders under a vault path, recursively, with extension and name filters |
obsidian_list_tags |
List vault tags with usage counts, most-used first |
obsidian_search_notes |
Search by text, JSONLogic, or BM25-ranked Omnisearch when that plugin is reachable |
obsidian_write_note |
Create a note, replace one section, or overwrite a whole file with overwrite: true |
obsidian_append_to_note |
Append to a note (creating it if missing) or to one heading, block, or frontmatter field |
obsidian_patch_note |
Append, prepend, or replace against one heading, block reference, or frontmatter field |
obsidian_replace_in_note |
Literal or regex search-replace inside one note, body-only by default |
obsidian_manage_frontmatter |
Get, set, or delete one frontmatter key |
obsidian_manage_tags |
Add, remove, or list a note's tags in frontmatter, inline, or both |
obsidian_delete_note |
Permanently delete a note after the user confirms |
obsidian_open_in_ui |
Open a file in the Obsidian app, optionally in a new pane |
obsidian_list_commands |
List command-palette commands (opt-in via OBSIDIAN_ENABLE_COMMANDS) |
obsidian_execute_command |
Run a command-palette command by ID (opt-in via OBSIDIAN_ENABLE_COMMANDS) |
| Resource | Description |
|---|---|
obsidian://vault/{+path} |
A note's content, frontmatter, tags, and file metadata |
obsidian://tags |
Every vault tag with its usage count, as an uncapped snapshot |
obsidian://status |
Plugin reachability, auth status, versions, and registered API extensions |
Note and tag data are also reachable through tools (obsidian_get_note, obsidian_list_tags); obsidian://status has no tool equivalent.
obsidian_get_note tooltarget is a vault path, the active file, or a periodic note (daily through yearly, optional date); format is content, full, document-map, or section, and full takes includeLinks: true for vault-internal outgoing linksresult.format discriminates the payload; a section read that matches several headings returns the first and lists every full path in candidatesobsidian_list_notes toolpath (default vault root) to depth 1–20 (default 2), filtered by extension and nameRegex (≤256 chars); a folder that fails nameRegex is not walkedentries[] (file / directory), totals, and appliedFilters; the walk stops at 1,000 entries with excluded.reason: "entry_cap", and a folder the depth limit or path policy kept out carries truncated: trueobsidian_list_tags toolnameRegex (≤256 chars) and minCount narrow the set, then tags are ranked by count and capped at limit (default 200, max 10000); hierarchical parents count (work/tasks adds to work)truncated, shown, and capobsidian_search_notes toolmode: "text" requires every whitespace-split token of query as a case-insensitive substring of the filename or body (quotes are literal), shaped by contextLength (default 100), pathPrefix, and maxMatchesPerHit (default 10); mode: "jsonlogic" evaluates a logic tree over path, content, frontmatter.<key>, tags, and stat, with glob / regexp taking [PATTERN, VALUE]result.mode discriminates the payload; every mode reports totalCount and pages via nextCursor, and a text hit clipped to maxMatchesPerHit carries truncated and totalMatchesmode: "omnisearch" (BM25 ranking, quoted phrases, -exclusion, path: / ext: filters) is offered only when the Omnisearch plugin answered at startup; its 50-hit upstream cap sets truncated: trueobsidian_write_note tooltarget and content, with optional section and contentType (markdown / json); a whole-file write to an existing note fails with file_exists unless overwrite: truesection, replaces only that heading, block, or frontmatter field and keeps the heading line; output reports created, sectionTargeted, and the resolved sectionTargetobsidian_append_to_note toolsection, appends to the file or creates it (created: true); with section, appends to that heading, block, or frontmatter field of an existing note, and createTargetIfMissing: true creates the sectioncontent_preexists; block targets add no separator, so start content with a newline if you want oneobsidian_patch_note tooloperation: "append" | "prepend" | "replace" against one section of an existing note; patchOptions takes createTargetIfMissing, applyIfContentPreexists, and trimTargetWhitespace (plugin v4.x only)section and operation; a repeat of content already at the target fails with content_preexists unless applyIfContentPreexists: trueobsidian_replace_in_note toolreplacements[] run in order, each over the previous one's output; each takes useRegex (≤1024 chars), caseSensitive (default true), wholeWord, flexibleWhitespace (literal mode only), and replaceAll (default true)totalReplacements and perReplacement[] with bodyCount / frontmatterCountscope: "body" (default) leaves frontmatter byte-identical; "frontmatter" and "both" re-parse the YAML afterward and write nothing if it breaks (frontmatter_invalid)obsidian_manage_frontmatter tooloperation: "get" | "set" | "delete" on one key; set requires a JSON-typed valueget returns exists and value (null when absent); set and delete return the full frontmatter after the change, and a delete against unparseable YAML fails with frontmatter_invalid without writingobsidian_manage_tags tooloperation: "add" | "remove" | "list" with tags; location: "frontmatter" (default, the tags: array), "inline" (body #tag; add appends at end of file), or "both"add / remove report applied, skipped, and the resulting tags; list returns frontmatter, inline, and all%% … %% comments are readobsidian_delete_note tooltarget; the first call answers with a confirmation request naming the path and byte size, and the note is deleted only after the user acceptscancelled, and a client without elicitation support cannot delete; there is no API-level undo, only Obsidian's local trashSTORAGE_PROVIDER_TYPE, default in-memory, process-local). That works for stdi