MCP.so
Sign In

Obsidian MCP Server

@cyanheads

About Obsidian MCP Server

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

Config

Add this server to your MCP-compatible client using the configuration below.

{
  "mcpServers": {
    "obsidian-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "obsidian-mcp-server@latest"
      ],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info",
        "OBSIDIAN_API_KEY": "your-local-rest-api-key"
      }
    }
  }
}

Tools

12

Read a note from the vault — by path, the active file, or a periodic note. Choose a `format` projection: raw body, full object, structural document map, or a single section.

List notes and subdirectories at a vault path. Defaults to the vault root when `path` is omitted. Tune recursion with `depth`, or filter the walk with `extension` / `nameRegex`. Capped at 1000 entries per call — when reached, walking stops and `excluded` is set; narrow `path` or tighten filters to surface the rest.

List every tag found across the vault, with usage counts. Includes hierarchical parents — `work/tasks` contributes to both `work` and `work/tasks`. Filter to a subset with the optional `nameRegex`. To find notes by tag, use `obsidian_search_notes` in jsonlogic mode (e.g. `{"in": ["work", {"var": "tags"}]}`).

Open a file in the Obsidian app UI. By default fails when the path does not exist; the `failIfMissing` flag controls the open-or-create behavior. Opening an existing file needs read access; opening a missing one creates it, so that case needs write access to the path.

Search the vault by text substring or JSONLogic predicate. Pick the mode that matches the query shape. Results paginate via opaque cursors: omit `cursor` for the first page, then pass `nextCursor` from the prior response. Text-mode hits additionally clip per file at `maxMatchesPerHit`.

Create or overwrite a note. With `section`, replaces just that heading/block/frontmatter section in place — use `obsidian_get_note` with `format: "document-map"` to discover available targets. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`. Whole-file writes fail with `file_exists` against an existing note unless `overwrite: true` — for in-place edits, prefer `obsidian_patch_note` (sections), `obsidian_append_to_note` (append), or `obsidian_replace_in_note` (find-and-replace). For heading sections, `content` is the new body; the heading line is preserved automatically.

Append content to a note. **Without `section`: appends to the end of the file, or creates the file if it does not exist (your content becomes the full file).** With `section`: appends to the end of that heading/block/frontmatter — use `obsidian_get_note` with `format: "document-map"` to discover available targets. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`. For block-reference targets, content is concatenated adjacent to the block line without inserting a separator — include a leading newline in `content` if you want one. Set `createTargetIfMissing` to bring the target section into existence rather than failing when it does not exist.

Edit a heading, block reference, or frontmatter field in place — append to, prepend to, or replace the target's body. Use `obsidian_get_note` with `format: "document-map"` to discover available targets first. A nested heading may be named either by its full `Parent::Child` path or by a bare leaf name that matches exactly one heading; a leaf shared by several headings is rejected with `ambiguous_section`.

Search and replace inside a single note, literally or by regex. Replacements run in array order, each over the previous one's output. Use for edits that don't fit `obsidian_patch_note`'s structural targets — e.g., body-wide find-and-replace.

Get, set, or delete a single frontmatter key on a note, atomically. `set` requires a JSON-typed `value` (string, number, boolean, array, or object).

Add, remove, or list a note's tags. Defaults to the frontmatter `tags:` array — set `location` to `inline` or `both` to mutate the note body. `add` ensures the tag is present in the requested location(s); `remove` strips it; `both` reconciles across both representations. Inline `#tag` occurrences inside fenced code blocks are intentionally left alone, and inline-location additions append the new tag at end-of-file. `list` ignores the input `tags` array.

Permanently delete a note from the vault. Confirms with the user before deleting when the client supports interactive confirmation. Recovery requires the local trash in Obsidian — there is no API-level undo.

Overview

What is Obsidian MCP Server?

Obsidian MCP Server lets AI agents read, write, search, and surgically edit Obsidian vault notes, tags, and frontmatter via the Model Context Protocol. It offers 14 tools and 3 resources, and supports STDIO or Streamable HTTP transport. It is built for developers and power users who want to automate or integrate with their Obsidian notes.

How to use Obsidian MCP Server?

Install via npm (npx -y obsidian-mcp-server) or Docker (ghcr.io/cyanheads/obsidian-mcp-server). Set the OBSIDIAN_API_KEY environment variable to your Obsidian Local REST API key. Configure the server in your MCP client (e.g., Claude Desktop, Cursor, VS Code) with the appropriate command and environment variable. The server can also be installed via a dedicated MCP bundle.

Key features of Obsidian MCP Server

  • Read notes as raw content, full structure, document map, or section.
  • Write, append, patch, and search‑replace notes with surgical precision.
  • Manage frontmatter and tags (frontmatter, inline, or both).
  • Search by text, JSONLogic, or Omnisearch BM25 ranking.
  • List notes, tags, and Obsidian commands.
  • Create notes safely with overwrite protection.
  • Execute Obsidian command‑palette commands (opt‑in).
  • Paginate search results via opaque cursors.
  • Supports optional Omnisearch plugin integration.

Use cases of Obsidian MCP Server

  • Automate note creation, updates, and tag management in a vault.
  • Search and retrieve notes programmatically for AI‑powered knowledge bases.
  • Perform bulk or targeted edits on frontmatter, headings, or inline tags.
  • Integrate Obsidian with MCP‑compatible agents for note‑taking workflows.

FAQ from Obsidian MCP Server

What transports does the server support?

STDIO and Streamable HTTP are both supported.

Does it require an API key?

Yes, you must set the OBSIDIAN_API_KEY environment variable with your Obsidian Local REST API key.

How can I avoid accidentally overwriting a note?

The obsidian_write_note tool refuses to clobber an existing file unless overwrite: true is explicitly set. Use obsidian_patch_note or obsidian_append_to_note for in‑place edits.

Does the server support Omnisearch?

Yes, if the Omnisearch plugin’s HTTP server is reachable at startup, the obsidian_search_notes tool offers an Omnisearch mode with BM25 ranking, quoted phrases, exclusions, and path/ext filters.

How do I paginate search results?

Pass the nextCursor value from the previous response as the cursor parameter for subsequent pages. Omit cursor for the first page.

Frequently asked questions

What transports does the server support?

STDIO and Streamable HTTP are both supported.

Does it require an API key?

Yes, you must set the `OBSIDIAN_API_KEY` environment variable with your Obsidian Local REST API key.

How can I avoid accidentally overwriting a note?

The `obsidian_write_note` tool refuses to clobber an existing file unless `overwrite: true` is explicitly set. Use `obsidian_patch_note` or `obsidian_append_to_note` for in‑place edits.

Does the server support Omnisearch?

Yes, if the Omnisearch plugin’s HTTP server is reachable at startup, the `obsidian_search_notes` tool offers an Omnisearch mode with BM25 ranking, quoted phrases, exclusions, and path/ext filters.

How do I paginate search results?

Pass the `nextCursor` value from the previous response as the `cursor` parameter for subsequent pages. Omit `cursor` for the first page.

Comments

More Memory & Knowledge MCP servers