obsidian-vault-mcp

obsidian-vault-mcp

An MCP server for Obsidian vaults that handles iCloud eviction gracefully, allowing reading, searching, creating, and updating notes without hanging.

Category
Visit Server

README

<p align="center"> <img src="./assets/header.svg" alt="obsidian-icloud-mcp — an Obsidian MCP that survives iCloud eviction" width="100%"> </p>

<p align="center"> <a href="https://github.com/QEbellavita/obsidian-icloud-mcp/actions/workflows/test.yml"><img src="https://github.com/QEbellavita/obsidian-icloud-mcp/actions/workflows/test.yml/badge.svg" alt="tests"></a> <a href="https://doi.org/10.5281/zenodo.21485168"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.21485168.svg" alt="DOI"></a> </p>

An MCP server for Obsidian vaults that doesn't hang on iCloud.

Read, search, create and update notes from your assistant — and see exactly how much of the vault iCloud has actually left on disk. Seven tools, no daemon, no index to rebuild.

Why another one

Because the obvious implementation breaks on iCloud Drive, and breaks in the worst possible way: it hangs forever.

If your vault lives in iCloud with Optimize Mac Storage on, macOS evicts note bodies and leaves dataless placeholders behind. They look like ordinary files — stat reports a real size — but the first read() blocks while macOS fetches the content over the network. On an evicted vault, a naive search hits hundreds of those in a row and never returns. No error, no timeout, just a search that never finishes.

A deadline alone doesn't fix it: a single blocking read never yields control back, so the between-files clock check is never reached. The only reliable signal is stat's block count — a dataless placeholder reports blocks == 0 despite a non-zero size.

This server checks that before every read, and bounds total search time on top. Evicted notes are skipped and reported, not waited on:

{
  "matches": [ ... ],
  "scanned": 112,
  "total": 486,
  "unavailable": 43,
  "incomplete": true,
  "note": "Searched 112/486 notes; 43 are not downloaded from iCloud yet and were skipped. Results may be incomplete."
}

incomplete: true means "there may be more" — rather than silently returning partial results as if they were the whole answer. The counts distinguish the two reasons: notes that weren't materialised (unavailable) versus hitting the time budget.

Reading one specific evicted note fails honestly with "not downloaded from iCloud" instead of blocking.

<p align="center"><img src="./assets/demo.gif" alt="Animated demo — a search reports 5 of 8 notes scanned with 3 iCloud-evicted notes skipped and flagged, then vault_health shows materialized vs evicted counts and points at obsidian_warm_notes" width="90%"></p>

Install

Point your MCP client at it:

{
  "mcpServers": {
    "obsidian": {
      "command": "npx",
      "args": ["-y", "obsidian-icloud-mcp"],
      "env": {
        "OBSIDIAN_VAULTS": "{\"Personal\":\"/Users/you/Documents/Notes\"}"
      }
    }
  }
}

Or from source: git clone https://github.com/QEbellavita/obsidian-icloud-mcp and point command: node, args: [/absolute/path/to/obsidian-icloud-mcp/server.js] at the checkout.

Formerly named obsidian-vault-mcp; renamed because that npm name belongs to an unrelated project by another author — npx obsidian-vault-mcp is not this server. The old GitHub URL redirects here.

OBSIDIAN_VAULTS is a JSON object of name → absolute path. Multiple vaults are fine:

"OBSIDIAN_VAULTS": "{\"Personal\":\"/Users/you/Notes\",\"Work\":\"/Users/you/Work/vault\"}"

With no vaults configured the server starts and advertises zero tools, rather than crashing in a way your host reports as a broken server.

Tools

Tool
obsidian_list_notes List Markdown notes, optionally under a subdirectory
obsidian_search_notes Full-text search with path, line number and excerpt
obsidian_read_note Read one note
obsidian_create_note Create a note; refuses to overwrite
obsidian_update_note Atomic overwrite of an existing note
obsidian_vault_health Materialized vs evicted counts, bytes pending, largest evicted notes — stat-only, never blocks
obsidian_warm_notes Opt-in background downloads for evicted notes, bounded per call

Safety

The vault boundary is enforced, not assumed:

  • Paths must be relative and stay inside the configured vault — ../ is rejected
  • Symlinks that resolve outside the vault are rejected, not followed
  • Only .md files are read or written
  • create refuses to clobber; update refuses to create
  • Writes are atomic (temp file + rename), so an interrupted write can't truncate a note

Directory walking skips anything that can't hold notes — .git, node_modules, .obsidian — which also stops a vault that happens to be a source checkout from taking minutes to list. And it never descends into a stalling bundle directory, where even readdir can block indefinitely on iCloud.

Tests

npm test

23 tests. Nineteen cover the service directly — including every iCloud failure mode above, driven through an injected fs so eviction is simulated deterministically rather than depending on your actual sync state. Four drive the real server over a real stdio transport.

Citing

If this server is useful in your workflow, cite it via the repo's CITATION.cff (GitHub's "Cite this repository" button), or the Zenodo DOI, 10.5281/zenodo.21485168 — a concept DOI that always resolves to the latest archived version.

Licence

MIT — see LICENSE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured