MCPVault Documentation

repository·main·Indexed 23 days ago

https://github.com/bitbonsai/mcpvault

A Model Context Protocol (MCP) server that acts as a universal bridge between AI assistants (such as Claude, ChatGPT, or Cursor) and Obsidian vaults. It enables AI agents to safely read, write, search, and manage notes and metadata within a local knowledge base without requiring Obsidian plugins. Key features include BM25 relevance reranking for search, AST-aware YAML frontmatter updates, and comprehensive security measures to prevent path traversal.

Tokens
25.2K
Snippets
61
Records
167
Agent score
81%

What's inside MCPVault

  1. Overview of MCPVault Core Features

    main

    MCPVault is designed for safe, high-performance AI access to local knowledge bases. Key capabilities include:

    • Powerful Search: Fast full-text search using multi-word matching and BM25 relevance ranking across names, content, tags, and metadata.
    • Safe Frontmatter Handling: Uses AST-aware YAML updates to preserve raw formatting (dates, quotes, time values) for unmodified fields during updates.
    • File Operations: Safe read, write, create, update, and organize operations for vault management.
    • Security: Includes path traversal protection and controlled access via the MCP protocol.
    • Token Optimization: Uses minified JSON field names and compact responses to reduce token usage in AI API calls.
    • Complete Toolkit: Provides 15 MCP tools including read, write, patch, move files, search content, manage tags, update frontmatter, and vault stats.
  2. MCPVault Feature Set and Capabilities

    main

    MCPVault provides a comprehensive toolkit for interacting with an Obsidian vault via MCP.

    Core Capabilities

    • File Operations: read_note, write_note, patch_note, delete_note, move_note, move_file.
    • Directory Operations: list_directory.
    • Batch Operations: read_multiple_notes.
    • Search: search_notes (supports multi-word matching and BM25 relevance reranking).
    • Metadata Management: get_frontmatter, update_frontmatter, get_notes_info, get_vault_stats.
    • Tag Management: manage_tags (add, remove, list).

    Key Technical Features

    • Safe Frontmatter: Uses gray-matter with AST-aware updates to prevent corruption of YAML frontmatter.
    • Write Modes: Supports overwrite, append, and prepend for content editing.
    • Token Optimization: Responses are 40-60% smaller due to minified field names and compact JSON.
    • Path Filtering: Automatically excludes system files like the .obsidian directory.
    • Zero Dependencies: Does not require any Obsidian plugins to function.
  3. Enforce triage caps for automated fixes

    main

    To prevent runaway automation, the following caps must be respected during triage:

    • Per-run fix cap: 3: A maximum of 3 findings can be sent for fan-out per run. Rank by priority; remaining findings should be moved to the inbox as open to be picked up in the next run. Never silently drop deferred findings.
    • Attempt cap: 2: If the automation loop fails to fix a finding twice, it must stop retrying and move to needs_human. A maintainer must manually reopen it.
    • Scope cap: 2 files: Any draft that touches more than 2 source files is considered too large for the loop and must be sent to the inbox, regardless of the reviewer's verdict.
  4. Apply the Fit-to-Ethos gate for PR reviews

    main

    A PR being technically mergeable is not sufficient. Before recommending a merge, evaluate it against the project's ethos (defined in README.md and AGENTS.md).

    mcpvault Ethos:

    • Universal MCP bridge for Obsidian vaults.
    • Safe read/write operations.
    • Preserve YAML frontmatter.
    • Enforce security boundaries (never expose .git, .obsidian, or system directories).
    • Simplicity.

    Verdict Actions:

    • Fits Ethos: Eligible to merge.
    • Mismatch: If a PR expands scope unnecessarily, weakens security/safety, or adds complexity, do not merge. Instead, draft a decline-or-redirect comment to the inbox explaining the mismatch.
    • Documentation: State the fit verdict explicitly in the inbox review entry (e.g., "fits ethos: X" or "scope creep vs README: Y").
  5. Understand the Obsidian Skill routing policy

    main

    The Obsidian Skill routes requests between three different backends based on user intent to ensure data integrity and optimal performance:

    1. MCP (Default): Used for standard vault data operations like reading, writing, patching, searching notes, and managing frontmatter or tags. This is the preferred method for headless or sandboxed operations.
    2. Obsidian CLI/App Context: Used when app-specific context is required, such as opening a note in the editor, accessing the currently active file, or triggering plugin workflows.
      • Crucial for Renaming: Use the CLI move command when the Obsidian app is running. The CLI's move rewrites all internal links to the old path. If the app is not running, the skill falls back to MCP move_note, which is a filesystem move and will leave backlinks stale.
    3. CLI Git: Used for sync, backup, or repository management workflows (commit, pull, push, etc.).

    Decision Rule: If a request is ambiguous, prioritize MCP unless the user explicitly asks for sync, backup, git, or app-specific behavior.

  6. How the Obsidian Skill routes operations

    main

    The Obsidian Skill acts as an orchestrator that routes user intent to one of three backends:

    1. MCP (Model Context Protocol): Used for safe, sandboxed file I/O. This is the default for reading, writing, searching, and managing tags/frontmatter. It is the preferred method for headless operations.
    2. Obsidian CLI: Used for operations requiring the running Obsidian desktop app. This includes getting the active file, opening notes in the editor, managing daily notes with templates, checking backlinks, and performing link-aware moves/renames (which rewrite internal links).
    3. Git CLI: Used for vault synchronization, backups, and versioning. This works headlessly and does not require the Obsidian app to be running.
  7. Identify worth-doing signals for automated fixes

    main

    A signal is only worth-doing (eligible for fan-out) if it meets all of the following criteria:

    • Bounded and mechanical: e.g., a failing test with an obvious cause, a regression, a small correctness bug, a typo, an off-by-one error, or a missing guard.
    • Within scope cap: The expected change must affect $\le 2$ files and include an updated test.
    • Clear pass/fail signal: A test that should pass or a build that should compile.
    • Not a complex change: It must not be a feature request, an API change, a dependency major-bump, or anything requiring a design decision.

    Priority Order for Fixes:

    1. CI failures on main.
    2. CI failures on open PRs.
    3. Regressions from recent commits.
    4. Open issues with clear, small, reproducible bugs.
  8. Project architecture and core modules

    main

    The MCPVault codebase is organized into the following core modules:

    • server.ts: The MCP server entry point.
    • src/frontmatter.ts: Handles YAML frontmatter using gray-matter.
    • src/filesystem.ts: Manages safe file operations with path validation.
    • src/pathfilter.ts: Handles directory and file filtering.
    • src/search.ts: Provides note search functionality supporting both content and frontmatter.
    • src/uri.ts: Generates Obsidian URIs for deep linking.
    • src/types.ts: Contains TypeScript type definitions.
  9. Derive stable finding IDs

    main

    To ensure deduplication works across different runs, findings must use a stable, lowercased, and hyphenated composite ID. The format is:

    id = "<source>:<signature>" (where spaces are replaced by -)

    Signature Selection by Source

    SourceSignature Strategy
    issue / prThe number (e.g., issue:107, pr:132).
    ciThe failing test name, NOT the run ID or SHA (e.g., ci:filesystem.test.ts-rejects-path-traversal).
    commitThe regression caused by the commit, NOT the SHA.
    promiseThe thread the unkept commitment lives on (e.g., promise:49).

    Using the same signature ensures that different runs of the same broken test map to the same finding ID.

  10. Understand the Triage Skill loop

    main

    The Triage Skill is a self-resuming automation loop designed to manage repository health. It follows a specific lifecycle:

    1. Gather: A read-only phase that collects signals from the last 24 hours (or since the last run), including CI failures, open issues, recent commits, and unfulfilled promises made by the maintainer in comments.
    2. Load State: Reads .triage/state.json to map findings to stable IDs (hashes of source + signature).
    3. Triage: Classifies signals as known + terminal (skip), known + open (retry), new + worth-doing (proceed to fix), new + needs judgment (move to inbox), or noise (ignore).
    4. Fan-out:
      • First, it checks for existing contributor PRs to review instead of creating new ones.
      • If no PR exists, it creates an isolated git worktree for the fix.
      • It spawns a Draft agent to write the fix and a Review agent to verify it via npm test and npm run build.
    5. Persist: Updates .triage/state.json and logs the run to .triage/runs/<date>.md.
    6. Comments: Drafts responses (acknowledgments, decisions) to .triage/inbox.md for human approval. Note: The loop is configured to NEVER post comments directly.
    7. Spill: Moves unclassifiable or overflow items to .triage/inbox.md for manual review.
  11. Manage Tags in Obsidian

    main

    Tags in Obsidian come from two sources:

    1. Frontmatter tags: Defined in the YAML block (e.g., tags: [foo, bar]).
    2. Inline tags: Written in the body text using the # symbol (e.g., #foo).

    Key Behaviors:

    • Nesting: Use forward slashes for hierarchy, such as #project/active.
    • MCP Tooling: The manage_tags tool merges both sources when performing a list operation, but it only modifies the frontmatter when performing add or remove operations.
  12. Identify promised but undone commitments

    main

    A signal is classified as promised but undone when a maintainer has made a commitment in a comment (e.g., "I'll fix this", "on it") on a thread that remains open without a merged PR.

    • ID Signature: promise:<issue#> (deduplicated across runs).
    • Routing: Always lands in the inbox under ## Open commitments (you promised, not shipped).
    • Content: Must include the thread, the quoted promise, how long ago it was made, and the current state.
    • Automation: If the promised fix meets the worth-doing criteria and has no open PR, the loop may draft it. The nudge should then read "drafted PR #X toward this" instead of just "still open". The nudge is posted to the inbox, never as a public comment.