MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

Fast DuckDB BM25 MCP search server for Obsidian vaults

Created 5/18/2026
Updated about 4 hours ago
Repository documentation and setup instructions

Obsidian DuckDB MCP

Fast local search for Obsidian vaults, exposed as an MCP server for Claude Code, Codex, and other MCP clients.

The vault stays the source of truth. DuckDB is only a derived, rebuildable index.

Why

Large Obsidian vaults are useful, but plain filesystem search wastes context and returns noisy snippets. This project builds a local DuckDB index with BM25 full-text search, tags, links, backlinks, metadata, and vault statistics, then exposes that index through MCP tools.

Typical result:

  • rg over markdown: fast enough, but noisy and token-heavy.
  • DuckDB BM25 MCP: ranked note-level results, fewer tokens, better recall.

Features

  • Index any local Obsidian vault into DuckDB.
  • BM25 full-text search over note title and body.
  • Parse frontmatter tags and inline #tags.
  • Parse Obsidian wikilinks and Markdown links.
  • Resolve backlinks and broken links.
  • Expose MCP tools:
    • search(query, limit)
    • get_note(path)
    • backlinks(path)
    • list_tags(prefix, limit)
    • stats()
    • rebuild_index()
  • Works over stdio, so it fits Claude Code and Codex.
  • No cloud service required.

Architecture

Obsidian vault
  └─ Markdown files
      │
      ▼
DuckDB index
  ├─ notes
  ├─ note_tags
  ├─ note_links
  ├─ note_meta
  └─ build_log
      │
      ▼
MCP stdio server
  ├─ Claude Code
  ├─ Codex
  └─ any MCP client

Install

Option 1: use uvx from GitHub

uvx --from git+https://github.com/gemini-it/obsidian-duckdb-mcp obsidian-duckdb-index \
  --vault "$HOME/Documents/Obsidian/MyVault" \
  --db "$HOME/.cache/obsidian-duckdb/vault.duckdb"

Run MCP server:

uvx --from git+https://github.com/gemini-it/obsidian-duckdb-mcp obsidian-duckdb-mcp \
  --vault "$HOME/Documents/Obsidian/MyVault" \
  --db "$HOME/.cache/obsidian-duckdb/vault.duckdb"

Option 2: clone locally

git clone https://github.com/gemini-it/obsidian-duckdb-mcp.git
cd obsidian-duckdb-mcp
uv sync
uv run obsidian-duckdb-index --vault "$HOME/Documents/Obsidian/MyVault" --db ./vault.duckdb
uv run obsidian-duckdb-mcp --vault "$HOME/Documents/Obsidian/MyVault" --db ./vault.duckdb

Claude Code configuration

Add this to your Claude Code MCP config.

{
  "mcpServers": {
    "vault": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/gemini-it/obsidian-duckdb-mcp",
        "obsidian-duckdb-mcp",
        "--vault",
        "/absolute/path/to/ObsidianVault",
        "--db",
        "/absolute/path/to/vault.duckdb"
      ]
    }
  }
}

Restart Claude Code after changing MCP configuration.

Codex configuration

Add this to ~/.codex/config.toml.

[mcp_servers.vault]
command = "uvx"
args = [
  "--from",
  "git+https://github.com/gemini-it/obsidian-duckdb-mcp",
  "obsidian-duckdb-mcp",
  "--vault",
  "/absolute/path/to/ObsidianVault",
  "--db",
  "/absolute/path/to/vault.duckdb"
]

Restart Codex after changing MCP configuration.

Environment variables

Instead of CLI flags:

export OBSIDIAN_VAULT_PATH="$HOME/Documents/Obsidian/MyVault"
export OBSIDIAN_DUCKDB_PATH="$HOME/.cache/obsidian-duckdb/vault.duckdb"
uvx --from git+https://github.com/gemini-it/obsidian-duckdb-mcp obsidian-duckdb-mcp

MCP tools

search(query, limit=10)

BM25 search over note titles and content.

{
  "query": "typebot delete resultIds",
  "limit": 10
}

Returns:

[
  {
    "path": "04 - Incidents/2026-05-18 - Typebot.md",
    "title": "2026-05-18 - Typebot DELETE resultIds",
    "score": 10.0639
  }
]

get_note(path)

Returns one full note with tags, metadata, incoming links, outgoing links, and content.

backlinks(path)

Returns notes linking to a path.

list_tags(prefix="", limit=50)

Returns tags and usage counts.

stats()

Returns note count, tag count, link count, broken links, and last build time.

rebuild_index()

Rebuilds the DuckDB index from the configured vault path.

Reindexing

Manual:

obsidian-duckdb-index --vault "/absolute/path/to/ObsidianVault" --db "/absolute/path/to/vault.duckdb"

Cron example:

*/5 * * * * uvx --from git+https://github.com/gemini-it/obsidian-duckdb-mcp obsidian-duckdb-index --vault "$HOME/Documents/Obsidian/MyVault" --db "$HOME/.cache/obsidian-duckdb/vault.duckdb"

Systemd examples are in examples/systemd/.

Recommended assistant instruction

Use vault search first:

Before answering questions about local technical, client, or operational context, use the vault MCP search tool. Prefer search/get_note/backlinks over filesystem grep/read. Use filesystem reads only when editing files or when MCP cannot answer the question.

What this is not

  • Not an Obsidian plugin.
  • Not a hosted search service.
  • Not a vector database.
  • Not a replacement for your Markdown files.

DuckDB is a derived index. Delete it any time and rebuild.

ChromaDB?

Not in v1. BM25 plus tags and backlinks are enough for most small and medium vaults. A vector sidecar can be added later for semantic search, but should not replace DuckDB as the canonical structured index.

Development

git clone https://github.com/gemini-it/obsidian-duckdb-mcp.git
cd obsidian-duckdb-mcp
uv sync
uv run obsidian-duckdb-index --vault ./tests/fixtures/vault --db ./tmp/test.duckdb
uv run obsidian-duckdb-mcp --vault ./tests/fixtures/vault --db ./tmp/test.duckdb

Security

The MCP server exposes whatever is in the configured vault. Run it only for trusted local MCP clients. Do not expose stdio wrappers or HTTP bridges to untrusted networks.

License

MIT

Quick Setup
Installation guide for this server

Install Package (if required)

uvx obsidian-duckdb-mcp

Cursor configuration (mcp.json)

{ "mcpServers": { "gemini-it-obsidian-duckdb-mcp": { "command": "uvx", "args": [ "obsidian-duckdb-mcp" ] } } }