obsidian-cli-mcp

obsidian-cli-mcp

Gives Claude and other MCP clients full control of a running Obsidian vault through the official Obsidian CLI, with fast filesystem reads for bulk operations and link-safe writes via the app.

Category
访问服务器

README

obsidian-cli-mcp

An MCP server that gives Claude and other MCP clients full control of a running Obsidian vault through the official Obsidian CLI (Obsidian 1.12+), with fast direct filesystem reads where correctness allows it.

Companion project to things-for-mac-mcp.

What makes this different?

Most Obsidian MCP servers either talk to a community REST plugin or read the vault folder directly. The first requires installing and trusting a plugin. The second silently breaks wikilinks the moment it moves or renames a file, because only Obsidian knows about every link, alias, and embed pointing at it.

This server routes every operation by capability:

Typical filesystem-only MCPs obsidian-cli-mcp
Full-text search across thousands of notes Fast Fast (filesystem)
Move or rename a note Breaks every inbound link Link-safe (Obsidian CLI)
Backlinks, aliases, unresolved links Guesswork Obsidian's own resolver
Bases queries, template variables Impossible Runtime evaluation via the app
Writes land in Obsidian's index and file recovery No Yes
iCloud evicted files Read as empty notes Detected, read through Obsidian
Requires a community plugin Sometimes No

The architecture mirrors its sibling project exactly:

things-for-mac-mcp obsidian-cli-mcp
Fast reads SQLite direct Filesystem direct
Authoritative writes AppleScript Obsidian CLI
Convenience creates URL scheme Obsidian CLI

The rule behind the split: bulk reads go to the filesystem because they need throughput, and anything that moves, renames, deletes, or depends on link resolution or app state goes through the CLI because it needs Obsidian's knowledge. The filesystem adapter structurally cannot mutate the vault, it exports no writing function at all.

Requirements

  • macOS, Windows, or Linux desktop with Obsidian 1.12 or later
  • The Obsidian CLI enabled: Obsidian, Settings, General, Command line interface
  • Obsidian must be running. The CLI is a client to the app, not a standalone binary. This is desktop only, mobile is not supported.
  • Node.js 18 or later

Installation

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

Connect to an MCP client

Claude (Desktop / Code)

Add to claude_desktop_config.json (Claude Desktop) or run claude mcp add (Claude Code):

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

Use the absolute path to node, not the bare word. GUI-launched apps do not inherit your shell's PATH, so "command": "node" fails silently in many clients. Find yours with which node.

Set OBSIDIAN_VAULT if you have more than one vault. The CLI otherwise targets whichever vault was focused last, which is a terrible property for automated writes. With a single vault the server pins it automatically at startup.

Configuration

Variable Default Purpose
OBSIDIAN_BIN /usr/local/bin/obsidian Path to the Obsidian CLI binary
OBSIDIAN_VAULT auto-pinned if exactly one vault exists Vault name every command targets
OBSIDIAN_VAULT_PATH auto-detected via the CLI Vault folder for the filesystem adapter
OBSIDIAN_MCP_TIMEOUT 20000 Per-command timeout in ms
OBSIDIAN_MCP_ALLOW_DANGEROUS unset Set to 1 to unlock tier 3 commands
OBSIDIAN_MCP_READONLY unset Set to 1 to reject every mutating tool

Guardrails

Three tiers, enforced before the binary is ever spawned:

  • Tier 1, free: reads, searches, and additive writes (create_note, append_note, append_daily, set_property, update_task, capture).
  • Tier 2, requires confirm: true in the tool call: delete_note, move_note, rename_note, remove_property, run_obsidian_command, and through the passthrough: history:restore, publish:*, plugin:enable/disable/reload, theme:*, snippet:*, sync, sync:restore, reload, template:insert, workspace:save/delete. Any call carrying an overwrite or permanent flag is escalated to tier 2 as well.
  • Tier 3, blocked unless the server runs with OBSIDIAN_MCP_ALLOW_DANGEROUS=1: eval, restart, plugin:install, plugin:uninstall, plugins:restrict, devtools, dev:cdp, dev:debug, dev:mobile, and delete_note with permanent: true.

An honest note on what these are. Tier 2 is a speed bump against accidental calls, not security: the calling model can set confirm: true itself. Tier 3 is a real boundary, because only whoever configures the server environment can unlock it. If you point an autonomous agent at a vault you care about, run with OBSIDIAN_MCP_READONLY=1, which rejects every mutating command before dispatch regardless of tier.

Link-safe moves and renames

The single most important rule in this project: files are never moved, renamed, or deleted through the filesystem. Obsidian updates every wikilink in the vault when it performs the operation. A plain mv does not.

Before, with Projects/Roadmap.md linked from three notes:

Weekly Review.md:   Progress on [[Roadmap]] is on track.
Team Notes.md:      See [[Roadmap#Q3]] for the plan.
Index.md:           - [[Roadmap|2026 roadmap]]

After move_note with to: "Archive/2026 Roadmap.md":

Weekly Review.md:   Progress on [[2026 Roadmap]] is on track.
Team Notes.md:      See [[2026 Roadmap#Q3]] for the plan.
Index.md:           - [[2026 Roadmap|2026 roadmap]]

All three links updated, including the heading anchor and the alias, because Obsidian did the move. A filesystem move would have left three broken links and no error.

Why hybrid? The performance rationale

Every CLI invocation is one full IPC round trip through the running Obsidian app. That is correct but slow: reading 2,000 notes via obsidian read is 2,000 round trips, minutes of wall time. Reading them from disk is one directory walk, well under a second on any SSD.

So bulk reads (search, listings, tag and property scans, exports, digests) hit the filesystem, and the CLI is reserved for what only Obsidian can answer (links, aliases, Bases, templates, app state) and for every write. To compare on your own vault, time search_notes against the passthrough obsidian_cli with ["search", "query=..."].

Troubleshooting

"Obsidian is not running." The most common failure. The CLI needs the app open and fully loaded. Start Obsidian and retry.

"Could not find the Obsidian CLI binary." Enable the CLI in Obsidian under Settings, General, Command line interface, or point OBSIDIAN_BIN at the binary.

Timeouts on the first command. A cold Obsidian start can exceed the 20s default. Raise OBSIDIAN_MCP_TIMEOUT.

Notes read as missing or the server falls back to the CLI a lot. If your vault lives in iCloud with Optimize Mac Storage on, evicted files exist only as .name.icloud stubs. The server detects these and reads them through Obsidian, which re-downloads them, instead of reporting empty notes. Bulk scans skip evicted files and say so in their output.

Writes land in the wrong vault. You have multiple vaults and no OBSIDIAN_VAULT set. The server warns about this on stderr at startup. Pin one.

Tools do not appear in the client. Check the client's MCP logs, and check the absolute node path issue above.

Staying up to date

git pull && npm install && npm run build

The server checks for updates at startup, at most once per 24 hours, caching the result in ~/.config/obsidian-cli-mcp/update-check.json. It fails silently offline and prints a single stderr line when a newer version exists.

Tools (39 total)

Read tools (18)

Tool Adapter Description
read_note Filesystem, CLI fallback Read a note by wikilink-style name or exact path
search_notes Filesystem Full-text search with folder, case, context, and limit options
list_notes Filesystem List files, filtered by folder and extension
list_folders Filesystem List folders
get_note_info CLI Path, size, created and modified dates
get_outline Filesystem Heading tree with line numbers
get_backlinks CLI Inbound links, resolved by Obsidian
get_outgoing_links CLI Outbound links
get_tags Filesystem All tags with counts, frontmatter and inline
get_properties Filesystem Vault-wide frontmatter keys with counts
read_property Filesystem One frontmatter key on one note
get_vault_info CLI Vault name, path, stats
get_recents CLI Recently opened files
list_bases CLI All .base files
query_base CLI Run a Bases view query, evaluated by the app
list_templates CLI Templates in the configured folder
read_template CLI Template content, optionally with variables resolved
get_word_count Filesystem Words and characters, excluding frontmatter

Write tools (16)

All writes go through the CLI. Every one requires an explicit file or path target, none can fall through to the currently active file.

Tool Guard tier Description
create_note 1, 2 with overwrite Create a note, optionally from a template
append_note 1 Append content
prepend_note 1 Prepend content after frontmatter
read_daily 1 Read today's daily note
append_daily 1 Append to today's daily note
prepend_daily 1 Prepend to today's daily note
get_daily_path 1 Path of today's daily note
set_property 1 Set a frontmatter property
remove_property 2 Remove a frontmatter property
move_note 2 Link-safe move
rename_note 2 Link-safe rename
delete_note 2, 3 with permanent Delete to trash, or permanently
list_tasks 1 List markdown tasks with refs
update_task 1 Toggle or set task status by ref or line
open_note 1 Open in the Obsidian UI, navigation only
run_obsidian_command 2 to execute List or run command palette commands, including plugin commands

run_obsidian_command is the widest door in the server: it reaches every command palette action, including those registered by community plugins. It is exposed deliberately and gated at tier 2.

Workflow tools (4)

Tool Description
capture Timestamped append to today's daily note, the highest frequency operation in practice
daily_digest Aggregate a date range of daily notes into one document
export_notes Export a folder as JSON, Markdown, or CSV, inline or to a file outside the vault
vault_health Orphans, dead ends, unresolved links, and empty notes in one report. Deliberately scoped to the link graph

Escape hatch (1)

Tool Description
obsidian_cli Run any CLI command. Takes args as a pre-split array of strings, never a shell string, so the server spawns without a shell and content cannot break out of quoting. All guard tiers apply

MCP Resources

Client support for resources varies, Claude Desktop does not currently surface them.

Resource Content
obsidian://vault Vault info
obsidian://daily Today's daily note
obsidian://tags All tags with counts
obsidian://recents Recently opened files
obsidian://orphans Notes with no inbound links
obsidian://note/{path} Any note by vault-relative path

MCP Prompts

Prompt Purpose
daily_note_review Summarize a daily note, surface open tasks, suggest follow-ups
vault_cleanup Walk the vault health report and propose link-safe fixes
note_from_source Turn pasted material into a note using an existing template
weekly_digest Summarize a week of daily notes into a digest note

Architecture

src/
├── index.ts              MCP server entry, stdio transport
├── config.ts             Environment configuration
├── adapters/
│   ├── cli.ts            execFile wrapper, vault injection, error contract
│   └── filesystem.ts     Read-only vault access, iCloud stub detection
├── tools/
│   ├── common.ts         Shared note loading with CLI fallback
│   ├── read.ts           18 read tools
│   ├── write.ts          16 write tools
│   ├── workflow.ts       4 composite tools
│   └── passthrough.ts    obsidian_cli escape hatch
├── resources/
│   └── vault.ts          MCP resources
├── prompts/
│   └── workflows.ts      MCP prompts
└── utils/
    ├── guardrails.ts     Tier policy, readonly allowlist
    ├── markdown.ts       Frontmatter, headings, tags, word counts
    ├── output.ts         Truncation at 60,000 characters
    └── update-check.ts   Daily update check

Tests run against a stub binary that scans its full argv and can be told to fail, hang, or emit oversized output, so the whole suite passes with no Obsidian installed:

npm test

Support

Issues and feature requests: GitHub issues.

More from the author

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选