Skip to main content
Glama
achyuta0001

obsidian-mcp

by achyuta0001
README.md
# obsidian-mcp

An MCP server that gives Claude a per-project notes folder inside one local Obsidian vault.

Each project gets its own subfolder under `<vault>/Projects/<project-slug>/`. There is still a
single vault, so cross-project links and the graph view keep working — you never have to switch
vaults in Obsidian.

## Tools

| Tool | What it does |
| --- | --- |
| `resolve_project` | Report which project folder notes will go to, and how that was decided. |
| `write_note` | Create a note. Refuses to clobber an existing one unless `overwrite: true`. |
| `read_note` | Read a note's full contents. |
| `append_note` | Append to the end of a note, creating it if absent. |
| `list_notes` | List notes in the project, or across the whole vault with `scope: "vault"`. |
| `search_notes` | Case-insensitive text search returning `note:line: text` matches. |

Every tool takes an optional `project` argument that overrides inference.

## How the project is chosen

1. An explicit `project` argument, if given.
2. Otherwise, walk up from the server's working directory to the nearest `.git` and use that
   directory's name — so a call made from `~/Developer/Projects/foo/src/lib` still resolves to
   `foo`.
3. Otherwise, use the working directory's own name.

Names are slugified: `Job Search` becomes `job-search`.

If inference lands on a container directory (`Developer`, `Projects`, `src`, `$HOME`, …) the
server refuses to guess and asks for an explicit `project`. That is the intended behavior, not a
bug — guessing there would scatter notes into a folder named after nothing in particular.

**In Claude Desktop, always pass `project` explicitly.** Desktop spawns MCP servers with an
arbitrary working directory, so there is nothing meaningful to infer from. Claude Code inherits
its own working directory, so inference works there.

## Configuration

| Variable | Default |
| --- | --- |
| `OBSIDIAN_VAULT_PATH` | `~/Documents/Obsidian Vault` |
| `OBSIDIAN_PROJECTS_DIR` | `Projects` (relative to the vault root) |

The vault itself must already exist — the server will not create one, since a bare directory is
not a vault. Project subfolders are created on first write.

## Development

```bash
npm install
npm run build
npm test
```

`npm test` runs unit tests for path handling and project resolution, plus an end-to-end suite
that speaks real JSON-RPC to the built server over stdio against a temporary vault.

## Registration

Claude Code (user scope, so it applies to every project):

```bash
claude mcp add --scope user obsidian -- node /path/to/obsidian-mcp/dist/index.js
```

Claude Desktop — in `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "obsidian": {
      "command": "node",
      "args": ["/path/to/obsidian-mcp/dist/index.js"]
    }
  }
}
```

Rebuild after changing `src/`; both clients run `dist/`.

## macOS folder protection

A vault under `~/Documents` (also `~/Desktop`, `~/Downloads`) sits in a TCC-protected
location. A sandboxed host can end up able to write into folders it created while still
being denied a listing of the vault root — which breaks `scope: "vault"` for
`list_notes` and `search_notes` while everything project-scoped works fine.

The server raises `Permission denied reading …` rather than reporting an empty vault, so
this is visible instead of silent. Two ways out:

- Grant Full Disk Access to whatever runs the server (System Settings → Privacy &
  Security → Full Disk Access).
- Or move the vault somewhere unprotected and set `OBSIDIAN_VAULT_PATH`, e.g.
  `~/Vaults/main`.

## Safety

Note names are resolved and checked against the project folder, so `../../etc/passwd` and
absolute paths are rejected rather than written. Writes never leave `<vault>/Projects/<slug>/`.

TDQS

A4.1/5.0

Scored across 6 tools

Disambiguation5/5

Each tool serves a clearly distinct purpose: resolving project routing, writing, reading, appending, listing, and searching notes. Even write_note and append_note are well differentiated by their overwrite and append semantics.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: resolve_project, write_note, read_note, append_note, list_notes, search_notes. This makes the API predictable and easy to navigate.

Tool Count5/5

Six tools is a well-scoped set for an Obsidian note management server. Each tool covers a distinct operation without redundancy or bloat.

Completeness4/5

The core note lifecycle is well covered: create/write, read, append, list, and search. Missing delete, move, or rename operations are noticeable gaps, but agents can still accomplish most note workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues