ragnarok
The ragnarok MCP server gives Claude Code local search and reading tools over indexed Obsidian vault notes.
search— Hybrid meaning + keyword search across notes, with filters for vault, project, area, and type; can optionally include private or archived notes.find_projects— Finds earlier projects that a prompt resembles or continues, returning project metadata and matching notes.list_project— Lists all notes in a project, including type, status, description, stage, and next action.open_note— Opens a full note or a specific heading, returning text, frontmatter, links, and backlinks; credentials are redacted and private notes refused.find_by_jira— Finds notes containing a Jira ticket key such asABC-123.
Indexes the Markdown notes of one or more local Obsidian vaults and exposes hybrid search over them: a dense vector search plus a SQLite FTS5/BM25 keyword search fused by reciprocal rank. Supports heading-based chunking, metadata extracted from frontmatter or path rules (vault, project, area, type, status), filtered search, project discovery and listing, opening a note or a single section with its links and backlinks, lookup by ticket key, private-note exclusion, and credential redaction. The index stays local in a single SQLite file and is refreshed from changed notes on every tool call.
Uses a local Ollama embedding model to embed note chunks for the dense half of the hybrid search, so no vault content leaves the machine; the model and vector dimension are configurable and a command sets up/checks the Ollama service.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ragnaroksearch my notes for the authentication design doc"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ragnarok
Local RAG search over Obsidian vaults for Claude Code.
ragnarok indexes the Markdown notes of one or more Obsidian vaults on your computer. A local MCP server gives Claude Code search tools over the index. No note leaves the computer: the embeddings come from a local Ollama model, and the index is one SQLite file.
Features
Hybrid search. Each query runs a dense search (embeddings in
sqlite-vec) and a keyword search (SQLite FTS5 with BM25). Reciprocal rank fusion joins the two lists. The unit of rank is the note, with its best section.Heading chunks. The splitter cuts each note at its headings and joins very short sections.
Metadata from frontmatter or path. Each note gets a vault, a project, an area, a type, a status and ticket keys. The frontmatter gives these values first. For a note without them, path rules in the configuration give them.
Project search.
find_projectsfinds the earlier projects that a prompt continues or resembles, also when the prompt does not name the project.list_projectgives all notes of a project.Always current. Each tool call first scans the vaults for changed notes (usually less than 100 ms) and embeds them. There is no watcher process.
Private notes. Notes under the configured private paths are in the index, but the server does not return them. Only the user can open them, with
allow_private = truein the configuration.Credential redaction. The indexer and
open_notereplace literal passwords, tokens and keys with[REDACTED]. The vault files do not change.Frontmatter backfill.
ragnarok backfill proposewrites a proposal of the missing frontmatter keys for a vault.ragnarok backfill exportwrites a JSON file with the title and the first lines of each public note that needs a description (credentials removed). Claude writes the descriptions into one or more JSON files,{path: {"description": "...", "type": "..."}}.ragnarok backfill merge <vault> <file>...puts them into the proposal, removes credentials, reports each description of more than 25 words and each row with no description, and replaces a default type with a valid type from Claude. You examine the proposal, thenragnarok backfill applymakes a backup archive of the vault and adds only the missing keys.Evaluation.
ragnarok evalcompares grep, keyword, dense and hybrid search on your own question sets.ragnarok eval agentcompares a Claude Code agent with grep and an agent with the MCP tools.One-command setup.
./setup.shinstalls the tools, the model and the index, and registers the MCP server in Claude Code.ragnarok doctorchecks the setup.
Related MCP server: obsidian-mcp
Requirements
macOS with Homebrew. The setup uses
brew servicesfor Ollama.Ollama:
brew install ollama.setup.shinstalls uv if it is missing. uv installs Python 3.12.
Setup
git clone https://github.com/freyr/ragnarok.git
cd ragnarok
./setup.sh # installs uv if needed, then runs `ragnarok init`ragnarok init does six steps. It skips each step that is already done:
It writes
config.tomlfromconfig.example.toml. It asks for the vault root, the folder that holds your vault folders, and adds each subfolder as a vault.It checks that Ollama is installed.
It runs Ollama as a login service with
brew services start ollama(it asks first). If Ollama runs outside brew services, for exampleollama servein a terminal, init stops it and starts the service.It pulls the embedding model.
It builds the index. A vault with 1,500 notes takes approximately 12 minutes on an Apple Silicon Mac.
It registers the MCP server
ragnarokin Claude Code at the user scope (it asks before it replaces another registration).
Restart Claude Code after step 6. uv run ragnarok doctor checks the same six parts and prints the fix for
each failure.
Before step 5, examine config.toml: remove a folder that is not a vault, and add your private paths. A later
change of the configuration applies at the next ragnarok index or MCP tool call, with no restart.
Use in Claude Code
The server gives five tools:
Tool | What it does |
| Hybrid search over the notes. Filters: vault, project, area, type, archived. |
| The projects that match a prompt, with the summary and the matching notes of each project. |
| All notes of one project. |
| The text of a note or of one section, with its links and backlinks. |
| The notes that contain a ticket key, for example |
Claude Code loads MCP tools on demand. To make Claude use them before grep, add a short instruction to your
~/.claude/CLAUDE.md file, for example:
## 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.
- `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_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.Adapting to your vaults
docs/vault-requirements.md tells how a vault must look to get the most from
ragnarok: headings, project folders, SUMMARY.md, frontmatter and private folders.
The default path rules expect <vault>/<area>/<project>/note.md. If your vaults look different, the repo
skill .claude/skills/adapt-vault/ guides Claude Code through the changes. Open Claude Code in the checkout
and ask it to adapt ragnarok to your vaults. The skill:
runs
ragnarok surveyon each vault;agrees the private folders with you, before any other change and before a new vault goes into
vaults;writes the path rules into
config.toml, checked withragnarok inspect;runs the frontmatter backfill, if you agree, with your review before
apply;writes a small evaluation set from your notes and runs
ragnarok eval mechanical;adds the guidance above to your
~/.claude/CLAUDE.md, after it asks you.
It changes only config.toml and adds frontmatter keys. It never moves, renames or deletes a note or a folder.
Configuration
config.toml is in the checkout. A relative path in it is relative to the checkout. config.example.toml
explains each key. The most important keys:
Key | What |
| The folder that holds the vaults, and the vault folders to index. |
| Glob patterns of private notes, for example |
| The Ollama embedding model and its vector size. A change needs |
| The chunk size limits of the splitter. A change needs |
| A folder that holds one of these files is a project folder (default |
| The ticket prefixes that |
| The path rules of one vault: which folder gives the area and the project. |
Note metadata
ragnarok reads these frontmatter keys. Each key is optional:
---
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 stage: DONE, is archived
description: One sentence about the note, which improves find_projects.
jira: [ABC-123] # ticket keys, in addition to the keys in the text
---Without frontmatter, the path rules give the metadata. The default rules work for a vault with the layout
<vault>/<area>/<project>/note.md. For a different layout, add a [vault_rules.<vault>] table. Use
ragnarok inspect <note path> to see the metadata of a note.
Commands
Command | What it does |
| Sets up this computer (see Setup). |
| Checks the setup. |
| Adds, changes and removes notes in the index. After a change of the path rules, the private paths or the markers, it derives the metadata of all notes again, with no new embeddings. When a |
| Shows the size and the state of the index. |
| Searches from the terminal. |
| Shows the metadata of notes. |
| Shows the chunks of notes, or the totals. |
| Runs the MCP server on stdio. Claude Code starts it. |
| Proposes, describes and applies missing frontmatter keys. The order is |
| Prints the folders, frontmatter keys, marker files, name patterns and ticket prefixes of a vault folder. Run it before you write |
| Runs an evaluation on the question sets in |
Run each command with uv run in the checkout, for example uv run ragnarok search "boiler".
Where things are
Everything is in the checkout. Git ignores config.toml, data/ and logs/.
Path | What |
| The configuration of this computer. |
| The SQLite index. Copy it to a second computer to skip the first index. |
| The vault archives that |
| The output of |
| Your question sets ( |
| The MCP server log, one line for each tool call with its time. |
Ollama keeps the model in ~/.ollama. Set RAGNAROK_HOME to use a different home folder.
Development
uv run pytest
uv run ruff check . && uv run ruff format --check .License
MIT. See LICENSE.
Available Tools
5 toolsfind_by_jiraC
The notes that contain a Jira key, for example ABC-123.
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It identifies the filter condition but does not disclose read-only status, match semantics (exact/substring/case), permissions, pagination, or return behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one sentence with no filler and includes a useful example. However, it reads as a sentence fragment without an explicit verb, so it is concise but not perfectly front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter finder, the description adequately conveys the high-level result: notes containing a Jira key. With no annotations, no output schema, and 0% schema coverage, it still omits matching behavior and result completeness, leaving important gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for the single key parameter. It adds meaningful format context by naming it a Jira key and giving ABC-123 as an example, but it does not clarify matching exactness, case sensitivity, or other constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the resource (notes) and the filtering condition (contains a Jira key), with a concrete example ABC-123. It is clear what the tool retrieves, but it does not explicitly differentiate itself from sibling tools such as search or open_note.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no explicit when-to-use guidance, no alternatives, and no exclusions. The Jira key example implies the expected input, but it does not help the agent choose this tool over search or other siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_projectsC
Find the earlier projects that a prompt continues or resembles, ranked by their matching notes.
Each project has its slug, vault, folder, description, stage, next action and matching notes.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| vault | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden; it does disclose that results are ranked by matching notes and enumerates the returned fields (slug, vault, folder, description, stage, next action, matching notes), which is valuable given there is no output schema. However, it says nothing about read-only nature, result limits beyond the default, or the ranking algorithm's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Only two sentences and front-loaded with the core action, but the wording is awkward ("ranked by their matching notes") and the second sentence is a field list that could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with no annotations and no output schema, the description omits parameter semantics entirely and gives no usage context. It partially compensates by listing return fields, but an agent still lacks enough to call it correctly against alternatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description says nothing about `query` (format, natural language vs keyword), `limit` (default 5, max), or `vault` (filter scope). The word "vault" appears only as a returned field, which does not clarify the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A verb and a resource appear (find + projects), but the phrase "earlier projects that a prompt continues or resembles" is vague — it's not clear whether this is a similarity search, a continuation lookup, or a keyword match. Nothing distinguishes it from the sibling `search` or `list_project`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool rather than `search`, `list_project`, or `find_by_jira`. The agent must infer the selection rule from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_projectC
All notes of a project in any folder, with type, status and description, plus its stage and next action.
| Name | Required | Description | Default |
|---|---|---|---|
| vault | No | ||
| project | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It says nothing about permission/auth needs, whether an unknown project errors or returns empty, result size or pagination, or whether the call is purely read-only — only the field names hint at read semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single short clause with no filler words, but it is a sentence fragment rather than a front-loaded statement of the action. Brevity here comes partly from omission rather than efficient information density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-parameter tool with undocumented schema fields, no annotations, and no output schema, the description should cover the identifier format and the vault scoping. It describes the return payload loosely but leaves the calling contract (what a valid 'project' and 'vault' look like) unresolved.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both parameters, and the description never mentions 'vault' at all nor clarifies whether 'project' is a name, path, or ID. The one thing it does imply — that the project identifier scopes the returned notes — is the minimum the agent could already infer from the parameter name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The phrase 'All notes of a project in any folder' conveys the resource and scope, but there is no verb, so the operation (list/retrieve) is only inferred from the tool name. It also blends two things — the project's notes and the project's 'stage and next action' — without making the relation explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no indication of when to use this versus siblings like search, find_projects, or open_note. 'in any folder' hints at a broad-recall use case, but the agent gets no explicit selection rule or prerequisite (e.g., needs an existing project identifier).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_noteB
The text of a note (or of one section, by heading), its frontmatter, links and backlinks.
Credentials in the text are replaced with [REDACTED]. Private notes are refused.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| heading | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description carries the full burden. It discloses two important behaviors: credential redaction and refusal of private notes. However, it does not explicitly state that the operation is read-only, nor does it describe error handling or permission requirements beyond private notes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero waste. It front-loads what the tool returns and follows with critical behavioral constraints. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and no output schema, the description does a decent job of describing return values and key constraints. However, it omits important details such as path format, error behavior if the note is not found, and explicit read-only status, leaving gaps for an agent to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It hints at the 'heading' parameter ('or of one section, by heading'), but does not explain the required 'path' parameter or its expected format. The compensation is partial and insufficient for full clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description specifies the resource (a note or section by heading) and the returned data (text, frontmatter, links, backlinks), making the tool's purpose clear. It does not explicitly differentiate from siblings like search or find_projects, but the scope is sufficiently distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives such as search or find_projects is provided. The description implies usage (opening a note by path), but there are no when/when-not statements or named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchA
Hybrid search (meaning and keywords) over the vault notes. Returns notes, each with its best section.
Filters: vault (the name of a vault folder), project (folder slug), area, type (research,
spec, plan, summary, drivers, guide, note, ...). include_private works only when the user allows it.
| Name | Required | Description | Default |
|---|---|---|---|
| area | No | ||
| type | No | ||
| limit | No | ||
| query | Yes | ||
| vault | No | ||
| project | No | ||
| include_private | No | ||
| include_archived | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It usefully discloses that the search is hybrid and that results are notes with their best section, and it notes the include_private permission constraint. However, it does not explain read-only behavior, limit/pagination, result ordering, or include_archived defaults.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and return shape, then compactly lists relevant filters. It is appropriately sized and contains no filler or redundant restatement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the core search behavior and return format, but with 8 parameters, no annotations, no output schema, and 0% schema description coverage, it leaves important gaps around limit, include_archived, area semantics, and default behavior. It is adequate but not complete for an agent to invoke with full confidence.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for 8 parameters. It adds meaning for vault as a vault folder name, project as a folder slug, type with examples, and the include_private caveat, but leaves query, limit, area, and include_archived unexplained or underspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: hybrid meaning-and-keyword search over vault notes, returning notes with their best section. It clearly identifies the tool's function, though it does not explicitly contrast itself with siblings such as find_by_jira or open_note.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the search-over-notes framing and by the filter list, but there is no explicit guidance on when to use this tool versus alternatives. The include_private caveat gives one useful condition, but broader when/when-not guidance is absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.0.0- First observed
find_by_jira - First observed
find_projects - First observed
list_project - First observed
open_note - First observed
search
TDQS
Scored across 5 tools
Each tool has a fairly clear niche: search is general hybrid retrieval, find_projects is prompt-driven project matching, list_project enumerates one project's notes, open_note reads full content, and find_by_jira is a keyed lookup. The only real friction is between search and find_by_jira (both retrieve notes) and between find_projects and list_project, though the descriptions make the intent distinguishable.
Four of five tools follow a clean verb_noun snake_case pattern (find_projects, list_project, open_note, find_by_jira). The bare verb 'search' is a minor but reasonable deviation as the primary entry point.
Five tools is well within a healthy range and each covers a distinct retrieval need (general search, project discovery, project detail, note reading, Jira lookup). Nothing feels redundant or bolted on.
For a read-only vault retrieval server, the surface covers the main workflows: find notes, drill into projects, open content, and resolve Jira keys. Minor gaps exist around enumerating projects/vaults/areas without a prompt (all project discovery routes through find_projects), which agents would have to work around via search.
Maintenance
Related MCP Connectors
Search and reason over your Obsidian-style Markdown vault, right from ChatGPT.
Connect AI assistants to your GitHub-hosted Obsidian vault to seamlessly access, search, and analy…
Search your Obsidian vault to quickly find notes by title or keyword, summarize related content, a…
Work on your own computers from Claude or ChatGPT: run commands, edit and search files.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables Claude Code read/write access to an Obsidian vault, including creating, editing, searching, and browsing notes.8MIT
- AlicenseNot gradedqualityCmaintenanceConnects Claude to a local Obsidian vault, enabling listing, reading, searching, and optionally editing notes via natural language, with all operations running locally.3,805 npmMIT
- AlicenseNot gradedqualityBmaintenanceLets Claude Code and Claude Desktop retrieve and explore an Obsidian vault through tools for semantic search, reading notes, following graph neighbors, and listing topics.MIT
- AlicenseNot gradedqualityBmaintenanceGives Claude Code read-only semantic search over an Obsidian vault by reading the embedding files the Smart Connections plugin already produces, so no API key or network is needed at query time and it works across the WSL/Windows boundary. Exposes tools for meaning-based note and block search with folder scoping, related-note discovery, note reading, and index health checks.37 npmMIT