About Obsidian Web MCP
Obsidian Web MCP is an MCP server in the Cloud category: secure remote MCP server for Obsidian vaults -- access your notes from Claude, your phone, or any MCP client, anywhere. OAuth 2.0 auth, Cloudflare Tunnel, atomic writes safe for Obsidian Sync.
Install
git clone https://github.com/jimprosser/obsidian-web-mcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (20)
vault_analytics_findingsDetailed findings for one analytics category (`frontmatter_missing`, `required_frontmatter_missing`, `broken_wikilinks`, `suspicious_tag_variants`, `encoding_issues`, `oversized_files`)
Parameters not published.
vault_analytics_summaryCompact vault-hygiene summary: counts and examples of missing frontmatter, broken wikilinks, near-duplicate tag variants, and non-UTF-8 files
Parameters not published.
vault_appendAppend content to the end of a file without resending the existing body; creates the file when missing
Parameters not published.
vault_batch_frontmatter_updateUpdate YAML frontmatter fields on multiple files without touching body content
Parameters not published.
vault_batch_readRead multiple files in one call; handles missing files gracefully
Parameters not published.
vault_canvas_add_edgeAppend an edge to an existing `.canvas` file; both endpoints must reference existing node ids
Parameters not published.
vault_canvas_add_nodeAppend a node to a `.canvas` file (created if missing); generates an id when omitted and preserves unknown node fields
Parameters not published.
vault_canvas_readRead an Obsidian `.canvas` file and return its parsed nodes and edges
Parameters not published.
vault_daily_note_appendAppend to today's daily note, creating it from the template when missing
Parameters not published.
vault_daily_note_pathResolve today's daily-note path from the configured folder/format
Parameters not published.
Show all 20 tools
vault_daily_note_readRead today's daily note; returns an error (does not create it) when missing
Parameters not published.
vault_deleteSoft-delete a file by moving it to `.trash/` (requires explicit confirmation)
Parameters not published.
vault_editPatch a file with ordered exact text replacements (token-efficient partial edits); supports dry-run diff previews
Parameters not published.
vault_listList directory contents with recursion depth, glob filtering, and file/dir toggles
Parameters not published.
vault_moveMove or rename a file or directory within the vault
Parameters not published.
vault_readRead a file, returning content, metadata, and parsed YAML frontmatter
Parameters not published.
vault_searchFull-text search across vault files (uses ripgrep if available, falls back to Python)
Parameters not published.
vault_search_frontmatterQuery the in-memory frontmatter index by field value, substring, or field existence
Parameters not published.
vault_writeWrite a file with optional frontmatter merging; creates parent dirs
Parameters not published.
vault_write_binaryWrite an allowed binary file (image/PDF) to the vault from base64 content; enforces a media-type allowlist (declared type/extension, not byte-sniffed) and size cap, writes atomically
Parameters not published.
Ask AI
Ask AI about Obsidian Web MCP
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
obsidian-web-mcp
A secure, remote-accessible MCP server that gives LLMs read/write access to your Obsidian vault from anywhere -- your desktop, your phone, a hotel Wi-Fi network. Unlike local-only Obsidian MCP servers, this one runs over HTTPS with real authentication, so Claude (or any MCP client) can reach your vault whether you're at your desk or not.
It reads and writes markdown files on disk, parses YAML frontmatter, maintains an in-memory frontmatter index for fast queries, and handles full-text search -- all behind OAuth 2.0 authentication and a Cloudflare Tunnel that never exposes your machine directly to the internet.
Why This Exists
There are many Obsidian MCP servers. Most are local stdio servers -- they work when Claude Code is running on the same machine as your vault. That's useful, but it means:
- Claude.ai (web) can't reach your vault. The browser-based Claude has no way to connect to a local stdio server.
- Claude on your phone can't reach your vault. Same problem.
- If you use Obsidian Sync, local MCP servers can corrupt files. Non-atomic writes create partial files that Sync propagates to every device.
This server solves all three. It runs as a persistent HTTP service on the machine where your vault lives, tunneled securely through Cloudflare, and authenticates via OAuth 2.0 -- the same protocol Claude uses for Gmail, Google Calendar, and other integrations. The result: your vault becomes a first-class MCP connector available everywhere Claude is.
Architecture
+----------+ +------------+ +-----------------+ +------------------+
| Obsidian | <-> | Filesystem | <-> | obsidian-web-mcp| <-> | Cloudflare |
| (app) | | (*.md) | | (MCP over HTTPS)| | Tunnel |
+----------+ +------------+ +-----------------+ +------------------+
|
+------+-------+
| Claude |
| (web/desktop/|
| mobile) |
+--------------+
Your vault files never leave your machine. Cloudflare Tunnel creates an outbound-only connection from your server to Cloudflare's edge -- no inbound ports opened, no public IP exposed, no port forwarding. Claude connects to the Cloudflare edge, which relays requests through the tunnel to your server.
Obsidian and the MCP server both operate on the same directory of markdown files. The server uses atomic writes (write-to-temp-then-rename) so Obsidian Sync and the server never conflict.
Security Model
This is a server that provides network access to your personal notes. Security is not optional.
Authentication is enforced on every request. The server implements OAuth 2.0 authorization code flow with PKCE for initial client authentication (what Claude uses when you connect the integration), plus bearer token validation on every subsequent MCP tool call. No request reaches a tool function without a valid token.
Your vault is never exposed directly to the internet. The recommended deployment uses a Cloudflare Tunnel -- an outbound-only encrypted connection. Your machine opens no inbound ports. You can layer Cloudflare Access on top for additional authentication (SSO, device posture checks, IP restrictions) if you want defense in depth.
Path traversal is blocked at the filesystem layer. Every file operation resolves paths against the vault root directory and rejects any attempt to escape it -- .. traversal, symlink following, null byte injection, and dotfile access (.obsidian, .git, .trash) are all caught before they reach the filesystem. The server will never read or write outside your vault directory.
Writes are atomic. Every file write goes to a temporary file first, then atomically replaces the target via os.replace(). This guarantees that neither Obsidian nor Obsidian Sync ever sees a partially-written file -- the operation either completes fully or doesn't happen at all.
Safety limits prevent abuse. Writes are capped at 1MB per file, batch operations at 20 files per request, and search results at 50 matches. Deletions are soft -- files move to .trash/ rather than being permanently removed, matching Obsidian's own behavior. The delete tool also requires an explicit confirm=true parameter as a safety gate.
Tools
| Tool | Description |
|---|---|
vault_read |
Read a file, returning content, metadata, and parsed YAML frontmatter |
vault_batch_read |
Read multiple files in one call; handles missing files gracefully |
vault_write |
Write a file with optional frontmatter merging; creates parent dirs |
vault_batch_frontmatter_update |
Update YAML frontmatter fields on multiple files without touching body content |
vault_search |
Full-text search across vault files (uses ripgrep if available, falls back to Python) |
vault_search_frontmatter |
Query the in-memory frontmatter index by field value, substring, or field existence |
vault_list |
List directory contents with recursion depth, glob filtering, and file/dir toggles |
vault_move |
Move or rename a file or directory within the vault |
vault_delete |
Soft-delete a file by moving it to .trash/ (requires explicit confirmation) |
Prerequisites
- Python 3.12+
- uv (recommended) or pip
- An Obsidian vault (any directory of markdown files)
- cloudflared (only needed for remote access)
- A domain managed by Cloudflare (only needed for remote access)
Quick Start
Local development
# Clone and enter the project
git clone https://github.com/yourname/obsidian-web-mcp.git
cd obsidian-web-mcp
# Generate auth tokens
export VAULT_MCP_TOKEN=$(python -c "import secrets; print(secrets.token_hex(32))")
export VAULT_OAUTH_CLIENT_SECRET=$(python -c "import secrets; print(secrets.token_hex(32))")
# Point at your vault
export VAULT_PATH="$HOME/Obsidian/MyVault"
# Run the server
uv run vault-mcp
The server starts on port 8420 by default. It serves MCP over Streamable HTTP at /mcp/.
Configuration
All configuration is via environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
VAULT_PATH |
Yes | ~/Obsidian/MyVault |
Absolute path to your Obsidian vault directory |
VAULT_MCP_TOKEN |
Yes | (none) | 256-bit bearer token for authenticating MCP requests |
VAULT_MCP_PORT |
No | 8420 |
Port the HTTP server listens on |
VAULT_OAUTH_CLIENT_ID |
No | vault-mcp-client |
OAuth 2.0 client ID for Claude integration |
VAULT_OAUTH_CLIENT_SECRET |
Yes | (none) | OAuth 2.0 client secret for Claude integration |
Generate tokens with: python -c "import secrets; print(secrets.token_hex(32))"
Connecting to Claude
The Claude desktop and mobile apps can connect to remote MCP servers via OAuth.
- Start the server (locally or behind a tunnel)
- Open Claude and go to Settings > Integrations > Add Integration
- Enter your server URL (e.g.
https://vault-mcp.yourdomain.com) - Enter the OAuth client ID and client secret you configured
- Claude will discover the OAuth endpoints automatically and open a browser window
- The server auto-approves the authorization (single-user model) and redirects back
- Claude now has access to all nine vault tools -- on desktop and mobile
For local-only use (no tunnel), point Claude at http://localhost:8420.
Remote Access with Cloudflare Tunnel
To make the server accessible from anywhere:
# Install cloudflared
brew install cloudflare/cloudflare/cloudflared
# Set your desired hostname and run the interactive setup
export VAULT_MCP_HOSTNAME="vault-mcp.yourdomain.com"
./scripts/setup-tunnel.sh
The script authenticates with Cloudflare, creates a tunnel, writes the config, and sets up the DNS record. You will need a domain managed by Cloudflare.
After setup, add your tunnel hostname to the allowed_hosts list in server.py so the MCP library's DNS rebinding protection accepts requests from your domain:
allowed_hosts=[
"127.0.0.1:*",
"localhost:*",
"[::1]:*",
"vault-mcp.yourdomain.com", # add your hostname here
],
Production Deployment (macOS)
For always-on operation, use launchd to run both the MCP server and the Cloudflare Tunnel as persistent background services that start at login and restart on failure.
1. Edit the plist templates
cp scripts/launchd/com.example.vault-mcp.plist ~/Library/LaunchAgents/
cp scripts/launchd/com.example.cloudflared-vault.plist ~/Library/LaunchAgents/
Open each plist and replace the placeholder tokens:
REPLACE_WITH_UV_PATH-- path touvbinary (runwhich uv)REPLACE_WITH_PROJECT_PATH-- absolute path to this project directoryREPLACE_WITH_VAULT_PATH-- absolute path to your Obsidian vaultREPLACE_WITH_TOKEN-- yourVAULT_MCP_TOKENvalueREPLACE_WITH_OAUTH_SECRET-- yourVAULT_OAUTH_CLIENT_SECRETvalueREPLACE_WITH_HOME-- your home directory (e.g./Users/yourname)REPLACE_WITH_CLOUDFLARED_PATH-- path tocloudflaredbinary (runwhich cloudflared)
2. Load the services
launchctl load ~/Library/LaunchAgents/com.example.vault-mcp.plist
launchctl load ~/Library/LaunchAgents/com.example.cloudflared-vault.plist
Both services are configured with RunAtLoad (start at login) and KeepAlive (restart on failure). They will survive reboots.
3. Verify
# Check both services are running
launchctl list | grep vault
# Test the server responds
curl -s http://localhost:8420/.well-known/oauth-authorization-server
# Check logs
tail -f ~/Library/Logs/vault-mcp-error.log
Obsidian Sync Compatibility
The server coexists with Obsidian Sync (or any file-based sync mechanism) without conflict. All writes use atomic file replacement (write-to-temp-then-rename), which means:
- Obsidian never sees a half-written file
- If Sync and the MCP server write to the same file simultaneously, the last write wins (standard filesystem semantics) but neither write is corrupted
- The frontmatter index watches for filesystem changes via
watchdogand updates automatically when Sync brings in new files
Development
Running tests
uv run pytest tests/ -v
Tests use temporary directories and never touch your real vault.
Project structure
src/obsidian_vault_mcp/
auth.py # Bearer token middleware (Starlette)
config.py # Environment variable configuration
frontmatter_index.py # In-memory YAML frontmatter index with filesystem watcher
models.py # Pydantic input validation models
oauth.py # OAuth 2.0 authorization code flow with PKCE
server.py # FastMCP server setup, tool registration, entry point
vault.py # Core filesystem operations (path security, atomic writes)
tools/
manage.py # list, move, delete tools
read.py # read, batch_read tools
search.py # full-text search, frontmatter search tools
write.py # write, batch_frontmatter_update tools
tests/
conftest.py # Shared fixtures (temp vault with sample files)
test_frontmatter.py # Frontmatter index and query tests
test_tools.py # Integration tests for tool functions
test_vault.py # Path resolution and file operation tests
scripts/
setup-tunnel.sh # Interactive Cloudflare Tunnel setup
launchd/ # macOS launchd plist templates
License
MIT -- see LICENSE.
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.