Obsidian MCP Server
# Obsidian MCP Server
Enables MCP clients (e.g., Claude Desktop) to interact with Obsidian vaults seamlessly.
## Features
- **Multi-Vault Support**: Access unlimited Obsidian vaults without per-vault configuration
- **Auto-Discovery**: Automatically discovers REST API credentials from plugin configuration
- **Concurrent-Safe**: File locking prevents data corruption during simultaneous access
- **Hybrid Access**: Filesystem operations (always available) + REST API integration (optional)
- **Security-First**: Path validation, rate limiting, command allowlist, and secure credential handling
- **Zero-Config**: Works immediately with filesystem access; REST API features activate when plugin is installed
## Installation
### From Source (Current)
Currently, installation from source is required:
```bash
git clone <repository-url>
cd obsidian-mcp-server
npm install
npm run build
```
### Via NPM (Coming Soon)
Once published to npm, you'll be able to install globally:
```bash
npm install -g obsidian-mcp-server
```
**Note**: The package is not yet published. Use "From Source" installation for now.
## Quick Start
### 1. Basic Setup (Filesystem Access Only)
The server automatically detects and configures your Obsidian vaults on first run! No manual configuration needed.
**What happens automatically:**
- Config file is created at `~/.config/mcp-obsidian/config.json` (macOS/Linux) or `%APPDATA%/mcp-obsidian/config.json` (Windows)
- Server scans common locations (Documents, Dropbox, iCloud, etc.) for Obsidian vaults
- Discovered vault paths are automatically added to the configuration
- Ready to use immediately!
**Common locations scanned:**
- `~/Documents/Obsidian`
- `~/Dropbox` and subdirectories
- `~/Library/CloudStorage/Dropbox` (macOS)
- `~/Library/Mobile Documents/iCloud~md~obsidian` (macOS)
- `~/OneDrive/Documents/Obsidian` (Windows)
**Note**: You can override the config location by setting the `MCP_OBSIDIAN_CONFIG` environment variable.
This enables immediate access to all discovered vaults using filesystem operations.
### 2. Enable REST API Features (Optional)
Install the [Obsidian Local REST API plugin](https://github.com/coddingtonbear/obsidian-local-rest-api) in your vault:
1. Open Obsidian Settings → Community Plugins
2. Browse and install "Local REST API"
3. Enable the plugin
4. The plugin will generate an API key automatically
No additional configuration needed - the server will auto-discover the credentials.
### 3. Connect to Claude
Add to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"obsidian": {
"command": "node",
"args": ["/path/to/obsidian-mcp-server/dist/index.js"]
}
}
}
```
**Note**: The `env` section is optional. If omitted, the server uses the default config location (`~/.config/mcp-obsidian/config.json`). Only add it if you want to use a custom config path:
```json
{
"mcpServers": {
"obsidian": {
"command": "node",
"args": ["/path/to/obsidian-mcp-server/dist/index.js"],
"env": {
"MCP_OBSIDIAN_CONFIG": "/custom/path/to/config.json"
}
}
}
}
```
Restart Claude Desktop.
## Configuration
**Most users don't need to configure anything!** The server auto-detects your vaults on first run.
### Manual Configuration (Optional)
If you need to customize settings or add vaults in non-standard locations, edit `~/.config/mcp-obsidian/config.json`:
**Minimal Configuration:**
```json
{
"defaultVaultPath": "/Users/yourname/Documents/Obsidian"
}
```
**Full Configuration:**
See `config.example.json` for a complete configuration with all options:
- **defaultVaultPath**: Base directory containing your vaults
- **vaults**: Named vault mappings for easy access
- **security**: Path restrictions, rate limits, allowed hosts/ports
- **features**: File locking, caching, file watching settings
- **logging**: Log level and sensitive data sanitization
### Named Vaults
For easier access, define named vaults in your config:
```json
{
"defaultVaultPath": "/Users/yourname/Documents/Obsidian",
"vaults": {
"personal": "PersonalVault",
"work": "WorkVault"
}
}
```
Then reference them by name in Claude: `"vault": "personal"` instead of full paths.
## Available Tools
### File Operations
- **list_vaults**: List all accessible vaults
- **get_vault_info**: Get vault metadata (file count, plugin status)
- **list_files**: List files in a vault (supports recursive, hidden files)
- **get_file**: Read file content with optional frontmatter parsing
- **write_file**: Write or update files with conflict detection
- **append_content**: Append content to existing files
- **search_files**: Search with regex, case sensitivity, context
- **get_metadata**: Extract frontmatter, tags, links, word count
### Obsidian Integration (Requires REST API Plugin)
- **execute_command**: Execute whitelisted Obsidian commands
- **open_file**: Open files in Obsidian UI
- **get_active_file**: Get currently active file
- **open_graph**: Open graph view
### Allowed Commands
For security, only these Obsidian commands are allowed:
- `graph:open`, `graph:open-local`
- `editor:toggle-source`
- `app:go-back`, `app:go-forward`
- `global-search:open`
- `workspace:new-file`, `file-explorer:reveal-active-file`
- `workspace:split-vertical`, `workspace:split-horizontal`
## Testing
### Test with Claude Desktop
1. Restart Claude Desktop after configuration
2. Open a conversation and try:
```
List my Obsidian vaults
```
Expected response: List of discovered vaults with metadata.
```
Read the file "Daily Notes/2026-01-14.md" from my Personal vault
```
Expected response: File content with metadata.
```
Search for "project" in my Work vault
```
Expected response: Search results with context.
### Test with MCP Inspector
```bash
npx @modelcontextprotocol/inspector dist/index.js
```
This opens a web interface to test all tools interactively.
### Verify File Locking
Open a file in Obsidian and simultaneously have Claude read/write it. The server will handle concurrent access safely with file locking.
### Verify Auto-Discovery
Install the REST API plugin in a vault, then:
```
Get info about my Personal vault
```
Expected response should include `"hasRestApi": true` and `"pluginVersion": "1.x.x"`.
## Architecture
### Hybrid Provider System
```
Operation Request
↓
Router Decision
↓
┌───┴───┐
↓ ↓
Filesystem REST API
Provider Provider
↓ ↓
Direct Plugin
File I/O Commands
```
- **Filesystem Provider**: Always available, handles read/write/search
- **REST API Provider**: Optional, handles UI integration and commands
- **Operation Router**: Intelligently selects the appropriate provider
### Security Layers
1. **Path Validation**: Prevents directory traversal, validates symlinks
2. **Rate Limiting**: Global, per-vault, and per-operation limits
3. **Command Allowlist**: Only whitelisted Obsidian commands allowed
4. **Credential Security**: Memory-only cache, no disk serialization
### Concurrent Access Handling
- **File Locking**: Read locks (shared) and write locks (exclusive)
- **Conflict Detection**: Timestamp verification before writes
- **Atomic Writes**: Write to temp file, then rename
- **Lock Timeout**: Automatic cleanup of expired locks
## Troubleshooting
### Vaults Not Found
**Problem**: `list_vaults` returns empty array
**Solutions**:
- **First check**: Restart Claude Desktop to trigger auto-detection
- Verify `defaultVaultPath` in config points to correct directory
- Ensure vaults have `.obsidian` directory (valid Obsidian vaults)
- Check `security.allowedVaultPaths` includes the vault location
- If your vaults are in a non-standard location, manually add the path to `allowedVaultPaths` in the config
### REST API Features Not Working
**Problem**: "REST API required but plugin not installed"
**Solutions**:
- Install "Local REST API" plugin in Obsidian
- Enable the plugin in Obsidian settings
- Verify plugin created `data.json` in `.obsidian/plugins/obsidian-local-rest-api/`
- Clear credential cache: restart the MCP server
### File Lock Timeout
**Problem**: "Could not acquire write lock"
**Solutions**:
- Close files in Obsidian that are being edited
- Wait for ongoing operations to complete
- Increase `features.fileLocking.timeout` in config
- Check for stuck locks: restart the server
### Rate Limit Exceeded
**Problem**: "Rate limit exceeded"
**Solutions**:
- Wait before retrying
- Increase rate limits in config if legitimate usage
- Check for loops in your Claude interactions
### Permission Denied
**Problem**: "Vault path not in allowed directories"
**Solutions**:
- **First try**: Delete `~/.config/mcp-obsidian/config.json` and restart to trigger auto-detection
- Manually add vault path to `security.allowedVaultPaths` in the config
- Use absolute paths, not relative paths
- Check symlink targets are also in allowed paths
- Ensure the path exists and is accessible
## Security Considerations
### Threat Model
This server operates locally and assumes:
- The local machine is trusted
- Claude Desktop is trusted
- Only you have access to the MCP server process
### Protections Implemented
- **Path Traversal Prevention**: Rejects `..` and `~` patterns, validates all paths
- **API Key Security**: Credentials stored only in memory, never logged
- **Command Injection Prevention**: Explicit allowlist of safe commands only
- **Rate Limiting**: Prevents abuse and DoS scenarios
- **Symlink Validation**: Resolves and validates symlink targets
- **Host/Port Validation**: Only localhost connections allowed
### What This Does NOT Protect Against
- Malicious code in your Obsidian vault (markdown files can't execute code)
- Attacks on Obsidian itself
- Physical access to your machine
- Compromised Claude Desktop application
## Development
### Build
```bash
npm run build
```
### Watch Mode
```bash
npm run watch
```
### Run Tests
```bash
npm test
```
### Lint
```bash
npm run lint
```
## Contributing
Contributions welcome! Please:
1. Follow existing code style (TypeScript, ESLint, Prettier)
2. Add tests for new features
3. Update documentation
4. Ensure security best practices
## License
MIT
## Support
For issues, questions, or feature requests, please open an issue on the repository.
## Credits
Built with:
- [Model Context Protocol SDK](https://github.com/modelcontextprotocol/typescript-sdk)
- [gray-matter](https://github.com/jonschlinkert/gray-matter) for frontmatter parsing
- [axios](https://github.com/axios/axios) for HTTP requestsTDQS
Scored across 12 tools
Every tool has a clearly distinct purpose with no ambiguity. For example, 'get_file' reads file content while 'get_metadata' extracts structured data, and 'list_files' enumerates files whereas 'search_files' finds specific content. The actions (append, execute, get, list, open, search, write) are well-differentiated and target specific Obsidian operations.
All tool names follow a consistent verb_noun pattern using snake_case throughout, such as 'append_content', 'execute_command', 'get_active_file', and 'write_file'. This predictable naming convention makes it easy for agents to understand and select the right tool based on the intended action and target resource.
With 12 tools, the count is well-scoped for managing Obsidian vaults and files. Each tool earns its place by covering distinct aspects like file operations (read, write, append), metadata handling, vault management, UI interactions, and search capabilities, without being overly broad or sparse for the domain.
The tool set provides complete CRUD/lifecycle coverage for Obsidian vault and file management, including create (write_file), read (get_file, get_metadata), update (append_content, write_file), delete (implied via write/overwrite), and utility operations like listing, searching, and UI control. No obvious gaps exist for core workflows in this domain.