Skip to main content
Glama
rtbarnes

Obsidian Collaboration MCP

by rtbarnes
README.md
# Obsidian Collaboration MCP

A small Model Context Protocol server for deliberate access to an Obsidian vault.
It reads ordinary Markdown files directly, so Obsidian does not need to be open.

The server is intentionally narrower than a “second brain” system:

- No embeddings, vector database, or background indexing.
- No automatic chat persistence or agent memory.
- No delete, move, command execution, or hidden-folder access.
- Edits require the SHA-256 returned by `read_note`, which prevents stale overwrites.
- New notes default to a configurable collaboration folder.
- An optional folder allowlist can restrict every write.

## Tools

| Tool | Access | Purpose |
| --- | --- | --- |
| `vault_info` | Read | Show vault details and access boundaries. |
| `list_notes` | Read | List Markdown notes without loading their contents. |
| `search_notes` | Read | Run case-insensitive literal full-text search. |
| `read_note` | Read | Read a note and return its SHA-256. |
| `create_note` | Write | Create a note without overwriting an existing file. |
| `append_note` | Write | Append after an optimistic-concurrency check. |
| `replace_note_text` | Write | Replace one exact, unique text span after a concurrency check. |

Set `OBSIDIAN_READ_ONLY=1` to omit all write tools.

## Requirements

- [Bun](https://bun.sh/) 1.3 or newer
- A local Obsidian vault, which is simply a directory containing Markdown files
- An MCP client with stdio support

## Install

```sh
git clone https://github.com/rtbarnes/obsidian-collaboration-mcp.git
cd obsidian-collaboration-mcp
bun install --frozen-lockfile
```

## Configure

| Environment variable | Required | Default | Description |
| --- | --- | --- | --- |
| `OBSIDIAN_VAULT_PATH` | Yes | — | Absolute path to the vault. |
| `OBSIDIAN_DEFAULT_FOLDER` | No | `ChatGPT` | Destination used when `create_note` omits `path`. |
| `OBSIDIAN_WRITE_FOLDERS` | No | All non-hidden folders | Comma-separated folder allowlist for every write. |
| `OBSIDIAN_READ_ONLY` | No | `0` | Set to `1`, `true`, or `yes` to omit write tools. |

All tool paths are vault-relative. The server rejects traversal, hidden paths,
non-Markdown files, and symlink escapes.

### Codex

Add the server to `~/.codex/config.toml`:

```toml
[mcp_servers.obsidian]
command = "bun"
args = ["run", "/absolute/path/to/obsidian-collaboration-mcp/src/index.ts"]

[mcp_servers.obsidian.env]
OBSIDIAN_VAULT_PATH = "/absolute/path/to/your/vault"
OBSIDIAN_DEFAULT_FOLDER = "ChatGPT"
OBSIDIAN_WRITE_FOLDERS = "ChatGPT"
```

Restart Codex after editing the configuration.

### Other stdio clients

Use `bun run /absolute/path/to/obsidian-collaboration-mcp/src/index.ts` as the
server command and provide the same environment variables. The exact config
format depends on the client.

## Safe editing model

`read_note` returns `sha256`. Pass it as `expectedSha256` to `append_note` or
`replace_note_text`. If Obsidian Sync, another device, or another process changes
the note between the read and the write, the edit fails and the client must read
the note again.

`replace_note_text` also requires the search text to occur exactly once. This
keeps edits targeted and avoids replacing an unexpected section.

## Remote access

This is a stdio server and does not open a network port. Run it beside a trusted
MCP tunnel or gateway when a remote client needs access. Keep authentication and
authorization in that outer layer.

For an always-on Obsidian Sync bridge, run the server beside
[Obsidian Headless](https://github.com/obsidianmd/obsidian-headless) on a trusted
host with encrypted storage.

## Development

```sh
bun run typecheck
bun test
```

The integration test starts the real stdio server, inspects its tool surface,
and creates a note in a temporary vault.

## Security

An MCP client can read any Markdown note that its tools expose. Start with a
non-sensitive test vault or `OBSIDIAN_READ_ONLY=1`. Use
`OBSIDIAN_WRITE_FOLDERS` when the client should write only to a dedicated area.

The server does not authenticate clients because stdio MCP servers inherit the
trust boundary of the process that launches them. Do not expose the process
directly to a network.