MCP Hub
Back to servers

obsidian-mcp

Wraps the Obsidian CLI to allow LLM agents to read/write notes, search, manage frontmatter, navigate links, and run plugins on a running Obsidian instance.

glama
Stars
1
Updated
May 5, 2026
Validated
May 9, 2026

obsidian-mcp

MCP server that wraps the official Obsidian CLI so an LLM agent can drive a running Obsidian instance — read/write notes, search, manage frontmatter, navigate links, run plugins, and more.

This server is a thin, comprehensive wrapper. Every tool maps 1:1 to an obsidian CLI command.

Prerequisites

  1. Obsidian must be running. The CLI talks to the live app over IPC; it does not read the vault on disk directly.
  2. Register the CLI binary. In Obsidian: Settings → General → Command line interface → Register CLI. Obsidian will add obsidian to your PATH.
  3. Verify: obsidian version prints the CLI version.

Install

Two paths depending on whether you want to build it yourself or grab a pre-published version from npm.

Option A — Clone & build (works today)

Clone the repo and build locally, then point Claude Code at the built file:

git clone https://github.com/yuchichang/obsidian-mcp.git
cd obsidian-mcp
npm install
npm run build

Register it with Claude Code (one command):

# Add (user scope — available across all projects)
claude mcp add -s user obsidian -- node /absolute/path/to/obsidian-mcp/dist/index.js

# Remove
claude mcp remove obsidian

# List configured servers
claude mcp list

-s user registers it for your whole user account. Use -s project to commit it to the repo's .mcp.json instead, or -s local for the current project only (default).

Or write it into .mcp.json manually:

{
  "mcpServers": {
    "obsidian": {
      "command": "node",
      "args": ["/absolute/path/to/obsidian-mcp/dist/index.js"]
    }
  }
}

Option B — Install from npm (zero-build)

Prerequisite: the package must already be published to npm. The maintainer publishes once via npm publish; all subsequent users get it via npx automatically. If you forked this repo and want this flow under your own scope, change name in package.json to @<your-npm-username>/obsidian-mcp, then npm publish.

Once published, no clone or build needed:

claude mcp add -s user obsidian -- npx -y @yuchichang/obsidian-mcp

Or in .mcp.json / Claude Desktop's claude_desktop_config.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "npx",
      "args": ["-y", "@yuchichang/obsidian-mcp"]
    }
  }
}

Override the CLI path

If obsidian isn't on PATH, set the OBSIDIAN_CLI env var. Works with either install path:

{
  "mcpServers": {
    "obsidian": {
      "command": "node",
      "args": ["/absolute/path/to/obsidian-mcp/dist/index.js"],
      "env": {
        "OBSIDIAN_CLI": "C:/Users/you/AppData/Local/Obsidian/obsidian.cmd"
      }
    }
  }
}

Tools

Vault & files

ToolWraps
obsidian_list_filesobsidian files
obsidian_list_foldersobsidian folders
obsidian_read_noteobsidian read
obsidian_get_metadataobsidian file
obsidian_create_noteobsidian create
obsidian_append_noteobsidian append
obsidian_prepend_noteobsidian prepend
obsidian_move_noteobsidian move
obsidian_delete_noteobsidian delete (permanent flag supported)

Frontmatter properties

ToolWraps
obsidian_get_propertiesobsidian properties
obsidian_set_propertyobsidian property:set
obsidian_remove_propertyobsidian property:remove

Search

ToolWraps
obsidian_searchobsidian search
obsidian_search_contextobsidian search:context

Tags & links

ToolWraps
obsidian_list_tagsobsidian tags
obsidian_files_with_tagobsidian tag
obsidian_rename_tagobsidian tags:rename
obsidian_get_linksobsidian links
obsidian_get_backlinksobsidian backlinks
obsidian_list_unresolvedobsidian unresolved
obsidian_list_orphansobsidian orphans

Daily notes

ToolWraps
obsidian_daily_readobsidian daily:read
obsidian_daily_appendobsidian daily:append
obsidian_daily_pathobsidian daily:path

Plugins

ToolWraps
obsidian_list_pluginsobsidian plugins
obsidian_enable_pluginobsidian plugin:enable
obsidian_disable_pluginobsidian plugin:disable
obsidian_reload_pluginobsidian plugin:reload

Developer / advanced

ToolWrapsNotes
obsidian_evalobsidian eval⚠️ Runs arbitrary JS inside Obsidian. Treat as destructive.
obsidian_dev_screenshotobsidian dev:screenshotReturns base64 PNG.
obsidian_dev_errorsobsidian dev:errors
obsidian_dev_consoleobsidian dev:console

Meta

ToolWraps
obsidian_versionobsidian version
obsidian_helpobsidian help

Conventions

  • Targeting a note — file-targeting tools accept either:
    • file — wikilink-style note name (e.g. "My Note"), or
    • path — vault-relative file path (e.g. "Folder/My Note.md").
  • Multi-vault setups — every tool accepts an optional vault parameter. When omitted, the most recently focused vault is used.
  • Output format — list/search/metadata tools default to JSON for easy machine parsing.

Sensitive operations & user confirmation

The following tools are gated behind a user-confirmation step:

ToolReason
obsidian_delete_noteRemoves data (especially with permanent: true).
obsidian_move_noteRenames + rewrites wikilinks across the vault.
obsidian_remove_propertyRemoves frontmatter data.
obsidian_rename_tagBulk-rewrites tags across every note.
obsidian_enable_pluginGrants a community plugin code execution.
obsidian_evalRuns arbitrary JavaScript inside Obsidian.

How the gate works:

  1. MCP elicitation (preferred). If the connected client supports the elicitation capability (Claude Code does), the server sends an elicitation/create request and the client shows the user a Proceed? prompt with the action and target spelled out. Only accept + confirm: true proceeds.
  2. Explicit confirm: true parameter. Every sensitive tool's input schema includes an optional confirm: boolean. Passing confirm: true skips the elicitation prompt — use this only when the caller has already obtained user approval.
  3. Refusal fallback. If the client doesn't support elicitation and confirm: true was not provided, the tool returns an isError result that names the action and instructs the caller to retry with confirm: true.

Bypass for batch / automation

OBSIDIAN_MCP_AUTO_CONFIRM=1

Set this env var (in your MCP client's env block) to skip every confirmation prompt. Use only in fully-trusted automation contexts.

Long content & argv limits

The Obsidian CLI does not (yet) support reading parameter values from stdin or from files — every value travels on the command line. That collides with platform limits:

PlatformPractical command-line limit
Windows (cmd.exe)~8,191 chars total
macOS / LinuxARG_MAX (typically 128 KB – 2 MB)

To stay safe, the server automatically chunks long writes:

ToolChunking strategy
obsidian_create_noteFirst chunk via create, remaining chunks via append.
obsidian_append_noteSequential append calls.
obsidian_prepend_noteprepend calls in reverse order so final order is preserved.
obsidian_daily_appendResolves the daily note path, then chunked append.
obsidian_evalNot chunked — JS can't be split. Returns an error suggesting the script-via-note workaround.

Splits happen at line boundaries when possible; oversized single lines fall back to UTF-8-safe character boundaries. Reassembled content is byte-identical to the original.

Configure the per-call byte threshold (defaults: 6,000 on Windows, 100,000 elsewhere):

OBSIDIAN_MCP_MAX_ARG_BYTES=4000

If a chunk in the middle of a multi-chunk write fails, the server returns isError with a clear message stating which chunks made it to disk so the caller can recover.

Develop

npm run dev      # tsc --watch
npm run inspect  # launch MCP Inspector against the built server
node scripts/smoke-test.mjs   # initialize + tools/list smoke test

How it works

runObsidian() (src/exec.ts) shell-quotes arguments, invokes the obsidian binary via child_process.exec, and parses stdout. Most read-style tools request format=json; results are parsed to structuredContent for clients that consume structured tool output, while still returning a text representation in content.

Tool registry lives in src/tools.ts — adding a new wrapped command is a single entry there.

Reference

Reviews

No reviews yet

Sign in to write a review