obsidian-brain
by pace551
README.md
# obsidian-brain
A local MCP server that lets Claude — in **Claude Desktop / claude.ai** as well as Claude
Code — capture sessions into the personal Obsidian vault and recall them later, plus the
version-controlled source for the `obsidian-capture` and `obsidian-recall` skills.
The point of the server is that the note schema is a **tool contract, not a prompt**. An
invented area or a missing Resume Prompt comes back as a validation error instead of a
malformed note nobody notices for six months.
## Tools
| Tool | Purpose |
| -------------- | -------------------------------------------------------------------------------------------- |
| `capture_note` | Write a structured note to `Inbox/`. Owns filename, frontmatter, sections. Never overwrites. |
| `search_notes` | Ranked keyword search with area/type/tag/recency filters. Read-only. |
| `list_recent` | The N most recently modified notes. Read-only. |
| `read_note` | One note by vault-relative path, with frontmatter and sections parsed out. Read-only. |
| `update_note` | Edit a `source: claude` note in place: replace/append sections, retitle, change frontmatter. |
Notes land as `Inbox/YYYY-MM-DD <slug>.md`:
```text
---
date: 2026-08-05
type: how-to
areas:
- van
tags:
- victron
source: claude
status: inbox
---
# Victron MPPT charge profile for the lithium bank
## Summary
## Key Learnings
## Ideas / Follow-ups <- omitted entirely when empty
## Resume Prompt
## Context
```
- `type` — one of `learning`, `idea`, `research`, `how-to`, `project-note`
- `areas` — one or more from a fixed list of life/work areas (see
[Customizing areas](#customizing-areas))
- `tags` — freeform, lowercase, hyphenated
New notes go to `Inbox/` and nowhere else. Reads and edits are confined to the vault:
absolute paths, `..`, non-`.md` files, and symlinks pointing outside are all rejected.
`update_note` edits notes this server wrote (`source: claude` in the frontmatter) wherever
they now live in the vault; hand-written notes are refused. Edits are surgical — fields you
don't pass stay byte-for-byte as they were, including frontmatter keys and sections added
by hand in Obsidian. Each edit must carry the `hash` from the `read_note` (or previous
`update_note`) that preceded it, and is refused if the file changed in between, so a stale
model can't overwrite something you just edited. There is no delete tool — Obsidian is for
that.
### Customizing areas
The shipped areas are the author's own (`van`, `motorcycles`, `cycling`, `sailing`,
`automotive`, `home-automation`, `homestead`, `spa-rpa`, `ai-learning`, `diy`, `family`,
`work`, `general`) — an example, not a recommendation. Replace them with whatever buckets
fit your vault before you start capturing. Area keys are lowercase and hyphenated.
1. Edit `AREAS` in `src/schema.ts`. It is the single source of truth: the server rejects
any area not in that list, on capture and on the `search_notes` area filter. Keeping
`general` (or some catch-all) is recommended so there is always a valid fallback.
2. Update the skills that spell the list out so clients pick from the same values:
`skills/obsidian-capture/SKILL.md`, `skills-desktop/obsidian-capture/SKILL.md`, and
`skills-desktop/obsidian-recall/SKILL.md`. `scripts/test.sh` fails until every listed
copy matches `src/schema.ts` exactly, in order.
3. Rebuild and redeploy: `npm run build`, `npm run deploy:skills`, and — if you uploaded
the Desktop skills — `npm run build:desktop-skills` and re-upload the zips. Restart
Claude Desktop so it launches the new server.
Renaming or removing an area does not touch existing notes; their frontmatter keeps the
old value, and the `search_notes` area filter will no longer accept it. Retag them in
Obsidian if that matters to you. `NOTE_TYPES` in the same file can be customized the same
way.
## Setup
```bash
npm install
npm run build # dist/index.js — what Claude Desktop launches
scripts/register-desktop.sh # backs up and merges into claude_desktop_config.json
```
Then restart Claude Desktop. For the skills:
```bash
npm run deploy:skills # skills/ -> ~/.claude/skills/ (Claude Code)
npm run build:desktop-skills # skills-desktop/ -> dist/skills/*.zip
```
Optionally, upload each zip via **Claude Desktop → Settings → Customize → Skills**
(requires code execution). Desktop works without them: the MCP server registered above is
what gives it the vault tools, and it enforces the note schema itself. The skills only add
capture/recall workflow guidance. Uploaded skills are per-user and update by re-uploading.
## The two skill variants
`skills/` and `skills-desktop/` hold the same two skills written for different runtimes:
- **`skills/`** — Claude Code. Uses Read/Write/ripgrep against the vault directly; no
server needed. `~/.claude/skills/` is a _deployed copy_; edit the repo, not the copy.
`scripts/check-skill-drift.sh` fails if they diverge.
- **`skills-desktop/`** — Claude Desktop / claude.ai. No filesystem, so these drive the MCP
tools above.
They share no template on purpose: the invariants that matter (the enums, the note format)
are enforced by the server, and `tests/skills.test.ts` fails if the taxonomy listed in any
SKILL.md drifts from `src/schema.ts`.
## Commands
```bash
scripts/lint.sh # prettier --check + eslint
scripts/test.sh # vitest + coverage
npm run typecheck # tsc --noEmit
npm run inspect # MCP inspector against a live server
npm run check:skill-drift # deployed skills vs canonical
```
Configuration is one env var, `OBSIDIAN_VAULT_ROOT` (default
`~/Documents/Obsidian/Personal`), supplied by the MCP client config. No credentials.
Governed at **T1** — see `GOVERNANCE.md`.
## License
[Business Source License 1.1](LICENSE). You may use, modify, and redistribute obsidian-brain
for your own vaults, including for commercial work; offering it to others as a hosted
service is not covered. Each version converts to MIT on 2029-09-30.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues