Skip to main content
Glama

Obsidian MCP Server

README.md10.5 kB
# Custom Obsidian MCP Server A comprehensive Model Context Protocol (MCP) server for Obsidian vault operations, optimized for **Zettelkasten note creation workflows**. Works with any LLM that supports MCP (Claude, Perplexity, etc.). ## Overview This MCP server connects to the [Obsidian Local REST API plugin](https://github.com/coddingtonbear/obsidian-local-rest-api) and provides 12 powerful tools for: - **File Operations**: List, read, and manage files in your vault - **Content Operations**: Create, append, and precisely edit notes - **Search**: Find related notes across your vault - **Metadata Management**: Tags, frontmatter, and note properties Designed specifically for **Zettelkasten practitioners** who want AI assistance in creating atomic notes, finding connections, and maintaining a knowledge graph. ## Features ✅ **Zettelkasten-Optimized**: Tools designed for atomic note creation and linking ✅ **LLM-Agnostic**: Works with any MCP-compatible LLM ✅ **Safe by Default**: CREATE mode won't overwrite existing notes ✅ **Powerful Search**: Find existing notes before creating duplicates ✅ **Precise Editing**: Insert content at specific headings or blocks ✅ **Metadata Rich**: Full frontmatter and tag management ## Prerequisites 1. **Obsidian** with [Local REST API plugin](https://github.com/coddingtonbear/obsidian-local-rest-api) installed and configured 2. **Python 3.10+** 3. **uv** (optional but recommended for managing Python environments) ## Installation ### 1. Install the MCP Server Using `uv` (recommended): ```bash cd custom-obsidian-mcp uv sync ``` Or using pip: ```bash cd custom-obsidian-mcp pip install -e . ``` ### 2. Set Up Obsidian Local REST API 1. Install the "Local REST API" plugin in Obsidian 2. Enable the plugin in Settings → Community plugins 3. Go to plugin settings and copy your API key 4. Note the port (default: 27124) ### 3. Configure Environment Variables Create a `.env` file or set these variables: ```bash export OBSIDIAN_API_KEY="your-api-key-here" export OBSIDIAN_HOST="127.0.0.1" # Usually localhost export OBSIDIAN_PORT="27124" # Default port ``` ## Configuration for LLM Clients ### Claude Desktop (Desktop App) Add to your `claude_desktop_config.json`: ```json { "mcpServers": { "obsidian": { "command": "/path/to/uvx", "args": ["custom-obsidian-mcp"], "env": { "OBSIDIAN_API_KEY": "your-api-key-here", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" } } } } ``` Or if using pip installation: ```json { "mcpServers": { "obsidian": { "command": "python", "args": ["-m", "custom_obsidian_mcp.server"], "env": { "OBSIDIAN_API_KEY": "your-api-key-here", "OBSIDIAN_HOST": "127.0.0.1", "OBSIDIAN_PORT": "27124" } } } } ``` ### Perplexity or Other MCP Clients Use similar configuration structure adapted to your client's format. ## Available Tools ### File Operations #### `obsidian_list_files_in_vault` List all files and directories in vault root. ```python # No parameters needed ``` #### `obsidian_list_files_in_dir` List contents of a specific directory. ```python { "dirpath": "Zettelkasten" # Empty string for root } ``` #### `obsidian_get_file_contents` Read a single file's complete contents. ```python { "filepath": "Zettelkasten/202411061234.md" } ``` #### `obsidian_batch_get_file_contents` Read multiple files at once (max 20). ```python { "filepaths": [ "Zettelkasten/note1.md", "Zettelkasten/note2.md" ] } ``` ### Search Operations #### `obsidian_simple_search` Text search across all vault files with context. ```python { "query": "systems thinking", "context_length": 100 # Optional, default 100 } ``` #### `obsidian_complex_search` Advanced JsonLogic-based search. ```python { "query": {"glob": ["*.md", {"var": "path"}]} } ``` ### Content Operations #### `obsidian_write_note` Create or modify notes with optional frontmatter. ```python { "filepath": "Zettelkasten/202411061234 Systems Thinking.md", "content": "# Systems Thinking\n\nContent here...", "mode": "create", # create|overwrite|append|prepend "frontmatter": { "tags": ["zettelkasten", "systems"], "created": "2024-11-06" } } ``` **Modes:** - `create`: Only create new files (won't overwrite) - `overwrite`: Replace entire file - `append`: Add to end - `prepend`: Add to beginning #### `obsidian_append_content` Quick append to file (creates if doesn't exist). ```python { "filepath": "Zettelkasten/note.md", "content": "\n## New Section\n\nNew content..." } ``` #### `obsidian_patch_content` Insert content at specific locations within notes. ```python { "filepath": "Zettelkasten/note.md", "target_type": "heading", # heading|block|frontmatter "target": "Related Concepts/Subsection", "operation": "append", # append|prepend|replace "content": "New related concept..." } ``` **Target Types:** - `heading`: Navigate to heading path (e.g., "Section/Subsection") - `block`: Use block reference (e.g., "^block-id") - `frontmatter`: Update specific frontmatter field #### `obsidian_delete_file` Delete file or directory (requires confirmation). ```python { "filepath": "Zettelkasten/old-note.md", "confirm": true # Must be true to proceed } ``` ### Metadata Operations #### `obsidian_get_frontmatter` Extract YAML frontmatter from a note. ```python { "filepath": "Zettelkasten/note.md" } ``` #### `obsidian_update_frontmatter` Update frontmatter without modifying content. ```python { "filepath": "Zettelkasten/note.md", "updates": { "tags": ["zettelkasten", "new-tag"], "status": "published" } } ``` #### `obsidian_manage_tags` Add, remove, or list tags. ```python { "filepath": "Zettelkasten/note.md", "action": "add", # add|remove|list "tags": ["systems-thinking", "mental-models"] } ``` #### `obsidian_get_notes_info` Get metadata for multiple notes (max 50). ```python { "filepaths": [ "Zettelkasten/note1.md", "Zettelkasten/note2.md" ] } ``` Returns: tags, creation date, size, and other metadata. ## Zettelkasten Workflow Examples ### Creating a New Atomic Note 1. **Search for existing related notes:** ``` Use obsidian_simple_search with query "systems thinking" ``` 2. **Read related notes:** ``` Use obsidian_batch_get_file_contents with discovered notes ``` 3. **Create new atomic note:** ``` Use obsidian_write_note: - filepath: "Zettelkasten/202411061234 Systems Thinking Core Concept.md" - content: Your atomic note content - mode: "create" (safe - won't overwrite) - frontmatter: {tags: ["zettelkasten", "systems"], created: "2024-11-06"} ``` ### Linking Related Notes 1. **Find notes in topic cluster:** ``` Use obsidian_simple_search or obsidian_get_notes_info ``` 2. **Add connection to existing note:** ``` Use obsidian_patch_content: - target_type: "heading" - target: "Related Concepts" - operation: "append" - content: "- [[202411061234 Systems Thinking Core Concept]]" ``` ### Organizing with Tags 1. **Check current tags:** ``` Use obsidian_manage_tags with action: "list" ``` 2. **Add topic tags:** ``` Use obsidian_manage_tags with action: "add" ``` ## Best Practices ### For Zettelkasten - **Always search first**: Use `obsidian_simple_search` before creating new notes to avoid duplicates - **Atomic notes**: One idea per note, clearly titled - **Link liberally**: Use `obsidian_patch_content` to add connections - **Tag consistently**: Use `obsidian_manage_tags` for topic organization - **Use CREATE mode**: Default to `mode="create"` to prevent accidental overwrites ### For Safety - **CREATE mode is default**: Won't overwrite existing notes - **Confirmation required**: Destructive operations need explicit confirmation - **Test in dev vault**: Try tools in a test vault before using on your main Zettelkasten ## Troubleshooting ### Connection Errors **Error:** "Connection error for GET /vault/" **Solutions:** 1. Verify Obsidian is running 2. Check Local REST API plugin is enabled 3. Verify API key is correct 4. Check port matches plugin settings (default: 27124) ### Authentication Errors **Error:** "Authentication failed" **Solutions:** 1. Check `OBSIDIAN_API_KEY` environment variable 2. Regenerate API key in plugin settings 3. Ensure no extra spaces in API key ### File Not Found **Error:** "Resource not found" **Solutions:** 1. Verify file path is relative to vault root 2. Check file exists: use `obsidian_list_files_in_dir` 3. Ensure proper file extension (e.g., `.md`) ## Architecture ``` custom-obsidian-mcp/ ├── src/ │ └── custom_obsidian_mcp/ │ ├── __init__.py │ ├── server.py # FastMCP server with all tools │ └── obsidian_client.py # REST API client ├── pyproject.toml # Project configuration └── README.md ``` ### Key Components - **FastMCP**: Modern Python MCP framework with Pydantic validation - **ObsidianClient**: Async HTTP client for REST API communication - **Pydantic Models**: Type-safe input validation for all tools - **Error Handling**: Actionable error messages guide correct usage ## Development ### Running Tests ```bash # Verify Python syntax python -m py_compile src/custom_obsidian_mcp/server.py # Test basic import python -c "from custom_obsidian_mcp.server import mcp; print('OK')" ``` ### Adding New Tools 1. Define Pydantic input model 2. Add tool function with `@mcp.tool` decorator 3. Include proper annotations (readOnlyHint, etc.) 4. Add comprehensive docstring 5. Implement error handling ## Contributing Contributions welcome! Please: 1. Follow existing code style 2. Add Pydantic models for validation 3. Include docstrings with examples 4. Test with Obsidian Local REST API ## License MIT License - See LICENSE file for details ## Acknowledgments - Built on [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) - Inspired by [MarkusPfundstein's mcp-obsidian](https://github.com/MarkusPfundstein/mcp-obsidian) - Uses [Obsidian Local REST API](https://github.com/coddingtonbear/obsidian-local-rest-api) ## Support For issues or questions: 1. Check Troubleshooting section 2. Verify Obsidian Local REST API is working 3. Test with simple tools first (list_files_in_vault) 4. Open an issue with error messages and configuration --- **Happy note-taking! 📝✨**

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

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