Skip to main content
Glama
pascalweiss

vault-graph-mcp

by pascalweiss
README.md
# Vault Graph MCP Server

[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Node Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](package.json)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)

> 🧠 AI-powered knowledge graph navigation for Obsidian vaults

An MCP (Model Context Protocol) server for Obsidian vault graph navigation and ranking. Provides AI agents with structured access to your knowledge graph.

## Why Vault Graph MCP?

**For AI Agents & Personal Knowledge Management:**

- šŸ¤– **Give AI agents context-aware access** to your Obsidian vault without exposing raw file contents
- šŸ”— **Discover connections you didn't know existed** through 2-hop relationship analysis
- šŸŽÆ **Smart recommendations** based on graph structure, not just keyword matching
- šŸ“Š **Identify knowledge hubs** to understand which concepts are central to your thinking
- 🧭 **Navigate semantically** using tag overlap and shared neighbor relationships
- ⚔ **Fast & cached** - millisecond-level queries even on large vaults (1000+ notes)

**Use Cases:**
- Ask Claude "What should I read next after this note on Kubernetes?"
- Find thematically related notes even when not directly linked
- Discover central concepts and knowledge clusters in your vault
- Get AI-powered note recommendations based on graph topology
- Explore your knowledge graph through natural language queries

## Features

- **Graph Navigation**: Traverse links between notes
- **Ranked Recommendations**: Get relevant note suggestions based on shared neighbors, in-degree, and tag overlap
- **Hub Discovery**: Find central concepts in your vault
- **2-Hop Related**: Discover notes connected through intermediate links
- **Search**: Find notes by title or tags
- **Loki-Compatible Logging**: Structured JSON logs for observability

## Installation

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

## Usage

### 1. Via .mcp.json (Claude Code Projects)

Create a `.mcp.json` file in your project root. Claude Code automatically loads this file when starting in the directory.

**If your working directory is your Obsidian vault**, no `VAULT_PATH` is needed — the server auto-detects it from MCP roots:

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

**If your vault is elsewhere**, set `VAULT_PATH` explicitly:

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

> **Note:** `.mcp.json` is currently only supported by Claude Code. Gemini CLI uses `.gemini/settings.json` and Codex CLI uses `.codex/config.toml` for project-level configuration (see sections below).

### 2. Via Claude CLI

Use the Claude CLI to install directly:

```bash
# Build the project first
npm run build

# Add the MCP server via CLI
claude mcp add --transport stdio \
  --env VAULT_PATH=/path/to/your/obsidian/vault \
  vault-graph -- node /path/to/vault-graph-mcp/dist/index.js

# List installed servers
claude mcp list

# Remove if needed
claude mcp remove vault-graph
```

> **Note:** All options (`--transport`, `--env`, `--scope`) must come **before** the server name. The `--` separates the server name from the command and arguments.

See [Claude CLI MCP documentation](https://code.claude.com/docs/en/mcp) for more details.

### 3. With Claude Desktop (Global)

Add to your Claude Desktop configuration:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

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

### 4. With Gemini CLI

Add to your Gemini CLI settings at `~/.gemini/settings.json`:

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

Or use the CLI:

```bash
gemini mcp add vault-graph -- node /path/to/vault-graph-mcp/dist/index.js
```

See [Gemini CLI MCP documentation](https://geminicli.com/docs/tools/mcp-server/) for more details.

### 5. With Codex CLI (OpenAI)

Add to your Codex configuration at `~/.codex/config.toml`:

```toml
[mcp_servers.vault-graph]
command = "node"
args = ["/path/to/vault-graph-mcp/dist/index.js"]

[mcp_servers.vault-graph.env]
VAULT_PATH = "/path/to/your/obsidian/vault"
```

Or use the CLI:

```bash
codex mcp add vault-graph --env VAULT_PATH=/path/to/your/obsidian/vault \
  -- node /path/to/vault-graph-mcp/dist/index.js
```

See [Codex MCP documentation](https://developers.openai.com/codex/mcp) for more details.

### 6. Standalone

```bash
VAULT_PATH=/path/to/vault npm start
```

### 7. Development

```bash
VAULT_PATH=./test/vault npm run dev
```

## MCP Support in Different AI Systems

### āœ… Claude (Anthropic)
- **Claude Desktop**: Full support via config file
- **Claude Code**: Full support with `claude mcp add` command and `.mcp.json`

### āœ… Gemini (Google)
- **Gemini CLI**: Full support via `settings.json` or `gemini mcp add` command

### āœ… Codex (OpenAI)
- **Codex CLI**: Full support via `config.toml` or `codex mcp add` command

**Note:** MCP is an open standard, so support continues to expand. Check your AI platform's documentation for the latest MCP capabilities.

## Configuration

### Vault Path Resolution

`VAULT_PATH` is optional. The server resolves the vault path in this order:

1. **`VAULT_PATH` environment variable** — if set, used directly (backwards compatible)
2. **MCP client roots** — if the client supports [roots](https://modelcontextprotocol.io/docs/concepts/roots), the server uses the first `file://` root as the vault path

This means MCP clients like Claude Code, which expose the working directory as a root, work with zero configuration when launched from inside an Obsidian vault.

If neither source provides a vault path, the server exits with a descriptive error.

### Environment Variables

| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| `VAULT_PATH` | Path to Obsidian vault (auto-detected from MCP roots if omitted) | - |
| `VAULT_GRAPH_INCLUDE_GLOBS` | Comma-separated include patterns | `**/*.md` |
| `VAULT_GRAPH_EXCLUDE_GLOBS` | Comma-separated exclude patterns | `.obsidian/**,.trash/**` |
| `VAULT_GRAPH_CACHE_DIR` | Cache directory (relative to vault) | `.mcp-cache` |
| `VAULT_GRAPH_LOG_LEVEL` | Log level: debug, info, warn, error | `info` |
| `VAULT_GRAPH_JSON_LOGS` | Output JSON logs (for Loki) | `true` |

## MCP Tools

### `graph_build_index`

Rebuild the vault graph index.

```json
{
  "force": true  // Force rebuild even if cache is valid
}
```

### `graph_get_neighbors`

Get all neighbors (linked notes) for a node.

```json
{
  "node": "DevOps/GitOps.md",
  "direction": "out"  // "in", "out", or "both"
}
```

### `graph_get_neighbors_ranked`

Get neighbors ranked by relevance with explanations.

```json
{
  "node": "DevOps/GitOps.md",
  "direction": "out",
  "limit": 10,
  "weights": {
    "commonNeighbors": 0.55,
    "degree": 0.35,
    "tagOverlap": 0.10
  }
}
```

**Response:**
```json
{
  "node": "DevOps/GitOps.md",
  "direction": "out",
  "results": [
    {
      "id": "DevOps/FluxCD.md",
      "title": "FluxCD",
      "score": 0.72,
      "reasons": [
        "3 shared neighbors",
        "high in-degree (5)",
        "tag overlap: devops, gitops"
      ]
    }
  ],
  "count": 5
}
```

### `graph_related`

Find related notes that are 2 hops away (not directly linked).

```json
{
  "node": "DevOps/GitOps.md",
  "limit": 10,
  "direction": "out"
}
```

### `graph_hubs`

Find the most connected notes (central concepts).

```json
{
  "limit": 10,
  "mode": "in"  // "in" (most referenced), "out" (most linking), "both"
}
```

### `graph_search`

Search for notes by title or tags.

```json
{
  "query": "kubernetes",
  "limit": 20,
  "searchIn": ["title", "tags"]
}
```

### `graph_get_node`

Get detailed information about a specific node.

```json
{
  "node": "DevOps/GitOps.md"
}
```

## MCP Resources

### `vault://node/{id}`

Get information about a specific node.

### `vault://graph`

Get the full vault graph (paginated). Supports query parameters:
- `page`: Page number (default: 1)
- `pageSize`: Results per page (default: 100)

### `vault://stats`

Get vault statistics: node count, edge count, top hubs, etc.

### `vault://metrics`

Get server performance metrics (Loki-compatible).

## Ranking Algorithm

The ranking engine uses a weighted combination of three factors:

| Factor | Weight | Description |
|--------|--------|-------------|
| Common Neighbors | 0.55 | Nodes that share connections tend to be thematically related |
| In-Degree | 0.35 | Highly referenced nodes are important concepts |
| Tag Overlap | 0.10 | Shared tags indicate semantic similarity |

**Score Formula:**
```
score = 0.55 * commonNeighborsNorm + 0.35 * degreeNorm + 0.10 * tagJaccard
```

All components are normalized to [0, 1].

## Logging

Logs are output in JSON format for Loki compatibility:

```json
{
  "timestamp": "2024-01-15T10:30:00.000Z",
  "level": "info",
  "component": "graph.builder",
  "event": "build_complete",
  "vault": "/path/to/vault",
  "nodeCount": 842,
  "edgeCount": 3421,
  "duration_ms": 312
}
```

### Loki Integration

Ship logs to Loki via:
- **Promtail**: Tail stdout logs
- **Docker logging driver**: Configure JSON logging

Recommended labels:
- `app=vault-graph-mcp`
- `component={component}`

## Performance

| Operation | Target | Typical |
|-----------|--------|---------|
| Full index (1k files) | < 1s | ~300ms |
| Ranked neighbors | < 50ms | ~5ms |
| Related (2-hop) | < 150ms | ~15ms |

## Development

```bash
# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build
npm run build

# Lint
npm run lint

# Type check
npm run typecheck
```

## Project Structure

```
vault-graph-mcp/
ā”œā”€ā”€ src/
│   ā”œā”€ā”€ index.ts              # Entry point
│   ā”œā”€ā”€ types.ts              # Type definitions
│   ā”œā”€ā”€ config.ts             # Configuration loader
│   ā”œā”€ā”€ scanner/              # Vault file scanner
│   ā”œā”€ā”€ parser/               # Markdown parser
│   ā”œā”€ā”€ graph/                # Graph index & cache
│   ā”œā”€ā”€ ranking/              # Ranking engine
│   ā”œā”€ā”€ server/               # MCP server & handlers
│   └── logger/               # Logging & metrics
ā”œā”€ā”€ test/
│   ā”œā”€ā”€ vault/                # Test vault
│   └── *.test.ts             # Test files
└── dist/                     # Compiled output
```

## License

MIT