Skip to main content
Glama

agent-kb

A drop-in, local-first knowledge base for LLM coding agents. Index your repository's documentation, concept ontology, and build targets into Qdrant, and expose retrieval to any MCP-capable agent (Claude Code, Cursor, custom agents) as tools — not context stuffing.

No closed corpora, no paid APIs, no managed vector database: one Qdrant container, CPU-local embeddings via fastembed, and a small Python MCP server.

The idea

Agents lose accuracy the moment they're asked about anything outside their pre-training corpus. The usual fix is RAG, but how the agent consumes retrieval matters more than the embedding model: inline context-stuffing burns tokens and amplifies noise; tool-shaped retrieval lets the agent ground claims selectively, the same way it already uses other tools.

Grounding splits into three layers with different staleness profiles:

Layer

Question shape

Owned by

Prose

"How does X work?" "What's the deployment story?"

this KB (markdown sources)

Ontology

"Which class implements concept X?"

this KB (concept → symbol bindings)

Live code

"Where is that class right now? Who calls it?"

your LSP — see agent-code-intel

The KB deliberately stops at the symbol name. It never stores file paths or line numbers for code — that's the LSP's job, and indexing source into a vector store just guarantees churn.

Related MCP server: agentmako

Install as a Claude Code plugin (fastest)

The repo doubles as a plugin marketplace covering both grounding repos:

/plugin marketplace add zmij/agent-kb
/plugin install agent-kb@agent-grounding
/plugin install agent-code-intel@agent-grounding   # optional: the LSP layer

The agent-kb plugin ships the knowledge-base operating skill and the MCP server — Claude Code launches kb serve-mcp via uv run from the plugin checkout, and the server discovers your repo root by walking up from the session's working directory to the nearest kb.yaml. No per-worktree registration needed.

Then type /kb-setup in your repo: the bundled setup skill walks the agent through the rest — start Qdrant, author a starter kb.yaml (it asks which doc trees to index), run the first index, and verify search. Requires uv on PATH and Docker for Qdrant.

Install (clone / submodule)

Requirements: Python 3.11+, uv, Docker (for Qdrant).

git clone https://github.com/zmij/agent-kb          # next to your repo, or as a submodule
cd agent-kb
make install        # uv venv + editable install
make up             # start Qdrant (docker compose)

Or from your own repo, if you vendor this as a submodule and include kb.mk in your Makefile (see Make integration):

make kb-install kb-up

Configure your project

Create kb.yaml at your repository's root (not in this repo). It declares the project identity and the sources to index:

project: my-project           # → collection "my_project_kb", MCP server "my-project-kb"

sources:
  user_docs:
    type: markdown            # heading-aware chunking, frontmatter lifted to payload
    root: docs/guides
    uri_prefix: "docs://guides"   # optional: preserve your internal link scheme
  arch_docs:
    type: markdown
    root: docs
    exclude: [guides, ontology]   # subtrees that have their own indexers
  ontology:
    type: ontology            # concept → code-symbol bindings (see below)
    root: docs/ontology
  make_targets:
    type: make_targets        # every documented `target: ## description`
    files: [Makefile, "scripts/make/*.mk"]

# Only needed if you use the ontology maintenance loop (verify/heal/suggest-new)
symbols:
  language: cpp
  include_root: include/myproject   # public header tree to parse
  base_classes: [Strategy]          # subclasses of these are discoverable concepts
  strip_suffixes: [Strategy, Impl]  # trimmed when deriving stub titles/slugs
  stub_subdir: strategies           # stubs land in docs/ontology/strategies/
  stub_kind: strategy               # `kind:` value written into stubs

All sources share one collection by default (cross-source retrieval in a single search); override per-source with collection: or globally with default_collection:.

kb index --all                 # chunk → embed → upsert (incremental by default)
kb search "how do I deploy"    # semantic search across all sources
kb sources                     # what's indexed, per source
kb index user_docs --full      # re-embed one source from scratch

Incremental indexing hashes file content and only re-embeds changed files; chunks of deleted files are evicted automatically.

Expose to your agent (MCP)

kb serve-mcp                   # stdio MCP server

For Claude Code, register per project/worktree:

claude mcp add my-project-kb -e KB_REPO_ROOT=$(pwd) -- \
  /path/to/agent-kb/.venv/bin/kb serve-mcp

(the kb-register make target below does this for you, self-healing).

Tools exposed: kb_search, kb_get, kb_list_sources, kb_reindex.

The ontology layer

An ontology entry is a small markdown file binding a domain concept to the code symbols that implement it:

---
concept: x-wing
title: X-Wing
kind: technique
implements:
  - sudoku::XWingTechnique
related_concepts: [swordfish]
---

A fish pattern on two rows and two columns…

The chunk text bakes the symbol list into the embeddable body, so "which class implements X-Wing" hits the bound names, not just prose. And because bindings are curated, they need a maintenance loop:

Command

What it does

kb verify

Checks every implements:/underlying: binding still resolves to a symbol defined under symbols.include_root. Non-zero exit on drift — wire it into pre-commit.

kb heal

Proposes replacements for broken bindings by name-similarity against current symbols (deterministic, stdlib-only). --apply rewrites entries when confidence ≥ 0.85.

kb suggest-new

Finds subclasses of symbols.base_classes with no ontology entry and drafts stub files (--apply to write). Stubs carry only the binding + header @brief; prose is for humans.

Currently the symbol parser covers C++ headers (tree-sitter). Other languages: PRs welcome — the parser interface is one function, parse_header(path, root) -> [Symbol].

Make integration

kb.mk ships includable targets (kb-up, kb-index, kb-search, kb-register, kb-verify, …). From a consuming repo:

KB_DIR := tools/knowledge_base       # wherever the submodule/clone lives
KB_MCP_NAME := my-project-kb
include $(KB_DIR)/kb.mk

Run make kb-help for the full target list.

Per-worktree collection scoping

If you use git worktrees, each worktree writes to its own Qdrant collections, suffixed with a slug derived from the worktree directory name (my_project_kb_backend, my_project_kb_frontend, …). Concurrent indexing across worktrees never collides, while one Qdrant container serves them all.

The slug derives from KB_REPO_ROOTkb-register bakes KB_REPO_ROOT=$(pwd) into the MCP registration so queries always land in the registering worktree's collections. kb collections --all shows every worktree's collections.

Configuration reference

Environment (infrastructure — machine-level, .env supported):

Variable

Default

Purpose

KB_REPO_ROOT

auto-detected (kb.yaml walk-up)

Consuming repo root

KB_CONFIG

<repo_root>/kb.yaml

Project config path

KB_WORKTREE_SLUG

derived from repo root basename

Collection suffix override

KB_EMBED_BACKEND

fastembed

fastembed or ollama

KB_FASTEMBED_MODEL

BAAI/bge-small-en-v1.5

Embedding model

QDRANT_HOST / QDRANT_HTTP_PORT / QDRANT_GRPC_PORT

localhost / 6333 / 6334

Qdrant endpoint

Switching embedding backends changes vector dimensions — re-index with kb index --all --full.

Layout

agent-kb/
├── kb.example.yaml        # annotated project-config template
├── kb.mk                  # includable make module
├── docker-compose.yml     # Qdrant
├── src/kb/
│   ├── config.py          # Settings (env) + KBConfig (kb.yaml)
│   ├── chunking/          # heading-aware markdown chunker
│   ├── embedding/         # provider Protocol + fastembed/ollama backends
│   ├── indexers/          # markdown / ontology / make_targets
│   ├── parsing/           # C++ header parser (tree-sitter)
│   ├── runner.py          # chunk → embed → upsert, incremental + retries
│   ├── verify.py, heal.py, discover.py   # ontology maintenance loop
│   ├── qdrant_client.py   # store wrapper, per-worktree namespacing
│   ├── mcp_server.py      # stdio MCP server
│   └── cli.py             # `kb` entrypoint
├── tests/
└── docs/WORKSHOP.md       # background: design rationale and the workshop story

For agents

If you are an LLM agent working in a repo that uses agent-kb, read AGENTS.md for when to search the KB, how to phrase queries per source, and how to run the ontology maintenance loop.

Contributing

main is branch-protected: no direct pushes (admins and their agents included), linear history, everything lands through a pull request. Run make test before opening one. This is the same Gate discipline the tool exists to enforce — the repo practises it on itself.

Licence

MIT.

Available Tools

4 tools
kb_getA

Fetch the full text and payload of a chunk by id.

Args: id: The chunk id returned by kb_search. source: Optional source hint to scope which collection to look in. If omitted, every known collection is checked.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYes
sourceNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral disclosure burden. It explains the result content ('full text and payload') and adds important scoping behavior: when source is omitted, every known collection is checked. It doesn't cover not-found behavior or auth requirements, but for a simple getter this is reasonably transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: one clear summary sentence followed by a concise Args section. Every sentence contributes meaningful information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter getter with an output schema present, the description covers the essential call semantics and parameter behavior. It could have explicitly pointed to kb_list_sources for valid source values or described not-found behavior, but these are minor gaps given the tool's simplicity and the availability of an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description fully compensates by explaining both parameters. It defines 'id' as the chunk id returned by kb_search, and 'source' as an optional collection-scoping hint with explicit default behavior when omitted. This adds real meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Fetch the full text and payload of a chunk by id.' This clearly distinguishes the tool from siblings like kb_search, kb_list_sources, and kb_reindex, which serve different operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: the id should come from 'kb_search', and the source hint scopes the lookup, with the default behavior of checking every known collection if omitted. It doesn't explicitly state when not to use this tool or name alternatives, but the linkage to kb_search provides strong usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kb_list_sourcesA

List configured sources and the state of their Qdrant collections.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the behavioral disclosure burden. 'List' implies a read-only operation and 'state of their Qdrant collections' indicates the kind of information returned. However, it does not explicitly state that it is non-mutating, requires no setup, or has no side effects. It is minimally adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, direct sentence that efficiently communicates the tool's purpose. Every word earns its place, and the core action is front-loaded with 'List configured sources.' No filler or redundant phrasing is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has zero parameters and an output schema is present, the description does not need to explain return values. It captures the essential scope ('configured sources' and collection state). It could be more complete by noting how this relates to sibling tools, such as using it before reindexing, but overall it is sufficient for a simple list operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so schema coverage is trivially 100%. The baseline for 0-parameter tools is 4. The description does not add parameter-specific meaning, but none is needed because there are no parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb ('List'), a specific resource ('configured sources'), and the additional detail of 'the state of their Qdrant collections.' This distinguishes it from the sibling tools (kb_search, kb_get, kb_reindex), which imply searching, retrieving, and reindexing rather than listing sources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no explicit guidance on when to use this tool versus the siblings. It does not mention scenarios like checking configured sources, verifying collection state before reindexing, or troubleshooting. Usage must be inferred from the word 'List,' so this is a clear gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

kb_reindexB

Re-run an indexer.

Args: source: Indexer name from kb_list_sources.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourceYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavioral traits itself. It only says 'Re-run an indexer' and does not mention side effects, runtime, permissions, idempotency, or potential impact, leaving the agent with little safety context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely lean: one action sentence plus one parameter explanation. Every element carries information, and the core purpose is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with an output schema, the core invocation details are present. However, with zero annotations, the absence of any behavioral context such as side effects or prerequisites leaves moderate gaps for an agent deciding whether and how to invoke it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema only defines source as a string, and schema description coverage is 0%. The description compensates by explaining that source is an indexer name and tells the caller to obtain it from kb_list_sources, which is meaningful guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'Re-run an indexer.' This is distinct from the sibling tools kb_search, kb_get, and kb_list_sources, though it does not elaborate on what re-running entails.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies the intended workflow by directing the caller to use an indexer name from kb_list_sources, but it does not explicitly state when to use this tool over alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.1/5.0
Disambiguation5/5

Each tool targets a distinct operation: search, fetch-by-id, list sources, and reindex. There is no meaningful overlap; kb_search and kb_get are clearly separated by query-based retrieval versus direct ID lookup.

Naming Consistency5/5

All tools use the consistent kb_ prefix followed by a clear verb or verb-noun phrase: search, get, list_sources, reindex. The naming pattern is uniform and predictable.

Tool Count5/5

Four tools is compact but well-scoped for a knowledge base server covering retrieval, inspection, source listing, and maintenance. Each tool earns its place without unnecessary redundancy.

Completeness4/5

Core knowledge base operations are covered: search, fetch chunk content, list sources, and reindex. Minor gaps exist such as no delete/clear collection or detailed status beyond source listing, but these are not critical for the apparent purpose.

Maintenance

ActivitySlowing
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Persistent codebase knowledge layer for AI agents. Pre-digests codebases into structured knowledge (symbols, dependency graphs, co-change patterns, architectural decisions) and serves via MCP. 28 languages, 14 tools, ~85% token reduction.
    12
    7
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Local-first codebase intelligence engine providing AI coding agents with a typed MCP toolset for understanding and navigating code repositories.
    100
    51
    Apache 2.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    An in-memory knowledge graph MCP server that gives coding agents structural and semantic recall over codebases by indexing Python source, ADR documents, and project configuration, exposing 7 tools for search, traversal, context retrieval, and natural-language Q&A.
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides LLM agents with a structured, queryable, local-first knowledge base with typed documents and full-text search via MCP.
    MIT

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/zmij/agent-kb'

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