mcpField
R
ragnarok

ragnarok

本地服务
github.com/freyr记忆与知识02 天前更新

关于 ragnarok

ragnarok 为 Claude Code 在本机 Obsidian vault 中建立 RAG 搜索索引,适合需要检索个人笔记的用户。它结合 SQLite 关键词与向量搜索,并使用本地 Ollama 嵌入模型处理笔记。

主要功能

  1. 01SQLite 关键词与向量混合搜索
  2. 02按标题切分笔记
  3. 03按项目查找与列出笔记
  4. 04调用工具前更新索引
  5. 05私密笔记过滤与凭据脱敏
  6. 06评估不同搜索方式

适用场景

  1. 01从多个 Obsidian vault 检索事实与决策
  2. 02查找与当前任务相关的过往项目
  3. 03查看笔记正文、章节及反向链接
  4. 04比较 grep、关键词与混合搜索效果

MCP 相关

本地 MCP 服务向 Claude Code 提供笔记搜索、项目查询和笔记打开等工具。索引与嵌入在本机进行。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"freyr-ragnarok": {
"command": "uvx",
"args": [
"ragnarok-mcp"
],
"env": {
"RAGNAROK_HOME": "<RAGNAROK_HOME>"
}
}
}
}
启动命令uvx ragnarok-mcp
需要配置的环境变量
RAGNAROK_HOMEThe folder that holds config.toml, data/ and logs/. Default: ~/.ragnarok.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiragnarok-mcp2.3.0

工具

6

收录的工具列表 · 更新于 2 天前

参数类型必填说明
areaany否
typeany否
limitinteger否
querystring是
vaultany否
projectany否
include_privateboolean否
include_archivedboolean否

详细介绍

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 会执行六个步骤。已完成的步骤会跳过:

  1. 根据 config.example.toml 写入 config.toml。它会询问 vault 根目录(存放各个 vault 文件夹的目录),并将每个子文件夹添加为一个 vault。
  2. 检查是否已安装 Ollama。
  3. 使用 brew services start ollama 将 Ollama 作为登录服务运行(会先征求你的同意)。如果 Ollama 在 brew services 之外运行,例如在终端中运行 ollama serve,init 会先停止它,再启动该服务。
  4. 拉取嵌入模型。
  5. 构建索引。在 Apple Silicon Mac 上,为包含 1,500 篇笔记的 vault 构建索引约需 12 分钟。
  6. 如果插件 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。该技能会:

  1. 对每个 vault 运行 ragnarok survey;
  2. 在进行任何其他更改以及将新 vault 添加到 vaults 之前,先与你确认私有文件夹;
  3. 将路径规则写入 config.toml,并使用 ragnarok inspect 检查;
  4. 如果你同意,则运行 frontmatter 回填;在 apply 之前供你审核;
  5. 根据你的笔记编写一组小型评估集,并运行 ragnarok eval mechanical;
  6. 征求你的同意后,将上述指导添加到 ~/.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、dimensionOllama 嵌入模型及其向量维度。维度低于模型的原生维度时,会生成较短的向量(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_aliveOllama 在调用后将嵌入模型保留在内存中的时长:整数表示秒数,-1(默认值)表示保持加载,也可以使用 "30m" 这样的时长。更改后无需重建索引。
min_words、max_words分块器的分块大小限制。分块器还会根据模型配置文件的令牌上限拆分文本(每个令牌按 4 个字符计算);如果 Ollama 拒绝过长的文本,则会将其分成两半进行嵌入。Ollama 不会截断文本。更改后需要运行 ragnarok index --rebuild。
chunk_prefixnone(默认值)或 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_prefixesfind_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.dbSQLite 索引。将它和 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.logMCP 服务日志,每次工具调用记录一行及其时间。

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。

服务端发布
  1. 在 pyproject.toml 和 server.json 的两个 version 字段中设置版本,并在 CHANGELOG.md 中添加相应章节。
  2. 合并后,推送标签:git tag server-v1.2.3 && git push origin server-v1.2.3。
  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.0Rename the search skill [major]
[minor]1.4.2 → 1.5.0Add the setup command [minor]
[patch]1.4.2 → 1.4.3Fix 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。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。