A small Model Context Protocol server that lets an AI assistant search and read an Obsidian vault over stdio: full-text search, notes with frontmatter, tags, backlinks and outgoing links. It never writes and never touches the network.
An Obsidian vault holds years of notes an AI assistant could use as context. Handing it over should not mean uploading it, or giving a model write access to files it only needs to read.
TypeScript over stdio, with two runtime dependencies: the official MCP SDK and zod. Five tools, all read-only: search, read_note, backlinks, outgoing_links and list_notes. Search ranks with BM25 over an in-memory index that re-reads only changed files. Links resolve the way Obsidian resolves them: wikilinks with aliases and headings, embeds, Markdown links, frontmatter tags and aliases.
The code only lists, stats, resolves and reads files, and a test fails if any other filesystem call or a network call appears. Path traversal, absolute paths outside the vault, NUL bytes and dot-folders such as .obsidian and .git are refused. Symlinks and junctions that resolve outside the vault are ignored, and each file's real path is checked again right before it is read.
49 tests: parsing, link resolution, every tool, path-traversal and symlink attempts, plus an end-to-end run that starts the server over stdio and calls each tool through the MCP SDK client. CI runs them on Node 20 and 22, on Ubuntu and Windows. On a real 215-note vault the index built in 87 ms, searches took 3 to 12 ms, and one note's backlinks (33 notes, 48 links) matched an independent count.