Skip to main content
Glama
artificemachine

Obsidian Semantic MCP

Obsidian Semantic MCP

Tests License: Apache 2.0 Python 3.10+ Docker Hub

A persistent memory layer for Claude Desktop — semantic search across your entire Obsidian vault using local embeddings and PostgreSQL + pgvector.

Monitoring dashboard — live stats, recent indexing activity, and semantic search test panel

The Problem

AI assistants forget everything between sessions. You repeat context, lose continuity, and start from zero every time. Your notes, projects, and preferences sit in Obsidian but never make it into your AI conversations automatically.

Related MCP server: Obsidian MCP Server

The Solution

Obsidian Semantic MCP turns your vault into a queryable brain for Claude. It:

  • Indexes every note as a vector embedding (via Ollama + nomic-embed-text)

  • Stores embeddings in PostgreSQL with pgvector for fast semantic search

  • Watches your vault for changes and re-indexes automatically

  • Provides full vault CRUD (read, write, search, list) — works even when Obsidian is closed

  • Exposes everything through MCP so Claude can retrieve and manage vault content on the fly

No cloud services. No API keys. Everything runs locally.

Quick Start

Start with the bootstrap installer for your platform. If you already cloned the repo, you can skip bootstrap and run uv run osm init from the project root.

First 60 seconds (new user)

If you're in a fresh environment (no osm launcher yet), run these from the repo root.

Pick the mode number for your OS — the recommended path is Full Docker (everything in containers, nothing to install but Docker):

OS

Recommended --mode

macOS

--mode 3

Linux / Windows

--mode 2

# 1) Preview setup actions safely — no changes made (use YOUR mode from the table)
uv run osm init --dry-run --mode 3 --vault "/path/to/your/vault" --pg-password "obsidian" --persistent --data-dir "/path/to/data"

# 2) Run setup for real
uv run osm init --mode 3 --vault "/path/to/your/vault" --pg-password "obsidian" --persistent --data-dir "/path/to/data"

# 3) Open the monitoring dashboard
uv run osm dashboard

The commands above use --mode 3 (macOS). On Linux/Windows use --mode 2. Already running Ollama locally? Use --mode 4 (Docker + host Ollama) to skip re-downloading the Ollama image and model. --mode 1 is a native (non-Docker) macOS install — only pick it if you specifically want Postgres and the server running outside containers. For ephemeral/CI setups, use --no-persistent instead.

Platform support: Linux is the CI-tested path — the full test suite (including PostgreSQL integration tests) runs on ubuntu-latest in CI on every push. macOS is supported via osm init --mode 3 (Docker Desktop on the recommended path, or osm init --mode 1 native) but is not yet covered by CI. Windows is supported via the WSL2 Docker backend and the install.ps1 / osm.ps1 launchers, but is not yet covered by CI; treat it as community-tested until a Windows runner lands.

Before you start:

  • uv must be installed — curl -LsSf https://astral.sh/uv/install.sh | sh (macOS/Linux) or powershell -c "irm https://astral.sh/uv/install.ps1 | iex" (Windows)

  • Docker Desktop — the wizard will offer to install it automatically if missing (brew on macOS, winget on Windows, get.docker.com on Linux). On Windows, enable the WSL2 backend.

  • Know your vault path — in Obsidian: Settings → About → Vault location

1. Bootstrap and run the setup wizard

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/artificemachine/obsidian-semantic-mcp/main/install.sh | bash

If ~/.local/share/obsidian-semantic-mcp already exists, the installer updates that checkout before continuing. If that install directory has uncommitted local changes, the update step can abort with a Git merge error. In that case either commit/stash those changes there, or use your current checkout directly with uv run osm init.

Windows PowerShell:

powershell -c "irm https://raw.githubusercontent.com/artificemachine/obsidian-semantic-mcp/main/install.ps1 | iex"

Tip: The bootstrap installer launches osm init for you. After a full install, you can run osm init --dry-run from an existing checkout to preview every action without making any changes.

If you already cloned the repo, scripts/osm (macOS/Linux) and scripts/osm.ps1 (Windows PowerShell) work the same as the bootstrap installers. If you prefer a manual checkout, clone the repo and run uv run osm init from the project root.

One server, all projects: obsidian-semantic is registered globally — running osm init from any other project is safe and idempotent. If already configured, it skips registration and informs you.

OpenCode/GitHub Copilot note: In this repository, osm means the Obsidian Semantic MCP CLI, not OpenStreetMap. In a new chat session, run commands explicitly (for example, osm dashboard) to avoid acronym ambiguity.

If osm is not found: use uv run osm <command> from the repo root (for example, uv run osm init --dry-run).

Session starter (copy/paste):

In this repo, "osm" means the obsidian-semantic-mcp CLI (not OpenStreetMap).
Please execute shell commands directly when I type them.
If `osm` is not found, use `uv run osm ...` from the repo root.
Examples: osm init, osm dashboard.

Exit the wizard at any prompt: type q, quit, exit, or skip — or press Ctrl+C.

The bootstrap installers clone into the local data directory, create a PATH shim for osm, and launch the wizard.

The wizard detects your OS and asks which installation mode you want:

macOS:

  1)  Native              Homebrew + local Postgres + local Ollama
  2)  Docker + host Ollama    Postgres in Docker, Ollama already on this Mac
  3)  Full Docker         Everything in containers  (recommended)
  4)  Docker + remote Ollama  Postgres in Docker, Ollama on another machine

Linux:

  1)  Docker + host Ollama    Postgres in Docker, Ollama on this machine
  2)  Full Docker         Everything in containers  (recommended)
  3)  Docker + remote Ollama  Postgres in Docker, Ollama on another machine

Windows (requires Docker Desktop with WSL2 backend):

  1)  Docker + host Ollama    Postgres in Docker, Ollama already on this PC
  2)  Full Docker         Everything in containers  (recommended)
  3)  Docker + remote Ollama  Postgres in Docker, Ollama on another machine

Which mode? Pick Full Docker (mode 3 on macOS, mode 2 on Linux/Windows) unless you already have Ollama running locally - in that case pick Docker + host Ollama to avoid re-downloading the Ollama image and model.

It then:

  • Sets up the local install directory and PATH shim

  • Installs prerequisites or verifies they already exist (Docker is installed and started automatically if missing)

  • Pulls nomic-embed-text if needed

  • Writes a .env file (gitignored) with your vault path and credentials

  • Updates MCP client config automatically for Claude Desktop, Claude Code CLI, OpenCode, and pi (whichever are installed)

  • Uses the repo launcher script in generated MCP entries, so startup does not depend on a raw Docker command or container-name-specific config

2. Restart your MCP client(s)

Restart Claude Desktop / OpenCode to pick up the new server. For Claude Code CLI, the entry is registered live; verify with claude mcp list. For pi, run /reload inside an active session or restart pi.

pi users: osm init also patches ~/.pi/agent/extensions/mcp-bridge.ts if present. obsidian-semantic requires heartbeat: true and a spawn-time heartbeat in the bridge due to its blocking asyncio stdin transport. See docs/pi_mcp_bridge_heartbeat.md for details.

Manual config (only if osm init could not detect your client)

Add the same block to ~/.opencode.json, claude_desktop_config.json, or whatever JSON config your MCP client uses:

{
  "mcpServers": {
    "obsidian-semantic": {
      "command": "/absolute/path/to/obsidian-semantic-mcp/scripts/obsidian-semantic-mcp",
      "args": [],
      "env": {}
    }
  }
}

Replace /absolute/path/to/obsidian-semantic-mcp with your local clone path. The launcher prefers the running Docker stack and falls back to the repo-local .venv when Docker is unavailable.

3. First-run indexing

The server indexes your vault on first run, then watches for changes automatically.

First-run indexing takes roughly 1–2 seconds per note — expect 5–15 minutes for a 500-note vault. Monitor progress at http://localhost:8484. Claude will return no results until indexing completes.

Prefer running without Docker? See Native Install (macOS). Want to skip the wizard? See Manual start.


Native Install (macOS)

Prefer not to run Docker? osm init --mode 1 installs PostgreSQL + pgvector and Ollama via Homebrew and runs the MCP server in-process — no containers. Pick this if you already avoid Docker, or want the server sharing your Mac's native Ollama install directly.

uv run osm init --mode 1 --vault "/path/to/your/vault"

This mode registers the MCP client entry with OBSIDIAN_VAULT/DATABASE_URL set directly on the entry (Docker mode instead loads a .env the launcher finds via the running container's project root) — restart your MCP client afterward the same as any other mode.

Manual start (without wizard)

OBSIDIAN_VAULT="/path/to/your/vault" POSTGRES_PASSWORD=obsidian docker compose up -d

Docker Compose also reads a .env file in the repo root (gitignored).

First run pulls all images and the nomic-embed-text model automatically. This starts:

Service

Port

Description

PostgreSQL + pgvector

5433

Vector storage (avoids conflict with host pg)

Ollama

11435

Local embeddings (auto-pulls model)

MCP server

stdio

Clients connect via scripts/obsidian-semantic-mcp, which prefers Docker and falls back to local .venv

Dashboard

8484

http://localhost:8484

Useful commands

# View server logs
docker compose logs -f mcp-server

# Rebuild after code changes
docker compose up -d --build mcp-server dashboard

# Stop everything
docker compose down

# Stop and wipe all data (re-index from scratch)
# ⚠️  WARNING: -v deletes all indexed embeddings. Re-indexing will restart from scratch.
docker compose down -v

GPU support (optional)

For faster embeddings on Linux with NVIDIA GPU, add to the ollama service in docker-compose.yml:

deploy:
  resources:
    reservations:
      devices:
        - capabilities: [gpu]

Troubleshoot

The top 3 things that go wrong on first install:

  • No search results / Claude says the server isn't connected — first-run indexing takes 5–15 minutes for a 500-note vault; watch progress at http://localhost:8484, or docker compose logs -f mcp-server.

  • Postgres connection failures — check the container is healthy: docker compose ps, then docker compose exec postgres pg_isready -U obsidian.

  • Ollama unreachable — confirm it's running: curl http://localhost:11434/api/tags (or the SSH tunnel's local port for remote-Ollama mode).

Full incident-by-incident guide, including dashboard/indexing/Ollama-container recovery steps: docs/RUNBOOK.md.


Using with Claude

Once the MCP server is connected, Claude can access your vault directly — no special syntax needed. Just talk to it naturally.

Example prompts

"Search my notes for anything about project X"
"What did I write about ketosis last month?"
"Find my notes on the Zettelkasten method"
"Read my Daily/2026-03-14.md note"
"Append this meeting summary to my inbox note"
"Write a new note at Projects/obsidian-mcp.md with this content"
"List all files in my Fleeting folder"
"Show me what's been modified recently"
"Re-index my vault"

Claude will automatically choose the right MCP tool (search_vault, get_file, write_file, etc.) based on your request.

osm — Setup & management CLI

Use osm to set up, manage, and tear down the stack. The wizard installs all prerequisites, configures Docker, and updates Claude Desktop automatically.

osm in this repo means the Obsidian Semantic MCP CLI (not OpenStreetMap).

Command

Description

osm init

Interactive setup wizard

osm init --mode <1-4> --vault <path>

Non-interactive setup (agent/script friendly)

osm init --dry-run

Preview all actions without making any changes

osm status

Check service health (Docker, Ollama reachability/inference, Claude Desktop)

osm vaults

List configured Obsidian vault(s)

osm dashboard

Open monitoring dashboard in browser

osm rebuild

Rebuild Docker images after a code change

osm tunnel

Reconnect SSH tunnel (remote Ollama mode)

osm remove

Stop services and wipe all volumes and config

osm remove --yes

Non-interactive teardown (agent/script friendly)

osm help

Full flag reference

osm init flags: --mode, --vault, --pg-password, --persistent / --no-persistent, --data-dir, --ssh-host, --ssh-user, --ssh-port, --ssh-key, --vault-remote

osm status probes both Ollama reachability (/api/tags) and embeddings (/api/embeddings) so it can catch the case where the daemon is up but model execution is broken.

Windows launcher: osm init installs osm.cmd into %USERPROFILE%\.local\bin\. Windows resolves .cmd automatically, so you invoke it as osm from any terminal. If osm is not found, add %USERPROFILE%\.local\bin to your Path environment variable.

Using with Claude Code, Codex, and OpenCode

When you type osm init or osm dashboard directly in your terminal, those commands execute normally.

In chat-based coding agents, a bare osm ... message can be interpreted as text (or as OpenStreetMap) instead of a shell command. To force execution, phrase it explicitly:

  • Run osm init

  • Run osm dashboard

If the launcher is not installed yet (or not on PATH), use:

  • Run uv run osm init --dry-run --mode 1 --vault <vault-path> --pg-password <password>

  • Run uv run osm dashboard

What to expect for new users:

  • First install: osm init sets up services and registers obsidian-semantic in global MCP config for that OS user.

  • Later sessions: re-running osm init is safe and idempotent.

  • osm dashboard opens http://localhost:8484; if the stack is not running yet, it warns and still opens the URL.

Session starter (copy/paste):

In this repo, "osm" means the obsidian-semantic-mcp CLI (not OpenStreetMap).
Please execute shell commands directly when I type them.
If `osm` is not found, use `uv run osm ...` from the repo root.
Examples: osm init, osm dashboard.

Example Output

When Claude searches your vault, results come back ranked with similarity scores and content previews:

## Search: "what did I write about ketosis"

1. health/ketosis-diet.md (similarity: 0.87)
   Ketosis is a metabolic state where the body burns fat for fuel...
   
2. Daily/2026-03-14.md (similarity: 0.72)
   Started keto today. Meal prepped for the week...
   
3. research/low-carb-studies.md (similarity: 0.65)
   Recent studies on low-carb diets show...

For vault CRUD, get_file returns the full note content; recent_changes lists recently modified files with timestamps.

Architecture

Claude Desktop
    ↓ MCP protocol (stdio)
src/server.py (unified MCP server)
    ├── Semantic search (pgvector cosine similarity)
    ├── Vault CRUD (direct filesystem access)
    └── Live file watcher (watchdog)
    ↓
PostgreSQL + pgvector (vector storage + IVFFlat index)
    ↓
Ollama / nomic-embed-text (local 768-dim embeddings)
    ↓
Your Obsidian vault (e.g. $HOME/Documents/MyVault)

Project Structure

obsidian-semantic-mcp/
├── install.sh          # Bootstrap installer for macOS/Linux
├── install.ps1         # Bootstrap installer for Windows PowerShell
├── scripts/
│   ├── osm                # CLI wrapper (macOS/Linux) — `uv run osm init` or `scripts/osm init`
│   └── osm.ps1            # CLI wrapper (Windows) — `.\scripts\osm.ps1 init`
├── src/
│   ├── server.py          # MCP server — semantic search + vault CRUD (11 tools)
│   └── dashboard.py       # Monitoring dashboard (http://localhost:8484)
├── tests/
│   ├── test_unit.py            # Unit tests (no real DB/Ollama needed)
│   ├── test_osm_init.py        # Unit tests for the osm CLI wizard
│   ├── test_dashboard_smoke.py # Dashboard static analysis + live HTTP smoke tests
│   ├── test_setup.py           # Prerequisites checker (deps, DB, Ollama) — run directly
│   └── test_e2e.py             # End-to-end MCP protocol test — run directly
├── osm_init.py            # Interactive setup wizard (used by scripts/osm)
├── Dockerfile             # Python 3.13 + uv
├── docker-compose.yml     # Full stack: postgres, ollama, server, dashboard
├── pyproject.toml         # Project metadata + dependencies (osm script entry)
├── uv.lock                # Pinned lockfile
└── LICENSE                # Apache 2.0

Prerequisites

  • An Obsidian vault on your filesystem

  • macOS native: Homebrew (auto-installs everything else)

  • Docker modes: Docker Desktop (macOS/Linux/Windows) — the wizard offers to install it if missing via brew (macOS), winget (Windows), or get.docker.com (Linux), and starts the daemon automatically

  • Windows: WSL2 backend enabled, uv installed via powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

MCP Tools

Tool

Description

search_vault

Semantic search by meaning across the entire vault. Returns ranked excerpts with similarity scores. Supports graph_expand: true to follow wikilinks from top results and surface connected notes that didn't rank semantically.

simple_search

Exact text/keyword search across vault files.

get_note_connections

Return all notes connected to a given note via wikilinks — both outgoing links and incoming backlinks. Useful for exploring the knowledge graph and finding related notes.

Vault Management

Tool

Description

list_files

List files and directories in a vault directory.

get_file

Read the full content of a single file.

get_files_batch

Read multiple files at once.

append_content

Append content to a file (creates if missing).

write_file

Overwrites the target file completely — existing content is replaced with no undo. Use append_content if you want to add to an existing file instead.

recent_changes

Get recently modified files.

Index Management

Tool

Description

list_indexed_notes

List all indexed notes with their last indexed timestamp.

reindex_vault

Force a full re-index of all notes. Runs in the background.

Multi-Vault Support

To index multiple vaults, set OBSIDIAN_VAULTS to a comma-separated list of absolute paths:

OBSIDIAN_VAULTS="/path/to/vault1,/path/to/vault2" docker compose up -d

Or in docker-compose.yml (uncomment the multi-vault lines):

environment:
  OBSIDIAN_VAULTS: /vault1,/vault2   # multi-vault
volumes:
  - /path/to/vault1:/vault1
  - /path/to/vault2:/vault2

When using multiple vaults, the search_vault MCP tool gains a vault parameter to filter results by vault name. The dashboard also shows a vault selector. Each vault is watched and indexed independently.

How It Works

  1. Indexing — On startup, the server walks your vault, reads each .md file, generates a 768-dim embedding via Ollama, and upserts it into PostgreSQL with pgvector. Unchanged files (same SHA-256 hash) are skipped on subsequent runs. First-run indexing takes roughly 1–2 seconds per note with a local Ollama instance — expect 5–15 minutes for a 500-note vault. Watch progress at http://localhost:8484 or via docker compose logs -f mcp-server.

  2. Watching — A file watcher (watchdog) monitors the vault for creates, updates, deletes, and moves — re-embedding changed files automatically.

  3. Searching — When Claude calls search_vault, the query is embedded and matched against stored vectors using cosine similarity (IVFFlat index). The top results are returned with similarity scores and content previews.

  4. CRUD — All file operations use direct filesystem access, so the server works whether Obsidian is open or not. Path traversal outside the vault is blocked.

Environment Variables

Variable

Description

Default

OBSIDIAN_VAULT

Absolute path to your Obsidian vault. Mounted read-write so MCP write/append tools can create and update notes. Mount with :ro if you only need search.

required

OBSIDIAN_VAULTS

Comma-separated list of vault paths for multi-vault mode. Overrides OBSIDIAN_VAULT when set.

OBSIDIAN_IGNORE_PATHS

Comma-separated vault-relative path segments to skip during indexing and watching. Defaults to archive; set it to an empty string to index archived notes.

archive

POSTGRES_PASSWORD

PostgreSQL password (Docker)

required for Docker

DATABASE_URL

Full connection string (overrides POSTGRES_* vars)

built from POSTGRES_* vars

POSTGRES_HOST

PostgreSQL host

localhost

POSTGRES_PORT

PostgreSQL port

5432

POSTGRES_DB

Database name

obsidian_brain

POSTGRES_USER

Database user

obsidian

OLLAMA_URL

Ollama API endpoint

http://localhost:11434

EMBEDDING_MODEL

Ollama model for embeddings

nomic-embed-text

EMBED_WORKERS

Parallel threads for bulk indexing

4

RERANK_MODEL

Optional Ollama model for cross-encoder re-ranking (e.g. llama3.2). Disabled when empty.

RERANK_CANDIDATES

Candidate pool size fetched before re-ranking

20

DASHBOARD_BIND

Interface the monitoring dashboard binds to. Loopback by default; set 0.0.0.0 only for a native install reachable from another host.

127.0.0.1

DASHBOARD_TOKEN

Bearer token for the dashboard's mutating endpoints. Generated and stored at ~/.config/obsidian-semantic-mcp/dashboard_token (mode 0600) if unset.

auto-generated

OSM_SKIP_PI

Set to 1 to skip configuring the optional pi MCP client during osm init, even if the pi binary is installed. Useful for a clean setup matching what most users (no pi) see.

Monitoring Dashboard

A built-in dashboard is available at http://localhost:8484 (started automatically with Docker). It shows:

  • Service health (PostgreSQL, Ollama, embedding model)

  • Indexed notes count, vault coverage, DB size

  • Recently indexed files (collapsible — click the heading to hide/show)

  • Re-index — incremental re-index (skips unchanged notes, fast)

  • Clear & Rebuild — wipes all embeddings and re-indexes from scratch

  • A "Start Ollama" button if Ollama is down

To run the dashboard without Docker:

OBSIDIAN_VAULT="/path/to/your/vault" uv run python3 src/dashboard.py

Testing

Unit tests (no real DB or Ollama needed)

uv run pytest -q

Runs 400+ tests (see CI logs for the exact count — the Tests badge above shows pass/fail status, not a number). Most run without a database. A set of PostgreSQL integration tests are gated behind a pg marker and run in CI against a pgvector service. Coverage spans embedding, search, vault path safety, connection pool, dashboard auth, cross-process locking, schema migrations, the osm CLI wizard, and CI governance.

test_dashboard_smoke.py — Dashboard health checks (Docker stack)

Offline static analysis (always runs — no services needed) + live HTTP smoke tests (auto-skipped when the dashboard is unreachable).

# Offline + live (stack must be running)
uv run pytest tests/test_dashboard_smoke.py -v

# Target a remote instance
DASHBOARD_URL=http://host:8484 uv run pytest tests/test_dashboard_smoke.py -v

Checks: JS string safety, DOM element completeness, /api/stats schema, service health, response time, and routing.

test_setup.py — Prerequisites check (native installs)

Verifies Python deps, vault path, PostgreSQL + pgvector, Ollama, and embedding smoke test. Run directly — not via pytest.

DATABASE_URL="postgresql://localhost/obsidian_brain" \
OBSIDIAN_VAULT="/path/to/your/vault" \
uv run python3 tests/test_setup.py

test_e2e.py — End-to-end MCP test (native installs)

Launches the server, initializes MCP protocol, waits for indexing, runs semantic search, and verifies results. Run directly — not via pytest.

Requires DATABASE_URL or POSTGRES_PASSWORD — the server will exit immediately without one.

DATABASE_URL="postgresql://localhost/obsidian_brain" \
OBSIDIAN_VAULT="/path/to/your/vault" \
uv run python3 tests/test_e2e.py

Windows + network vault (NFS / SMB)

If your vault lives on a NAS and is mounted on Windows as a drive letter (Z:\), osm init will fail to bind-mount it into the container — Docker Desktop on Windows uses WSL2, and WSL2 cannot follow a Windows-side network drive into a container. The UNC form (\\host\share\...) is rejected by the daemon outright; the drive-letter form silently mounts an empty directory.

Recommended fix: mount the share inside WSL2 and point osm init at the Linux path.

# inside your WSL2 distro (Ubuntu/Debian)
sudo apt install nfs-common
sudo mkdir -p /mnt/obsidian_vault
sudo mount -t nfs <nas-host>:/<export-path> /mnt/obsidian_vault
# add to /etc/fstab to persist across reboots

osm init --mode 2 --vault /mnt/obsidian_vault

Docker Desktop shares WSL2 paths cleanly with no volume-driver gymnastics. Starting in v0.5.11, osm init also fails fast when docker compose up is rejected and points you at this section instead of letting the postgres health check time out 90 seconds later.

Alternative: native NFS / CIFS named volumes (--vault-fs, v0.5.12+)

If WSL2 isn't an option, osm init can generate a docker-compose.override.yml that backs each vault with a Docker named volume using NFS or CIFS driver_opts. Vault entries use protocol-specific syntax instead of host paths:

# NFS (one or more vaults; entries use host:/export/path)
osm init --mode 3 \
  --vault 10.0.0.1:/exports/coredev \
  --vault-fs nfs

# CIFS / SMB
osm init --mode 3 \
  --vault //nas.local/share/coredev \
  --vault-fs cifs \
  --vault-cifs-user alice --vault-cifs-pass 'secret'

For multi-vault, pass each entry to a comma-joined OBSIDIAN_VAULTS env (or repeat --vault); each generates its own named volume (obsidian_vault_<basename>). osm remove drops these volumes on teardown.

Limitations: NFSv4 with no auth, SMB with username/password only. NFS Kerberos and CIFS credential files are not supported in v0.5.12. WSL2 is still the recommended path for most users.

Troubleshooting

Symptom

Cause

Fix

uv: command not found

uv not installed or not in PATH

Run curl -LsSf https://astral.sh/uv/install.sh | sh then restart your terminal

Cannot connect to the Docker daemon

Docker Desktop not running

The wizard offers to start it automatically; or start Docker Desktop manually from Applications (macOS) / system tray (Windows/Linux)

Permission denied: /path/to/vault

Vault path not readable by Docker

On macOS: Docker Desktop → Settings → Resources → File Sharing — add your vault path

ModuleNotFoundError: No module named 'mcp'

System Python instead of venv

Use .venv/bin/python3 in config, or use Docker

ModuleNotFoundError: No module named 'psycopg2' in Docker

Container built before venv PATH fix

docker compose up -d --build mcp-server

Search returns 0 results

IVFFlat index built on empty table

Run psql obsidian_brain -c "REINDEX INDEX notes_embedding_idx;"

Vault indexing is in progress — no results yet

First-boot indexing not complete

Wait for indexing to finish (check docker compose logs -f mcp-server)

Cannot reach Ollama

Ollama not running

Run ollama serve or docker compose up ollama

Skipped <file>: vector must have at least 1 dimension

Ollama returned empty embedding (blank/tiny file)

Expected — file is skipped and indexing continues

Skipped <file>: 500 Server Error

Ollama internal error (file too large or model issue)

Expected — file is skipped; try ollama pull nomic-embed-text to refresh model

pgvector extension not found

Not installed for your PG version

Use Docker, or build from source (see native install)

Server crashes on startup

OBSIDIAN_VAULT not set

Set the env var in your config or docker compose command

Docker container can't see vault

Wrong path or missing volume

Ensure OBSIDIAN_VAULT is an absolute path accessible to Docker


Native Install (macOS)

Manual install only. Use this if you want to control every step yourself instead of using the bootstrap installer.

1. Clone and install

git clone https://github.com/artificemachine/obsidian-semantic-mcp.git && cd obsidian-semantic-mcp
uv sync

2. Install system dependencies

brew install postgresql@17 pgvector ollama
brew services start postgresql@17
ollama serve &
ollama pull nomic-embed-text

PostgreSQL 16: Homebrew's pgvector bottle requires pg17 or pg18. If you must use pg16, build pgvector from source:

cd /tmp
git clone --branch v0.8.2 --depth 1 https://github.com/pgvector/pgvector.git
cd pgvector
make PG_CONFIG=$(brew --prefix postgresql@16)/bin/pg_config
make install PG_CONFIG=$(brew --prefix postgresql@16)/bin/pg_config

3. Set up the database

createdb obsidian_brain
psql obsidian_brain -c "CREATE EXTENSION vector;"

4. Verify

DATABASE_URL="postgresql://localhost/obsidian_brain" \
OBSIDIAN_VAULT="/path/to/your/vault" \
uv run python3 tests/test_setup.py

5. Configure Claude Desktop

Add to $HOME/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "obsidian-semantic": {
      "command": "/absolute/path/to/obsidian-semantic-mcp/scripts/obsidian-semantic-mcp",
      "args": [],
      "env": {}
    }
  }
}

The launcher reads the repo .env for local fallback, and uses the running Docker service automatically when it is available.

Important: Use .venv/bin/python3 — not system Python. Homebrew Python won't have the required packages.

6. Restart Claude Desktop

The server indexes your vault on first run, then watches for changes automatically.

Cost

Everything runs locally. No cloud APIs, no subscriptions. The only cost is disk space for the database (~a few MB for most vaults).

Documentation

Full documentation — architecture, operations runbook, design records, explainers, and incident postmortems — is indexed in docs/README.md.

License

Apache 2.0

Available Tools

11 tools
append_contentA

Append content to the end of a file. Creates the file if it doesn't exist.

ParametersJSON Schema
NameRequiredDescriptionDefault
contentYesContent to append
filepathYesFile path relative to vault root

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses two key behaviors: appends to end and creates file if missing. Without annotations, this provides sufficient behavioral info, though missing details like encoding or error cases.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no fluff, front-loaded with verb. Perfectly concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Simple tool with 2 params and clear function. Lacks return value info but acceptable given low complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers both parameters fully, so description adds no extra semantic value beyond the action context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the action (append) and resource (file), including the creation behavior. Differentiates from sibling 'write_file' by specifying append vs overwrite.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives like 'write_file' or when to avoid. Usage context must be inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fileB

Read the full content of a file in the vault.

ParametersJSON Schema
NameRequiredDescriptionDefault
filepathYesFile path relative to vault root

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided. The description does not disclose side effects, error behavior (e.g., file not found), size limits, or auth requirements. Only states 'Read', which is minimal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no fluff. Efficient but could benefit from slight expansion (e.g., mentioning limitations).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema. Description does not explain what 'full content' includes (e.g., encoding, binary?), nor any constraints. Incomplete for a read operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the param description clarifies path format. The tool description adds no extra meaning beyond the schema, but the baseline is acceptable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Read' and the resource 'full content of a file in the vault', which is distinct from sibling tools like write_file or list_files.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives (e.g., get_files_batch or search_vault). No mention of prerequisites or context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_files_batchC

Read the contents of multiple files at once.

ParametersJSON Schema
NameRequiredDescriptionDefault
filepathsYesList of file paths relative to vault root

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. 'Read' implies read-only, but lacks details on limitations (max files, size limits), error handling, or side effects. Only states it reads contents without further behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, efficient sentence with no unnecessary words. However, it could be improved by adding a bit more detail without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does not explain what is returned (e.g., array of contents, map, error handling). The low parameter count (1) means the description should compensate, but it falls short.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema describes the parameter well ('List of file paths relative to vault root'). The description adds no additional semantic value beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Read the contents of multiple files at once' clearly states the verb (read) and resource (multiple files). It implicitly distinguishes from sibling 'get_file' which reads a single file, but could be more explicit about being a batch operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use versus alternatives. Does not mention that for a single file, 'get_file' is more appropriate, nor any prerequisites or context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_note_connectionsA

Return all notes connected to a given note via wikilinks — both notes it links to (outgoing) and notes that link back to it (incoming). Useful for exploring your knowledge graph and finding related notes.

ParametersJSON Schema
NameRequiredDescriptionDefault
hopsNoHow many link-hops to traverse (default: 1, max: 2)
filepathYesVault-relative path to the note (e.g. 'notes/concepts/resilience.md')

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, description carries full burden. It adds context about bidirectional links and knowledge graph but omits details on traversal limits (already in schema), potential performance, or results format. Adequate but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no superfluous words. Front-loaded with action and scope, followed by use case. Highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks output schema and annotations; description could elaborate on result format (e.g., list of file paths) and how hops affect traversal. Provides essential context but has gaps for a link-traversal tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. Description does not add extra meaning beyond schema for parameters; it focuses on overall function. No added value for parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it returns all notes connected via wikilinks, including outgoing and incoming. It distinguishes from siblings like search_vault and list_indexed_notes by focusing on link connections.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly mentions usefulness for exploring knowledge graph and finding related notes. While it doesn't contrast with siblings or state when not to use, the context provided is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_filesB

List all files and directories in a vault directory. Defaults to vault root.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirpathNoDirectory path relative to vault root (default: root)

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided. Description only states listing behavior without disclosing details like recursion, hidden files, or non-destructive nature. Minimal behavioral info for a read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, front-loaded with action and resource. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with one optional param and no output schema, description is adequate but lacks details on return format, recursion, or edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and description repeats the default value and relative path. Adds no extra meaning beyond what schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states verb 'List', resource 'files and directories', and scope 'in a vault directory' with default behavior. Clearly distinguishes from sibling tools like get_file and search_vault.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool vs alternatives like search_vault or list_indexed_notes. Context implies directory listing, but lacks when-not or alternative suggestions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_indexed_notesA

List all notes that have been indexed, with their last indexed timestamp.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It states the tool lists indexed notes with timestamps, implying a read-only operation, but does not explicitly state no side effects, rate limits, or prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence that is front-loaded with the key action. It is concise but could benefit from additional context about the output format or ordering. However, for a zero-parameter tool, it is appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no parameters and no output schema, the description is the sole source of information. It covers the purpose and output fields (timestamp), but lacks details on pagination, ordering, or what 'indexed' means. It is adequate but not fully complete for an agent seeking to understand behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so the baseline is 4. The description does not need to add parameter semantics. It correctly implies that no input is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists all indexed notes and includes the last indexed timestamp. The verb 'list' and resource 'notes that have been indexed' are specific and distinguish this from sibling tools like 'list_files' which presumably list all files, or 'search_vault'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives like 'search_vault' or 'list_files'. Since the tool has no parameters, usage is self-evident, but there is no mention of exclusions or context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

recent_changesB

Get recently modified files in the vault.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoOnly files modified within this many days (default: 30)
limitNoMax files to return (default: 10)

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, and the description only states it gets files without disclosing behavioral traits such as authentication needs, performance characteristics, or what happens when no files match.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single concise sentence with no waste. However, it could be slightly more structured to include context without adding verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Missing output schema and no explanation of return values. With 11 sibling tools and only a terse description, the agent lacks sufficient context to use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear parameter descriptions. The tool description adds no extra meaning beyond the schema, meeting the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'get' and resource 'recently modified files' within the vault, distinguishing it from siblings like list_files and search_vault.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like list_files or search_vault. The description is too brief to help an agent choose correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reindex_vaultA

Force a full re-index of all notes in the vault. Runs in the background — use list_indexed_notes to check progress.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states that the re-index 'runs in the background,' indicating asynchronicity. It also implies a potentially heavy operation ('full re-index'). However, it does not disclose side effects (e.g., performance impact, whether the operation is destructive, or if authentication is required). Given no annotations, the description carries the full burden but only partially addresses behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with no filler. The first sentence conveys the core action, and the second adds useful context about background execution and monitoring. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the action and mentions background execution and progress checking, which is adequate for a zero-parameter tool. However, with no output schema, it does not describe what the tool returns immediately (e.g., a confirmation or task ID). This leaves a gap for the AI agent to infer behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters (0 params, 100% schema coverage), so the description essentially provides all semantic meaning. It explains that the tool acts on the entire vault without input, which adds value beyond the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Force a full re-index of all notes in the vault,' specifying the exact action and resource. It distinguishes from sibling tools like list_indexed_notes and search_vault by implying its purpose is to rebuild the index, not to query or modify individual files.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage context: it should be used when a full re-index is needed, and it advises checking progress via list_indexed_notes. However, it does not mention when NOT to use this tool (e.g., if indexing is unnecessary or if other tools suffice), so some exclusion guidance is missing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_vaultA

Search across your Obsidian vault(s). Three modes: 'hybrid' (default) combines semantic meaning with keyword matching for best results; 'semantic' searches by meaning only; 'keyword' matches exact words using full-text search. Use this to retrieve context, past decisions, notes, or research from the vault.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoSearch mode: 'hybrid' (default) combines semantic + keyword; 'semantic' uses vector similarity only; 'keyword' uses full-text search only.hybrid
limitNoNumber of results to return (default: 5, max: 20)
queryYesNatural language search query
vaultNoFilter results to a specific vault by its name (basename of vault path). Omit to search all vaults.
graph_expandNoFollow wikilinks from top results to surface connected notes that didn't rank semantically. Useful for discovering missed connections.
min_similarityNoMinimum similarity score (0.0–1.0). Results below this threshold are excluded. Default: 0.0

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It transparently explains the three search modes, default behavior (hybrid), the graph_expand feature, and similarity threshold. It does not mention error handling or performance, but for a read-only search tool the description is sufficiently revealing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loading the core purpose, then efficiently expanding on modes and use cases. No redundant or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and no annotations, the description covers the essential functionality, modes, and typical usage. It does not specify the return format or error conditions, but for a search tool the description is adequate for an agent to select and invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents each parameter. The description adds context for modes and the graph_expand feature (e.g., 'Useful for discovering missed connections'), but does not significantly augment the schema's own descriptions. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it searches across Obsidian vaults, describes three distinct modes (hybrid, semantic, keyword), and lists use cases (retrieve context, past decisions, notes, research). It distinguishes from sibling tools like simple_search and get_note_connections by being more comprehensive.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says 'Use this to retrieve context, past decisions, notes, or research' which implies appropriate usage. It does not explicitly state when not to use it or compare to siblings, but the context signals show it is more powerful than simple_search, so some differentiation is possible.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

write_fileA

Write or overwrite a file in the vault. Creates parent directories if needed. WARNING: overwrites existing content without confirmation — use append_content if you want to add to an existing file without replacing it.

ParametersJSON Schema
NameRequiredDescriptionDefault
contentYesFull content to write
filepathYesFile path relative to vault root

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full responsibility for disclosing behavior. It warns about overwriting without confirmation and notes that parent directories are created automatically. This is fairly transparent, though it could mention if the operation is reversible or requires specific permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with three sentences: action, behavior, warning+alternative. Every sentence earns its place with no superfluous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of annotations and output schema, the description covers the essential aspects: operation, side effects (overwrite, create dirs), and provides an alternative. It is complete enough for a simple write tool, though it could mention return value or confirmation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the description adds minimal value beyond the schema. It mentions 'full content' but does not elaborate on parameter details. Baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Write or overwrite' and the resource 'file in the vault'. It distinguishes itself from the sibling 'append_content' by warning about overwriting behavior, making the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly advises when to use this tool versus the alternative 'append_content': use this for writing/overwriting, and use append_content for adding without overwriting. This provides clear usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A3.6/5.0
Disambiguation4/5

Tools are generally distinct with clear purposes. However, simple_search and search_vault's keyword mode overlap; agents may be unsure which to use for exact keyword searches, though descriptions help differentiate.

Naming Consistency4/5

Most tools follow a verb_noun pattern (append_content, get_file, search_vault), but 'recent_changes' and 'simple_search' deviate as adjective_noun. Overall consistent but not perfect.

Tool Count5/5

11 tools is well-scoped for an Obsidian vault management server, covering file operations, search, indexing, and connections without excess.

Completeness3/5

Covers core read/write/search operations, but lacks delete and rename/move functionality, which are notable gaps for file management in a vault.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent, searchable memory for Claude Code using local SQLite, semantic embeddings, and full-text search, enabling Claude to recall and retrieve context across sessions and projects without external services.
    19
    4
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A persistent memory layer for Claude Desktop that enables semantic search and CRUD operations on your Obsidian vault using local embeddings and PostgreSQL+pgvector.
    1
    Apache 2.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/artificemachine/obsidian-semantic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server