# Obsidian MCP Server Setup for WSL Documentation for connecting Claude Code CLI (running in WSL) to an Obsidian vault on Windows via the Model Context Protocol (MCP). ## Overview This setup allows Claude Code running in WSL/Ubuntu to interact with your Obsidian vault on Windows through the Obsidian Local REST API plugin. ## Prerequisites 1. **Obsidian** installed and running on Windows 2. **Obsidian Local REST API Plugin** installed and enabled 3. **Claude Code CLI** installed in WSL 4. **Node.js** installed in WSL (for npx) ## Installation Steps ### 1. Install and Configure Obsidian Local REST API Plugin 1. Open Obsidian on Windows 2. Go to Settings → Community Plugins → Browse 3. Search for "Local REST API" and install it 4. Enable the plugin 5. Click the settings/gear icon for the Local REST API plugin ### 2. Configure the REST API Plugin In the Local REST API plugin settings: 1. **Generate an API Key** - Copy this key, you'll need it later 2. **Set Binding Host**: Change from `127.0.0.1` to `0.0.0.0` - This allows WSL to connect to the Windows host - Default `127.0.0.1` only accepts localhost connections 3. **Port**: Default is `27123` (note this down) 4. Save settings and ensure the server starts ### 3. Get Windows Host IP from WSL From your WSL terminal, run: ```bash ip route show | grep -i default | awk '{print $3}' ``` This will return your Windows host IP (e.g., `172.24.192.1`). You'll use this instead of `localhost` or `127.0.0.1`. ### 4. Test Connection from WSL Verify you can reach the Obsidian API: ```bash # Replace 172.24.192.1 with your actual Windows host IP curl -I http://172.24.192.1:27123 ``` You should see a `HTTP/1.1 200 OK` response. ### 5. Add Obsidian MCP Server to Claude Code Run the following command in WSL (replace values as needed): ```bash claude mcp add-json obsidian '{ "type":"stdio", "command":"npx", "args":["obsidian-mcp-server"], "env":{ "OBSIDIAN_API_KEY":"YOUR_API_KEY_HERE", "OBSIDIAN_BASE_URL":"http://YOUR_WINDOWS_HOST_IP:27123", "OBSIDIAN_VERIFY_SSL":"false" } }' ``` **Example with actual values:** ```bash claude mcp add-json obsidian '{ "type":"stdio", "command":"npx", "args":["obsidian-mcp-server"], "env":{ "OBSIDIAN_API_KEY":"YOUR_ACTUAL_API_KEY_HERE", "OBSIDIAN_BASE_URL":"http://172.24.192.1:27123", "OBSIDIAN_VERIFY_SSL":"false" } }' ``` ### 6. Verify Connection Check that the MCP server is connected: ```bash claude mcp list ``` You should see: ``` obsidian: npx obsidian-mcp-server - ✓ Connected ``` ## Available Tools Once connected, the Obsidian MCP server provides the following capabilities: ### Core Operations | Tool | Description | Common Use Cases | |------|-------------|------------------| | `obsidian_read_note` | Read note content and metadata | Retrieve information, analyze existing notes | | `obsidian_update_note` | Modify notes (append, prepend, overwrite) | Add sections, update content, bulk edits | | `obsidian_search_replace` | Search and replace within notes | Refactor content, fix typos, update references | | `obsidian_global_search` | Search across entire vault | Find notes by keyword, discover related content | | `obsidian_list_notes` | List notes and directories | Navigate vault structure, discover files | | `obsidian_manage_frontmatter` | Manage YAML frontmatter | Update metadata, add tags, set properties | | `obsidian_manage_tags` | Add, remove, or list tags | Tag management, categorization | | `obsidian_delete_note` | Delete notes from vault | Clean up, remove outdated content | ### Tool Details **obsidian_read_note** - Returns full note content including frontmatter - Provides metadata (creation date, modification date, size) - Supports both absolute and relative paths within vault **obsidian_update_note** - Modes: append, prepend, overwrite - Preserves formatting and frontmatter - Safe for concurrent edits (Obsidian handles file watching) **obsidian_global_search** - Full-text search across all notes - Returns matching notes with context - Supports Obsidian's search syntax **obsidian_manage_frontmatter** - Add/update/remove YAML frontmatter properties - Supports complex data types (arrays, nested objects) - Preserves existing frontmatter structure ## Usage in Claude Code ### Checking MCP Status ```bash /mcp # View MCP server status claude mcp list # List all configured MCP servers ``` ### Interactive Usage Examples Simply ask Claude to interact with your vault using natural language: **Reading Notes** - "Read the note at How To/Linux Commands Cheat Sheet.md" - "Show me the contents of Work Stuff/Charter/Charter.md" - "What's in my School Stuff/AWS Sys Ops folder?" **Searching** - "Search my vault for notes about networking" - "Find all notes mentioning Raspberry Pi" - "Show me notes tagged with #homelab" - "Search for references to Docker in my vault" **Creating and Updating** - "Create a new note in How To/ called 'MCP Server Setup'" - "Add a section about troubleshooting to the Obsidian setup guide" - "Append my homelab documentation with today's changes" - "Update the frontmatter in my project note with status: completed" **Organization** - "List all notes in the Work Stuff folder" - "Show me all my project notes" - "What are all the tags used in my vault?" - "Find notes without tags in the How To folder" **Bulk Operations** - "Add a 'reviewed' tag to all notes in School Stuff/CCNA" - "Replace 'old-server' with 'new-server' in all my homelab notes" - "Update the date in frontmatter for all notes modified this week" ### Advanced Workflows **Documentation Generation** ``` "Read all my Proxmox-related notes and create a comprehensive homelab setup guide in the root folder" ``` **Knowledge Base Management** ``` "Search for incomplete tasks across my vault and create a summary note in @INBOX" ``` **Cross-Reference Analysis** ``` "Find all notes that reference 'Ansible' and create a backlinks report showing how they're connected" ``` ## Troubleshooting ### Connection Failed **Issue**: `claude mcp list` shows "✗ Failed to connect" or error messages **Diagnostic Steps**: 1. **Check if Obsidian is running** ```bash # From WSL, test if the REST API responds curl -I http://172.24.192.1:27123 ``` Expected response: `HTTP/1.1 200 OK` 2. **Verify the Local REST API plugin is active** - Open Obsidian on Windows - Go to Settings → Community Plugins - Ensure "Local REST API" is enabled (toggle is ON) - Click the gear icon to verify server is running 3. **Check Binding Host setting** - In Local REST API settings, verify **Binding Host** = `0.0.0.0` - This is CRITICAL for WSL connectivity - `127.0.0.1` will NOT work from WSL 4. **Verify Windows host IP hasn't changed** ```bash # Get current Windows host IP from WSL ip route show | grep -i default | awk '{print $3}' ``` - If different from `172.24.192.1`, update your MCP configuration 5. **Test with verbose curl** ```bash curl -v http://172.24.192.1:27123 ``` This shows detailed connection information **Solutions**: If connection still fails after diagnostics: ```bash # 1. Remove existing configuration claude mcp remove obsidian -s local # 2. Get current Windows IP WINDOWS_IP=$(ip route show | grep -i default | awk '{print $3}') echo "Windows IP: $WINDOWS_IP" # 3. Re-add with correct IP claude mcp add-json obsidian "{ \"type\":\"stdio\", \"command\":\"npx\", \"args\":[\"obsidian-mcp-server\"], \"env\":{ \"OBSIDIAN_API_KEY\":\"YOUR_ACTUAL_API_KEY_HERE\", \"OBSIDIAN_BASE_URL\":\"http://${WINDOWS_IP}:27123\", \"OBSIDIAN_VERIFY_SSL\":\"false\" } }" ``` ### Windows Host IP Changed **Why this happens**: WSL2 creates a virtual network adapter on each boot, and the Windows host IP can change. **Quick fix**: ```bash # One-liner to update configuration WINDOWS_IP=$(ip route show | grep -i default | awk '{print $3}') && \ claude mcp remove obsidian -s local && \ claude mcp add-json obsidian "{\"type\":\"stdio\",\"command\":\"npx\",\"args\":[\"obsidian-mcp-server\"],\"env\":{\"OBSIDIAN_API_KEY\":\"YOUR_ACTUAL_API_KEY_HERE\",\"OBSIDIAN_BASE_URL\":\"http://${WINDOWS_IP}:27123\",\"OBSIDIAN_VERIFY_SSL\":\"false\"}}" ``` **Permanent solution**: Create a shell alias in `~/.bashrc` or `~/.zshrc`: ```bash alias fix-obsidian-mcp='WINDOWS_IP=$(ip route show | grep -i default | awk '\''{print $3}'\'') && claude mcp remove obsidian -s local && claude mcp add-json obsidian "{\"type\":\"stdio\",\"command\":\"npx\",\"args\":[\"obsidian-mcp-server\"],\"env\":{\"OBSIDIAN_API_KEY\":\"YOUR_ACTUAL_API_KEY_HERE\",\"OBSIDIAN_BASE_URL\":\"http://${WINDOWS_IP}:27123\",\"OBSIDIAN_VERIFY_SSL\":\"false\"}}"' ``` Then simply run `fix-obsidian-mcp` after a reboot. ### Port Already in Use **Issue**: Port 27123 is already bound by another service **Solution**: 1. Change port in Obsidian plugin settings (e.g., to 27124) 2. Update MCP configuration with new port: ```bash claude mcp remove obsidian -s local # Re-add with new port in OBSIDIAN_BASE_URL ``` **Check what's using the port** (from Windows PowerShell): ```powershell netstat -ano | findstr :27123 ``` ### Firewall Blocking Connection **Issue**: Windows Firewall blocks WSL from accessing the port **Solutions**: 1. **Allow Obsidian through Windows Firewall**: - Open Windows Security → Firewall & network protection - Click "Allow an app through firewall" - Find Obsidian and ensure both Private and Public are checked 2. **Allow specific port** (PowerShell as Administrator): ```powershell New-NetFirewallRule -DisplayName "Obsidian REST API" -Direction Inbound -LocalPort 27123 -Protocol TCP -Action Allow ``` 3. **Test from Windows first**: ```powershell # From PowerShell on Windows curl http://localhost:27123 ``` If this works but WSL doesn't, it's definitely a firewall issue. ### API Key Issues **Issue**: Authentication errors or "Unauthorized" responses **Solutions**: 1. **Verify API key is correct**: - In Obsidian → Settings → Local REST API - Copy the API key exactly (no extra spaces) 2. **Check if API key has changed**: - The plugin generates a new key if you toggle it off/on - Always use the current key from the plugin settings 3. **Verify environment variable** in your MCP config: ```bash # Check the stored configuration cat ~/.claude.json | grep -A 10 obsidian ``` ### npx or Node.js Not Found **Issue**: `npx: command not found` or `obsidian-mcp-server` fails to start **Solutions**: 1. **Install Node.js in WSL**: ```bash # Using nvm (recommended) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash source ~/.bashrc nvm install --lts # Or using apt (Ubuntu/Debian) sudo apt update sudo apt install nodejs npm ``` 2. **Verify installation**: ```bash node --version npx --version ``` 3. **Test obsidian-mcp-server directly**: ```bash OBSIDIAN_API_KEY="your-key" \ OBSIDIAN_BASE_URL="http://172.24.192.1:27123" \ OBSIDIAN_VERIFY_SSL="false" \ npx obsidian-mcp-server ``` ### WSL Network Connectivity Issues **Issue**: General WSL networking problems **Diagnostic commands**: ```bash # Check WSL can reach Windows ping $(ip route show | grep -i default | awk '{print $3}') # Check DNS resolution nslookup google.com # Check routing ip route show # Test specific port nc -zv 172.24.192.1 27123 ``` **Common fixes**: 1. **Restart WSL networking**: ```powershell # From Windows PowerShell as Administrator wsl --shutdown # Then restart your WSL terminal ``` 2. **Check Windows network adapters**: - Look for "vEthernet (WSL)" in Windows Network Connections - Ensure it's enabled 3. **Reset WSL network** (last resort): ```powershell # From Windows PowerShell as Administrator netsh winsock reset netsh int ip reset wsl --shutdown ``` ### Permission Denied Errors **Issue**: Cannot write to vault or modify files **Causes**: - Vault folder has incorrect permissions - Obsidian has files locked - Windows/WSL file permission conflicts **Solutions**: 1. **Check vault permissions**: ```bash ls -la /mnt/c/Users/fam1n/Documents/Mind-Vault ``` 2. **Ensure Obsidian isn't locking files**: - Close and reopen the vault in Obsidian - Restart Obsidian completely 3. **Verify API has write permissions**: - Check Local REST API plugin settings - Ensure "Read-only mode" is NOT enabled ## Configuration Location The MCP server configuration is stored in: ``` /home/USERNAME/.claude.json ``` Under the `projects` section for your working directory. ## WSL-Specific Networking Considerations ### Understanding WSL2 Network Architecture WSL2 uses a virtualized network adapter, which creates some unique behaviors: 1. **Dynamic IP Assignment**: The Windows host IP can change on every WSL restart or Windows reboot 2. **NAT Network**: WSL2 sits behind NAT, accessing Windows services via the virtual network 3. **Separate Network Stack**: Windows and WSL have different network interfaces ### Why Binding Host Must Be 0.0.0.0 This is the most critical configuration for WSL connectivity: - `127.0.0.1` (localhost) - Only accepts connections from Windows itself - `0.0.0.0` (all interfaces) - Accepts connections from any network interface, including the WSL virtual network **The WSL connection path**: ``` WSL (172.x.x.x) → Virtual Network Adapter → Windows (172.24.192.1) → Obsidian (0.0.0.0:27123) ``` If Obsidian binds to `127.0.0.1`, it will reject WSL connections because they come from a different network interface. ### Finding the Windows Host IP The Windows host IP from WSL's perspective changes, but you can always find it: ```bash # Method 1: Using ip route (recommended) ip route show | grep -i default | awk '{print $3}' # Method 2: Using /etc/resolv.conf grep nameserver /etc/resolv.conf | awk '{print $2}' # Method 3: Environment variable (if set) echo $WSL_HOST_IP ``` **Pro tip**: Add this to your `~/.bashrc`: ```bash export WSL_HOST_IP=$(ip route show | grep -i default | awk '{print $3}') ``` ### Network Persistence Scripts Create a script to automatically detect and update the MCP configuration: ```bash #!/bin/bash # ~/bin/update-obsidian-mcp.sh WINDOWS_IP=$(ip route show | grep -i default | awk '{print $3}') API_KEY="YOUR_ACTUAL_API_KEY_HERE" PORT="27123" echo "Detected Windows IP: $WINDOWS_IP" # Remove old configuration claude mcp remove obsidian -s local 2>/dev/null # Add new configuration claude mcp add-json obsidian "{ \"type\":\"stdio\", \"command\":\"npx\", \"args\":[\"obsidian-mcp-server\"], \"env\":{ \"OBSIDIAN_API_KEY\":\"$API_KEY\", \"OBSIDIAN_BASE_URL\":\"http://${WINDOWS_IP}:${PORT}\", \"OBSIDIAN_VERIFY_SSL\":\"false\" } }" echo "MCP configuration updated successfully" claude mcp list | grep obsidian ``` Make it executable: ```bash chmod +x ~/bin/update-obsidian-mcp.sh ``` Run after any reboot: ```bash ~/bin/update-obsidian-mcp.sh ``` ### Testing WSL-to-Windows Connectivity Before troubleshooting the MCP server, verify basic WSL-to-Windows connectivity: ```bash # Get Windows IP WINDOWS_IP=$(ip route show | grep -i default | awk '{print $3}') # Test ICMP (ping) ping -c 3 $WINDOWS_IP # Test HTTP on Obsidian port curl -I http://$WINDOWS_IP:27123 # Test with timeout timeout 5 curl http://$WINDOWS_IP:27123 # Verbose connection test nc -zv $WINDOWS_IP 27123 ``` If basic connectivity fails, the issue is with WSL networking, not MCP/Obsidian. ## Security Notes ### API Key Security 1. **Storage**: The API key is stored in `~/.claude.json` in your WSL home directory - This file should have permissions `600` (readable only by you) - Check: `ls -la ~/.claude.json` - Fix: `chmod 600 ~/.claude.json` 2. **Key Rotation**: To change the API key: - Generate a new key in Obsidian Local REST API settings - Update MCP configuration using the setup command from Step 5 - Old key becomes invalid immediately 3. **Never commit to Git**: - `.claude.json` should be in `.gitignore` - Don't share API keys in documentation or scripts - Use environment variables for scripts ### Network Binding Security **Binding to 0.0.0.0 implications**: - **On private network (home/lab)**: Generally safe, only local network can access - **On public/shared network**: Could expose API to other devices on the network - **Security recommendations**: 1. Enable Windows Firewall to restrict access 2. Use strong API key (default is random 64-character hex) 3. Only run when needed if on untrusted networks 4. Consider disabling plugin when traveling with laptop **Creating a firewall rule** (Windows PowerShell as Administrator): ```powershell # Allow only from WSL subnet New-NetFirewallRule -DisplayName "Obsidian REST API (WSL Only)" ` -Direction Inbound -LocalPort 27123 -Protocol TCP -Action Allow ` -RemoteAddress 172.16.0.0/12 ``` ### SSL/TLS Considerations 1. **Local Development** (current setup): - `OBSIDIAN_VERIFY_SSL: "false"` - No SSL verification - Acceptable for WSL-to-Windows communication (same machine) - Traffic stays within local virtual network 2. **Remote Access** (if exposing externally): - Enable SSL in Obsidian Local REST API plugin - Set `OBSIDIAN_VERIFY_SSL: "true"` - Use proper certificates (not self-signed if possible) 3. **Why SSL is disabled here**: - Communication is between WSL and Windows on same physical machine - Traffic doesn't leave the computer - Simplifies setup for local development ### Data Protection 1. **Vault Access**: The MCP server has FULL access to your Obsidian vault - Can read any note - Can modify any note - Can delete notes - Keep API key secure 2. **Backup Strategy**: - Enable Obsidian's File Recovery core plugin - Use git for version control of your vault - Regular backups before using MCP operations: ```bash # Quick backup before bulk operations cd /mnt/c/Users/fam1n/Documents tar -czf Mind-Vault-backup-$(date +%Y%m%d-%H%M%S).tar.gz Mind-Vault/ ``` 3. **Safe Practices**: - Test MCP commands on non-critical notes first - Review changes before committing to git - Use Obsidian's File Recovery to revert mistakes ### Multi-User Considerations If multiple users/WSL instances access the same vault: 1. **Separate API Keys**: Generate different keys for different WSL instances 2. **Concurrent Access**: Obsidian handles file locking, but be aware of race conditions 3. **File Watchers**: Obsidian auto-refreshes when files change externally ## Best Practices and Tips ### Daily Workflow 1. **Check connection status** before starting work: ```bash claude mcp list ``` 2. **If connection fails** after reboot: ```bash ~/bin/update-obsidian-mcp.sh # Run your update script ``` 3. **Verify Obsidian is running** on Windows before using MCP commands ### Performance Optimization 1. **Keep Obsidian open**: The REST API only works when Obsidian is running 2. **Large vaults**: Global search may be slower on vaults with thousands of notes 3. **Batch operations**: Group related changes together rather than multiple individual calls ### Debugging Tips 1. **Enable verbose logging** in the Obsidian Local REST API plugin: - Settings → Local REST API → Enable HTTPS request logging - Check Obsidian's Developer Console (Ctrl+Shift+I on Windows) 2. **Monitor MCP server output**: ```bash # Run MCP server directly to see detailed output OBSIDIAN_API_KEY="your-key" \ OBSIDIAN_BASE_URL="http://172.24.192.1:27123" \ OBSIDIAN_VERIFY_SSL="false" \ npx obsidian-mcp-server ``` 3. **Check Claude Code logs**: ```bash # Look for MCP-related errors cat ~/.claude/logs/*.log | grep -i obsidian ``` ### Integration with Other Tools **Git Version Control**: ```bash # Initialize vault as git repository cd /mnt/c/Users/fam1n/Documents/Mind-Vault git init echo ".obsidian/workspace*" >> .gitignore git add . git commit -m "Initial vault snapshot" ``` **Backup Automation**: ```bash # Add to crontab for daily backups 0 2 * * * tar -czf ~/backups/Mind-Vault-$(date +\%Y\%m\%d).tar.gz /mnt/c/Users/fam1n/Documents/Mind-Vault/ ``` **Scripts for Common Tasks**: ```bash # Quick script to backup before MCP operations #!/bin/bash # ~/bin/backup-vault.sh BACKUP_DIR=~/vault-backups mkdir -p $BACKUP_DIR tar -czf $BACKUP_DIR/vault-$(date +%Y%m%d-%H%M%S).tar.gz \ /mnt/c/Users/fam1n/Documents/Mind-Vault/ echo "Backup created: $BACKUP_DIR/vault-$(date +%Y%m%d-%H%M%S).tar.gz" ``` ### Common Patterns **Daily Note Creation**: ``` "Create a daily note for today in the Journal folder with template: # YYYY-MM-DD ## Tasks - ## Notes " ``` **Tag Management**: ``` "Find all notes in School Stuff/AWS Sys Ops and ensure they have the #aws tag" ``` **Content Organization**: ``` "List all notes in Work Stuff that don't have frontmatter and add basic frontmatter with tags based on their folder structure" ``` **Knowledge Graph Analysis**: ``` "Find all notes that link to the Proxmox note and create a summary of how they're related" ``` ### Limitations and Workarounds **Limitation**: Cannot access notes while Obsidian is closed - **Workaround**: Use Obsidian's "Start at login" option in Windows **Limitation**: IP address changes on reboot - **Workaround**: Use the `update-obsidian-mcp.sh` script or shell alias **Limitation**: Windows Firewall may block after Windows updates - **Workaround**: Create permanent firewall rules as shown in Security Notes **Limitation**: Large file operations may timeout - **Workaround**: Process files in smaller batches or increase timeout settings ### Quick Reference Commands ```bash # Check connection claude mcp list # Get Windows IP ip route show | grep -i default | awk '{print $3}' # Test Obsidian API curl -I http://$(ip route show | grep -i default | awk '{print $3}'):27123 # Update MCP after reboot ~/bin/update-obsidian-mcp.sh # View MCP configuration cat ~/.claude.json | jq '.mcpServers.obsidian' # Remove MCP server claude mcp remove obsidian -s local # Backup vault tar -czf ~/vault-backup-$(date +%Y%m%d).tar.gz /mnt/c/Users/fam1n/Documents/Mind-Vault/ ``` ## References - [Obsidian Local REST API Plugin](https://github.com/coddingtonbear/obsidian-local-rest-api) - [obsidian-mcp-server NPM Package](https://www.npmjs.com/package/obsidian-mcp-server) - [Claude Code MCP Documentation](https://code.claude.com/docs/en/mcp.md) - [Model Context Protocol](https://modelcontextprotocol.io/) - [WSL Networking Documentation](https://docs.microsoft.com/en-us/windows/wsl/networking) ## Vault Location - **Windows Path**: `C:\Users\fam1n\Documents\Mind-Vault` - **WSL Path**: `/mnt/c/Users/fam1n/Documents/Mind-Vault` ## Environment Details - **OS**: Windows 11 with WSL2 (Ubuntu) - **Obsidian**: Running on Windows - **Claude Code**: Running in WSL2 - **Network**: WSL virtual network adapter - **Windows Host IP**: Dynamic (typically 172.24.192.1) - **API Port**: 27123 - **Binding**: 0.0.0.0 (all interfaces) --- *Last Updated: 2025-11-29* *Setup completed for Mind-Vault on Windows 11 with WSL2 (Ubuntu)* *Comprehensive documentation including WSL networking, troubleshooting, and best practices*