Skip to content

fufic123/obsidian-mcp

Repository files navigation

obsidian-mcp

MCP server that turns an Obsidian vault into persistent memory for AI models. Works with any MCP client (Claude Code, Claude Desktop, Cursor, Windsurf). Vault syncs via iCloud/Git/Obsidian Sync — same memory across all devices and clients.

How it works

AI Client (Claude, Cursor, ...)
    ↕ MCP protocol (stdio) : ?http
obsidian-mcp server
    ↕ file read/write
Obsidian vault (synced across devices)

Memory is organized in three tiers to minimize token usage:

Tier What When loaded
1 memory/core/ — who you are, how to work with you Always (at conversation start)
2 memory/highlights/ + conversations/summaries/ On demand via get_relevant_context(query)
3 conversations/archive/ — full conversation text Never automatically

The server picks which vault to use based on your working directory ($PWD) mapped through config.toml namespaces. Different projects inside one vault are separated by project: tags in frontmatter.

Vault structure

vault/
├── memory/
│   ├── MEMORY.md              ← auto-generated index (max 200 lines / 25KB)
│   ├── core/                  ← persistent context about you
│   │   └── *.md
│   ├── highlights/            ← insights, decisions, knowledge
│   │   └── *.md
│   └── conversations/
│       ├── summaries/         ← Q&A callout format
│       └── archive/           ← full conversation text
├── tasks/                     ← Obsidian Tasks format
└── daily/                     ← daily notes

Every note has YAML frontmatter:

---
name: SSH multi-account setup
description: Configure multiple Git accounts via ~/.ssh/config
type: highlight
project: devops
tags: [ssh, git]
created: 2026-04-01
---

MEMORY.md index (auto-generated by rebuild_index()):

# Memory Index

## Core
- [Role and preferences](core/role.md) — senior engineer, Python, uv

## Highlights
- [SSH multi-account](highlights/ssh-setup.md) — hostinger + personal config
- [MCP architecture](highlights/mcp-design.md) — decisions on Obsidian MCP server

Installation

Requirements

  • uv — that's it, uv handles Python and dependencies

1. Create config

mkdir -p ~/.config/obsidian-mcp
curl -o ~/.config/obsidian-mcp/config.toml https://github.com/fufic123/obsidian-mcp/main/config.toml.example

Edit ~/.config/obsidian-mcp/config.toml — set your vault paths:

[namespaces.default]
vault = "~/Documents/my-vault"

[memory]
max_index_lines = 200
max_index_bytes = 25600
frontmatter_scan_lines = 30
max_search_results = 20

Add more namespaces as needed — see Configuration for the full format.

2. Connect to your MCP client

All MCP clients use the same server config — the only difference is where the config file lives.

Create a .mcp.json file with this content:

{
  "mcpServers": {
    "obsidian": {
      "command": "uvx",
      "args": ["obsidian-mcp"],
      "env": {
        "OBSIDIAN_MCP_CONFIG": "/Users/username/.config/obsidian-mcp/config.toml"
      }
    }
  }
}

OBSIDIAN_MCP_CONFIG is optional if your config lives at ~/.config/obsidian-mcp/config.toml.

Where to place .mcp.json:

Client Path Scope
Claude Code (global) ~/.mcp.json All projects
Claude Code (project) .mcp.json in project root Single project
Claude Desktop ~/Library/Application Support/Claude/claude_desktop_config.json All conversations
Cursor Settings → MCP Servers → Add (paste the server object) Workspace or global
Windsurf MCP settings (same format) Workspace or global

Claude Code notes:

  • .mcp.json in a project directory applies only when Claude Code is launched from that directory
  • ~/.mcp.json applies globally to all projects — put it here if you want memory everywhere
  • After adding/changing .mcp.json, restart Claude Code — MCP servers are loaded at startup
  • On first launch Claude Code will ask to approve the new server — confirm it

Configuration

Each namespace has a human-readable name, a match prefix for $PWD resolution, and a vault path. default is the fallback — no match needed.

[namespaces.personal]
match = "~/Documents/personal"   # matches any $PWD starting with this
vault = "~/Documents/personal/obsidian"

[namespaces.work]
match = "~/work"
vault = "~/vaults/work"

[namespaces.default]             # fallback — no match needed
vault = "~/Documents/personal/obsidian"

[memory]
max_index_lines = 200        # MEMORY.md max lines (truncated beyond this)
max_index_bytes = 25600      # MEMORY.md max bytes — 25KB (dual truncation)
frontmatter_scan_lines = 30  # lines read per file for frontmatter parsing
max_search_results = 20      # max results from get_relevant_context

Config is loaded in this order (first found wins):

  1. $OBSIDIAN_MCP_CONFIG env var
  2. ~/.config/obsidian-mcp/config.toml
  3. ./config.toml (for development)

MCP tools

Memory — polymorphic CRUD over note types

Memory notes come in three types (highlight, core, conversation). A single set of CRUD tools dispatches by the type field on the note payload.

Tool Description When to call
create_note(note) Create a highlight / core / conversation. Note self-identifies via type. New insight, user preference, or end-of-session summary
read_note(note_type, name, project?) Load one note's full content Need full details of a specific note
list_notes(note_type, project?) List notes of a type, optionally by project Browsing what exists
update_note(note_type, name, updates, project?) Patch fields — only provided keys change. Renames / project moves rewrite the file. Fixing or refining a saved note
delete_note(note_type, name, project?) Permanently remove a note Cleaning up stale memory
get_core_context() Load all core notes inline Start of every conversation
get_relevant_context(query, project?) Search highlights and summaries by frontmatter When you need context on a topic
rebuild_index() Regenerate MEMORY.md and sub-indexes After bulk edits outside the MCP

create_note payload shape by type:

  • highlight{"type": "highlight", "name", "description", "content", "tags"?, "project"?}
  • core{"type": "core", "name", "description", "content"}
  • conversation{"type": "conversation", "title", "key_points", "full_content", "project"?, "tags"?}

Knowledge

Tool Description When to call
search_vault(query) Full-text search across all vault files Looking for specific content
get_note(path) Read a note by path Need full content of a specific note

Tasks

Tool Description When to call
create_task(title, due?, project?) Create an Obsidian Tasks entry User mentions a todo
list_tasks(project?) List open tasks Reviewing what needs to be done

Productivity

Tool Description When to call
create_daily_note(content?) Create/append to today's daily note Daily logging
generate_moc(folder) Generate Map of Content for a folder Organizing a folder

Recommended system prompt

Add to your CLAUDE.md or client system prompt:

You have access to an Obsidian vault via MCP tools for persistent memory.

At conversation start:
1. Call get_core_context() to load who the user is and how to work with them.
2. Call get_relevant_context(topic) for the current conversation topic.

During conversation:
- When the user expresses a preference or tells you about themselves →
  create_note({type: "core", ...}) or update_note("core", name, updates)
- When an important insight, decision, or knowledge emerges →
  create_note({type: "highlight", ..., project?})

At conversation end:
- If the conversation was meaningful →
  create_note({type: "conversation", ..., project?})

Recommended Obsidian plugins

Plugin Why
Dataview Query notes by frontmatter — filter highlights by project, type, date
Tasks Render and manage tasks created by create_task()
Templater Templates for notes you create manually — keeps frontmatter consistent
Calendar Navigate daily notes created by create_daily_note()
Git Auto-commit vault — version history + sync across machines without Obsidian Sync
Minimal Theme Renders callout format used by save_conversation() cleanly

Dataview example — show all highlights for a project:

TABLE description, file.mtime AS updated
FROM "memory/highlights"
WHERE project = "my-project"
SORT file.mtime DESC

Development

git clone https://github.com/fufic123/obsidian-mcp
cd obsidian-mcp
uv sync

# Run tests
uv run pytest

# Type checking
uv run mypy app/

# Lint
uv run ruff check app/

Project structure:

app/
├── domain/          ← models, interfaces (ABC), exceptions
├── adapters/        ← file system implementations
├── services/        ← business logic
├── tools/           ← thin MCP wrappers
└── main.py          ← DI wiring, FastMCP init

Dependencies flow downward only: tools → services → adapters → domain.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages