关于 ragnarok
ragnarok 为 Claude Code 在本机 Obsidian vault 中建立 RAG 搜索索引,适合需要检索个人笔记的用户。它结合 SQLite 关键词与向量搜索,并使用本地 Ollama 嵌入模型处理笔记。
主要功能
- 01SQLite 关键词与向量混合搜索
- 02按标题切分笔记
- 03按项目查找与列出笔记
- 04调用工具前更新索引
- 05私密笔记过滤与凭据脱敏
- 06评估不同搜索方式
适用场景
- 01从多个 Obsidian vault 检索事实与决策
- 02查找与当前任务相关的过往项目
- 03查看笔记正文、章节及反向链接
- 04比较 grep、关键词与混合搜索效果
MCP 相关
本地 MCP 服务向 Claude Code 提供笔记搜索、项目查询和笔记打开等工具。索引与嵌入在本机进行。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
6收录的工具列表 · 更新于 2 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| area | any | 否 | |
| type | any | 否 | |
| limit | integer | 否 | |
| query | string | 是 | |
| vault | any | 否 | |
| project | any | 否 | |
| include_private | boolean | 否 | |
| include_archived | boolean | 否 |
详细介绍
ragnarok
面向 Claude Code 的 Obsidian 库本地 RAG 搜索。
ragnarok 会为你电脑上一个或多个 Obsidian 库中的 Markdown 笔记建立索引。本地 MCP 服务通过索引为 Claude Code 提供搜索工具。笔记不会离开电脑:嵌入向量由本地 Ollama 模型生成,索引则是一个 SQLite 文件。
功能
- 混合搜索。 每个查询都会执行稠密搜索(在
sqlite-vec中搜索嵌入向量)和关键词搜索(使用 BM25 的 SQLite FTS5)。通过倒数排名融合合并两个列表。排名单位为笔记,并采用笔记中得分最高的章节。 - 按标题分块。 分块器会在每篇笔记的标题处切分,并合并过短的章节。
- 从 frontmatter 或路径获取元数据。 每篇笔记都会获得一个库、一个项目、一个领域、一个类型、一个状态和工单键。首先从 frontmatter 获取这些值。对于没有这些值的笔记,则根据配置中的路径规则获取。
- 项目搜索。
find_projects可查找提示词所延续或相似的早期项目,即使提示词没有提及项目名称也可以。list_project会列出项目的所有笔记。 - 始终保持最新。 每次调用工具时,都会先扫描库中的变更笔记(通常少于 100 ms),并为其生成嵌入向量。无需运行监视进程。
- 私密笔记。 配置的私密路径下的笔记会纳入索引,但服务不会返回这些笔记。只有用户可以通过在配置中设置
allow_private = true来打开它们。 - 凭据脱敏。 索引器和
open_note会将明文密码、令牌和密钥替换为[REDACTED]。库文件不会更改。 - 回填 frontmatter。
ragnarok backfill propose会为一个库生成缺失 frontmatter 键的提案。ragnarok backfill export会生成一个 JSON 文件,其中包含每篇需要描述的公开笔记的标题和开头几行(已移除凭据)。Claude 会将描述写入一个或多个 JSON 文件,格式为{path: {"description": "...", "type": "..."}}。ragnarok backfill merge <vault> <file>...会将这些内容加入提案,移除凭据,报告每条超过 25 个单词的描述以及缺少描述的每一行,并用 Claude 提供的有效类型替换默认类型。你检查提案后,运行ragnarok backfill apply,它会创建库的备份归档,并且只添加缺失的键。 - 评估。
ragnarok eval会在你自己的问题集上比较 grep、关键词、稠密和混合搜索。ragnarok eval agent会比较 Claude Code Agent 与 grep,以及使用 MCP 工具的 Agent。 - 一键设置。
ragnarok init会安装模型和索引;如果 Claude Code 插件没有注册 MCP 服务,也会将其注册到 Claude Code。ragnarok doctor会检查设置。
要求
- macOS 和 Homebrew。设置过程会使用
brew services管理 Ollama。 - Ollama:
brew install ollama。 - Claude Code。
- uv:
brew install uv。uv 会安装 Python 3.12。如果缺少 uv,setup.sh会安装它。
设置
ragnarok 已发布到 PyPI,包名为 ragnarok-mcp;也已发布到 MCP Registry,名称为 io.github.freyr/ragnarok。
使用 Claude Code 插件(无需克隆)
在 Claude Code 中:
/plugin marketplace add freyr/ragnarok-bundle
/plugin install ragnarok@ragnarok
然后在终端中:
uvx ragnarok-mcp init
插件会通过 uvx ragnarok-mcp serve 启动服务,并在每个会话中添加搜索指南。主文件夹为 ~/.ragnarok。若要使用其他文件夹,请在 ~/.claude/settings.json 的 env 中以及你的 shell 中设置 RAGNAROK_HOME。
从代码检出目录安装
git clone https://github.com/freyr/ragnarok-bundle.git
cd ragnarok-bundle
./setup.sh # installs uv if needed, then runs `ragnarok init`
代码检出目录就是主文件夹。
init 的作用
ragnarok init 会执行六个步骤。已完成的步骤会跳过:
- 根据
config.example.toml写入config.toml。它会询问 vault 根目录(存放各个 vault 文件夹的目录),并将每个子文件夹添加为一个 vault。 - 检查是否已安装 Ollama。
- 使用
brew services start ollama将 Ollama 作为登录服务运行(会先征求你的同意)。如果 Ollama 在 brew services 之外运行,例如在终端中运行ollama serve,init 会先停止它,再启动该服务。 - 拉取嵌入模型。
- 构建索引。在 Apple Silicon Mac 上,为包含 1,500 篇笔记的 vault 构建索引约需 12 分钟。
- 如果插件
ragnarok提供 MCP 服务,则移除用户级注册(会先征求你的同意)。否则,它会在 Claude Code 中以用户级注册 MCP 服务ragnarok(如果要替换其他注册项,会先征求你的同意)。
完成第 6 步后,重启 Claude Code。ragnarok doctor 会检查相同的六项内容,并为每项故障打印修复方法。
在第 5 步之前,请检查 config.toml:移除不属于 vault 的文件夹,并添加你的私有路径。之后修改配置,会在下次调用 ragnarok index 或 MCP 工具时生效,无需重启。
在 Claude Code 中使用
该服务提供六个工具:
| 工具 | 作用 |
|---|---|
search | 对笔记进行混合搜索。筛选条件:vault、项目、领域、类型、已归档。 |
find_projects | 查找与提示词匹配的项目,并返回每个项目的摘要和匹配笔记。 |
list_project | 列出某个项目的所有笔记。 |
open_projects | 列出开放项目(默认包括 state: in-progress 和 paused),按状态分组,并按更新时间从新到旧排序。 |
open_note | 查看笔记或某个章节的文本,以及它的链接和反向链接。超过 4,000 词的笔记会显示大纲:每个章节的标题路径、词数和首句。 |
find_by_jira | 查找包含工单键的笔记,例如 ABC-123。 |
插件会在每个会话中自行添加以下指导,使用插件工具名称
mcp__plugin_ragnarok_ragnarok__*。如果不使用插件,Claude Code 会按需加载 MCP 工具。若要让 Claude 在使用 grep 之前先调用这些工具,可以在 ~/.claude/CLAUDE.md 文件中添加简短说明,例如:
## Finding notes: ragnarok first
The `ragnarok` MCP server indexes my Obsidian vaults. Use it before Grep or Glob whenever you look for
notes, earlier work or context:
- `find_projects`: the prompt continues or resembles earlier work and names no project. Then call
`list_project` on the best match (look at the top 3).
- `search`: facts, decisions, how something was done. Filters: vault, project, area, type.
- `open_note`: read a note or one section, with its links and backlinks. A long note gives its outline first; open the section you need by heading.
- `open_projects`: which projects are in progress or paused.
- `find_by_jira`: a ticket key such as `OPS-77`.
The tools are deferred. Load them in one call before the first use:
`ToolSearch` with `select:mcp__ragnarok__search,mcp__ragnarok__find_projects,mcp__ragnarok__list_project,mcp__ragnarok__open_projects,mcp__ragnarok__open_note,mcp__ragnarok__find_by_jira`.
If the tools are absent (for example on a computer without ragnarok), fall back to Grep and say so.
Results can be unrelated: read the text before you rely on it, and cite note paths. Private notes are
refused by design; do not work around the refusal with Read or Grep.
适配你的 vault
docs/vault-requirements.md 介绍了 vault 的结构要求,帮助你充分利用
ragnarok:标题、项目文件夹、SUMMARY.md、frontmatter 和私有文件夹。
默认路径规则要求使用 <vault>/<area>/<project>/note.md 结构。如果你的 vault 结构不同,仓库技能 .claude/skills/adapt-vault/ 会指导 Claude Code 完成适配。在检出目录中打开 Claude Code,并让它根据你的 vault 适配 ragnarok。该技能会:
- 对每个 vault 运行
ragnarok survey; - 在进行任何其他更改以及将新 vault 添加到
vaults之前,先与你确认私有文件夹; - 将路径规则写入
config.toml,并使用ragnarok inspect检查; - 如果你同意,则运行 frontmatter 回填;在
apply之前供你审核; - 根据你的笔记编写一组小型评估集,并运行
ragnarok eval mechanical; - 征求你的同意后,将上述指导添加到
~/.claude/CLAUDE.md。
它只会修改 config.toml 并添加 frontmatter 键。绝不会移动、重命名或删除笔记或文件夹。
配置
config.toml 位于主目录中。其中的相对路径均相对于主目录。
config.example.toml 说明了各个键的含义。最重要的键如下:
| 键 | 说明 |
|---|---|
root、vaults | 存放各个知识库的文件夹,以及要建立索引的知识库文件夹。 |
[vault_paths] | 不在 root 中的知识库文件夹,例如 kb = "~/code/kb"。笔记键仍为 <vault>/<path>。 |
private_patterns | 私密笔记的 Glob 模式,例如 "Notes/Journal/**"。 |
model、dimension | Ollama 嵌入模型及其向量维度。维度低于模型的原生维度时,会生成较短的向量(Ollama dimensions)。更改后需要运行 ragnarok index --rebuild。 |
query_prefix、doc_template | 覆盖模型配置文件中的查询前缀和文档模板。模板中的 {title} 表示笔记标题和标题路径。配置文件涵盖 embeddinggemma-2:270m(以及 -bf16-text)、qwen3-embedding:0.6b 和 :4b、snowflake-arctic-embed2 和 bge-m3;其他模型会使用 embeddinggemma-2:270m 的前缀。旧键 doc_prefix 仍可作为 doc_template 使用。更改后需要运行 ragnarok index --rebuild。 |
keep_alive | Ollama 在调用后将嵌入模型保留在内存中的时长:整数表示秒数,-1(默认值)表示保持加载,也可以使用 "30m" 这样的时长。更改后无需重建索引。 |
min_words、max_words | 分块器的分块大小限制。分块器还会根据模型配置文件的令牌上限拆分文本(每个令牌按 4 个字符计算);如果 Ollama 拒绝过长的文本,则会将其分成两半进行嵌入。Ollama 不会截断文本。更改后需要运行 ragnarok index --rebuild。 |
chunk_prefix | none(默认值)或 description:将笔记描述放在每个正文分块的文本前,再传给模型。存储的文本和关键词索引不会改变。更改后需要运行 ragnarok index --rebuild。 |
note_rank | 笔记分块如何决定笔记排名:maxp(默认值,取最佳分块)、topk_sum(对笔记在密集列表和关键词列表中得分最高的 3 个分块求和),或 note_vector(还会将每篇笔记的分块向量均值作为第三个列表)。更改后需要重新建立索引。 |
[variants.<name>] | 基准测试:变体会覆盖 model、dimension、query_prefix、doc_template、min_words、max_words、chunk_prefix 和 note_rank。 |
[corpora.<name>] | 基准测试:变体要建立索引的 root 和 vaults 列表。 |
project_markers | 含有其中任意一个文件的文件夹即为项目文件夹(默认值为 DRIVERS.md、SUMMARY.md)。 |
jira_prefixes | find_by_jira 可识别的工单前缀。 |
[vault_rules.<vault>] | 某个知识库的路径规则:哪些文件夹用于确定区域和项目。 |
笔记元数据
ragnarok 会读取以下 frontmatter 键。每个键均为可选项:
---
project: heating-upgrade # the project slug; default: from the path rules
area: home # a wide subject; default: from the path rules
type: plan # drivers, summary, research, spec, plan, brainstorm, review, decision,
# guide, reference, meeting, log, template or note
status: active # active or archived; a note in an _archive folder, or in a project
# whose SUMMARY.md has state: superseded or abandoned, is archived; state: done is current
description: One sentence about the note, which improves find_projects.
jira: [ABC-123] # ticket keys, in addition to the keys in the text
---
如果没有 frontmatter,则由路径规则提供元数据。默认规则适用于目录结构为
<vault>/<area>/<project>/note.md 的知识库。对于不同的目录结构,请添加 [vault_rules.<vault>] 表。使用
ragnarok inspect <note path> 可查看笔记的元数据。
命令
| 命令 | 功能 |
|---|---|
ragnarok init | 配置这台计算机(参见 Setup)。 |
ragnarok doctor | 检查配置。 |
ragnarok index [--rebuild] | 在索引中添加、修改和移除笔记。路径规则、私有路径或标记发生变更后,它会重新推导所有笔记的元数据,不会生成新的嵌入。添加或移除 .md 标记文件时,它会对该文件所在文件夹下的笔记执行相同操作。只有在 model、dimension、min_words 或 max_words 发生变更后,才需要使用 --rebuild。它会保留嵌入缓存,因此只会为缓存中不存在的文本块生成嵌入。 |
ragnarok status | 显示索引的大小和状态。 |
ragnarok search "<query>" | 从终端执行搜索。 |
ragnarok inspect <path>... | 显示笔记的元数据。 |
ragnarok chunks <path>... | --stats | 显示笔记的文本块或总计。 |
ragnarok serve | 通过 stdio 运行 MCP 服务。Claude Code 会启动它。 |
ragnarok backfill propose|export|merge|apply <vault> [file...] | 提出、描述并应用缺失的 frontmatter 键。顺序为 propose、export、由 Claude 编写描述、merge <vault> <file>...、检查提案,然后 apply。 |
ragnarok survey <vault> [--json] | 输出知识库文件夹、frontmatter 键、标记文件、名称模式和工单前缀。请在编写 [vault_rules.<vault>] 之前运行。它不会输出笔记文本。 |
ragnarok eval mechanical|pool|agent | 使用 data/eval/sets/ 中的问题集运行评估。 |
ragnarok bench index --variant <name> --corpus <name> | 在语料库上构建或更新变体的索引,路径为 data/variants/<variant>/<corpus>/index.db。它会共享嵌入缓存,因此使用默认嵌入设置的变体无需再次生成嵌入。如果索引是使用该变体的其他设置构建的,它会拒绝使用该索引。 |
ragnarok bench run --set <file> --variant <name> | 对问题集中的每个问题,通过 MCP 搜索运行搜索(limit 为 20,启用变更扫描,不设筛选条件),使用该变体在问题集所属语料库上的索引。它会将每个预期笔记的排名、扫描时间和每个问题的搜索时间、问题与黄金笔记的关键词重合度,以及黄金笔记的 BM25 排名写入 data/bench/<set hash>-<variant hash>.json。它会先不设限制地更新该变体的索引。如果预期路径不在索引中或属于私有路径,它会拒绝该问题集,逐一列出这些路径及原因,并且不会运行任何问题。 |
ragnarok bench compare --set <file> <A> <B> [<B2>...] [--margin 0.05] | 按分层和区域给出各变体的 recall@5 和 MRR,以及 B − A 的差值和基于集群自助抽样的 95% 区间(10,000 个样本,固定种子)。如果有多个 B,区间水平会遵循 Holm 校正。它会列出不一致问题的占比,以及每个发生变化的问题及其诊断信息。最后会为每个 B 输出一行结论(参见问题集格式)。 |
ragnarok bench convert <draft set> --out <file> --name <name> --kind synthetic|real --corpus <name> | 将 ragnarok eval 的草稿问题集转换为问题集格式。分层取自旧的 type,集群取自第一个预期路径,区域取自第一个预期笔记的元数据规则(笔记缺失时为 unknown)。如果问题没有预期路径,或预期路径是文件夹,则不会转换该问题,并会逐一列出。 |
集合格式
一个集合是一个 JSON 文件:
{
"name": "pilot", "kind": "real", "version": 2, "corpus": "real", "hash": "<SHA-256 of the questions>",
"questions": [
{"id": "q01", "question": "What is a field stop?", "expected": ["Private/Astro/Field Stop.md"],
"stratum": "lookup", "area": "astro", "cluster": "Private/Astro/Field Stop.md", "notes": "optional"}
]
}
kind是synthetic或real。corpus是配置中的一个表[corpora.<name>]。hash是questions列表的 SHA-256 值,计算时将其序列化为 JSON,并对键排序且不加空格。哈希值不匹配时,bench 会拒绝该集合。expected包含一个或多个笔记路径。后续问题会列出其项目的SUMMARY.md。cluster是主要 gold 笔记的路径。bootstrap 抽取的是集群,而不是问题。- recall@5 在所有预期笔记都位于前 5 条笔记中时为 1,否则为 0。MRR 使用首个预期笔记的排名;前 20 条中没有预期笔记时为 0。
bench compare 的判定结果:
- 对于合成集合:当 B − A 在其 Holm 水平上的区间对 recall@5 或 MRR 高于 0、另一项指标的差值不低于 0,且 p95 搜索时间(包括扫描)低于 500 ms 时,B 获胜。报告还会给出每个 vault 中差值的符号。
- 真实集合不会判定胜负,而是检查 B 是否没有变差:对于 recall@5 和 MRR,B − A 区间的下限都必须高于 −margin。它也会检查 p95 时间。
使用 uvx ragnarok-mcp 运行每条命令,例如 uvx ragnarok-mcp search "boiler";也可以在
checkout 中使用 uv run。
文件位置
所有内容都位于主目录中:RAGNAROK_HOME,否则为 checkout,再否则为 ~/.ragnarok。在 checkout 中,git
会忽略 config.toml、data/ 和 logs/。
| 路径 | 内容 |
|---|---|
config.toml | 这台计算机的配置。 |
data/index.db | SQLite 索引。将它和 data/embed-cache.db 复制到另一台计算机,可跳过首次建索引。 |
data/embed-cache.db | 所有索引文件共用的嵌入缓存。其键包含模型、维度、文档模板和文本哈希。 |
data/variants/<variant>/<corpus>/index.db | 某个语料库上 bench 变体的索引。MCP 服务不会使用它。 |
data/bench/ | bench run 的结果,每个集合和变体设置各对应一个文件。 |
data/backups/ | backfill apply 写入前创建的 vault 归档。 |
data/proposals/ | backfill propose 和 backfill export 的输出。 |
data/eval/ | 你的问题集合(sets/)、评估结果以及 Agent 评估的镜像。 |
logs/server.log | MCP 服务日志,每次工具调用记录一行及其时间。 |
Ollama 将模型保存在 ~/.ollama 中。
仓库布局
此仓库包含 MCP 服务和 Claude Code 插件市场 ragnarok。
src/ragnarok/ tests/ the MCP server, the PyPI package ragnarok-mcp
pyproject.toml server.json the package and the MCP Registry entry
CHANGELOG.md the changelog of the server
.claude-plugin/marketplace.json the marketplace "ragnarok": lists each plugin and its folder
plugins/<name>/ one folder for each plugin, with .claude-plugin/plugin.json
plugins/CHANGELOG.md the changelog of the plugins
templates/plugin/ the skeleton for a new plugin
scripts/ the version bump and the validation of the plugins
服务和插件有各自独立的版本和标签:server-vX.Y.Z 和 plugin-vX.Y.Z。
开发
服务端
uv run pytest
uv run ruff check . && uv run ruff format --check .
插件
在一个会话中从插件文件夹加载插件:
claude --plugin-dir plugins/<name>
或者将此 checkout 添加为本地市场。然后 /reload-plugins 会读取你的编辑,无需发布新版本:
claude plugin marketplace add <path of the checkout>
要添加插件,请将 templates/plugin/ 复制到 plugins/<name>/,替换 PLUGIN_NAME 和
ONE_LINE_DESCRIPTION,并在 .claude-plugin/marketplace.json 中添加条目。scripts/validate-plugins.sh
会验证所有插件。不要手动更改插件的 version。
服务端发布
- 在
pyproject.toml和server.json的两个version字段中设置版本,并在CHANGELOG.md中添加相应章节。 - 合并后,推送标签:
git tag server-v1.2.3 && git push origin server-v1.2.3。 - 工作流
publish.yml会检查三个版本是否与标签一致、运行测试、通过可信发布将软件包发布到 PyPI,然后将server.json发布到 MCP Registry。
标签 v1.0.0 到 v2.1.0 是插件迁入此仓库之前的服务端版本。
插件发布
所有插件和插件市场共用一个版本。每次向 main 推送会更改 plugins/ 或
.claude-plugin/ 的内容时,都会运行 plugins-release.yml。它会检查自上一个 plugin-v 标签以来的提交消息。
提交消息中的标记用于选择发布类型:
| 标记 | 发布类型 | 示例 |
|---|---|---|
[major] | 1.4.2 → 2.0.0 | Rename the search skill [major] |
[minor] | 1.4.2 → 1.5.0 | Add the setup command [minor] |
[patch] | 1.4.2 → 1.4.3 | Fix the hook matcher [patch] |
无,或 [none] | 不发布 | Edit the README |
标记只应放在更改插件的提交中:工作流会读取自上一个插件标签以来的所有提交消息。找到标记后,工作流会运行 plugins-ci.yml,在
.claude-plugin/marketplace.json 和每个 plugin.json 中设置新版本,使用
git-cliff(cliff.toml)将对应章节添加到 plugins/CHANGELOG.md,
创建提交,打上 plugin-vX.Y.Z 标签,并发布 GitHub
版本。
许可证
MIT。详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。