Skip to main content
Glama

mcp-markdown-kb

An MCP server that turns any folder of Markdown notes into a knowledge base an AI assistant can search and read. Point it at your Obsidian vault, your docs/ folder, or a pile of meeting notes, and Claude can find the right note, follow links between notes, and quote from them.

No database, no embeddings, no API keys: everything is indexed in memory at startup with a small BM25 implementation written for this project.

What it exposes

Tool

What it does

search_notes

BM25 full-text search. Title, tags and headings are weighted above body text. Optional tag filter. Returns path, score and a snippet per hit.

read_note

Full body plus metadata (title, tags, headings, outgoing links, word count, modified time).

list_notes

Every note, optionally filtered by tag.

get_backlinks

Notes that link to a given note through [[wikilinks]] or relative .md links.

list_tags

Tag cloud with counts.

reindex

Re-scan the folder after you edit notes.

Every note is also published as a resource at note:///<relative/path.md> with text/markdown content, so clients that support resources can attach a note directly to the conversation.

Note format

Plain Markdown works as-is. The parser additionally understands:

  • Frontmatter between --- fences: title, tags: [a, b] or a - item list, and any other key: value pairs (kept in frontmatter). This is a small YAML subset, not a full YAML parser.

  • Titles: frontmatter title, else the first # heading, else the file name.

  • Links: [[Wiki links]], [[Wiki links|alias]], [[Note#heading]], and [text](relative/path.md). Wikilinks resolve by title, file name, or path, case-insensitively.

Hidden folders and node_modules are skipped.

Related MCP server: mcp-vault-reader

Running it

Requires Node 22.18+.

npm install
npm run build
node dist/cli.js ~/notes        # or: MARKDOWN_KB_DIR=~/notes node dist/cli.js

The server speaks MCP over stdio. Logs go to stderr so they never corrupt the protocol stream.

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "markdown-kb": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-markdown-kb/dist/cli.js", "/absolute/path/to/notes"]
    }
  }
}

Claude Code

claude mcp add markdown-kb -- node /absolute/path/to/mcp-markdown-kb/dist/cli.js /absolute/path/to/notes

Then ask things like "what do my notes say about rate limiting?" or "which notes link to the API gateway design doc?".

Development

npm run typecheck   # tsc over source and tests
npm test            # node --test, no test framework dependency
npm run build       # emits dist/
npm run dev -- ./test/fixtures/notes   # run from source, no build step

Tests spin up the real server and a real MCP client joined by the SDK's InMemoryTransport, so the protocol layer (schemas, tool listing, resource templates) is exercised end to end without spawning a process.

How the pieces fit

src/markdown.ts   parse one note: frontmatter, title, headings, tags, links
src/search.ts     tokenizer + BM25 index + snippet extraction
src/kb.ts         walk the folder, build the index, resolve links, backlinks
src/server.ts     McpServer: tools and the note:/// resource template
src/cli.ts        argument handling and the stdio transport

Design notes:

  • read_note and the resource handler only accept paths that resolve inside the root folder, so a client cannot read arbitrary files.

  • Tools are annotated (readOnlyHint) so hosts can skip confirmation prompts for the read-only ones.

  • Only two runtime dependencies: the MCP SDK and Zod (which the SDK uses for input validation and JSON Schema generation).

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers