Skip to main content
Glama
JonHollander

Obsidian Vault MCP Server

by JonHollander

Obsidian + Claude via Cloudflare

Access your Obsidian vault from Claude (web, desktop, Code) using an MCP server on Cloudflare Workers + Containers.

No NAS, no Docker Compose, no tunnels. Just Cloudflare infrastructure with the Agents SDK for a proper MCP server.

Architecture

Obsidian (phone, desktop)
        │
        │ Obsidian Sync (your existing subscription)
        ▼
Cloudflare Container (Node.js 22)
   runs `ob sync --continuous`
   serves vault files over HTTP API
        ▲
        │ container fetch (native)
        │
Cloudflare Worker (MCP server via Agents SDK)
   tools: list, read, search, write, append, delete
   auth via bearer token (or OAuth / Cloudflare Access)
        ▲
        │ MCP over Streamable HTTP
        │
Claude (web, desktop, Code)

The Container is the single source of truth. It runs obsidian-headless to sync with Obsidian Sync and exposes an HTTP API for file operations. The Worker proxies all MCP tool calls to the Container's API.

MCP Tools

Tool

Description

list_notes

List all markdown notes with paths, sizes, and dates

read_note

Read the full content of a note by path

search_notes

Full-text search across all notes with snippets

write_note

Create or overwrite a note

append_to_note

Append to an existing note (or create it)

delete_note

Delete a note

create_folder

Create a folder (with intermediate directories)

delete_folder

Delete a folder (empty or recursive)

list_folders

List immediate subfolders at a path

Prerequisites

  • Cloudflare account with Workers Paid plan ($5/month)

  • Active Obsidian Sync subscription

  • Node.js 22+ on your workstation

  • wrangler CLI: npm install -g wrangler

Setup

0. Wrangler Login

wrangler login

All required scopes are granted by default.

1. Generate Obsidian Auth Token

One-time step on your workstation:

npm install -g obsidian-headless

ob login
# Enter email, password, MFA code if enabled

ob sync-list-remote
# Note your vault name

2. Configure Environment

Copy the example env file and fill in your values:

cp .dev.vars.example .dev.vars

Edit .dev.vars with your Obsidian credentials and optional MCP auth token. This file is used by wrangler dev for local development and by the setup script to push secrets to Cloudflare. It's already in .gitignore.

3. Deploy

Run the setup script to push all secrets and deploy:

./scripts/setup.sh

Or run steps individually:

./scripts/setup.sh secrets         # Push secrets to Cloudflare
./scripts/setup.sh validate        # Check prerequisites
./scripts/setup.sh deploy          # Validate + install deps + deploy + restart container
./scripts/setup.sh status          # Check sync container health
./scripts/setup.sh restart         # Restart sync container
./scripts/setup.sh container-logs  # View sync container logs

Your MCP server is live at: https://obsidian-mcp.<your-subdomain>.workers.dev/mcp

4. Connect Claude

Claude.ai (web)

Settings → Connectors → Add custom connector:

  • URL: https://obsidian-mcp.<your-subdomain>.workers.dev/mcp?token=YOUR_MCP_AUTH_TOKEN

  • Leave OAuth fields blank — the token in the URL handles auth

Claude Code

claude mcp add \
  --transport http \
  --scope user \
  obsidian-vault \
  https://obsidian-mcp.<your-subdomain>.workers.dev/mcp

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "obsidian-vault": {
      "url": "https://obsidian-mcp.<your-subdomain>.workers.dev/mcp"
    }
  }
}

How Data Flows

You edit a note on your phone:

  1. Obsidian Sync pushes the change

  2. Container's ob sync --continuous pulls it to /vault

  3. Next time Claude reads or searches, the Worker proxies the request to the Container's HTTP API which reads directly from /vault

Claude creates a note:

  1. Worker receives MCP write_note call

  2. Worker proxies it to the Container's HTTP API

  3. Container writes the file to /vault

  4. ob sync detects the new file and pushes it via Obsidian Sync

  5. It appears on your phone and desktop

Development

# Local dev (MCP server only, no container)
npm run dev

# Deploy
npm run deploy

Cost

Service

Usage

Cost

Workers Paid Plan

Already paying

$5/month (covers everything)

Container

1 instance, mostly idle

Included in Workers plan

Total additional

$0

Project Structure

obsidian-mcp/
├── src/
│   └── index.ts              # MCP server (Agents SDK, proxies to container)
├── sync-container/
│   ├── Dockerfile            # Headless sync container image
│   ├── entrypoint.sh         # Auth, sync startup
│   └── server.js             # HTTP API for vault file operations
├── scripts/
│   └── setup.sh              # Push secrets, deploy
├── .dev.vars.example         # Template for env vars / secrets
├── wrangler.jsonc            # Worker + Container config
└── package.json

Next Steps

These are left as exercises to harden the setup for your needs:

Auth Hardening

The included auth (MCP_AUTH_TOKEN secret) supports both Authorization: Bearer headers and ?token= query params. The URL token approach is convenient for Claude.ai connectors where custom headers aren't always available.

For shared or public deployments, consider stronger options:

Container Auth

Check whether obsidian-headless supports --token or env-var-based auth for ob login to avoid interactive prompts. If not, persist the auth session from a one-time interactive login and restore it on container start.

Container Restart Resilience

The ob sqlite state file lives on ephemeral container disk. A restart triggers a full re-sync. To fix: add a SIGTERM trap in entrypoint.sh that persists the state file, and restore it on startup.

Search Performance

The brute-force search reads every .md file per query — fine for <500 files. For larger vaults, build a search index in D1 or Workers KV.

Attachments

Currently filters to .md only. Extend to support images, PDFs, and other vault attachments with additional tools.

Troubleshooting

Docker must be running — The sync container requires Docker. Run docker info to verify. The validate subcommand checks this automatically.

Two passwordsOBSIDIAN_PASSWORD is your Obsidian account password (used to log in at obsidian.md). VAULT_PASSWORD is the separate end-to-end encryption password set in Obsidian → Sync → Encryption. Leave VAULT_PASSWORD empty if your vault doesn't use E2EE.

Deploy doesn't restart containerswrangler deploy does not restart running containers. The setup script handles this automatically. If deploying manually, restart with ./scripts/setup.sh restart.

Container logs not in wrangler tail — Container stdout is not streamed through wrangler tail. Use ./scripts/setup.sh container-logs instead.

Component Reference

Component

What it does

obsidian-headless

Official Obsidian CLI, syncs vault headlessly

McpAgent (Agents SDK)

Handles MCP transport, sessions, auth

McpServer (MCP SDK)

Tool registration, JSON-RPC protocol

Cloudflare Containers

Runs the sync process alongside the Worker

A
license - permissive license
-
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JonHollander/obsidian-mcp-cloudflare'

If you have feedback or need assistance with the MCP directory API, please join our Discord server