Skip to main content
Glama

Obsidian MCP Server

by suhailnajeeb
configure.py8.63 kB
#!/usr/bin/env python3 """Configure Claude Desktop to use Obsidian MCP server.""" import json import os import sys import platform import argparse import shutil from pathlib import Path from datetime import datetime from typing import Dict, Any, Optional class ConfigManager: """Manages Claude Desktop configuration for Obsidian MCP.""" def __init__(self): self.config_path = self._get_config_path() self.config: Dict[str, Any] = {} def _get_config_path(self) -> Path: """Get Claude Desktop config path based on OS.""" system = platform.system() if system == "Darwin": # macOS config_dir = Path.home() / "Library" / "Application Support" / "Claude" elif system == "Windows": config_dir = Path(os.environ["APPDATA"]) / "Claude" elif system == "Linux": config_dir = Path.home() / ".config" / "Claude" else: raise ValueError(f"Unsupported operating system: {system}") config_path = config_dir / "claude_desktop_config.json" return config_path def load_config(self) -> bool: """Load existing config or create empty one.""" if self.config_path.exists(): try: with open(self.config_path, 'r') as f: self.config = json.load(f) return True except json.JSONDecodeError: print(f"⚠️ Warning: Invalid JSON in {self.config_path}") self.config = {} return False else: print(f"📝 Creating new config at {self.config_path}") self.config = {"mcpServers": {}} # Ensure directory exists self.config_path.parent.mkdir(parents=True, exist_ok=True) return False def backup_config(self) -> Optional[Path]: """Create backup of existing config.""" if self.config_path.exists(): timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") backup_path = self.config_path.with_name( f"{self.config_path.stem}.backup_{timestamp}.json" ) shutil.copy2(self.config_path, backup_path) print(f"💾 Backup saved to: {backup_path.name}") return backup_path return None def detect_old_config(self, server_name: str = "obsidian") -> Optional[Dict[str, Any]]: """Detect if old REST API configuration exists.""" if "mcpServers" not in self.config: return None servers = self.config["mcpServers"] if server_name not in servers: return None old_config = servers[server_name] # Check for indicators of old REST API config is_old = any([ "cwd" in old_config, old_config.get("args") == ["-m", "src.server"], "OBSIDIAN_REST_API_KEY" in old_config.get("env", {}), "PYTHONPATH" in old_config.get("env", {}), old_config.get("command", "").endswith("python") or old_config.get("command", "").endswith("python3") ]) return old_config if is_old else None def update_config(self, vault_path: str, server_name: str = "obsidian", force: bool = False) -> bool: """Update config with new Obsidian MCP settings.""" # Ensure mcpServers exists if "mcpServers" not in self.config: self.config["mcpServers"] = {} # Check for existing config old_config = self.detect_old_config(server_name) if old_config: print("\n🔄 Migration detected!") print("Found old REST API configuration:") print(f" - Command: {old_config.get('command', 'N/A')}") print(f" - Working directory: {old_config.get('cwd', 'N/A')}") print(" - Using REST API plugin") print("\nMigrating to v2.0 direct filesystem access...") # Try to extract vault path from old config if not provided if not vault_path and "OBSIDIAN_VAULT_PATH" in old_config.get("env", {}): vault_path = old_config["env"]["OBSIDIAN_VAULT_PATH"] print(f" - Reusing vault path: {vault_path}") elif server_name in self.config["mcpServers"] and not force: print(f"\n⚠️ Server '{server_name}' already exists in config.") response = input("Overwrite? (y/N): ").strip().lower() if response != 'y': print("❌ Configuration cancelled.") return False # Validate vault path vault_path = Path(vault_path).expanduser().resolve() if not vault_path.exists(): print(f"❌ Vault path does not exist: {vault_path}") return False if not vault_path.is_dir(): print(f"❌ Vault path is not a directory: {vault_path}") return False # Create new config new_config = { "command": "uvx", "args": ["obsidian-mcp"], "env": { "OBSIDIAN_VAULT_PATH": str(vault_path) } } # Update config self.config["mcpServers"][server_name] = new_config # Show what changed if old_config: print("\n✅ Migration complete!") print(" - Removed dependency on Local REST API plugin") print(" - Now using direct filesystem access (faster!)") print(f" - Vault path: {vault_path}") else: print(f"\n✅ Added Obsidian MCP server '{server_name}'") print(f" - Vault path: {vault_path}") return True def save_config(self) -> None: """Save config to file with pretty formatting.""" with open(self.config_path, 'w') as f: json.dump(self.config, f, indent=2) print(f"\n💾 Configuration saved to: {self.config_path}") def show_usage(self) -> None: """Show how to use the configured server.""" print("\n🚀 Setup complete! Restart Claude Desktop to use Obsidian MCP.") print("\nExample prompts to try:") print(" - 'Show me all notes I modified this week'") print(" - 'Create a new daily note for today'") print(" - 'Search for all notes about project planning'") def main(): """Main entry point for configuration script.""" parser = argparse.ArgumentParser( description="Configure Claude Desktop to use Obsidian MCP server", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: # Configure with your vault obsidian-mcp-configure --vault-path /path/to/vault # Use custom server name obsidian-mcp-configure --vault-path /path/to/vault --name my-vault # Force overwrite without prompting obsidian-mcp-configure --vault-path /path/to/vault --force """ ) parser.add_argument( "--vault-path", type=str, required=True, help="Path to your Obsidian vault" ) parser.add_argument( "--name", type=str, default="obsidian", help="Server name in Claude config (default: obsidian)" ) parser.add_argument( "--force", action="store_true", help="Force overwrite existing config without prompting" ) parser.add_argument( "--no-backup", action="store_true", help="Skip creating backup of existing config" ) args = parser.parse_args() # Header print("🔮 Obsidian MCP Configuration Tool") print("=" * 40) try: # Initialize config manager manager = ConfigManager() # Load existing config config_exists = manager.load_config() # Create backup if requested and config exists if config_exists and not args.no_backup: manager.backup_config() # Update configuration success = manager.update_config( vault_path=args.vault_path, server_name=args.name, force=args.force ) if success: # Save config manager.save_config() # Show usage instructions manager.show_usage() else: sys.exit(1) except Exception as e: print(f"\n❌ Error: {e}") sys.exit(1) if __name__ == "__main__": main()

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/suhailnajeeb/obsidian-mcp'

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