vault-graph-mcp
by pascalweiss
README.md
# Vault Graph MCP Server
[](LICENSE)
[](package.json)
[](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
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues