Skip to main content
Glama
obsidian-cli-mcp

obsidian-cli-mcp

by digster

obsidian-cli-mcp

An MCP server that wraps the official Obsidian CLI (obsidian, bundled with the Obsidian desktop app) instead of the Local REST API plugin. Each server instance is pinned to a single vault, so you run one entry per vault.

Why the CLI instead of the REST API?

The REST-API MCP (mcp-obsidian) needs the Local REST API community plugin, an API key, and a dedicated port per vault. This server drives the Obsidian app through its built-in CLI, which needs no plugin and no API key, and exposes a much richer surface: tasks, frontmatter properties, backlinks, search-with-context, vault metadata, and more.

Requirement: the Obsidian desktop app must be running with the target vault open. The CLI talks to the live app, not the files on disk.

Related MCP server: obsidian-mcp

Install

The server is a uv project. No global install is needed — MCP clients launch it on demand with uv run.

git clone <this repo> && cd obsidian-cli-mcp
uv sync          # install dependencies
uv run pytest    # run the test suite (no live Obsidian needed)

Configure (per vault)

Add one entry per vault to your MCP client config (e.g. Claude Desktop's claude_desktop_config.json). The vault is selected with the OBSIDIAN_VAULT environment variable — run obsidian vaults to see the exact names.

{
  "mcpServers": {
    "obsidian-cli-void": {
      "command": "uv",
      "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/obsidian-cli-mcp", "obsidian-cli-mcp"],
      "env": { "OBSIDIAN_VAULT": "void" }
    },
    "obsidian-cli-notebook": {
      "command": "uv",
      "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/obsidian-cli-mcp", "obsidian-cli-mcp"],
      "env": { "OBSIDIAN_VAULT": "notebook" }
    }
  }
}

Environment variables

Variable

Required

Default

Purpose

OBSIDIAN_VAULT

yes

—

Vault name this instance targets (injected as vault= on every call).

OBSIDIAN_CLI_PATH

no

obsidian

Path to the CLI binary if it isn't on PATH.

OBSIDIAN_VERIFY_READS

no

true

Run the vault guard before reads too (not just writes).

OBSIDIAN_ALLOW_PERMANENT_DELETE

no

false

Allow delete_note(permanent=True) to bypass trash.

OBSIDIAN_TIMEOUT

no

30

Per-command subprocess timeout (seconds).

OBSIDIAN_GUARD_TTL

no

5

Seconds to cache a successful vault-guard check.

OBSIDIAN_LOG_LEVEL

no

INFO

Log level (logs go to stderr).

Tools

Read / navigate: read_note, search_vault, list_files, list_folders, note_info, list_backlinks, list_tags, list_tasks, list_properties, read_property, vault_info, list_vaults

Write / organise: create_note, add_to_note, set_property, remove_property, move_note, rename_note, delete_note, update_task

Escape hatch: run_obsidian — run any other CLI command (e.g. bookmarks, wordcount, history). Disruptive commands (restart, reload, eval, devtools, plugins:restrict, and all dev:*) are blocked.

Notes are addressed by file (resolve by name, like a wikilink) or path (exact folder/note.md). Most read tools fall back to the active note when both are omitted; write tools require an explicit target.

Safety: the vault guard

The Obsidian CLI silently falls back to the active vault when vault=<name> names a vault that isn't currently open. To prevent acting on the wrong vault, this server verifies — via vault info=name — that the configured vault is the one actually responding before every write (and before reads, by default). If it isn't, the tool fails with a clear message instead of touching another vault.

This also means the CLI reports failures on stdout with exit code 0; the server detects them by inspecting the output, so genuine errors surface as MCP tool errors rather than being mistaken for success.

License

MIT © digster

Available Tools

21 tools
add_to_noteA

Append or prepend content to an existing note.

position is "append" (default) or "prepend". inline=True adds the content without a leading/trailing newline.

Inputs: content (required), file, path, position, +1 more. Returns: result

create_noteA

Create a new note.

Use name for a simple title or path for an exact location. Optionally seed content or apply a template. Set overwrite=True to replace an existing note (otherwise creation fails if it exists).

Inputs: name, path, content, template, +1 more. Returns: result

delete_noteA

Delete a note (moves it to trash by default — recoverable).

permanent=True bypasses trash and is only allowed when the server is configured with OBSIDIAN_ALLOW_PERMANENT_DELETE=true.

Inputs: file, path, permanent. Returns: result

list_filesC

List files in the vault, optionally filtered by folder and/or ext.

Inputs: folder, ext. Returns: result

list_foldersA

List folders in the vault, optionally under a parent folder.

Inputs: folder. Returns: result

list_propertiesB

List frontmatter properties for the vault or a specific note (JSON).

Inputs: file, path. Returns: result

list_tagsC

List tags in the vault, or for a specific note (JSON). counts=True adds counts.

Inputs: file, path, counts. Returns: result

list_tasksB

List tasks across the vault or a note (JSON).

Filter with todo=True (incomplete), done=True (completed), or a specific status character (e.g. "/" for in-progress).

Inputs: file, path, todo, done, +1 more. Returns: result

list_vaultsA

List all Obsidian vaults known to this machine, with their paths.

Useful for discovering the exact vault name to put in OBSIDIAN_VAULT. This is a machine-level query, so it is not scoped to the configured vault.

Inputs: no named parameters. Returns: result

move_noteC

Move a note to a destination folder or path (to).

Inputs: to (required), file, path. Returns: result

note_infoB

Show metadata for a note (size, dates, counts). Defaults to the active note.

Inputs: file, path. Returns: result

read_noteA

Read a note's full Markdown contents.

Specify the note by file (name) or path (exact). If both are omitted, the currently active note in Obsidian is used.

Inputs: file, path. Returns: result

read_propertyB

Read a single frontmatter property name from a note.

Inputs: name (required), file, path. Returns: result

remove_propertyC

Remove a frontmatter property name from a note.

Inputs: name (required), file, path. Returns: result

rename_noteB

Rename a note to a new name (keeping it in the same folder).

Inputs: name (required), file, path. Returns: result

run_obsidianA

Run any Obsidian CLI command not covered by a dedicated tool (power users).

Pass the command name (e.g. "bookmarks", "wordcount", "history") and a params mapping of CLI options. Boolean flags should be passed as true (e.g. {"total": true}); value options as strings (e.g. {"format": "json"}). Set json=True to parse the output as JSON. The configured vault is injected automatically and the vault guard still applies.

Disruptive commands (restart, reload, eval, devtools, plugins:restrict) and all dev:* commands are rejected.

Inputs: command (required), params, json.

search_vaultA

Search the vault for text and return matching files (JSON).

Set context=True to also get the matching lines around each hit, path to limit to a folder, limit to cap results, and case=True for case-sensitive matching.

Inputs: query (required), path, limit, context, +1 more. Returns: result

set_propertyC

Set a frontmatter property name=value on a note.

type may be one of text, list, number, checkbox, date, datetime.

Inputs: name (required), value (required), type, file, +1 more. Returns: result

update_taskA

Update a task's status.

Identify the task by ref ("path:line") or by file/path + line. action is "toggle", "done", or "todo". Alternatively pass a status character to set it directly (e.g. "/" for in-progress).

Inputs: action, ref, file, path, +2 more. Returns: result

vault_infoA

Show info about the configured vault (name, path, file/folder counts, size).

Inputs: no named parameters. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 21 tools

    Disambiguation5/5

    Each tool targets a distinct action and resource. The list_* family (files, folders, tags, etc.) has clear boundaries, and CRUD operations are separate. No two tools could be easily confused.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun or list_noun pattern (e.g., create_note, list_tags). The few exceptions like note_info and vault_info are clearly compound nouns and do not break the pattern.

    Tool Count4/5

    21 tools is slightly above the typical 3-15 range, but each tool addresses a specific need. The list_* tools could be simplified, but the count is still reasonable for a comprehensive Obsidian CLI interface.

    Completeness4/5

    The tool set covers most common operations: CRUD on notes, properties, tasks, search, and vault management. The run_obsidian fallback fills gaps. Missing a dedicated 'replace note content' tool is a minor gap that can be worked around.

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      C
      quality
      D
      maintenance
      Provides LLM agents with comprehensive access to Obsidian vaults via the official Obsidian CLI bridge. It enables users to read, search, and modify notes, tasks, properties, and plugins while the Obsidian desktop app is running.
      54
      16
      -
    • A
      license
      B
      quality
      D
      maintenance
      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.
      34
      2
      MIT