llm-wiki-mcp
Serves an LLM-maintained markdown wiki to agents over MCP, providing tools for querying and navigating wiki pages without direct filesystem access.
README
llm-wiki-mcp
Serve an LLM-maintained markdown wiki to agents over MCP.
If you keep a knowledge base in the shape Andrej Karpathy described — immutable raw sources, a wiki of markdown pages an LLM maintains, and a schema doc describing the conventions — this makes it queryable from any MCP client, without the agent having to walk your directory tree.
uvx llm-wiki-mcp --wiki ~/my-wiki
It is strictly read-only. It never writes to your wiki.
Why not just point the agent at the folder?
Because an agent given a directory reads the wrong things in the wrong order. It globs, opens files whole, and burns context rediscovering structure you already wrote down. This server front-loads the parts that are cheap and decisive: a curated index, one-line descriptions for every page, a tag vocabulary, and a best-match lookup that returns one page instead of forty snippets.
It also passes your wiki's own conventions doc through as the MCP server instructions — so a remote agent that has never opened your repo still follows your rules about linking, attribution, and what the page types mean.
Install
uv tool install llm-wiki-mcp # or: pipx install llm-wiki-mcp
uv tool install 'llm-wiki-mcp[ask]' # plus server-side synthesis
Register it with a client — for Claude Code:
claude mcp add my-wiki -- llm-wiki-mcp --wiki ~/my-wiki
Or in claude_desktop_config.json / any MCP client config:
{
"mcpServers": {
"my-wiki": {
"command": "llm-wiki-mcp",
"args": ["--wiki", "/absolute/path/to/wiki"]
}
}
}
Check what it found before wiring anything up:
llm-wiki-mcp --wiki ~/my-wiki --info
What it expects
Almost nothing. A directory of markdown files.
index.md |
reserved | Your curated catalog. Served by get_index; read first by convention. |
log.md |
reserved | Append-only history. Served by get_log. |
raw/ |
optional | Immutable source documents. Excluded from search; reachable via read_source. Rename with --raw-dir. |
CLAUDE.md |
optional | Your conventions doc — served as the MCP instructions. AGENTS.md, .llm-wiki.md, and CONVENTIONS.md also work. |
overview.md |
optional | A high-level orientation page. get_overview is only registered if it exists. |
| everything else | your pages | Any directory structure you like. |
Page types are discovered, not configured. A page's type is its frontmatter
type if it declares one, and otherwise the directory it lives in. So
concepts/, people/, notes/ — whatever you use — become filters
automatically. Filters tolerate singular and plural (--page_type concept finds
concepts/).
Frontmatter is plain YAML. Only type and title really matter; description
and tags are what make the cheap tools useful:
---
title: Grounding Data
description: Structured facts a publisher exposes to agents, rather than prose
type: concept
tags: [structured-news, publishing]
---
description is load-bearing. It's what list_pages shows and what find_page
ranks on, so a page without one is half-invisible. Keep it to one line.
Tools
| Tool | What it's for |
|---|---|
get_index |
The curated catalog. Read first. |
find_page(topic, …) |
The single best page, in full. "What does the wiki say about X?" |
search_wiki(query, …) |
Every mention across the corpus. "Where is X discussed?" |
read_page(name) |
A page by slug, path, or [[wikilink]]. |
list_pages(page_type?, tags?, match?) |
Pages with descriptions; filter by type and tags (and/or). |
list_types() |
The page types in use, with counts. |
list_tags(page_type?) |
The tag vocabulary with counts. Read before filtering by tag. |
get_log(since?, limit?) |
Change history. get_index says what the wiki holds; this says how it got there. |
read_source(path) |
A raw source document, text only. |
validate_wiki(path?, limit?) |
Conformance report. |
get_overview() |
Only if overview.md exists. |
ask(question) |
Only if ANTHROPIC_API_KEY is set. |
Tools that would always fail aren't registered at all — a tool that returns "not configured" costs the client context and invites a wasted call.
find_page vs search_wiki
search_wiki is ripgrep: every hit, as snippets. find_page returns one whole
page, plus the runners-up by name so an agent can pivot.
Ranking weights title and slug — the page's identity — far above tags and
description, and length-normalizes them. This matters more than it sounds: a
page about a person almost never repeats their name in its own description, so
without that weighting an entity's own page loses to every source that cites it.
Short query tokens must match exactly (otherwise the matches authenticity);
longer ones match by containment in either direction, so plurals find singulars.
Validation
A wiki written by an agent across many sessions doesn't fail by crashing — it drifts. A page never makes it into the index. A link's target gets renamed. A description picks up a colon and stops being valid YAML, so every consumer that isn't a hand-rolled parser goes blind to it.
llm-wiki-mcp --wiki ~/my-wiki --validate
llm-wiki-mcp --wiki ~/my-wiki --validate --level error # what a hook should run
Errors mean malformed — broken for any consumer: invalid YAML, frontmatter
opened and never closed, duplicate slugs that make a wikilink ambiguous.
Warnings mean degraded — still serves, but worse: no type, title,
description or tags; a page missing from the index; an index entry pointing at a
page that doesn't exist; a missing source; a wikilink split across lines by
hard-wrapping. Notes are informational: over-long descriptions, and
unresolved [[red links]] — aggregated per target with a citation count, so the
top of that list is a ranked backlog of pages worth writing.
Absent metadata is deliberately not an error. This server infers a title from the filename and a type from the directory, so a page without them still works — and a checker that fails on what its own server handles fine is a checker people turn off. A minimal wiki with no index, no log, and bare markdown pages passes a hook gating on errors.
Exit codes: 0 clean, 1 errors, 2 couldn't run. --strict fails on warnings
too. A ready-made git hook is in examples/pre-commit.
Two deliberate choices worth knowing about. Red links are notes, not warnings — in a living wiki most are pages you haven't written yet, and one finding per mention buries everything else. And a referenced source that is absent but gitignored is a note explaining why, not a warning: keeping large PDFs out of git is a normal policy, and a check that's mostly false positives teaches you to ignore the whole category.
Transports
stdio by default — what most MCP clients expect, and the client is the parent process, so there's nothing to authenticate.
HTTP for serving a wiki to agents on other machines:
LLM_WIKI_TOKEN=$(openssl rand -base64 32) llm-wiki-mcp --http --port 8848
Requires a bearer token; refuses to start without one. Install the http extra.
DNS-rebinding protection is off by default (the typical client is a CLI agent
behind a token on a trusted network, not a browser) — set
LLM_WIKI_ALLOWED_HOSTS to turn on the allowlist.
The ask tool
With ANTHROPIC_API_KEY set and the ask extra installed, ask(question) runs
a turn-capped sub-agent over the same read-only tools and returns an answer
citing [[wikilinks]]. The index is pinned into a cached system prefix, so
repeated questions reuse it.
Use it when you want a finished answer rather than raw pages. Everything else works without it, and without any API key.
Configuration
Every flag has an environment variable. Flags win.
| Env | Flag | Default |
|---|---|---|
LLM_WIKI_ROOT |
--wiki |
current directory |
LLM_WIKI_RAW_DIR |
--raw-dir |
raw |
LLM_WIKI_TOKEN |
— | (required for --http) |
LLM_WIKI_HOST / LLM_WIKI_PORT |
--host / --port |
127.0.0.1 / 8848 |
LLM_WIKI_OVERVIEW_FILE |
— | overview.md |
LLM_WIKI_SCHEMA_FILES |
— | CLAUDE.md,AGENTS.md,.llm-wiki.md,CONVENTIONS.md |
LLM_WIKI_LIST_MAX_DESCRIBED |
— | 250 |
LLM_WIKI_LOG_MAX_ENTRIES |
— | 10 |
LLM_WIKI_DESCRIPTION_MAX |
— | 400 |
ANTHROPIC_API_KEY |
— | unset (ask disabled) |
Relation to OKF
Google Cloud's Open Knowledge Format
describes a very similar artifact: markdown plus YAML frontmatter, type
required, index.md and log.md reserved. A Karpathy-format wiki that fills in
description is already close to an OKF bundle at the metadata layer. The
notable divergence is links — OKF uses relative markdown links, this expects
[[wikilinks]], which is what Obsidian and most LLM-maintained wikis actually
use. NRK's okf-mcp serves OKF bundles and is
worth a look if that's your format.
Development
uv sync --all-extras
uv run pytest
License
GNU General Public License v2.0. See LICENSE.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。