内容
# llm-wiki-mcp
用于 AI 代理的持久化 Markdown wiki,构建于 [Karpathy's LLM wiki gist](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) 之上。四个 MCP 工具(`wiki_read`、`wiki_write_page`、`wiki_log_append`、`wiki_inventory`)加上四个 Claude Code 技能(`wiki-init`、`wiki-ingest`、`wiki-query`、`wiki-lint`)。stdio 传输,本地文件系统。
服务器处理 LLMs 容易出错的层:原子写入、etag 冲突检查、仅追加日志完整性、路径包含。技能为代理提供工作流。wiki 模式存储在您自己的 `wiki/CLAUDE.md` 中,并随着您的领域增长。服务器没有第 3 层模式验证。
> 状态:alpha(v0.1.1)。仅本地后端。MIT 许可。
## 快速开始
需要 Python 3.11+ 和 [uv](https://docs.astral.sh/uv/)。
选择一个 wiki 文件夹的绝对路径。服务器会在首次运行时创建 `pages/` 和 `log.md`:
```bash
uvx llm-wiki-mcp --wiki-root /absolute/path/to/wiki
```
将其连接到您的 MCP 客户端。
**Claude Code:**
```bash
claude mcp add llm-wiki -- uvx llm-wiki-mcp --wiki-root /absolute/path/to/wiki
```
**Claude Desktop**(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS)或 **Cursor**(`~/.cursor/mcp.json`):
```json
{
"mcpServers": {
"llm-wiki": {
"command": "uvx",
"args": ["llm-wiki-mcp", "--wiki-root", "/absolute/path/to/wiki"]
}
}
}
```
重启客户端。应该会出现四个工具:`wiki_read`、`wiki_write_page`、`wiki_log_append`、`wiki_inventory`。
## Claude Code 技能
Claude Code 用户可以安装捆绑的工作流技能作为插件:
```bash
claude plugin marketplace add https://github.com/flsteven87/llm-wiki-mcp
claude plugin install llm-wiki-skills@llm-wiki-mcp
```
每个技能都会读取 `wiki/CLAUDE.md` 以获取每次运行的活动模式,因此您可以进化模式而无需重新安装任何内容。询问代理:
| 技能 | 提问内容 | 需要 MCP 服务器? |
|---|---|---|
| `wiki-init` | "为 `~/wikis/ai-safety` 创建一个 LLM wiki,用于 AI 安全研究。" | 否 |
| `wiki-ingest` | "将 https://arxiv.org/abs/2310.12345 吸收到 wiki 中。" | 是 |
| `wiki-query` | "wiki 中关于 steering vectors 的内容是什么?" | 是 |
| `wiki-lint` | "运行 wiki 健康检查。" | 是 |
`wiki-init` 是一个一次性脚手架;其他三个是 Karpathy 的三个操作。
其他 MCP 客户端(Claude Desktop,Cursor)获得四个工具但不是技能。代理必须仅从工具描述中推导出工作流,这适用于一次性读取和写入,但往往会跳过技能使显式记录的日志条目和反向链接审计。
## 四个工具
| 工具 | 注解 | 目的 |
|---|---|---|
| `wiki_read` | 只读,幂等 | 读取一个页面。返回正文,解析的前面内容,输出链接,etag。 |
| `wiki_write_page` | 破坏性,幂等 | 原子创建或更新,带有 etag CAS。传递 `etag=null` 以创建,读取 etag 以更新。 |
| `wiki_log_append` | 非幂等 | 将一个条目追加到 `log.md`,格式为 Karpathy 的 `## [YYYY-MM-DD] 操作 \| 标题`。 |
| `wiki_inventory` | 只读,幂等 | 快照整个图:页面,前面内容,链接边,日志条目,以及可选的用于反向链接审计的纯文本提及扫描。 |
`index.md` 和 `raw/` 不会作为工具公开。索引是 LLM 编辑的内容,通过宿主的 `Read`/`Write` 编辑。原始层从服务器的角度是不可变的。
## Wiki 布局
`wiki-init` 脚手架一个项目,类似这样:
```
your-project/
├── raw/ 不变源文件(论文,文章,转录)
│ └── ...
└── wiki/ ← --wiki-root 指向此处
├── pages/ Markdown 页面,每个主题一个
├── log.md 仅追加会话日志
├── index.md LLM 编辑的浏览页面
└── CLAUDE.md 模式文档,LLM 每次操作都会读取
```
`--wiki-root` 指向精选的 `wiki/` 文件夹,而不是包含 `raw/` 的父项目文件夹。安装时容易出错;下面的故障排除部分涵盖了您将看到的错误。
## 设计边界
服务器强制执行机制,而不是内容形状:
- **原子写入。** `tmp-file + fsync + rename` 用于页面。`O_APPEND` 单次写入日志条目。
- **乐观并发。** 每个页面都有一个 etag (`sha256(body) || mtime_ns`)。更新提供读取的 etag;如果不匹配,则会引发 `WikiConflictError`,代理会重新读取,合并,并重试。
- **路径包含。** 斜杠通过正则表达式验证。解析路径会检查根目录的 realpath,阻止 CVE-2025-53109 符号链接逃逸类。
- **格式锁定日志行。** `## [YYYY-MM-DD] 操作 \| 标题`。操作名称是自由字符串;只有会破坏行形状的字符会被拒绝。
服务器不会验证前面内容形状,页面类别或链接目标。这些层存在于您的 `wiki/CLAUDE.md` 模式文档中,并随着 LLM 的发展而增长。Karpathy 的 gist 故意对内容形状保持沉默;将模式嵌入服务器会破坏这一点。
## Python API
如果您想用自己的存储后端(SQLite,Notion,GDrive,测试伪造)包装 MCP 服务器,请实现 `WikiStorage` 协议并将实例传递给 `build_server`:
```python
from llm_wiki_mcp import WikiStorage, PageRead, LogEntry
from llm_wiki_mcp.server import build_server
class MyStorage: # 满足 WikiStorage 协议
async def read_page(self, slug: str) -> PageRead: ...
async def write_page(self, slug, body, expected_etag=None) -> str: ...
async def list_pages(self) -> list[str]: ...
async def append_log(self, entry: LogEntry) -> None: ...
async def read_log(self) -> str: ...
async def write_raw_file(self, name, data) -> None: ... # 通常会引发
server = build_server(storage=MyStorage())
server.run()
```
`build_server` 是组合根。CLI `main()` 是一个薄薄的调用者,它从 `--wiki-root` 构造 `LocalFilesystemStorage` 并将其传递进去。
捆绑的 Claude Code 技能作为包数据存储在 `llm_wiki_mcp/skills/` 下,如果您想将它们连接到非 Claude-Code 代理,可以通过 `importlib.resources` 加载。来自包根目录的 Typed 域错误(`WikiConflictError`、`WikiNotFoundError`、`WikiPermissionError`、`WikiPathError`、`WikiSchemaViolationError`)可导入并在您自己的边界处捕获。
## 故障排除
**`llm-wiki-mcp: command not found`** 在 `uv tool install` 后。`uv` 将二进制文件放在 `~/.local/bin`(或 Windows 上的 `%USERPROFILE%\.local\bin`)。将其添加到 `PATH`,或使用 `uvx llm-wiki-mcp ...` 调用而无需持久的 shim。
**编辑客户端配置后,`wiki_*` 工具未出现。** 重启 MCP 客户端。Claude Desktop,Claude Code 和 Cursor 只会在启动时重新读取 `mcpServers`。
**`WikiPathError: path escapes wiki root`.** 您将 `--wiki-root` 指向包含 `raw/` 的项目文件夹,而不是其中的精选 `wiki/` 文件夹。`/Users/me/wikis/ai-safety/wiki` 是正确的;`/Users/me/wikis/ai-safety` 不是。
**Claude Code 中技能未加载。** 运行 `claude plugin list`。如果 `llm-wiki-skills` 丢失,请在 [Claude Code 技能](#claude-code-skills) 部分重新运行市场命令。
## 开发
```bash
git clone https://github.com/flsteven87/llm-wiki-mcp
cd llm-wiki-mcp
uv sync --extra dev
uv run pytest
uv run ruff check .
uv run pyright src/llm_wiki_mcp
```
## 许可证
MIT。查看 [LICENSE](https://github.com/flsteven87/llm-wiki-mcp/blob/master/LICENSE)。
<!-- mcp-name: io.github.flsteven87/llm-wiki-mcp -->