Skip to main content
Glama
ferronicardoso

mcp-obsidian

README.md
# MCP Server for Obsidian

An MCP server for interacting with a local Obsidian vault via natural language, exposing read and write operations on the vault's notes (`.md`) to MCP clients (Claude Desktop, Claude Code, VS Code Copilot, Cursor, and compatible hosts).

Direct filesystem access to the vault — does not depend on the Obsidian app being open or on any installed plugin (e.g. Local REST API).

## Security guardrails

Every tool goes through `resolveNotePath()` before touching the filesystem. That function rejects:

- absolute paths, drive letters (`C:\...`) and UNC paths (`\\...`);
- traversal (`..`) in any path segment, even disguised inside subfolders;
- hidden segments (`.obsidian`, `.git`, `.trash`, etc.) — protects Obsidian's internal config and version control;
- any extension other than `.md`.

In addition:

- `create_note` does not overwrite by default — requires explicit `overwrite: true`;
- `delete_note` requires explicit `confirm: true`, even with a valid `path`;
- listing, search, and backlinks ignore hidden folders and `node_modules`.

These validations limit the model's blast radius to `.md` files inside the configured vault, even in the face of a malicious prompt or a model hallucination trying to escape scope.

## Available Tools

| Tool | Description |
|---|---|
| `list_notes` | Lists `.md` notes in the vault, optionally restricted to a subfolder |
| `read_note` | Reads a note: frontmatter, body, and wikilinks found |
| `search_notes` | Searches text across all notes, returning file/line/snippet |
| `get_backlinks` | Lists notes that reference the given note via `[[wikilink]]` |
| `create_note` | Creates a new note (fails if it already exists, unless `overwrite: true`) |
| `append_to_note` | Appends text to the end of an existing note |
| `delete_note` | Deletes a note (requires `confirm: true`) |

## Requirements

- Node.js 18+
- A local Obsidian vault (any folder of `.md` files — the Obsidian app does not need to be open)

## Configuration

| Variable | Required | Default | Description |
|---|---|---|---|
| `OBSIDIAN_VAULT_PATH` | Yes | — | Absolute path to the local Obsidian vault |
| `MCP_TRANSPORT` | No | `stdio` | Transport mode: `stdio` (default, for `npx`/Claude Desktop/VS Code) or `http` (Streamable HTTP, for Docker/remote clients) |
| `MCP_HTTP_PORT` | No | `3004` | HTTP server port (only used when `MCP_TRANSPORT=http`) |
| `MCP_HTTP_HOST` | No | `0.0.0.0` | HTTP server bind address (only used when `MCP_TRANSPORT=http`) |

## Usage

### Run directly from GitHub

```bash
npx github:ferronicardoso/mcp-obsidian
```

### Claude Code (CLI)

**PowerShell:**

```powershell
claude mcp add obsidian --scope user `
  --env OBSIDIAN_VAULT_PATH="/my/obsidian/vault/path/" `
  -- npx -y github:ferronicardoso/mcp-obsidian
```

`--scope` controls where the server registration is stored:

| Scope | Stored in | Visible to |
|---|---|---|
| `local` (default) | project-local, untracked | only you, only in this project |
| `project` | `.mcp.json` at the project root | anyone who clones the repository (commit it to share) |
| `user` | global Claude Code config | you, across all projects |

### Claude Desktop configuration

`%APPDATA%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "obsidian": {
      "command": "npx",
      "args": ["github:ferronicardoso/mcp-obsidian"],
      "env": {
        "OBSIDIAN_VAULT_PATH": "/my/obsidian/vault/path/"
      }
    }
  }
}
```

### VS Code MCP configuration

`.vscode/mcp.json`:

```json
{
  "servers": {
    "obsidian": {
      "command": "npx",
      "args": ["github:ferronicardoso/mcp-obsidian"],
      "env": {
        "OBSIDIAN_VAULT_PATH": "/my/obsidian/vault/path/"
      }
    }
  }
}
```

### Run with Docker (HTTP transport)

The vault needs to be mounted as a volume inside the container; `OBSIDIAN_VAULT_PATH` must point to the path *inside* the container.

```powershell
docker run -d --name mcp-obsidian `
  -p 3004:3004 `
  -v "/my/obsidian/vault/path/:/vault:rw" `
  -e OBSIDIAN_VAULT_PATH=/vault `
  ghcr.io/ferronicardoso/mcp-obsidian:latest
```

The MCP endpoint is then available at `http://localhost:3004/mcp`.

## Local Development

```bash
git clone https://github.com/ferronicardoso/mcp-obsidian
cd mcp-obsidian
npm install
npm run build
```

Run the compiled server:

```powershell
$env:OBSIDIAN_VAULT_PATH = "/my/obsidian/vault/path/"
npm start
```

Run the tests:

```bash
npm test
```

## Build and Commit Workflow

This repository keeps `dist/` tracked to support `npx github:user/repo`.

A Husky `pre-commit` hook:
1. builds TypeScript (`npm run build`)
2. stages the generated artifacts (`git add dist`)

Manual fallback:

```bash
npm run build
git add dist
```

## Security Notes

- `OBSIDIAN_VAULT_PATH` must point to a real user vault — the server refuses to start if the path does not exist or is not a directory.
- All write tools (`create_note`, `append_to_note`, `delete_note`) operate exclusively inside the vault, validated by `resolveNotePath()`.
- There is no audit trail (who/when changed what) and no automatic versioning of changes. Before pointing it at a production vault, consider versioning the vault with Git or keeping backups.

## License

[MIT](LICENSE) © Raphael Augusto Ferroni Cardoso

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a clearly distinct operation: listing, reading, searching, backlink lookup, creating, appending, and deleting. The read operations are differentiated by what they return, and the write operations are cleanly separated by semantics.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern (list_notes, read_note, search_notes, create_note, etc.). The naming style is uniform and predictable.

Tool Count5/5

Seven tools is well-scoped for an Obsidian vault server. Each tool covers a necessary note operation without redundancy or bloat.

Completeness4/5

Core note lifecycle operations are covered: list, read, search, create, append, delete, and backlink discovery. Minor gaps like rename/move or direct edit-by-section exist, but they are workable via create with overwrite and append.

Maintenance

ActivityMaintained
ResponsivenessNo issues