Skip to main content
Glama
t-rhex

mcp-obsidian-vault

by t-rhex

mcp-obsidian-vault

Turn your Obsidian vault into an AI command center.

npm version CI Node License: MIT

An MCP server that gives AI agents direct filesystem access to your Obsidian vault — no Obsidian running required. Manage notes, orchestrate multi-agent task workflows, persist context across sessions, and sync everything with git.

Quick StartToolsTask OrchestrationConfiguration


Why This Exists

Every time you start a new AI chat session, your agent forgets everything. Decisions made, bugs discovered, tasks in progress — all gone.

mcp-obsidian-vault solves this by making your Obsidian vault the single source of truth for AI development work:

  • Notes are your knowledge base — searchable, linked, tagged

  • Tasks are your work queue — agents claim, track, and complete them

  • Projects orchestrate multi-agent parallel work with dependency graphs

  • Decisions & Discoveries persist the why so future sessions don't repeat mistakes

  • Context briefings give any new session a full situation report in one call

npx mcp-obsidian-vault

Related MCP server: Obsidian MCP Server

How It Works

graph TB
    subgraph Clients["AI Clients"]
        CC[Claude Code]
        OC[opencode]
        CX[Codex CLI]
    end

    subgraph MCP["mcp-obsidian-vault"]
        direction TB
        NT["Note Tools<br/><small>read, create, update, delete<br/>search, tags, wikilinks, daily</small>"]
        TT["Task Tools<br/><small>create, claim, update, complete<br/>projects, dashboard</small>"]
        CT["Context Tools<br/><small>get_context, log_decision<br/>log_discovery</small>"]
        GS["Git Sync<br/><small>commit, pull, push<br/>auto-sync on write</small>"]
    end

    subgraph Vault["Obsidian Vault (filesystem)"]
        direction TB
        Notes["Notes/"]
        Tasks["Tasks/<br/><small>DASHBOARD.md</small>"]
        Dec["Decisions/"]
        Disc["Discoveries/"]
    end

    subgraph Remote["Remote"]
        GH["GitHub / GitLab"]
        Phone["Phone<br/><small>Obsidian Git plugin</small>"]
    end

    CC & OC & CX -->|MCP Protocol| MCP
    NT --> Notes
    TT --> Tasks
    CT --> Dec & Disc
    GS -->|auto-push| GH
    GH -->|pull| Phone

    style MCP fill:#1a1a2e,stroke:#e94560,color:#fff
    style Vault fill:#16213e,stroke:#0f3460,color:#fff
    style Clients fill:#0f3460,stroke:#533483,color:#fff
    style Remote fill:#1a1a2e,stroke:#533483,color:#fff

Features

Vault Management

Feature

Description

CRUD Notes

Read, create, update, delete with full YAML frontmatter support

Wikilinks

Resolve [[links]], find backlinks, outlinks, and broken links

Full-Text Search

Regex-capable search with folder filtering and timeout protection

Tag Management

Add, remove, list tags with automatic deduplication

Daily Notes

Get, create, append by date — today, yesterday, 2025-03-08

Vault Browsing

Recursive directory listing with depth control

Task Orchestration

Feature

Description

Agent Task Queue

Structured tasks with priority, type, scope, and deadlines

Atomic Claims

Race-condition-safe task claiming for multi-agent setups

Dependency Graphs

Tasks block/unblock automatically based on depends_on

Project Management

Create projects with sub-tasks, track rollup progress

Append Mode

Add new sub-tasks to existing projects with project_id

Conditional Workflows

Routing rules: branch task execution based on output (v0.3)

Auto Dashboard

DASHBOARD.md regenerated after every mutation

Human-in-the-Loop (v0.3)

Feature

Description

Review Gates

Tasks with review_required redirect to needs_review on completion

Approve / Reject

review_task tool for humans/agents to approve, reject, or request changes

Feedback Loop

Rejected tasks enter revision_requested → agents revise → resubmit

Risk Levels

Tag tasks as low / medium / high / critical risk

Agent Management (v0.3)

Feature

Description

Agent Registry

Register agents with capabilities, tags, and model info

Capability Routing

suggest_assignee recommends the best agent for a task

Timeout Detection

check_timeouts scans for overdue tasks with auto-retry and escalation

Usage Tracking

Record and aggregate token usage and cost per agent/task/project

Webhook Events

Fire HTTP POST notifications on task lifecycle events

Context Persistence

Feature

Description

Session Briefings

get_context returns full situation report for new sessions

Decision Records

Log architectural decisions with rationale and alternatives

Discovery Notes

Capture gotchas, TILs, and patterns for future agents

Project Filtering

Scope context briefings to a specific project

Git Sync

Feature

Description

Auto-Sync

Commit + push after every write (debounced)

Manual Control

commit, pull, push, sync, diff, log, init, remote management

Cross-Device

Laptop-to-phone sync via Obsidian Git plugin


Quick Start

1. Install

Pick your MCP client and add the config:

claude mcp add obsidian -- npx -y mcp-obsidian-vault

Then set your vault path:

claude mcp add obsidian \
  -e OBSIDIAN_VAULT_PATH=/path/to/your/vault \
  -e GIT_AUTO_SYNC=true \
  -- npx -y mcp-obsidian-vault

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "obsidian": {
      "command": "npx",
      "args": ["-y", "mcp-obsidian-vault"],
      "env": {
        "OBSIDIAN_VAULT_PATH": "/path/to/your/vault"
      }
    }
  }
}

Add to ~/.config/opencode/opencode.json (opencode has no env field — use sh -c):

{
  "mcp": {
    "obsidian": {
      "type": "local",
      "command": [
        "sh", "-c",
        "OBSIDIAN_VAULT_PATH=/path/to/your/vault GIT_AUTO_SYNC=true npx -y mcp-obsidian-vault"
      ],
      "enabled": true
    }
  }
}
[mcp_servers.obsidian]
command = "npx"
args = ["-y", "mcp-obsidian-vault"]

[mcp_servers.obsidian.env]
OBSIDIAN_VAULT_PATH = "/path/to/your/vault"
GIT_AUTO_SYNC = "true"
git clone https://github.com/t-rhex/obsidian-mcp-server.git
cd obsidian-mcp-server
npm install && npm run build
OBSIDIAN_VAULT_PATH=/path/to/vault node build/index.js

Updating

npx -y mcp-obsidian-vault always fetches the latest version automatically. If you've cached a specific version, clear the npx cache:

# Force npx to fetch the latest
npx -y mcp-obsidian-vault@latest

# Or clear the npx cache entirely
npx clear-npx-cache

From source:

git pull origin main
npm install && npm run build

Check your current version:

npx -y mcp-obsidian-vault --version
# Or ask your AI agent: "What version of mcp-obsidian-vault are you running?"

Uninstalling

claude mcp remove obsidian

Remove the "obsidian" entry from mcpServers in claude_desktop_config.json.

Remove the "obsidian" entry from mcp in ~/.config/opencode/opencode.json.

Remove the [mcp_servers.obsidian] section from your Codex config.

# Remove the cached package
npx clear-npx-cache
rm -rf obsidian-mcp-server

Your vault data (notes, tasks, decisions, discoveries) is never deleted — it stays in your Obsidian vault folder. Only the MCP server tool is removed.

2. Try It

Once configured, open a chat with your AI agent and try these:

"Read my Projects/roadmap note"
"Search my vault for anything about authentication"
"Create a task to refactor the auth module, high priority"
"What's the current context? Call get_context."

That's it. The agent now has full access to your vault through 27 MCP tools. Keep reading for real-world workflows.

3. Real-World Workflows

Scaffold a new project

Tell your agent what you want to build. It handles the rest:

"I need to build a REST API for user management. Set up a project with tasks for:
  1. Design the database schema (research)
  2. Set up Express with TypeScript (code)
  3. Implement CRUD endpoints (code, depends on 1 and 2)
  4. Add JWT authentication (code, depends on 3)
  5. Write integration tests (code, depends on 4)
  6. Write API documentation (writing)"

The agent calls create_project and your vault now has:

Tasks/
├── DASHBOARD.md                                          # auto-generated summary
└── user-management-api/                                  # project subfolder
    ├── proj-2026-03-09-a1b2c3-user-management-api.md     # project note
    ├── task-2026-03-09-d4e5f6-design-database-schema.md  # pending (no deps)
    ├── task-2026-03-09-g7h8i9-set-up-express.md          # pending (no deps)
    ├── task-2026-03-09-j0k1l2-implement-crud.md          # blocked (waits on 1, 2)
    ├── task-2026-03-09-m3n4o5-add-jwt-auth.md            # blocked (waits on 3)
    ├── task-2026-03-09-p6q7r8-write-tests.md             # blocked (waits on 4)
    └── task-2026-03-09-s9t0u1-write-api-docs.md          # pending (no deps)

Each task file has structured frontmatter (status, priority, dependencies, scope) and sections for description, acceptance criteria, and an agent log. The dashboard shows what's claimable, what's blocked, and overall progress.

From here, the agent (or multiple agents) can claim tasks, work them, and mark them done. Blocked tasks auto-unblock as their dependencies complete.

"Claim the database schema task and start working on it."
"What's the project status?"
→ 1/6 complete (17%), 2 in progress, 3 blocked

Save context before ending a session

When you're wrapping up a session, tell your agent:

"Log a decision: we chose Zod over Joi for validation because of TypeScript inference."
"Log a discovery: the Stripe webhook endpoint requires idempotency keys or charges double."

These get saved as structured notes in Decisions/ and Discoveries/. The next session picks them up automatically.

Pick up where you left off

Start any new session with:

"Call get_context to see what's in progress."

The agent gets back: active projects, in-progress tasks, blockers, recent decisions, recent discoveries, and pending work. No manual briefing needed.

Grow a project mid-flight

Requirements change. Append new tasks to an existing project without recreating it:

"Add these tasks to the User Management API project:
  - Add rate limiting middleware (code)
  - Add password reset flow (code, depends on JWT auth)
  - Security audit (research, depends on rate limiting and password reset)"

New tasks slot into the existing dependency graph. The dashboard updates automatically.

Multi-session continuity

Session 1: "Create a task to fix the memory leak in the worker pool"
           → agent claims it, investigates, logs progress, runs out of context

Session 2: "Call get_context"
           → sees the in-progress task, picks up from the agent log
           → completes the fix, marks task done

Session 3: "Call get_context"
           → sees the completed task, continues to next priority

Daily notes as a work journal

"Append to today's daily note: deployed v2.1 to staging, waiting on QA"
"What did I log yesterday?"

Tools (27)

Note Tools

path: "Projects/my-note.md"     # .md added automatically if missing
includeRaw: false                # include unparsed content
path: "Projects/new-idea"
content: "# My Idea\n\nSome content here."
frontmatter: { "tags": ["idea", "project"], "status": "draft" }
overwrite: false                 # fails if note exists (default)
path: "Projects/my-note"
content: "## New Section\n\nAdded content."
mode: "append"                   # "replace" | "append" | "prepend"
frontmatter: { "status": "in-progress" }
path: "Projects/old-note"
permanent: false                 # true for hard delete
query: "meeting notes"
regex: false
caseSensitive: false
folder: "Projects"               # limit to subfolder
maxResults: 20
path: "Projects"                 # defaults to vault root
recursive: true
maxDepth: 5
notesOnly: false                 # true to filter to .md files only
path: "Projects/my-note"
action: "add"                    # "list" | "add" | "remove"
tags: ["important", "review"]
action: "append"                 # "get" | "create" | "append"
date: "today"                    # "today" | "yesterday" | "tomorrow" | "2025-03-08"
content: "- Met with team about roadmap"
action: "backlinks"              # "resolve" | "backlinks" | "outlinks" | "unresolved"
path: "Projects/my-note"

Action

Description

resolve

Find the file a [[wikilink]] points to

backlinks

Find all notes that link TO a given note

outlinks

List all [[wikilinks]] FROM a note

unresolved

Find all broken [[wikilinks]] across the vault

action: "sync"                   # full pull + commit + push
message: "update notes"          # optional commit message

Action

Description

status

Working tree status

commit

Stage all + commit

pull

Pull from remote (rebase by default)

push

Push to remote

sync

Pull + commit + push in one call

log

Recent commit history

diff

Uncommitted changes

init

Initialize git repo with .gitignore

remote_add

Add a git remote

remote_list

List configured remotes

Task Tools

title: "Implement auth module"
description: "Build JWT-based authentication for the API."
priority: "high"                 # "critical" | "high" | "medium" | "low"
type: "code"                     # "code" | "research" | "writing" | "maintenance" | "other"
depends_on: ["task-abc-123"]     # task IDs that must complete first
scope: ["src/auth.ts"]           # advisory: files this task modifies
acceptance_criteria: ["Tests pass", "Docs written"]
timeout_minutes: 120
status: "pending"                # or "all"
priority: "high"                 # or "all"
type: "code"                     # or "all"
tags: ["auth"]                   # filter by tags
assignee: "claude-code-1"
unassigned_only: true
project: "proj-..."              # filter by project
task_id: "task-2026-03-09-abc123"
assignee: "claude-code-1"
worktree_branch: "worktree-auth-api"      # optional — for parallel multi-agent work
worktree_path: "/repo/.claude/worktrees/auth-api"  # optional

Blocks if dependencies aren't met. Two agents claiming the same task → second gets TASK_ALREADY_CLAIMED. Worktree fields are optional — pass them when using git worktrees for parallel development.

task_id: "task-2026-03-09-abc123"
status: "in_progress"
log_entry: "Found root cause — null check missing in auth middleware."
task_id: "task-2026-03-09-abc123"
summary: "Auth module implemented with JWT support."
deliverables: ["src/auth.ts", "https://github.com/org/repo/pull/42"]
status: "completed"              # "completed" | "failed" | "cancelled"

Completing a task auto-unblocks dependent tasks (blockedpending).

New project:

title: "Auth Rewrite"
description: "Rewrite authentication to use JWT tokens."
tasks: [
  { title: "Design API schema", type: "research" },
  { title: "Implement JWT", type: "code", depends_on_indices: [0] },
  { title: "Write tests", type: "code", depends_on_indices: [1] },
  { title: "Update docs", type: "writing" }
]

Append to existing project:

project_id: "proj-2026-03-09-abc123"
tasks: [
  { title: "Add rate limiting", type: "code" },
  { title: "Security audit", depends_on_existing: ["task-..."] }
]
project_id: "proj-2026-03-09-abc123"

Returns progress percentage, status breakdown, active agents, overdue tasks, and blockers.

Context Tools

project_id: "proj-..."           # optional: focus on one project
hours: 48                         # lookback window (default: 48)
include_completed: true

Returns: active projects, in-progress work, pending tasks, blockers, failures, overdue tasks, recent decisions, recent discoveries, pinned notes.

title: "Use JWT over session tokens"
context: "Need stateless auth for microservices."
decision: "JWT with RS256, 15min access tokens, refresh rotation."
alternatives: ["Session tokens with Redis", "API keys"]
consequences: ["Stateless (good)", "Revocation needs deny-list (tradeoff)"]
title: "gray-matter crashes on undefined values"
discovery: "js-yaml throws when serializing undefined. Strip before serialize."
impact: "high"
recommendation: "Filter with Object.entries().filter() first."
category: "bug"

Review & HITL Tools

task_id: "task-2026-03-09-abc123"
action: "approve"                # "approve" | "reject" | "request_changes"
reviewer: "human-alice"
feedback: "Looks good, ship it."  # required for reject/request_changes

On approve, the task moves to completed and dependents are unblocked. On reject/request_changes, the task moves to revision_requested for the assignee to revise and resubmit.

Agent Tools

agent_id: "claude-code-1"
capabilities: ["code", "research", "writing"]
tags: ["auth", "backend"]
model: "claude-sonnet-4"
max_concurrent: 3

Creates/updates an agent profile in the Agents/ folder. Agents are tracked with status (active, idle, offline) and heartbeat timestamps.

capability: "code"               # filter by capability
tag: "auth"                      # filter by tag
status: "active"                 # "active" | "idle" | "offline"
available_only: true             # only agents below max_concurrent
task_id: "task-2026-03-09-abc123"

Returns a ranked list of agents sorted by capability match, tag overlap, and current workload.

dry_run: false                   # true for preview without changes

Scans all claimed/in_progress tasks for timeout_minutes violations. For overdue tasks:

  • If retry_count < max_retries: resets to pending for retry

  • If retries exhausted + escalate_to set: marks as escalated

  • Returns list of all actions taken

Usage Tracking Tools

agent_id: "claude-code-1"
task_id: "task-abc-123"          # optional
input_tokens: 15000
output_tokens: 3000
model: "claude-sonnet-4"
cost_usd: 0.042
duration_seconds: 30
notes: "Implemented auth module"
agent_id: "claude-code-1"       # optional filter
project_id: "proj-..."          # optional filter
task_id: "task-..."             # optional filter
from_date: "2026-03-01"        # optional
to_date: "2026-03-09"          # optional

Returns: total_input_tokens, total_output_tokens, total_cost_usd, record_count, grouped by agent and model.


Task Orchestration

Single Agent Workflow

sequenceDiagram
    participant H as Human
    participant A as Agent
    participant V as Vault

    H->>V: create_task("Fix login bug")
    A->>V: list_tasks(status: "pending")
    V-->>A: [task-abc: "Fix login bug"]
    A->>V: claim_task(task_id, assignee: "agent-1")
    A->>V: update_task(status: "in_progress")
    A->>V: update_task(log: "Found null check issue")
    A->>V: complete_task(summary: "Fixed!", deliverables: [...])
    V-->>V: Auto-unblock dependents
    V-->>V: Refresh DASHBOARD.md

Multi-Agent Project Workflow

sequenceDiagram
    participant H as Human
    participant A as Agent A
    participant B as Agent B
    participant C as Agent C
    participant V as Vault

    H->>V: create_project("Auth Rewrite", tasks: [...])
    Note over V: Tasks created:<br/>1. Design API (pending)<br/>2. Implement JWT (blocked on 1)<br/>3. Write tests (blocked on 2)<br/>4. Update docs (pending)

    par Parallel Work
        A->>V: claim_task("Design API")
        B->>V: claim_task("Update docs")
    end

    A->>V: complete_task("Design API")
    Note over V: "Implement JWT" auto-unblocked

    C->>V: claim_task("Implement JWT")
    C->>V: complete_task("Implement JWT")
    Note over V: "Write tests" auto-unblocked

    H->>V: get_project_status(project_id)
    V-->>H: 3/4 complete (75%)

Task Dependency Graph

graph LR
    A["Design API<br/><small>research</small>"] --> B["Implement JWT<br/><small>code</small>"]
    B --> C["Write Tests<br/><small>code</small>"]
    D["Update Docs<br/><small>writing</small>"]

    style A fill:#2ecc71,stroke:#27ae60,color:#fff
    style B fill:#3498db,stroke:#2980b9,color:#fff
    style C fill:#e74c3c,stroke:#c0392b,color:#fff
    style D fill:#2ecc71,stroke:#27ae60,color:#fff

Append Mode — Growing Projects

When requirements evolve mid-project, append new tasks to an existing project without recreating it:

graph TB
    subgraph Original["Original Project (4 tasks)"]
        A1["Design API"] --> A2["Implement JWT"]
        A2 --> A3["Write Tests"]
        A4["Update Docs"]
    end

    subgraph Appended["Appended (3 new tasks)"]
        B1["Add Rate Limiting"]
        B1 --> B2["Security Audit"]
        A2 -.->|depends_on_existing| B3["Load Testing"]
    end

    style Original fill:#1a1a2e,stroke:#0f3460,color:#fff
    style Appended fill:#16213e,stroke:#e94560,color:#fff
create_project(
  project_id: "proj-...",              // existing project
  tasks: [
    { title: "Add Rate Limiting", type: "code" },
    { title: "Security Audit", depends_on_indices: [0] },
    { title: "Load Testing", depends_on_existing: ["task-implement-jwt-id"] }
  ]
)

Task State Machine

stateDiagram-v2
    [*] --> pending: create_task
    pending --> claimed: claim_task
    pending --> blocked: update_task
    pending --> cancelled: update_task

    claimed --> in_progress: update_task
    claimed --> pending: unclaim
    claimed --> blocked: update_task
    claimed --> cancelled: update_task

    in_progress --> completed: complete_task
    in_progress --> needs_review: complete_task (review_required)
    in_progress --> failed: complete_task
    in_progress --> blocked: update_task
    in_progress --> pending: update_task
    in_progress --> cancelled: update_task

    needs_review --> completed: review_task (approve)
    needs_review --> revision_requested: review_task (reject)

    revision_requested --> in_progress: update_task

    blocked --> pending: auto-unblock / update
    blocked --> cancelled: update_task

    completed --> pending: reopen
    failed --> pending: retry
    cancelled --> pending: reactivate

    completed --> [*]

Multi-Agent Parallel Development

Run multiple AI agents on the same codebase simultaneously, each in its own git worktree, with the vault coordinating who's working on what.

The architecture: Git worktrees provide filesystem isolation. The vault provides coordination metadata. No conflicts, no stepping on each other's work.

How It Works

  1. Claim a task with worktree metadata — when an agent claims a task, it records the branch and worktree path

  2. Work in isolation — each agent works in its own directory on its own branch

  3. Vault tracks everythingget_context shows which agents are on which branches, list_tasks includes worktree info

  4. Complete and PR — when done, complete_task tells you the branch is ready for a pull request

Claude Code v2.1.49+ has native worktree support via --worktree (-w):

# Terminal 1: Agent works on auth API
claude --worktree design-api
# → "Claim the 'Design API' task with worktree_branch 'worktree-design-api'"

# Terminal 2: Agent works on documentation
claude --worktree update-docs
# → "Claim the 'Update docs' task with worktree_branch 'worktree-update-docs'"

Claude Code creates worktrees at <repo>/.claude/worktrees/<name> with branch worktree-<name>. Each agent works in its own directory, on its own branch.

With opencode / Codex CLI

Create worktrees manually, then point the agent at the right directory:

# Create worktrees
git worktree add .worktrees/auth-api -b worktree-auth-api
git worktree add .worktrees/update-docs -b worktree-update-docs

# Start agents in their worktrees
cd .worktrees/auth-api && opencode
# → "Claim task X with worktree_branch 'worktree-auth-api' and worktree_path '$(pwd)'"

What the Vault Tracks

When you claim a task with worktree fields:

# Task frontmatter after claim
status: claimed
assignee: claude-code-1
worktree_branch: worktree-auth-api
worktree_path: /repo/.claude/worktrees/auth-api

get_context includes worktree info for all active work:

{
  "active_work": [
    {
      "id": "task-2026-03-09-abc123",
      "title": "Design API endpoints",
      "assignee": "claude-code-1",
      "worktree_branch": "worktree-design-api",
      "worktree_path": "/repo/.claude/worktrees/design-api"
    },
    {
      "id": "task-2026-03-09-def456",
      "title": "Update documentation",
      "assignee": "claude-code-2",
      "worktree_branch": "worktree-update-docs",
      "worktree_path": "/repo/.claude/worktrees/update-docs"
    }
  ]
}

When a task completes, the response tells you the branch is ready:

Task "Design API endpoints" completed. Branch `worktree-design-api` is ready for PR.

Context Persistence

The core problem: AI agents lose all context between sessions. Decisions, discoveries, and in-flight work vanish.

mcp-obsidian-vault solves this with three tools that build a persistent knowledge layer:

graph TB
    subgraph Session1["Session 1"]
        S1A["Discovers: gray-matter<br/>crashes on undefined"] --> S1B["log_discovery()"]
        S1C["Decides: use RS256<br/>for JWT signing"] --> S1D["log_decision()"]
        S1E["Completes 3 tasks,<br/>2 still in progress"]
    end

    subgraph Vault["Obsidian Vault"]
        V1["Discoveries/<br/>gray-matter-crash.md"]
        V2["Decisions/<br/>use-rs256-signing.md"]
        V3["Tasks/<br/>DASHBOARD.md"]
    end

    subgraph Session2["Session 2 (new agent, fresh context)"]
        S2A["get_context()"] --> S2B["Receives:<br/>- 2 tasks in progress<br/>- RS256 decision<br/>- gray-matter gotcha<br/>- project at 60%"]
        S2B --> S2C["Continues work<br/>without repeating<br/>mistakes"]
    end

    S1B --> V1
    S1D --> V2
    S1E --> V3
    V1 & V2 & V3 --> S2A

    style Session1 fill:#1a1a2e,stroke:#e94560,color:#fff
    style Vault fill:#16213e,stroke:#0f3460,color:#fff
    style Session2 fill:#0f3460,stroke:#533483,color:#fff

Context-First Discipline

Every new session should start with one call:

get_context() → {
  active_projects: [{ id, title, progress: "3/7 (43%)" }],
  in_progress: [{ id, title, assignee, claimed_at }],
  pending_work: { "proj-abc": [...], standalone: [...] },
  blockers: [{ id, title, waiting_on: [{ id, title }] }],
  recent_decisions: [{ title, decision, status }],
  recent_discoveries: [{ title, discovery, recommendation }],
  pinned_notes: [...]
}

Git Sync & Cross-Device Flow

sequenceDiagram
    participant L as Laptop<br/>(MCP Server)
    participant G as GitHub<br/>(Private Repo)
    participant P as Phone<br/>(Obsidian Git)

    L->>L: Agent edits note
    L->>G: Auto-sync: commit + push
    P->>G: Pull on open
    G-->>P: Latest notes
    P->>P: Edit on the go
    P->>G: Commit + push
    L->>G: Pull (next auto-sync)
    G-->>L: Phone changes merged

Setup

  1. Laptop — set GIT_AUTO_SYNC=true with a private GitHub repo

  2. Phone (iOS)Obsidian Git plugin or Working Copy

  3. Phone (Android)Obsidian Git plugin (built-in git on Android)

Obsidian Git Setting

Value

Why

Auto pull on open

Enabled

Get latest when you open the app

Auto push after commit

Enabled

Push edits immediately

Pull on interval

5-10 min

Catch changes while app is open

Commit message

mobile: {{date}}

Distinguish mobile vs MCP commits

Use a private repo. Your notes are personal.


Task Note Structure

Tasks are markdown notes with structured YAML frontmatter. Project tasks are organized in per-project subfolders, while standalone tasks live at the Tasks/ root:

Tasks/
├── DASHBOARD.md
├── auth-rewrite/                              # project subfolder
│   ├── proj-2026-03-09-abc123-auth-rewrite.md
│   ├── task-2026-03-09-def456-design-api.md
│   └── task-2026-03-09-ghi789-implement-jwt.md
├── api-migration/                             # another project
│   └── ...
└── task-2026-03-09-mno345-fix-typo.md         # standalone task

Example task note:

---
id: task-2026-03-09-abc123
title: Implement auth module
status: in_progress
priority: high
type: code
assignee: claude-code-1
created: "2026-03-09T14:00:00.000Z"
updated: "2026-03-09T15:45:00.000Z"
depends_on: []
scope:
  - src/auth.ts
tags:
  - auth
---

## Description

Build JWT-based authentication for the API.

## Acceptance Criteria

- [ ] Tests pass
- [ ] Docs written

## Agent Log

- **[2026-03-09 14:30:00]** Starting implementation. Found 3 endpoints to modify.
- **[2026-03-09 15:45:00] [COMPLETED]** Auth module done with JWT support.

## Deliverables

- src/auth.ts
- src/auth.test.ts

A DASHBOARD.md is auto-generated after every task mutation with summary counts, active work, pending queue, blockers, and recent completions.


Agent Prompts

Three built-in MCP prompts for different agent personas:

Prompt

Role

Use When

task-worker

Find, claim, complete tasks

Spawning a coding agent

project-manager

Plan projects, decompose work, monitor

Orchestrating multi-agent work

vault-assistant

Read, search, organize notes

General vault management

Request via MCP:

{
  "method": "prompts/get",
  "params": {
    "name": "task-worker",
    "arguments": { "agent_id": "claude-1", "project_id": "proj-abc" }
  }
}

Or copy from prompts/ into your agent's system prompt.


Configuration

Required

Variable

Description

OBSIDIAN_VAULT_PATH

Absolute path to your vault

Vault

Variable

Default

Description

DAILY_NOTE_FOLDER

Daily Notes

Subfolder for daily notes

TRASH_ON_DELETE

true

Move to .trash/ instead of permanent delete

MAX_FILE_SIZE_BYTES

10485760

Max file size (10 MB)

MAX_SEARCH_RESULTS

50

Max search results

SEARCH_TIMEOUT_MS

30000

Search timeout

NOTE_EXTENSIONS

.md,.markdown

Note file extensions

TASKS_FOLDER

Tasks

Task notes subfolder

DECISIONS_FOLDER

Decisions

Decision records subfolder

DISCOVERIES_FOLDER

Discoveries

Discovery notes subfolder

AGENTS_FOLDER

Agents

Agent profile notes subfolder

USAGE_FOLDER

Usage

Token usage records subfolder

Git

Variable

Default

Description

GIT_AUTO_SYNC

false

Auto commit + push after every write

GIT_AUTO_SYNC_DEBOUNCE_MS

5000

Debounce interval

GIT_COMMIT_MESSAGE_PREFIX

vault:

Auto-commit message prefix

GIT_REMOTE

origin

Default remote

GIT_BRANCH

main

Default branch

GIT_TIMEOUT_MS

30000

Git operation timeout

GIT_PULL_REBASE

true

Use --rebase on pull

Webhooks

Variable

Default

Description

WEBHOOK_URL

Comma-separated webhook URLs for task event notifications

WEBHOOK_SECRET

HMAC-SHA256 secret for signing webhook payloads

WEBHOOK_TIMEOUT_MS

5000

Webhook HTTP request timeout


Security

  • Path traversal prevention — all paths validated against vault root, including symlink resolution

  • No shell injection — git commands use execFile (not exec)

  • Atomic writes — temp file + rename prevents partial writes on crash

  • Overwrite protectioncreate_note fails if note exists unless explicitly overridden

  • Trash safety — unique filenames prevent collision in .trash/

  • File size limits — configurable cap prevents reading huge files

  • Search timeout — prevents runaway searches

  • Git mutex — prevents concurrent git commands from conflicting


Robustness

  • Retry failed tasksupdate_task(status: "pending") clears assignee, increments retry_count

  • Unclaim stuck tasks — reclaim tasks from crashed agents

  • Timeout detectionlist_tasks flags tasks past timeout_minutes with is_overdue: true

  • Dependency validation — warns on nonexistent depends_on references

  • Dashboard health — all mutation responses include dashboard_refreshed status

Known Limitations

  • No file locking — claims are atomic within a single server process (Node event loop). Multiple server processes sharing a vault need external coordination.

  • Scope is advisoryscope[] is not enforced by the server. Agents should respect it.

  • Timeouts need check_timeouts — overdue tasks are detected but not auto-released; an agent or cron must call check_timeouts periodically.

  • Webhooks are fire-and-forget — webhook delivery is best-effort with one retry. No persistent queue.


Project Structure

src/
├── index.ts              # MCP server entry, 27 tools + 3 prompts
├── config.ts             # Environment variable parsing
├── errors.ts             # Typed errors + safe handler wrapper
├── vault.ts              # Filesystem: path safety, atomic writes, list, search
├── frontmatter.ts        # YAML parse/serialize, tag extraction
├── git.ts                # Git CLI wrapper with mutex
├── events.ts             # EventBus with typed task lifecycle events
├── webhooks.ts           # WebhookEmitter with HMAC-SHA256 signing
├── agent-registry.ts     # Agent profiles, scanning, capability matching
├── task-schema.ts        # Task types, IDs, validation, state machine
├── task-dashboard.ts     # Task scanning + DASHBOARD.md generation
├── prompts.ts            # MCP prompt registration
└── tools/                # One file per tool (27 files)

prompts/                  # Agent persona prompts (ship with npm)
skills/                   # Agent skills (ship with npm, skills.sh compatible)
test/run.mjs              # 375 integration tests

Development

npm install
npm run build             # TypeScript → build/
npm test                  # 375 integration tests
npm run dev               # tsc --watch

Contributing

Contributions are welcome! Here's how to get started.

Setup

git clone https://github.com/t-rhex/obsidian-mcp-server.git
cd obsidian-mcp-server
npm install
npm run build
npm test              # All tests must pass

Development Workflow

  1. Create a branch from main:

    git checkout -b feat/your-feature
  2. Make your changes. Each tool lives in its own file under src/tools/. The pattern is consistent — look at any existing tool for the structure.

  3. Add tests. Tests are in test/run.mjs — plain Node.js assertions, no framework. Add your tests before the cleanup section at the end of the file.

  4. Build and test:

    npm run build && npm test
  5. Push and open a PR against main:

    git push -u origin feat/your-feature
    gh pr create

CI runs on Ubuntu + Windows across Node 18, 20, and 22. All 6 matrix jobs must pass.

Code Style

  • TypeScript with strict mode. No any unless absolutely necessary.

  • One file per tool in src/tools/. Export schema and handler.

  • Every handler wrapped in safeToolHandler() (from src/errors.ts) for consistent error handling.

  • Zod v4 for input validation — note that z.record() requires two args: z.record(z.string(), z.unknown()).

  • Atomic writes — use vault.writeNote() which writes to a .tmp file then renames.

  • Strip undefined — never put undefined values in frontmatter objects. serializeNote strips them automatically, but avoid creating them upstream when possible.

Adding a New Tool

  1. Create src/tools/your-tool.ts with exported schema and handler

  2. Register it in src/index.ts (follow the existing pattern)

  3. Add integration tests in test/run.mjs

  4. Update the tool count in README.md and package.json description if applicable

Gotchas

  • macOS /tmp is a symlink to /private/tmp — always resolve paths with realpathSync

  • gray-matter crashes on undefined values in YAML — serializeNote handles this, but be aware

  • routing_rules[].deactivate — omit the key entirely rather than setting to undefined

  • Windows path separators — use split(/[/\\]/) not split("/")

  • opencode has no env field in MCP config — must use sh -c with inline env vars

Releases

Releases are automated. When a PR is merged to main with a version bump in package.json, CI automatically:

  1. Detects the version change

  2. Runs the full test matrix

  3. Publishes to npm

  4. Creates a GitHub Release

No manual publish steps needed. Just bump the version in your PR.


License

MIT

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

Maintenance

Maintainers
Response time
0dRelease cycle
2Releases (12mo)
Commit activity

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/t-rhex/obsidian-mcp-server'

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