CCM
/MCP
SkillsMCPMarketplacesDigestToolsAdvertise

This week in Claude

Every Monday: Claude Code, Agent SDK, MCP, and the Anthropic platform moves worth your time.

Skills by Category
Frontend DevelopmentBackend & APIsTesting & QASecurityDevOps & CI/CDGit & Pull RequestsDocumentationCode Review & QualityAI & Agent BuildingSkill Development
MCP Servers by Category
Sales & MarketingWeb & Browser AutomationDatabasesAI & LLM ToolsCloud & InfrastructureCommunication & MessagingDeveloper ToolsDesign & CreativeDocuments & KnowledgeSearch & Web Crawling
Marketplaces by Category
AI Agents & OrchestrationLLM IntegrationDevelopment ToolsFrontend & UIBackend & APIsDatabasesTesting & Code QualityDevOps & CloudSecurity & ComplianceGit & Version Control

Claude Code Marketplaces

Discover Claude Code plugins, extensions, and tools. Automatically updated directory of Anthropic Claude AI marketplaces with development tools, productivity plugins, and integrations.

Resources

  • Browse Skills
  • Browse MCP Servers
  • Browse Marketplaces
  • Skill index
  • MCP index
  • Marketplace index
  • Plugins Reference

Community

  • About
  • Tools
  • Feedback
  • Privacy Policy
  • Advertise

Built for the Claude Code community with Claude Code by mertbuilds.com

Independent project, not affiliated with Anthropic
aliasunder avatar

Vault Cortex

aliasunder/vault-cortex
1authHTTPregistry active
Summary

Connects Claude to your Obsidian vault without running Obsidian itself or installing plugins. Ships as a Docker container that reads and writes markdown files directly, with SQLite FTS5 for BM25-ranked search across 23 tools. You get CRUD operations, backlink queries, frontmatter manipulation, and a structured memory layer that appends dated entries to designated notes. Works locally against a folder or remotely via OAuth with Obsidian Sync keeping the vault current. Useful when you want your AI assistant to treat your personal knowledge base as working memory, or when you're building workflows that need programmatic access to wikilinks, tags, and daily notes without spinning up the full Obsidian app.

CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Lid closed, agents working
Lid closed, agents working
Keeps your Mac awake while Claude Code, Codex or Cursor works. Lets it sleep when they are done.
Try free for 7 days →
Block distraction from your iPhone for freeBlock distraction from your iPhone for free
Block distraction from your iPhone for free
Block distracting apps from your iPhone permanently without a 3rd party app. Free and open source.
Block now (100% free) →
Granola, the best AI meeting recorder
Granola, the best AI meeting recorder
Notes, actions and memory. Without a meeting bot. First month 100% off.
Download for free →
belt - the only tool your agent needs
belt - the only tool your agent needs
belt cli automatically finds the best tools and skills for your agent. image, video, music, tts...
one prompt install →
Open Steps
Open Steps
Free an open-source skills that make AI coding agents easier to understand, verify, and control.
Download for free →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
Agent, connect blockchain
Agent, connect blockchain
Connect your Claude agent to live crypto prices and trading routes via 1inch
Get the MCP →
CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Lid closed, agents working
Lid closed, agents working
Keeps your Mac awake while Claude Code, Codex or Cursor works. Lets it sleep when they are done.
Try free for 7 days →
Block distraction from your iPhone for freeBlock distraction from your iPhone for free
Block distraction from your iPhone for free
Block distracting apps from your iPhone permanently without a 3rd party app. Free and open source.
Block now (100% free) →
Granola, the best AI meeting recorder
Granola, the best AI meeting recorder
Notes, actions and memory. Without a meeting bot. First month 100% off.
Download for free →
belt - the only tool your agent needs
belt - the only tool your agent needs
belt cli automatically finds the best tools and skills for your agent. image, video, music, tts...
one prompt install →
Open Steps
Open Steps
Free an open-source skills that make AI coding agents easier to understand, verify, and control.
Download for free →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
Agent, connect blockchain
Agent, connect blockchain
Connect your Claude agent to live crypto prices and trading routes via 1inch
Get the MCP →

Vault Cortex

CI Gitleaks Trivy GitHub Release npm OpenSSF Scorecard OpenSSF Best Practices Ask DeepWiki vault-cortex MCP server

Vault Cortex is a standalone MCP server that gives any AI agent hybrid search, task management, structured memory, and read/write access to your Obsidian vault. No plugins, no running Obsidian, no separate bridge. One Docker container, your vault folder, a full tool suite + guided prompts. Run it on a remote server with Obsidian Sync, and the same vault is accessible from your phone, claude.ai, or any remote MCP client, secured with OAuth 2.1. Deploy it with one click or self-host it; either way, the vault is always yours.

Contents — What you get · Quick Start · How It Works · Hybrid Search · Memory · Tasks · Files · Tools · Prompts · Properties · Config · Daily Notes · Data Integrity · Auth · Deployment · One-click Deploy · Community Deployments

What you get

Search the vault Reason over notes Write back to Obsidian
Ask Claude about a past trip — it searches the vault and recalls the route, cities, and highlights Ask what went wrong — Claude synthesizes lessons from session logs and itinerary notes Save lessons learned to the vault, update travel preferences, then see both in Obsidian

All three demos run on Claude mobile. The vault is on a remote server, not the phone.

  • Remote access — works from your phone, a remote server, or any MCP client via OAuth 2.1. One click on Render or Railway gets you there with no server to manage; a VPS works too.
  • Plugin-free — Obsidian doesn't need to be running. The server works directly with .md files on disk. Headless sync keeps the vault current.
  • Hybrid search — FTS5 keyword matching + vector semantic similarity via RRF fusion, refined by cross-encoder reranking for intent-heavy queries. Keywords stay precise on exact terms and jargon; vectors find notes even when your words differ from the vault's.
  • Structured memory — dated, append-only entries accumulate into a personal knowledge layer, auto-initialized for AI personalization. Topic recall answers "what do I think about X?" with the current take and the dated history behind it — evolution included.
  • Tasks — Kanban-aware task queries and updates: triage by status, dates, or priority, then complete, reprioritize, or move tasks between lanes in one call. Completing a recurring task spawns its next occurrence. Parses both Tasks plugin emoji and Dataview inline-field formats.
  • Link graph — backlinks, outgoing links, and orphan detection across the vault
  • Files — read the vault's non-markdown files too: images arrive as actual images (shrunk to fit when needed), PDFs as structured text or rendered pages, canvases as readable outlines, data files as text
  • Obsidian-native — understands frontmatter, wikilinks, tags, headings, and daily notes
  • Guided workflows — built-in prompts for vault health, memory review, and daily reconciliation — assembled from live vault data each time

Tested across a 15-day trip through Europe. 30+ sessions from a phone, 216 tool calls, zero laptop access needed. Writes in one session were immediately available in the next, across cities and days.


Quick Start

Local (2 minutes — Docker + your vault folder)

Prerequisites: Docker (or a Docker-compatible runtime, e.g. OrbStack, Colima, Podman), Node.js >= 22.12 (only for the CLI — the server itself runs in Docker), and an Obsidian vault (or any folder of .md files).

npx vault-cortex@latest init

That's it — the CLI asks for your vault path, generates the auth token and config files, starts the server, and prints the connection details for your MCP client (CLI reference →).

npx vault-cortex@latest init — the interactive setup wizard picks a mode, finds your vault, offers the optional settings, generates the config, and starts the server

Set up with the CLI? It manages the server from here on — configure, upgrade, start, restart, logs, down (CLI reference →).

Set up with Compose? Stick with Compose for updates too (docker compose pull && docker compose up -d) — the CLI and Compose manage the container independently.

Manual setup (no Node.js needed)
# 1. Get the quickstart files
curl -O https://raw.githubusercontent.com/aliasunder/vault-cortex/main/deploy/local/docker-compose.yml
curl -O https://raw.githubusercontent.com/aliasunder/vault-cortex/main/deploy/local/.env.example

# 2. Configure
cp .env.example .env
# Edit .env — set MCP_AUTH_TOKEN (openssl rand -hex 32) and VAULT_PATH

# 3. Start
docker compose up

Full local guide → (includes Windows setup)

Remote (access from anywhere)

Your vault on a server, kept current by Obsidian Sync, reachable from your phone, claude.ai, or any MCP client. The one-click options ask for your vault name and timezone (plus the vault password if your vault is encrypted), then handle HTTPS, restarts, a generated MCP token, and persistent storage. Once deployed, a setup page walks you through signing in to Obsidian Sync in your browser. On your own server the CLI asks for the public URL and vault name, captures the Sync token for you, and generates the MCP token; HTTPS is yours to set up.

RailwayRenderSelf-hosted
Deploy on RailwayDeploy to RenderCLI setup →
AccountRailway on the Hobby plan or higher — the 5 GB volume is includedRender with a card on fileA VPS with Docker
CostUsage-metered: typically $20–30 USD/mo for a personal vault — a little under Render for a quiet vault, a little over for a busy oneFlat: about $26 USD/mo for the Standard instance (2 GB) and 5 GB disk, billed by the secondWhatever your VPS costs
Pick it ifYou want the easier start — the template lands you in a configured projectA predictable bill matters more than setup polishYou already run a server or want full control
GuideRailway guide →Render guide →Remote guide →

All three need an Obsidian Sync subscription. Whichever you pick, the server is replaceable and your vault isn't — it stays in plain Markdown in Obsidian Sync and on your devices; the container only holds a copy.

The setup page. Deploy without an Obsidian Sync token and the server starts in setup mode: opening its URL in a browser lands on a sign-in page at /setup. Enter your Obsidian account credentials once (two-factor supported) — you sign in with Obsidian directly; the server keeps only the Sync token from that sign-in, restarts, and downloads your vault.

The Connect Obsidian Sync setup page with MCP token, email, and password fields

The sign-in page, gated by your MCP token. Each deploy guide walks through the full flow.

Self-hosted: your own VPS

The Vault Cortex CLI sets up the same container on any Linux box you run — you manage the server, the image, and updates. You need Node.js >= 22.12 for the CLI itself; the server runs in Docker.

# On your VPS:
npx vault-cortex@latest init --mode remote

That's it — the CLI walks through the public URL, Obsidian Sync token (it can run get-sync-token for you), vault name, the vault password for an encrypted vault, and auth config, then starts the server (CLI reference →).

Set up with the CLI? It manages the server from here on — configure, upgrade, start, restart, logs, down (CLI reference →).

Set up with Compose? Stick with Compose for updates too (docker compose pull && docker compose up -d) — the CLI and Compose manage the container independently.

Manual setup (no Node.js needed)
# On your VPS:
mkdir -p /opt/vault-cortex && cd /opt/vault-cortex
curl -O https://raw.githubusercontent.com/aliasunder/vault-cortex/main/deploy/remote/docker-compose.yml
curl -O https://raw.githubusercontent.com/aliasunder/vault-cortex/main/deploy/remote/.env.example
cp .env.example .env
# Edit .env — set MCP_AUTH_TOKEN, PUBLIC_URL, VAULT_NAME (OBSIDIAN_AUTH_TOKEN optional — /setup handles it)
docker compose up -d

Left OBSIDIAN_AUTH_TOKEN empty? Once the container is up, open <PUBLIC_URL>/setup in your browser and sign in — set up HTTPS first, since the page sends your Obsidian password to the server (full walkthrough →).

Connect your MCP client

SetupServer URL
Localhttp://localhost:8000/mcp
Remote (one-click)https://<host>/mcp — <host> is the domain Render or Railway shows on the service page
Remote (self-hosted)<PUBLIC_URL>/mcp

Add the server URL in any MCP client — Claude Code, Claude Desktop, Cursor, OpenCode, or any other. OAuth clients open a consent page in your browser — approve with your token, and the client handles token renewal from then on. Clients without OAuth (MCP Inspector, scripts) send the token directly as an Authorization: Bearer header.

Claude Code:

claude mcp add --scope user --transport http vault-cortex http://localhost:8000/mcp   # local (or <PUBLIC_URL>/mcp)

--scope user registers the server for every project; omit it to scope it to the current directory only.

Claude Desktop (http URLs require the mcp-remote bridge)

A remote server with a publicly reachable https URL adds directly in Claude Desktop's "Add custom connector" dialog — no file editing. Any http URL — localhost included — is rejected by that dialog, so register it in claude_desktop_config.json instead (Claude Desktop → Settings → Developer → Edit Config opens the file) through the mcp-remote stdio bridge:

{
  "mcpServers": {
    "vault-cortex": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "http://localhost:8000/mcp",
        "--header",
        "Authorization: Bearer <your MCP_AUTH_TOKEN>"
      ]
    }
  }
}

claude.ai (web and mobile) connects to the remote setup only — its connectors are fetched server-side and can never reach localhost.

"Remote MCP server" refers to the connection type (HTTP) — in the local setup the server still runs entirely on your machine.

See Authentication for both methods and token lifetimes.


How It Works

Everything runs in one Docker container, working directly with the .md files on disk:

  • Your vault stays the source of truth — the server reads and writes the same plain Markdown files your Obsidian apps do.
  • Search is derived data — a file watcher keeps the index (keywords + vectors) current as notes change, and it can be rebuilt from your notes at any time.
  • The remote image adds a sync loop — a bundled Obsidian Sync service keeps the container's vault current with every device: edit a note on your phone and it's searchable moments later; an agent writes a note and it shows up in Obsidian.
graph LR
    subgraph container ["One Docker container"]
        Sync["sync service<br/>(remote image)"]
        Vault[("/vault<br/>.md files — source of truth")]
        Index[("search index<br/>keywords + vectors")]
        Server["MCP server"]
        Sync <-->|read/write| Vault
        Vault -->|file watcher| Index
        Server <-->|read/write| Vault
        Server -->|query| Index
    end
    Obsidian["Your Obsidian apps<br/>(phone, laptop)"] <-->|Obsidian Sync| Sync
    Client["Any MCP client<br/>(Claude, Cursor, claude.ai)"] -->|OAuth 2.1 / Bearer| Server

See ARCHITECTURE.md for the full design, auth flow diagrams, and component breakdown.


Hybrid Search

Keyword search alone fails when your vocabulary doesn't match the vault's — "aspirations" won't find a note about "targets", "coworkers" won't surface your "references" file. In testing against a real vault, 30% of natural-language queries returned zero or tangential results with keywords alone. Hybrid search eliminated those misses in the same test.

Hybrid search fuses the keyword and vector rankings via Reciprocal Rank Fusion, then the reranker refines the fused result:

  • Keywords (FTS5) stay precise on exact terms, jargon, and property values
  • Vectors (sqlite-vec) bridge the vocabulary gap by matching on meaning
  • Reranker (cross-encoder) refines ordering by scoring each query-document pair jointly — rescues intent-heavy queries where keywords and vectors both miss

All models run locally (~45MB total, no external API). Set EMBEDDING_ENABLED=false for keyword-only search, or RERANK_MODE=none to skip reranking for lower latency.

See ARCHITECTURE.md → Hybrid Search for model details, blend weights, and the full pipeline breakdown.


Memory

A memory layer that only grows is only useful if agents can retrieve the right entries without reading everything back every time. Once you have hundreds of dated entries across multiple files — preferences, principles, communication style, ongoing commitments — whole-file reads bury the signal in irrelevant material. The memory system is designed for targeted retrieval.

The layer is a folder of plain Markdown files (default: About Me/) holding dated entries under topic headings — auto-created with starter templates on first run, grown by agents through vault_update_memory. Three properties make it work:

  • Append-only — entries are never overwritten; corrections arrive as new dated entries. The layer becomes a personal knowledge base that captures your current state and the evolution behind it
  • Topic recall — vault_memory_recall retrieves every relevant entry across all memory files at once, matched by keyword and by meaning, oldest first. Ask "what do I think about X?" and get the current take plus the dated history of how it developed — no need to read entire files or guess which file holds what
  • Grows without degrading — capping results (limit) drops the least-relevant entries, never a slice of the timeline. A memory layer with 500 entries serves a targeted query as well as one with 50

Files that describe what's current rather than what has been true (routines, active commitments) can declare entry-policy: living in frontmatter — their expired entries are prunable rather than preserved, keeping the current-state picture accurate.

The whole layer is optional — set MEMORY_ENABLED=false to hide the memory tools and skip the folder auto-creation entirely.

See ARCHITECTURE.md → Memory for the recall pipeline, indexing model, auto-initialization, and opt-out behavior, and templates/memory for the file format, entry-policy convention, and starter templates.


Tasks

Task metadata lives in plain markdown — scattered across files, encoded in emoji signifiers or inline fields, organized under Kanban headings. An agent answering "what's overdue?" would need to parse every file and understand your chosen format; completing a task on a Kanban board means knowing the board's lane structure, the date syntax, and which heading is the done lane.

The task layer handles this so agents don't have to:

  • Find — filter by status, six date fields (due, scheduled, start, created, done, cancelled), priority, folder, or Kanban lane. Each result carries its note path, line number, and nearest heading when the task sits under one (the lane on a Kanban board) — no follow-up reads needed to locate a task
  • Create — add a correctly-formatted task in one step: description, priority, dates, recurrence, "On completion" action, dependencies, block ID (^id), and checklist sub-items (text only, no dates), placed under a heading at the top, the bottom, or an exact position, or nested under a parent task as a sub-task with its own dates. On a Kanban board a sub-task gets no block ID, since the Kanban plugin copies it onto the card when it saves the board
  • Update — complete, reprioritize, edit the text, set or clear dates, recurrence, and the "On completion" action, add checklist items, move tasks between headings, and reorder within a lane in a single call
  • Complete — marking a task done auto-detects the done lane and stamps the completion date, honoring the plugin's "Set done date" setting; reversing it removes the date. Completion also runs the Tasks plugin's own behaviors:
    • a recurring task spawns its next occurrence, dates advanced the way the plugin computes them
    • a task set to delete "On completion" disappears from the note
  • Both formats — whichever format you use, Tasks plugin emoji signifiers or Dataview inline fields, the server reads both and writes in the format your Tasks plugin is configured for — read from the plugin's settings when your vault syncs .obsidian/, with emoji signifiers as the default otherwise

See ARCHITECTURE.md → Tasks for the indexing model, date cascade sorting, and Kanban lane detection.


Files

Your notes embed screenshots, reference architecture diagrams, and link out to canvases and data files — but to an agent reading markdown, ![[diagram.png]] is just text. Vault Cortex treats files as part of the vault rather than clutter around it — linked, sized, and readable, each in the form an agent can use:

  • Images — the image itself, not the filename. Screenshots and diagrams are downscaled and recompressed server-side when they exceed what MCP clients accept, so even a phone session can look at a 5MB architecture diagram
  • Canvases — a Canvas board arrives as a readable outline: its groups, each card's content in reading order, and the connections between them. Canvas content is full-text searchable, and file references on the board appear in the link graph — backlinks and outgoing links work just like note-to-note links. The exact JSON source is one flag away when full fidelity matters
  • PDFs — text is extracted with heading hierarchy, code blocks, and hyperlinks preserved; PDF content is full-text searchable alongside your notes. Set raw: true to render pages as images instead, showing layout, diagrams, and tables that text extraction can't preserve — scanned and image-only PDFs work in this mode
  • Text and data files — TXT, SVG, JSON, XML, CSV, YAML, logs, and Bases files return exactly as written; the first 100 KB of content is full-text searchable. Big data files and logs can be read a line range at a time, with each page reporting where you are and how much file remains
  • Browse — list any visible folder's files with per-extension counts and file sizes; files a note links to report their size in the link graph too

Set FILE_TOOLS_ENABLED=false to hide the file tools — useful when your remote vault syncs without attachments.

See ARCHITECTURE.md → Files for the image pipeline and dispatch model.


Tools

CategoryToolDescription
Vault CRUDvault_read_noteRead a note — full body, properties, outline, or a section
vault_write_noteCreate a note (fails if it already exists; set overwrite to replace)
vault_patch_noteHeading-targeted edit (append, prepend, replace with include_children guard, insert)
vault_replace_in_noteFind-and-replace text in a note (first match or replace_all_occurrences)
vault_delete_spanDelete a block of lines by short anchors, no full re-quote
vault_replace_spanReplace a block of lines by short anchors with new content
vault_insert_at_anchorInsert content before or after a line identified by a short anchor
vault_list_notesList notes with optional glob/folder filter
vault_delete_noteDelete a note, honoring the vault's trash setting (protected paths enforced)
vault_move_noteMove or rename a note, rewriting links across the vault
Searchvault_searchHybrid search with tag/folder/property/date filters
vault_search_by_tagFind notes by tag (exact or prefix match)
vault_search_by_folderBrowse notes in a folder with metadata
vault_recent_notesRecently modified or created notes
vault_list_tagsAll tags with usage counts
Tasksvault_list_tasksVault-wide task index with sub-task depth — Kanban-aware, date/priority/heading filters
vault_create_taskCreate a correctly-formatted task — dates, priority, recurrence, on_completion, sub-tasks, block_id
vault_update_taskEdit any task field in one call — completing a recurring task creates its next occurrence
Memoryvault_get_memoryRead structured memory (file, section, or all)
vault_update_memoryAppend a dated entry to a memory section
vault_delete_memoryRemove a specific memory entry by date
vault_list_memory_filesDiscover memory files, their sections, and each file's entry policy
vault_memory_recallEntry-granular hybrid recall of a topic across memory files, oldest-first
Propertiesvault_list_property_keysAll property keys with sample values
vault_list_property_valuesDistinct values for a property key
vault_search_by_propertyFind notes by property key-value
vault_update_propertiesAdd, update, or replace properties without touching the body
Linksvault_get_backlinksNotes linking to a given path
vault_get_outgoing_linksLinks from a given note
vault_find_orphansNotes with no incoming links
Filesvault_read_fileRead a non-markdown file — images delivered as images, canvases as readable outlines
vault_list_filesBrowse the vault's non-markdown files with sizes and per-extension counts
Daily Notesvault_get_daily_noteToday's (or any date's) daily note

Prompts

Tools are model-driven — the assistant calls them. Prompts are workflows you trigger. Each one queries the search index, link graph, and memory layer at invocation time, then assembles the results with guided instructions — so the session starts grounded in your vault's actual state, not assumptions.

PromptArgumentsWhat it does
vault-orientation—Surveys vault stats, folder distribution, property adoption rates (flags low adoption), orphans, broken link count, tags, recent notes, and the memory layer — with contextual tool suggestions
memory-reviewfile?, max_chars?Structural overview (scope callouts, section entry counts) + dated content as a timeline. Guided reflection: evolution narrative, scope-fit, backfill gaps, and coverage analysis — append-only by default, pruning proposed only for entry-policy: living files. Hidden when MEMORY_ENABLED=false, READONLY_MODE=true, or DISABLED_TOOLS includes vault_update_memory.
daily-reviewdate?, max_chars?Reconciles a day — daily note, vault-wide task status (due/overdue, scheduled), modified notes, outgoing links (broken-link detection), and backlinks — surfaces what happened, what's open, and what needs follow-up

Prompts adapt to your configuration (MEMORY_DIR, daily-notes settings) and work for any vault out of the box. Pass max_chars to cap embedded content if your client has payload limits.

Client support: Prompts work in Claude Desktop (Chat and Cowork — via the + menu under your connector), Claude Code (slash commands), and OpenCode. Support in other clients (Cursor, Windsurf) varies — see the MCP clients matrix for the latest.


Properties

Vault Cortex indexes every property in your notes, but five get promoted treatment — dedicated columns for fast filtering, and top-level fields in every search and discovery result:

PropertyWhat you can do
titleDisplay name in search results; falls back to the filename when missing
tagsSearch and filter by tag, including parent-child hierarchies (project matches project/vault-cortex)
typeFilter by note type — meeting, person, session-log, or any value your vault uses
createdSort by creation date and see when each note was created alongside every search result
relatedFilter for notes that cross-reference a specific link — surfaces connections invisible without a graph query

All other properties are still fully queryable — use vault_search with filters.properties for combined text + metadata queries, or vault_search_by_property for metadata-only lookups. vault_list_property_keys and vault_list_property_values discover what properties exist across your vault.

These are conventions, not requirements — Vault Cortex works with any property schema. Promoted properties give you richer filtering and cleaner results out of the box.

Leading callouts get the same treatment. When a note's first body content is an Obsidian callout (> [!type]) — either right after frontmatter or right after the title heading — it's indexed and surfaced alongside every discovery result (on vault_search, ask for it with include_leading_callout). This makes notes self-describing: an agent scanning results can see what each note is for before deciding which to read. The memory templates use > [!info] Scope of this file callouts for this, and any note in your vault can use the same pattern.


Configuration

All settings are environment variables with sensible defaults. Some defaults derive from other settings — the Default column shows each derivation, and a value you set replaces the whole derived default. Remote deployments also forward Obsidian Sync's own settings — DEVICE_NAME, SYNC_MODE, CONFLICT_STRATEGY, SYNC_CONFIGS, SYNC_EXCLUDED_FOLDERS, SYNC_FILE_TYPES — documented in the remote guide's configuration table.

VariableRequired?DefaultDescription
MCP_AUTH_TOKENYes—Bearer token for authentication (also the JWT signing key)
VAULT_PATHLocal only—Host path to your vault (bind mount source; remote uses a named volume). Must not contain *, ?, or [ — rejected at startup.
PUBLIC_URLRemote only—Public URL for OAuth discovery metadata. Filled in automatically on Render and Railway (from RENDER_EXTERNAL_URL or RAILWAY_PUBLIC_DOMAIN) when left unset
OBSIDIAN_AUTH_TOKEN——Obsidian Sync auth token. Leave empty to sign in through the /setup page after deploy; or the CLI's get-sync-token captures it for you
VAULT_NAMERemote only—Exact name of your Obsidian vault (case-sensitive)
VAULT_PASSWORDRemote only—End-to-end encryption password, if your vault has one. Leave empty otherwise.
STORAGE_ROOT——One directory for everything that must persist — the vault, the search index, and Obsidian Sync state — for container hosting platforms that allow a single persistent volume (Railway, Render). Mount the volume there and set this to the same path. Must not contain *, ?, or [ — rejected at startup.
EMBEDDING_ENABLED—trueSet false to disable the embedding pipeline — skips model download, vector tables, embedding passes, and hybrid search. Search falls back to FTS5 keyword matching.
RERANK_MODE—blendedCross-encoder reranking mode: blended applies position-aware score blending after RRF fusion (~200ms added latency), none skips reranking. Only takes effect when EMBEDDING_ENABLED is true.
MEMORY_ENABLED—trueSet false to fully disable the memory layer — hides memory tools, skips bootstrap, omits memory from server metadata. MEMORY_DIR still supplies the defaults for PROTECTED_PATHS and ORPHAN_EXCLUDE_FOLDERS when false.
FILE_TOOLS_ENABLED—trueSet false to hide file tools (vault_read_file, vault_list_files) — useful for remote deployments where Obsidian Sync has attachment syncing disabled.
READONLY_MODE—falseSet true to hide every tool that changes the vault and skip memory folder auto-creation — connected clients can read and search but never edit.
DISABLED_TOOLS——Hide individual tools by name, comma-separated (e.g. vault_delete_note,vault_move_note). Names match the Tool column in the tools table. Subtractive only — it cannot re-enable a tool another setting hides. An unknown tool name stops the server at startup, so typos surface immediately.
MEMORY_DIR—About MeVault folder for structured memory files
PROTECTED_PATHS—MEMORY_DIR, daily notes folderFolders that vault_delete_note and vault_move_note refuse to touch. The default daily notes folder is read from DAILY_NOTES_FOLDER or .obsidian/daily-notes.json (default Daily Notes); see Daily notes for root and empty settings. Overrides the default entirely when set.
ORPHAN_EXCLUDE_FOLDERS—daily notes folder, Templates, MEMORY_DIRFolders excluded from orphan detection. The daily notes folder is read from DAILY_NOTES_FOLDER or .obsidian/daily-notes.json (default Daily Notes); see Daily notes for root and empty settings. Set a list to replace all defaults, or ORPHAN_EXCLUDE_FOLDERS=, to exclude nothing. An empty value uses the defaults.
DAILY_NOTES_FOLDER—from daily-notes.jsonSets the folder your daily notes live in. When unset, read from .obsidian/daily-notes.json; Daily Notes when that file is missing or unreadable. See Daily notes.
DAILY_NOTES_FORMAT—from daily-notes.jsonSets the daily note filename format — same tokens as Obsidian's daily note date format setting. When unset, read from .obsidian/daily-notes.json, falling back to YYYY-MM-DD. See Daily notes.
TZ—UTCIANA timezone for timestamps and daily note resolution
SERVICE_DOCUMENTATION_URL—GitHub repo URLURL returned in OAuth discovery metadata
LOG_LEVEL—infoLogging verbosity: debug, info, warn, error
LOG_DIR—/data/logs (remote), $STORAGE_ROOT/data/logs (single-volume), none (local)Directory for log files that survive container re-creation. The container's own log (what docker logs shows) is always written, but Docker discards it whenever the container is recreated — on image updates or config changes. Date-stamped files under LOG_DIR live on the data volume and survive. none keeps only the container log.
LOG_RETENTION_DAYS—90Days to keep log files before automatic cleanup on startup; only applies when LOG_DIR is a path
WINDOWS_MODE—falseOn Windows? Set true. Switches the file watcher to polling and note moves to rename-based writes so a vault on a C: drive works through Docker Desktop. Safe to leave on for any Windows setup; unneeded on macOS/Linux/WSL2.
MAX_FILE_BYTES—52428800 (50 MiB)Maximum file size vault_read_file will read (in bytes). Files exceeding this are rejected before reading. Raise for vaults with very large individual files.
MAX_IMAGE_OUTPUT_BYTES—49152 (48 KiB)Byte budget for images delivered by vault_read_file, in binary bytes before base64 encoding. Images exceeding this are downscaled and recompressed to fit. Sized for the tightest mainstream MCP client cap; raise for clients that accept larger responses.
MAX_PDF_RENDER_PAGES—5Maximum PDF pages to render as images when raw: true is set on vault_read_file. The per-page byte budget is MAX_IMAGE_OUTPUT_BYTES divided evenly across the rendered pages — fewer pages means higher quality each.
TRASH_RETENTION_DAYSLocal only30Days a note deleted under Obsidian's default "Move to system trash" setting stays in .trash/ before the server cleans it up. Set none to keep those notes forever. Only notes the server itself moved there are cleaned up. With Obsidian Sync, deletes are permanent on the server and recoverable from Sync's version history.
TRUST_PROXY_HOPS—0Number of trusted reverse-proxy hops used to derive the client IP from X-Forwarded-For (OAuth rate limiting, request logs). Set 1 when exactly one proxy you control sits in front of the server (Caddy, nginx, Cloudflare Tunnel, API Gateway). With 0, injected forwarding headers are ignored.
TRUST_FORWARDED_HOPS—0How many trailing for= entries in the RFC 7239 Forwarded header belong to proxies you control. 0 ignores the header; 1 when the proxy in front writes it (e.g. AWS API Gateway); 2 when a CDN fronts that proxy and is the only way to reach it.

See templates/memory/ for memory file examples and the dated-entry design philosophy.

Daily notes

vault_get_daily_note and the daily-review prompt find your daily notes using the folder and filename date format configured in Obsidian, read from your vault's .obsidian/daily-notes.json:

  • Local mode reads the file straight from your bind-mounted vault — nothing to set up.
  • Remote mode receives it through Obsidian Sync's vault configuration syncing. The server pulls it by default (the SYNC_CONFIGS setting in .env), but your devices must also send it: turn on Obsidian Settings → Sync → Vault configuration sync on each device. Details: the remote guide's Daily notes section.

When the file isn't available — or if you use the Periodic Notes plugin, whose settings daily-notes.json doesn't hold — set the values yourself:

  • DAILY_NOTES_FOLDER — any vault-relative path: Journal, Planner/Daily, or / for the vault root
  • DAILY_NOTES_FORMAT — same tokens as Obsidian's date format setting: YYYY-MM-DD-dddd, YYYY/MM/DD, MMM D, YYYY, …

You can set one or both — a set value always wins over the config file. A value you leave unset comes from daily-notes.json; when that file is missing, the server uses Daily Notes and YYYY-MM-DD.

  • Changes in Obsidian apply on the next call when .obsidian/daily-notes.json is available in the server's vault.
  • Apply environment changes with the CLI's restart command, recreate the Compose container, or redeploy on your hosting platform.
  • If you leave the folder empty in Obsidian's Daily notes options, the server follows Obsidian's Default location for new notes setting (Settings → Files and links), read from .obsidian/app.json. Same folder as current file counts as the vault root, because Obsidian creates a daily note without reference to an open note and so has no folder to follow. When app.json isn't in the server's vault, as in remote mode with the default SYNC_CONFIGS, the server uses the vault root.
  • If your daily notes live in the vault root, or in the new-note folder because the folder setting is empty, delete and move don't protect them and orphan results can include them. Protecting or excluding that folder would also cover every other note in it.

Note: A few date format tokens are unsupported — ordinals (Do, Mo, DDDo, wo), dd (2-letter weekday), d (weekday number), e, k/kk, w (week number), Q (quarter), Z/ZZ (UTC offset), and the localized formats (L–LLLL, LT, LTS). The server can't reproduce the filenames Obsidian creates with these tokens, so it could never find the notes. If your format uses any of them, vault_get_daily_note returns a clear error — change the format in Obsidian or set DAILY_NOTES_FORMAT to a supported alternative.


Data Integrity

Vault Cortex writes to personal notes — the file safety layer is built to prevent corruption, not just errors.

  • Atomic writes — every file write stages to a temp file, then renames. Readers never see a partial or 0-byte note. Exclusive creates use link() (POSIX no-clobber) to close the TOCTOU window on note moves.
  • Per-file mutex — concurrent MCP tool calls serialize or fail-fast per file. Moves lock the source, destination, and every backlink source as one unit.
  • Properties are protected — an edit refuses a note whose properties block it can't keep (invalid YAML, a list, a single value, or a value with an explicit YAML tag such as !!str) and leaves the file unchanged, and a write that would leave a note opening with --- lines it can't keep is refused too. The error says how to repair the note; vault_update_properties with replace: true replaces the whole block. A rewrite keeps every property but not YAML comments in the block.
  • Notes with broken properties stay searchable — search reads a note whose properties block is not valid YAML as if it had no properties. The note still appears in search results and task lists, its body links still count as backlinks, and the server log names it as needing repair.
  • Path traversal blocked — resolveSafePath() resolves then prefix-checks every path. Protected-path deletion is refused after normalization. Memory file names reject separators at the boundary.
  • Hidden paths are off-limits — files and folders starting with a dot (.obsidian/, .trash/) never appear in listings or search, and any tool call that targets one directly is rejected, matching Obsidian. Plugin configs and their API keys stay out of reach.
  • Deletes honor Obsidian's trash setting — with "Deleted files" at Obsidian's default "Move to system trash" or at "Move to Obsidian trash", a deleted note moves to .trash/ inside the vault instead of being removed (a container has no system trash; .trash/ is Obsidian's own fallback for that). "Permanently delete" removes the note for good.
  • Obsidian Sync deployments delete permanently — the delete syncs to every device, and recovery is Sync's version history rather than a trash folder.
  • Bounded trash with a retention sweep — notes the server moves to .trash/ under the system-default setting are cleaned up after TRASH_RETENTION_DAYS (default 30 days; none keeps them forever). The sweep removes only files it recorded — notes Obsidian itself trashed, and "Move to Obsidian trash" deletes, are never touched.
  • Injection prevention — search queries are parameterized and FTS5-sanitized; prompt content is wrapped in XML data markers with closing-tag escaping to prevent tag-breakout injection.
  • Container hardening — non-root user, PID 1 init, no package managers in the runtime image, digest-pinned base, graceful shutdown.
  • Read-only mode — READONLY_MODE=true hides every tool that edits the vault, so a connected client can read and search but never change a note.

See ARCHITECTURE.md → Data Integrity for mechanism details and SECURITY.md → Runtime Hardening for how each part of the server is hardened.


Authentication

For a server with read/write access to personal notes, authentication is not optional. Vault Cortex implements the full OAuth 2.1 specification, including PKCE and refresh-token rotation. The AWS (SST) deployment adds defense-in-depth: requests are validated at two independent layers (API Gateway Lambda authorizer + Express middleware). Per BlueRock's 2026 MCP security analysis, only 8.5% of MCP servers implement OAuth; 41% have no authentication at all.

Two methods:

MethodUsed byToken format
OAuth 2.1Claude Desktop, Claude Code, claude.ai, any OAuth clientJWT (HS256, 6h)
Static bearerClaude Code, MCP Inspector, curlRaw MCP_AUTH_TOKEN

The method follows from your client — OAuth when it supports it, the raw token in a header otherwise (Connect your MCP client shows both).

OAuth uses dynamic client registration — no manual Client ID or Secret needed:

  1. Your client registers automatically and receives a client ID and secret.
  2. Enter your MCP_AUTH_TOKEN on the browser consent page to approve access.
  3. Your client includes the issued secret in subsequent token requests automatically.

Refresh tokens have a 60-day sliding expiry. Access tokens are bound to your server's URL, so a token minted for one deployment is never accepted by another. Rotating MCP_AUTH_TOKEN ends every session — each client re-authorizes through the consent page.

See ARCHITECTURE.md → Auth for the full flow diagram.


Deployment Options

Local runs on your machine. Remote deployments run on a VPS or a hosted container platform — your vault is accessible even when your laptop is closed.

Whichever path you pick, the server is replaceable and your vault isn't. Your notes are plain Markdown files, synced by Obsidian to every device you own; the container holds a copy and an index it can rebuild from scratch. Shut down the VPS, delete the Render or Railway service, switch hosts — the same files are still on your machine and in Obsidian Sync, readable by anything. That's the difference from an AI notebook whose real home is the vendor's database: here the host is a convenience, not a custodian.


View the full README on GitHub

Featured
CodeRabbit
CodeRabbit
AI writes the code. CodeRabbit catches the slop.
Try For Free →
Lid closed, agents working
Lid closed, agents working
Keeps your Mac awake while Claude Code, Codex or Cursor works. Lets it sleep when they are done.
Try free for 7 days →
Block distraction from your iPhone for freeBlock distraction from your iPhone for free
Block distraction from your iPhone for free
Block distracting apps from your iPhone permanently without a 3rd party app. Free and open source.
Block now (100% free) →
Granola, the best AI meeting recorder
Granola, the best AI meeting recorder
Notes, actions and memory. Without a meeting bot. First month 100% off.
Download for free →
belt - the only tool your agent needs
belt - the only tool your agent needs
belt cli automatically finds the best tools and skills for your agent. image, video, music, tts...
one prompt install →
Open Steps
Open Steps
Free an open-source skills that make AI coding agents easier to understand, verify, and control.
Download for free →
AppSignal
AppSignal
Monitor with ease. Code with confidence.
Start Free Trial →
Agent, connect blockchain
Agent, connect blockchain
Connect your Claude agent to live crypto prices and trading routes via 1inch
Get the MCP →

Configuration

MCP_AUTH_TOKEN*secret

Bearer token for MCP client authentication. Must match the Authorization header sent by clients. Generate with: openssl rand -hex 32

PUBLIC_URLdefault: http://localhost:8000

Public URL clients use to reach this server. Used as the OAuth issuer URL in discovery metadata. Override when exposing the server outside localhost or on a non-default port.

MEMORY_DIRdefault: About Me

Vault folder for structured memory files (About Me-style notes).

TZdefault: UTC

IANA timezone for timestamps and daily note resolution.

LOG_LEVELdefault: info

Logging verbosity.

LOG_DIR

Directory for persistent log files. Unset by default — logs go to stdout only. Set to /data/logs to also write date-stamped .log files to the persistent volume.

LOG_RETENTION_DAYSdefault: 30

Days to retain persistent log files before cleanup.

PROTECTED_PATHS

Comma-separated vault folder names blocked from vault_delete_note. Default: MEMORY_DIR and "Daily Notes".

ORPHAN_EXCLUDE_FOLDERS

Comma-separated vault folder names excluded from vault_find_orphans. Default: "Daily Notes", "Templates", MEMORY_DIR.

SERVICE_DOCUMENTATION_URLdefault: https://github.com/aliasunder/vault-cortex

Override the OAuth service documentation URL exposed via discovery metadata.

Categories
AI & LLM ToolsDocuments & KnowledgeSearch & Web Crawling
Registryactive
Packageghcr.io/aliasunder/vault-mcp:0.15.23
TransportHTTP
AuthRequired
UpdatedJun 10, 2026
View on GitHub

Related AI & LLM Tools MCP Servers

View all →
antoniotf5 avatar
Soul Mcp Server

antoniotf5/soul-mcp-server

MCP server for validating and generating SOUL.md agent identity files from Claude Desktop.
1
kiarashplusplus avatar
Stdio Proxy

app.undisk.mcp/stdio-proxy

Undisk MCP: safe file memory for AI agents.
1
archerkattri avatar
Mathlas

archerkattri/mathlas

Airtight math for AI agents: 3.68M-doc theorem search + numeric/Lean verification. No LLM, no key.
1
atriumn avatar
Tokencost Dev

atriumn/tokencost-dev

LLM pricing oracle — model lookup, cost estimation, and comparison via LiteLLM
1
bch1212 avatar
Mcp Grantiq

bch1212/mcp-grantiq

Search US grants + federal contracts (Grants.gov + SAM.gov) from any LLM.
1
bch1212 avatar
Queryshield

bch1212/queryshield

Secure SQL proxy for AI agents — NL→SQL, AST safety, per-agent RLS, audit log.
1