kmd
Provides tools for managing and searching an Obsidian markdown vault, with validation, indexing (SQLite FTS5), and MCP tools for AI 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., "@kmdsearch knowledge base for transformer models"
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.
kmd — knowledge-markdown
kmd is a knowledge system for AI agents, built on Open Knowledge Format primitives: plain markdown, YAML frontmatter, a controlled vocabulary. What it adds is timing. The right context reaches the agent at the right moment, and costs nothing the rest of the time.
A cold session gets its orientation in one prime call: current focus, invariants, what to read. search returns ranked candidates, never page dumps. Hooks steer the agent at the exact event where a rule applies: a reminder on the prompt that needs it, a gate on the tool call that would break it, validation on the write that touched the vault. Rules that would otherwise sit in instruction files, paying tokens on every request, fire only when they matter.
The vault stays plain markdown in git, Obsidian-compatible. Works with Claude Code, Codex, and Kiro. No database to run.
npx @bartolli/kmd --helpQuick start
Two setups. Pick one, or use both; they compose.
A global vault. One personal wiki serving all your projects:
npx @bartolli/kmd init ~/wiki-vault --set-default--set-default records the vault in ~/.kmd/config.yaml. Every kmd command and MCP server on this machine now finds it without configuration.
A project vault. The repo carries its own knowledge:
cd my-repo
npx @bartolli/kmd init --localThis scaffolds my-repo/vault/ plus a .kmd/ state home. Every command run inside the repo resolves this vault automatically, and it wins over the global default. Nothing else to configure.
Then, either way:
kmd validate # deterministic checker, no LLM
kmd sync # vault → SQLite indexRelated MCP server: markdown-vault-mcp
Where things live
Thing | Where | Nature |
Vault | wherever you put it ( | yours: markdown + |
Index |
| disposable: |
Machine config |
|
|
Project config |
| committed, repo-relative paths; |
Hook state |
| session dedup markers; survives |
A project vault's index and state live in the repo. Delete the repo and they go with it.
How kmd finds your vault
One resolution order, used by the CLI, the MCP server, and the hooks. First hit wins:
An explicit path argument: pins that vault, beats everything.
The project: nearest ancestor with
.kmd/config.local.yaml,.kmd/config.yaml,vault/vault.yaml, or avault.yamlwith a.kmd/directory beside it.--default-root <path>: a configured default the project may beat.$WIKI_VAULT.default_vaultfrom~/.kmd/config.yaml.
The project signal is the working directory: the shell's for CLI commands, the session's for hooks, KMD_PROJECT_DIR for MCP servers. When something resolves to the wrong vault, run kmd config. It prints the vault and which rank won.
Teams commit .kmd/config.yaml with a repo-relative vault: path or a ${VAR} expansion. Absolute paths belong in the gitignored config.local.yaml.
Commands
kmd init [<dir>] [-y] [--set-default] scaffold a vault; --set-default records it as the machine default
kmd init --local [-y] project vault at <git-root>/vault/ with a .kmd/ state home
kmd validate [<path>] deterministic vault checker
kmd sync [<vault-root>] vault → SQLite index (validates first, aborts on errors)
kmd mcp [<vault-root>] [--default-root <path>]
stdio MCP server
kmd config [<vault-root>] print resolved vault, index path, winning rank
kmd config <set|get|unset> default_vault [<path>]
kmd db reset [<vault-root>] delete the vault's index
kmd hook <prompt|pretool|posttool|stop|session-start> [--default-root <path>] [--scope <s>] [--harness <h>] [--explain|--dry-run]
harness gate engine (see Hooks)kmd --help is canonical for flags; this list names the surface.
MCP server
Two tools, deliberately few:
prime(scope, task?)returns an orientation briefing: identity, primer, active decision records, current plan, vocabulary, most-linked pages, recent activity, cross-scope links. Passtaskand it adds the top-ranked relevant pages, weighted so a page naming the concept in its title outranks pages that merely mention it.search(query, scope?, kind?, limit?)returns ranked candidates{path, title, kind, summary, score}. Never page bodies; the agent opens files itself.
Templates are served as MCP resources at wiki://template/{domain}/{kind}, and the authoring guide at wiki://authoring.
Registration:
{
"mcpServers": {
"wiki": {
"command": "npx",
"args": ["-y", "@bartolli/kmd", "mcp", "--default-root", "/absolute/path/to/vault"]
}
}
}--default-root keeps the resolution order live: a project that carries its own vault wins automatically. Passing the path as a bare positional instead pins that one vault unconditionally. Use it only when that is what you want.
Skills
The wiki-sdd plugin ships nine skills: a complete spec-driven development loop that reads and writes the vault. Each is a slash command ($name on Codex):
Skill | What it does |
| wires a project to the wiki; local-vs-global vault setup; the hub for everything below |
| interview that sharpens intent and scaffolds a scope: index, primer, glossary, lazy ADRs |
| turns the working conversation into a thin plan plus user stories with Gherkin scenarios |
| moves stories through |
| slices stories into vertical tracer bullets; mirrors to GitHub or GitLab when configured |
| implements one |
| two questions before every primer rewrite; converts the answers into wiki artifacts |
| turns a prose rule into a tested vault trigger: you own the intent, it owns the regex |
| canonical-vocabulary register for long agentic threads |
The working loop: /grill-with-docs → /to-prd → /triage → /to-issues → /tdd per slice → /retro before the session closes. /wiki is the on-ramp; /to-triggers joins whenever a rule proves it should be a gate. The same skills render for all three harnesses below.
Harness integration
Claude Code
The repo is a plugin marketplace. The wiki-sdd plugin wires everything: the MCP server, all five hook events, and the nine skills.
claude plugin marketplace add bartolli/kmd
claude plugin install wiki-sdd@kmdProject vaults resolve automatically: the plugin passes the project directory to the server. No per-project files.
Codex
codex plugin marketplace add bartolli/kmd
codex plugin add wiki-sdd@kmdHooks are project-aware out of the box. The MCP server needs one line of help, because Codex gives plugin MCP servers no workspace signal (openai/codex#37903). Add to your shell profile:
codex() { KMD_PROJECT_DIR="$PWD" command codex "$@"; }Now every Codex launch carries its project directory, and prime/search follow project vaults exactly as on Claude Code. Details: codex adapter README.
Kiro
Kiro consumes the same skills as Agent Skills. Copy the skill folders into ~/.kiro/skills/ or .kiro/skills/, and register the MCP server in .kiro/settings/mcp.json from the bundled template. Both Kiro seats (IDE and CLI) read the same layout.
Manual wiring
No plugin, any harness that supports command hooks. Install globally first. Hooks spawn per event, and a global install keeps the spawn fast:
npm i -g @bartolli/kmd{
"hooks": {
"UserPromptSubmit": [
{ "hooks": [{ "type": "command",
"command": "kmd hook prompt --default-root /absolute/path/to/vault" }] }
],
"PreToolUse": [
{ "hooks": [{ "type": "command",
"command": "kmd hook pretool --default-root /absolute/path/to/vault --harness claude" }] }
],
"PostToolUse": [
{ "matcher": "Write|Edit|Bash",
"hooks": [{ "type": "command",
"command": "kmd hook posttool --default-root /absolute/path/to/vault --harness claude" }] }
],
"Stop": [
{ "hooks": [{ "type": "command",
"command": "kmd hook stop --default-root /absolute/path/to/vault" }] }
],
"SessionStart": [
{ "hooks": [{ "type": "command",
"command": "kmd hook session-start --default-root /absolute/path/to/vault" }] }
]
}
}--harness claude emits Claude Code's decision JSON on tool events. Without it the output is a neutral JSON contract. Kiro IDE wires the prompt event with --harness kiro-ide.
Hooks
Rules in instruction files cost tokens on every request. A trigger costs nothing until the moment it applies, then delivers the whole rule. Triggers are declared in vault.yaml; kmd hook evaluates them when the harness fires an event.
Five events:
prompt: matching triggers inject one context line each, once per session.pretool: gates before a tool runs: inject, warn, or deny with a reason the agent reads.posttool: after a write inside the vault,kmd validateruns; findings return to the agent and the index holds until they are fixed. Clean writes sync silently.stop: a session ending with validation errors is sent back once with the fix list.session-start: a session opening inside a scope's repo gets one orientation line: prime first.
triggers_extra:
my-app:
- id: retro-before-tag
on: pretool
enforce: block
tool: Bash
args_match: "\\bgit tag\\b"
when: # precondition: the gate fires only while it is unmet
name: newer-than
fresh: ["notes/my-app-retro-*.md"]
than: ["projects/my-app/ops/release-*.md"]
reason: "Retro gate: run the retro before tagging."Prompt triggers match keywords with stemming on word boundaries; intent regexes are the escape hatch. Pretool matchers AND-compose: tool name, args_match regex, files globs. when predicates read your vault's files at call time. The example denies tagging until a retro note postdates the last release note.
You don't write this YAML by hand. The /to-triggers skill interviews your intent, authors the keyword and regex mechanics itself, proves fire and near-miss behavior with a dry run, and writes vault.yaml only after validation passes. You own the rule; it owns the regex.
Declare repo: on a scope and the engine resolves the active scope from the session's working directory:
scopes:
my-app:
status: active
repo: ~/Projects/my-appEverything fails open. A broken config means one stderr line and no gate work: never a blocked prompt, never a denied unrelated call. Test triggers by hand with kmd hook prompt --explain (a read-only trace; never wire probe flags into hook registrations).
If other Node tooling in your agent loop prints ExperimentalWarning noise, set NODE_OPTIONS="--disable-warning=ExperimentalWarning" in the harness env.
The vault
vault/
├── vault.yaml # controlled vocabulary, the contract
├── templates/ # frontmatter templates, served as MCP resources
├── projects/{scope}/ # specs, ADRs, plans, stories
├── research/{topic}/ # articles, sources
└── notes/ # low-ceremony captureEvery page carries YAML frontmatter validated against vault.yaml:
# projects/my-app/adr/adr-sqlite-index.md
---
title: "SQLite for the index"
kind: adr
status: active
tags: [storage]
created: "2025-03-15"
updated: 2025-06-01
---kind selects the template, status tracks lifecycle, and every value must appear in vault.yaml or validation fails. Loading is fail-loud: an invalid vault.yaml stops the server and blocks sync rather than serving drift.
kmd validate runs seventeen deterministic rules, no LLM involved. Among them: dangling-link (every [[wikilink]] resolves), ambiguous-link (a bare [[name]] owned by two files must disambiguate), supersession-reciprocal (an ADR superseding another requires the back-pointer), path-authority (the path, not frontmatter, decides scope and topic), and tag-alias (aliases normalize to canonical tags). Sync refuses to index a vault with errors.
vault.yaml also carries the served pedagogy: the authoring rules agents read at wiki://authoring, custom kinds with their own templates, your methodologies, and the trigger declarations. The full reference with every field and customization pattern: docs/vault-config.md. A complete annotated example: vault.yaml.example.
kmd vs OKF
Same primitives as Open Knowledge Format (markdown, YAML frontmatter, a directory tree), but opinionated where OKF is minimal:
OKF | kmd | |
Vocabulary | open: producer picks | controlled: |
Structure | flat: organize however | three domains: |
Validation | none: format spec only | seventeen deterministic rules, LLM-free; gates sync |
Cross-refs | bundle-relative |
|
Agent surface | none | two MCP tools ( |
Guardrails | none | prompt reminders and tool gates from |
Infrastructure | n/a |
|
Development
Node.js 22+ (node:sqlite) and pnpm 11+.
pnpm install
pnpm -r run typecheck && pnpm -r run test && pnpm lintThe plugin adapters under plugins/{claude,codex,kiro} are build output. Edit the shared source in plugins/src/wiki-sdd/, then render and verify:
pnpm --filter @llm-wiki/render render && pnpm --filter @llm-wiki/render checkA hand-edited adapter copy diverges silently until the next render overwrites it. check asserts every copy matches the rendered output.
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
- Flicense-qualityAmaintenanceMCP server that enables full-text search and link navigation over Markdown files as a knowledge graph.
- AlicenseAqualityAmaintenanceA generic Markdown vault MCP server with FTS5 full-text search, semantic vector search, frontmatter-aware indexing, incremental reindexing, and non-markdown attachment support that exposes search, read, write, and edit tools.2528MIT
- Alicense-qualityCmaintenanceMCP server for local knowledge management with Markdown and PDF indexing using SQLite FTS5.82MIT
- AlicenseAqualityAmaintenanceMCP server for managing a local, domain-agnostic knowledge base using Markdown notes with frontmatter. Enables AI agents to capture, read, search, link, and maintain notes with atomic writes and privacy controls.13MIT
Related MCP Connectors
MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.
Markdown-first MCP server for Notion API with 8 composite tools and 39 actions.
Token-efficient MCP memory for Markdown vaults. Tiered search, GraphRAG, AI memories.
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/bartolli/kmd'
If you have feedback or need assistance with the MCP directory API, please join our Discord server