qkb
Provides a hybrid search engine for Obsidian vaults, enabling semantic and keyword search with metadata filtering, retrieval of documents by ID, and index health status, exposed via MCP tools for LLM agents.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@qkbsearch my notes about certificate renewal"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
qkb — Query Knowledge Base
An on-device hybrid search engine for Obsidian vaults that understands YAML frontmatter metadata. Combines BM25 keyword search (SQLite FTS5) and vector semantic search (sqlite-vec) with metadata filtering, sibling-document surfacing, and two first-class interfaces: a CLI for humans and an MCP server for LLM agents.
Status: TypeScript rewrite — feature-parity with the Python v0.3.0 original, plus multi-provider embeddings and GPU-accelerated (Metal) local embedding on Apple Silicon.
Quickstart
1. Install (isolated global CLI):
npm i -g @miguelarios/qkbRequires Node ≥20. No separate service, no compile step for the default provider — node-llama-cpp ships prebuilt native binaries (Metal-accelerated on Apple Silicon) that download automatically on install.
2. Point qkb at your vault — create ~/.config/qkb/config.toml:
[vault]
path = "~/Documents/MyVault" # your Obsidian vault (read-only to qkb)
name = "MyVault" # used to build obsidian:// links3. Opt notes in. Only notes whose frontmatter has a context and/or
source property are indexed — and an opted-in note also needs an id and
a parseable date (created or date):
---
id: f47ac10b-58cc-4372-a567-0e02b2c3d401
context: homelab
created: 2026-03-15
---4. Index in two phases, then search:
qkb status # verify config, vault, and model resolve
qkb ingest # keyword index — fast, no model needed
qkb search "certificate renewal" # keyword (BM25) search works right away
qkb embed # compute vectors (downloads the model once; resumable)
qkb query "certificate renewal" # full hybrid (keyword + semantic) search
qkb mcp # stdio MCP server for Claude Code / DesktopIndexing is split so nothing blocks for hours: qkb ingest builds the
keyword index in seconds (no model), so qkb search works immediately;
qkb embed then computes the vectors that power semantic/hybrid search.
qkb embed is resumable — Ctrl-C is safe, and re-running continues where
it left off — and qkb status shows how many vectors are still pending.
Claude Code MCP registration:
claude mcp add qkb -- qkb mcpRelated MCP server: mcp-duckvault
Why the rewrite: Apple Silicon embedding is fast now
The Python original (qkb-search, still on PyPI — see Migrating from the Python version below) runs embeddings via onnxruntime, which is CPU-only on macOS: a full re-embed of a ~3,000-note vault takes roughly 4 hours. The TypeScript rewrite's default provider, node-llama-cpp, ships prebuilt Metal-accelerated binaries — the same full re-embed drops to ~10–15 minutes on an Apple Silicon Mac. Same model (embeddinggemma-300M), same search quality; the win is entirely in embedding throughput.
Embedding providers
Four interchangeable providers, set via [embedding].provider in config.toml:
provider | how it runs | when to use |
| in-process via | just works, fastest on-device option, especially on Apple Silicon |
| the Ollama HTTP API | you already run Ollama (e.g. a Linux box or shared server) |
| any OpenAI-compatible | OpenAI itself, Azure OpenAI, or a local server (LM Studio, vLLM, llamafile) |
| deterministic hash-based vectors, no model | tests and CI only |
Switching provider or model changes the vectors, so run qkb embed --full
afterward to re-embed everything.
# ~/.config/qkb/config.toml — llama (default)
[embedding]
provider = "llama"
model = "embeddinggemma-300M-Q8_0"
dimension = 768
# local_gguf_repo / local_gguf_file / model_cache_dir also configurable — see below# ~/.config/qkb/config.toml — ollama
[embedding]
provider = "ollama"
model = "embeddinggemma"
dimension = 768
ollama_host = "http://localhost:11434"# ~/.config/qkb/config.toml — openai-compatible
[embedding]
provider = "openai"
model = "text-embedding-3-small"
dimension = 1536
openai_base_url = "https://api.openai.com" # or a local/compatible endpointThe OpenAI API key is read from the QKB_OPENAI_API_KEY environment
variable only — it's never stored in config.toml.
Configuration reference
~/.config/qkb/config.toml (all keys optional; shown with their defaults).
QKB_CONFIG=/path/to/alt-config.toml points at a different config file
entirely.
[vault]
path = "~/Notes"
name = "Notes"
[database]
path = "~/.local/share/qkb/qkb.db"
[embedding]
provider = "llama" # llama | ollama | openai | fake
model = "embeddinggemma-300M-Q8_0"
dimension = 768
ollama_host = "http://localhost:11434"
local_gguf_repo = "ggml-org/embeddinggemma-300M-GGUF"
local_gguf_file = "embeddinggemma-300M-Q8_0.gguf"
model_cache_dir = "~/.cache/qkb/models"
openai_base_url = "" # optional override
# doc_template / query_template: optional explicit "{t}"-placeholder prompt
# templates, overriding the per-model default asymmetric prefixing.
[chunking]
target_tokens = 500
overlap_percent = 15
[search]
default_limit = 10
rrf_k = 60
vec_candidates = 30
fts_candidates = 30
fts_weights = [5.0, 3.0, 2.0, 1.0, 0.5]
[frontmatter]
# Optional alias mapping for non-default frontmatter property names, e.g.:
# id = ["uuid"]
# created = ["created", "date created"]Environment-variable overrides
Only the keys below have a QKB_* environment-variable override — [chunking], [search], and [frontmatter] keys do not (config-file-only). An env var always wins over config.toml.
| env var |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(no |
|
Plus QKB_CONFIG, which isn't a per-key override — it points qkb at a
different config.toml path entirely.
MCP usage
qkb mcp runs a stdio MCP server exposing three tools to LLM agents:
qkb— hybrid BM25 + vector search with the same filters as the CLI (context,source,type,tags, date range,limit).qkb_get— retrieve a single document by id (or unambiguous id prefix).qkb_status— index health: document/chunk/vector counts, contexts, pending-vector count.
Register with Claude Code:
claude mcp add qkb -- qkb mcpOr point any MCP-compatible client at the qkb mcp stdio command directly.
Homebrew
A single-file formula lives at Formula/qkb.rb in this repo (depends_on "node", installs the published npm package). Until a dedicated homebrew-qkb tap exists, install it directly from the repo:
brew install --formula https://raw.githubusercontent.com/miguelarios/qkb/main/Formula/qkb.rbThe Short Version
Notes opt in to indexing via frontmatter (context and/or source properties). An ingestion pipeline walks the vault, chunks markdown with structure-aware break-point scoring, embeds in-process (node-llama-cpp/GGUF by default; Ollama or an OpenAI-compatible endpoint optional), and stores everything in a single SQLite file. A search engine layers BM25 (document-level, weighted columns), vector similarity (chunk-level), and Reciprocal Rank Fusion on top — exposed as qkb search / vsearch / query, qkb get <UUID>, and qkb mcp.
Inspired by QMD's search architecture and its GPU-fast native-binary distribution model, adapted for structured knowledge systems with frontmatter metadata.
Documents
PRD — what we're building and why
Technical Design — architecture, schema, search algorithms
Architecture Decision Records — the decision log
Implementation Plans — milestone-by-milestone build plan, including the TypeScript rewrite plan
Migrating from the Python version
The original Python implementation (qkb-search, PyPI, v0.3.0) is kept in this repo at legacy/python/ and remains installable (pip install qkb-search / uv tool install qkb-search) but is superseded by this npm package — no further Python releases are planned except emergency patches. Both share the same ~/.config/qkb/config.toml, ~/.local/share/qkb/qkb.db, and ~/.cache/qkb/models paths, but switching between them (or between embedding providers) changes the vectors, so run qkb embed --full after switching.
Development
npm ci
npm test # vitest, offline (FakeProvider — no Ollama/OpenAI/model download)
npm run typecheck # tsc --noEmit
npm run lint # biome check
npm run build # tsc -p tsconfig.build.json -> dist/
npm run golden-queries -- ~/.config/qkb/golden_queries.yaml # acceptance harness (needs a real index)npm run golden-queries scores each query in the YAML file against the hybrid top-3 (PRD target: ≥80%); see legacy/python/scripts/golden_queries.example.yaml for the schema. Your real golden-queries file is personal vault data and must never be committed to this repo.
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceProvides semantic search and keyword search over Obsidian notes, along with direct note retrieval, allowing external AI agents to query and access the vault.18BSD Zero Clause
- Alicense-qualityAmaintenanceProvides a RAG system for your Obsidian Vault using DuckDB and vector search, enabling semantic search and note retrieval through AI agents.2MIT
- Alicense-qualityDmaintenanceEnables AI agents to navigate, search, and rank notes in an Obsidian vault using graph relationships, providing context-aware access to knowledge without exposing raw file contents.MIT
- Alicense-qualityFmaintenancePersistent semantic memory server for Obsidian vaults, enabling AI agents to search, read, write, and explore notes with semantic understanding and incremental indexing.Apache 2.0
Related MCP Connectors
Search your knowledge bases from any AI assistant using hybrid RAG.
Search your Obsidian vault to quickly find notes by title or keyword, summarize related content, a…
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/miguelarios/qkb'
If you have feedback or need assistance with the MCP directory API, please join our Discord server