Skip to content

ramanarupa/ObsidianPilotFastIndexing

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

43 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ObsidianPilot - Enhanced MCP Server

๐Ÿš€ Quick Start (Windows)

  1. Setup Claude Desktop: Visit this page for details: https://modelcontextprotocol.io/quickstart/user

  2. Configure Claude Desktop:

    • Open: %APPDATA%\Claude\claude_desktop_config.json
    • Add this configuration:
    {
      "mcpServers": {
        "obsidian": {
          "command": "obsidianpilot",
          "args": [],
          "env": {
            "OBSIDIAN_VAULT_PATH": "C:\\Users\\YourName\\Documents\\MyVault"
          }
        }
      }
    }
  3. Update the vault path in the config above to your actual Obsidian vault location

  4. Restart Claude Desktop - You must click file->exit... not just close and reopen. Then ObsidianPilot is now ready!


๐ŸŽ‰ Version 2.1.3 Released!

๐Ÿš€ Key Features:

  • โšก Ultra-fast search - SQLite FTS5 with boolean operators (AND, OR, NOT) for instant results on large vaults
  • ๐Ÿ” Smart search - Handles multi-word terms, quoted phrases, and complex boolean queries
  • ๐Ÿ”— Advanced link management - Find backlinks, analyze outgoing links with resolved paths, identify broken links
  • ๐Ÿ“ฆ Efficient API - Enhanced read_note tool fetches content and links in a single call
  • ๐Ÿ“ Accurate link resolution - Matches Obsidian's relative path resolution behavior
  • ๐Ÿ”„ Background indexing - Automatic index updates when notes change
  • ๐ŸŒ– Regex search - Find complex patterns with optional directory scoping
  • ๐Ÿท๏ธ Property search - Query by frontmatter properties with advanced operators
  • ๐Ÿ–ผ๏ธ Image support - View and analyze images from your vault
  • ๐Ÿ“ฆ Token-efficient editing - Edit specific sections without rewriting entire notes

ObsidianPilot is an enhanced Model Context Protocol (MCP) server that enables AI assistants like Claude to interact with your Obsidian vault with powerful token-efficient editing capabilities. This server provides tools for reading, creating, searching, and managing notes in Obsidian through direct filesystem access with blazing-fast performance and intelligent indexing.

Features

  • ๐Ÿ“– Read & write notes - Full access to your Obsidian vault with automatic overwrite protection
  • ๐Ÿ” Blazing-fast search - SQLite FTS5 full-text search with boolean operators (AND, OR, NOT) for instant results on large vaults
  • โšก Smart search optimization - Automatically chooses fastest search method based on vault size and query complexity
  • ๐Ÿ–ผ๏ธ Image analysis - View and analyze images embedded in notes or stored in your vault
  • ๐Ÿ”Ž Regex power search - Use regular expressions to find code patterns, URLs, or complex text structures
  • ๐Ÿ—‚๏ธ Property search - Query notes by frontmatter properties with operators (=, >, <, contains, exists)
  • ๐Ÿ“ Browse vault - List and navigate your notes and folders by directory
  • ๐Ÿท๏ธ Tag management - Add, remove, and organize tags (supports hierarchical tags, frontmatter, and inline tags)
  • ๐Ÿ”— Advanced link management - Find backlinks, analyze outgoing links with resolved paths, and identify broken links
  • ๐Ÿ“ฆ Efficient API - Enhanced read_note tool can fetch content and links in a single call
  • โœ๏ธ Smart rename - Rename notes with automatic link updates throughout your vault
  • ๐Ÿ“Š Note insights - Get statistics like word count and link analysis
  • ๐ŸŽฏ AI-optimized - Clear error messages and smart defaults for better AI interactions
  • ๐Ÿ”’ Secure - Direct filesystem access with path validation
  • โšก Performance optimized - Persistent SQLite index, concurrent operations, and streaming for large vaults
  • ๐Ÿš€ Bulk operations - Create folder hierarchies and move entire folders with all their contents

Prerequisites

  • Obsidian vault on your local filesystem
  • Python 3.10+ installed on your system
  • Node.js (optional, for running MCP Inspector)

Installation

For Other Platforms (macOS, Linux)

Install ObsidianPilot:

uvx ObsidianPilot

Configuration for All Platforms

  1. Locate your Obsidian vault:

    • Find the path to your Obsidian vault on your filesystem
    • Example: /Users/yourname/Documents/MyVault or C:\Users\YourName\Documents\MyVault
  2. **Configure your AI tool:**Edit your Claude Desktop config file:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    { "mcpServers": { "obsidian": { "command": "uvx", "args": ["ObsidianPilot"], "env": { "OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault" } } } }

    Add to your Cursor settings:

    • Project-specific: .cursor/mcp.json in your project directory
    • Global: ~/.cursor/mcp.json in your home directory

    { "mcpServers": { "obsidian": { "command": "uvx", "args": ["ObsidianPilot"], "env": { "OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault" } } } }

    Then: Open Settings โ†’ Cursor Settings โ†’ Enable MCP

    Edit your Windsurf config file:

    • Location: ~/.codeium/windsurf/mcp_config.json

    { "mcpServers": { "obsidian": { "command": "uvx", "args": ["ObsidianPilot"], "env": { "OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault" } } } }

    Then: Open Windsurf Settings โ†’ Advanced Settings โ†’ Cascade โ†’ Add Server โ†’ Refresh

  3. Restart your AI tool to load the new configuration.

That's it! The server will now be available in your AI tool with access to your Obsidian vault.

Note: This uses uvx which automatically downloads and runs the server in an isolated environment. Most users won't need to install anything else. If you don't have uv installed, you can also use pipx install ObsidianPilot and change the command to "obsidianpilot" in the config.

Try It Out

Here are some example prompts to get started:

  • "Show me all notes I modified this week"
  • "Create a new daily note for today with my meeting agenda"
  • "Search for all notes about project planning"
  • "Read my Ideas/startup.md note"

Development Installation

  1. Clone the repository:

    git clone https://github.com/that0n3guy/ObsidianPilot cd ObsidianPilot

  2. Set up Python environment:

    # Using pyenv (recommended) pyenv virtualenv 3.12.9 ObsidianPilot pyenv activate ObsidianPilot # Or using venv python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate

  3. Install dependencies:

    pip install -r requirements.txt

  4. Configure environment variables:

    export OBSIDIAN_VAULT_PATH="/path/to/your/obsidian/vault"

  5. Run the server:

    python -m obsidian_mcp.server

  6. **Add to Claude Desktop (for development):**Edit your Claude Desktop config file:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    { "mcpServers": { "obsidian": { "command": "/path/to/python", "args": ["-m", "obsidian_mcp.server"], "cwd": "/path/to/ObsidianPilot", "env": { "PYTHONPATH": "/path/to/ObsidianPilot", "OBSIDIAN_VAULT_PATH": "/path/to/your/obsidian/vault" } } } }

Project Structure

obsidian-mcp/ โ”œโ”€โ”€ obsidian_mcp/ โ”‚ โ”œโ”€โ”€ server.py # Main entry point with rich parameter schemas โ”‚ โ”œโ”€โ”€ tools/ # Tool implementations โ”‚ โ”‚ โ”œโ”€โ”€ note_management.py # CRUD operations โ”‚ โ”‚ โ”œโ”€โ”€ search_discovery.py # Search and navigation โ”‚ โ”‚ โ”œโ”€โ”€ organization.py # Tags, moves, metadata โ”‚ โ”‚ โ””โ”€โ”€ link_management.py # Backlinks, outgoing links, broken links โ”‚ โ”œโ”€โ”€ models/ # Pydantic models for validation โ”‚ โ”‚ โ””โ”€โ”€ obsidian.py # Note, SearchResult, VaultItem models โ”‚ โ”œโ”€โ”€ utils/ # Shared utilities โ”‚ โ”‚ โ”œโ”€โ”€ filesystem.py # Direct filesystem access โ”‚ โ”‚ โ”œโ”€โ”€ validators.py # Path validation, sanitization โ”‚ โ”‚ โ””โ”€โ”€ validation.py # Comprehensive parameter validation โ”‚ โ””โ”€โ”€ constants.py # Constants and error messages โ”œโ”€โ”€ tests/ โ”‚ โ”œโ”€โ”€ run_tests.py # Test runner โ”‚ โ””โ”€โ”€ test_filesystem_integration.py # Integration tests โ”œโ”€โ”€ docs/ # Additional documentation โ”œโ”€โ”€ requirements.txt # Python dependencies โ”œโ”€โ”€ CLAUDE.md # Instructions for Claude Code โ””โ”€โ”€ README.md

Available Tools

Note Management

read_note

Read the content and metadata of a specific note.

Parameters:

  • path: Path to the note (e.g., "Daily/2024-01-15.md")
  • include_outgoing_links (default: false): Include all links from this note with resolved file paths
  • include_backlinks (default: false): Include all notes that link to this note

Returns:

{ "path": "Daily/2024-01-15.md", "content": "# Daily Note\n\nContent here...", "metadata": { "tags": ["daily", "journal"], "aliases": [], "frontmatter": {} }, "outgoing_links": [...], // If include_outgoing_links=true "backlinks": [...] // If include_backlinks=true }

create_note

Create a new note or update an existing one.

Parameters:

  • path: Path where the note should be created
  • content: Markdown content of the note (consider adding tags for organization)
  • overwrite (default: false): Whether to overwrite existing notes

Best Practices:

  • Add relevant tags when creating notes to maintain organization
  • Use list_tags to see existing tags and maintain consistency
  • Tags can be added as inline hashtags (#tag) or in frontmatter
update_note

Update the content of an existing note.

โš ๏ธ IMPORTANT: By default, this tool REPLACES the entire note content. Always read the note first if you need to preserve existing content.

Parameters:

  • path: Path to the note to update
  • content: New markdown content (REPLACES existing content unless using append)
  • create_if_not_exists (default: false): Create if doesn't exist
  • merge_strategy (default: "replace"): How to handle content
    • "replace": Overwrites entire note content (default)
    • "append": Adds new content to the end of existing content

Safe Update Pattern:

  1. ALWAYS read first to preserve content
  2. Modify the content as needed
  3. Update with the complete new content
  4. Or use append mode to add content to the end
edit_note_section

Edit a specific section of a note identified by a markdown heading.

Parameters:

  • path: Path to the note to edit
  • section_identifier: Markdown heading that identifies the section (e.g., "## Tasks", "### Status")
  • content: Content to insert, replace, or append
  • operation (default: "insert_after"): How to edit the section
    • "insert_after": Add content after the section heading
    • "insert_before": Add content before the section heading
    • "replace_section": Replace entire section including heading
    • "append_to_section": Add content at the end of the section
    • "edit_heading": Change just the heading text while preserving section content
  • create_if_missing (default: false): Create section if it doesn't exist

Example usage:

Add tasks to a specific section

await edit_note_section( "Daily/2024-01-15.md", "## Tasks", "- [ ] Review PR\n- [ ] Update docs", operation="append_to_section" )

Update a status section

await edit_note_section( "Projects/Website.md", "### Current Status", "### Current Status\n\nPhase 2 completed!", operation="replace_section" )

Change just a heading

await edit_note_section( "Projects/Website.md", "## Old Heading", "## New Heading", operation="edit_heading" )

Use cases:

  • Adding items to task lists without rewriting the whole note
  • Updating status sections in project notes
  • Building up notes incrementally by section
  • Inserting content at precise locations
edit_note_content

Edit specific text content in a note using precise search and replace.

Parameters:

  • path: Path to the note to edit
  • search_text: Exact text to search for and replace
  • replacement_text: Text to replace the search_text with
  • occurrence (default: "first"): Replace "first" occurrence only or "all" occurrences

Example usage:

Update a specific value

await edit_note_content( "Projects/Website.md", "Status: In Progress", "Status: Completed" )

Fix a typo throughout the document

await edit_note_content( "Notes/Research.md", "recieve", "receive", occurrence="all" )

Update frontmatter property

await edit_note_content( "Daily/2024-01-15.md", "priority: low", "priority: high" )

Use cases:

  • Updating specific values or references
  • Fixing typos or correcting text
  • Modifying frontmatter properties
  • Changing URLs or links
  • Updating dates or numbers
delete_note

Delete a note from the vault.

Parameters:

  • path: Path to the note to delete

Search and Discovery

๐Ÿš€ Performance Note: v2.1.x introduces blazing-fast SQLite FTS5 search that automatically optimizes for large vaults. Search tools that previously timed out on 1800+ note vaults now complete in under 0.5 seconds!

search_notes (Ultra-Fast FTS5 Search)

Lightning-fast full-text search using SQLite FTS5 indexing with boolean operators and advanced search capabilities.

Performance Features:

  • 100-1000x faster: SQLite FTS5 indexing replaces slow SQL LIKE queries
  • Boolean operators: Support for AND, OR, NOT for complex searches
  • Phrase search: Automatic phrase detection for multi-word queries
  • Proper ranking: Results ranked by relevance with scoring
  • Background indexing: Index builds automatically without blocking AI interactions
  • Legacy compatibility: Supports tag:, path:, and property: prefixes for backward compatibility

Parameters:

  • query: Search query with boolean operators and special prefixes
  • max_results (default: 50): Maximum number of results to return (1-500)
  • context_length (default: 100): Number of characters to show around matches

Search Syntax:

Boolean Search (New):

  • "python AND tutorial" - Find notes containing both terms
  • "Eide Bailly OR CPA OR accounting" - Find notes with any of these terms
  • "machine learning NOT snake" - Exclude irrelevant results
  • "(python OR ruby) AND tutorial" - Complex nested queries
  • "exact phrase search" - Phrase matching for multi-word terms

Legacy Syntax (Still Supported):

  • Text search: "machine learning"
  • Tag search: tag:project or tag:#project
    • Hierarchical tags: tag:project/web (exact match)
    • Parent search: tag:project (finds project, project/web, project/mobile)
    • Child search: tag:web (finds project/web, design/web)
  • Path search: path:Daily/
  • Property search: property:status:active or property:priority:>2

Returns:

{ "results": [...], // Array of matched notes "total_count": 150, // Total matches found "limit": 50, // max_results used "truncated": true // More results available }

Property Search Examples:

  • property:status:active - Find notes where status = "active"
  • property:priority:>2 - Find notes where priority > 2
  • property:author:*john* - Find notes where author contains "john"
  • property:deadline:* - Find notes that have a deadline property
  • property:rating:>=4 - Find notes where rating >= 4
  • property:tags:project - Find notes with "project" in their tags array
  • property:due_date:<2024-12-31 - Find notes with due dates before Dec 31, 2024
search_by_date

Search for notes by creation or modification date.

Parameters:

  • date_type (default: "modified"): Either "created" or "modified"
  • days_ago (default: 7): Number of days to look back
  • operator (default: "within"): Either "within" (last N days) or "exactly" (exactly N days ago)

Returns:

{ "query": "Notes modified within last 7 days", "count": 15, "results": [ { "path": "Daily/2024-01-15.md", "date": "2024-01-15T10:30:00", "days_ago": 1 } ] }

Example usage:

  • "Show me all notes modified today" โ†’ search_by_date("modified", 0, "within")
  • "Show me all notes modified this week" โ†’ search_by_date("modified", 7, "within")
  • "Find notes created in the last 30 days" โ†’ search_by_date("created", 30, "within")
  • "What notes were modified exactly 2 days ago?" โ†’ search_by_date("modified", 2, "exactly")
search_by_regex (Performance Optimized)

Search for notes using regular expressions with smart timeout protection for large vaults.

v2.1.x Improvements:

  • Timeout protection: 20-30s timeouts prevent hanging on large vaults
  • Smart suggestions: Detects simple patterns and suggests faster alternatives
  • Auto-optimization: Reduces result limits and applies timeouts based on vault size
  • Helpful errors: When timeouts occur, suggests specific fast search alternatives

Parameters:

  • pattern: Regular expression pattern to search for
  • flags (optional): List of regex flags ("ignorecase", "multiline", "dotall")
  • context_length (default: 100): Characters to show around matches
  • max_results (default: 50): Maximum number of results (auto-limited for large vaults)

Performance Tips: For better performance on large vaults, consider these alternatives:

  • Simple text: Use search_notes("your text")
  • Boolean queries: Use search_notes("term1 AND term2")
  • Field search: Use search_notes("tag:tagname") or search_notes("path:foldername")

When to use regex:

  • Finding code patterns (functions, imports, syntax)
  • Searching for structured data
  • Complex text patterns that simple search can't handle

Common patterns:

# Find Python imports "(import|from)\\s+fastmcp" # Find function definitions "def\\s+\\w+\\s*\\([^)]*\\):" # Find TODO comments "(TODO|FIXME)\\s*:?\\s*(.+)" # Find URLs "https?://[^\\s)>]+" # Find code blocks "```python([^`]+)```"

Returns:

{ "pattern": "def\\s+search\\w*", "count": 2, "results": [ { "path": "code/utils.py", "match_count": 3, "matches": [ { "match": "def search_notes", "line": 42, "context": "...async def search_notes(query)..." } ] } ] }

search_by_property

Search for notes by their frontmatter property values with advanced filtering.

Parameters:

  • property_name: Name of the property to search for
  • value (optional): Value to compare against
  • operator (default: "="): Comparison operator
  • context_length (default: 100): Characters of note content to include

Operators:

  • "=": Exact match (case-insensitive)
  • "!=": Not equal
  • ">", "<", ">=", "<=": Numeric/date comparisons
  • "contains": Property value contains the search value
  • "exists": Property exists (value parameter ignored)

Supported Property Types:

  • Text/String: Standard text comparison
  • Numbers: Automatic numeric comparison for operators
  • Dates: ISO format (YYYY-MM-DD) with intelligent date parsing
  • Arrays/Lists: Searches within array items, comparisons use array length
  • Legacy properties: Automatically handles tagโ†’tags, aliasโ†’aliases migrations

Returns:

{ "property": "status", "operator": "=", "value": "active", "count": 5, "results": [ { "path": "Projects/Website.md", "matches": ["status = active"], "context": "status: active\n\n# Website Redesign Project...", "property_value": "active" } ] }

Example usage:

  • Find all active projects: search_by_property("status", "active")
  • Find high priority items: search_by_property("priority", "2", ">")
  • Find notes with deadlines: search_by_property("deadline", operator="exists")
  • Find notes by partial author: search_by_property("author", "john", "contains")
list_notes

List notes in your vault with optional recursive traversal.

Parameters:

  • directory (optional): Specific directory to list (e.g., "Daily", "Projects")
  • recursive (default: true): List all notes recursively

Returns:

{ "directory": "Daily", "recursive": true, "count": 365, "notes": [ {"path": "Daily/2024-01-01.md", "name": "2024-01-01.md"}, {"path": "Daily/2024-01-02.md", "name": "2024-01-02.md"} ] }

list_folders

List folders in your vault with optional recursive traversal.

Parameters:

  • directory (optional): Specific directory to list from
  • recursive (default: true): Include all nested subfolders

Returns:

{ "directory": "Projects", "recursive": true, "count": 12, "folders": [ {"path": "Projects/Active", "name": "Active"}, {"path": "Projects/Archive", "name": "Archive"}, {"path": "Projects/Ideas", "name": "Ideas"} ] }

Organization

create_folder

Create a new folder in the vault, including all parent folders in the path.

Parameters:

  • folder_path: Path of the folder to create (e.g., "Research/Studies/2024")
  • create_placeholder (default: true): Whether to create a placeholder file

Returns:

{ "folder": "Research/Studies/2024", "created": true, "placeholder_file": "Research/Studies/2024/.gitkeep", "folders_created": ["Research", "Research/Studies", "Research/Studies/2024"] }

Note: This tool will create all necessary parent folders. For example, if "Research" exists but "Studies" doesn't, it will create both "Studies" and "2024".

move_note

Move a note to a new location, optionally with a new name.

Parameters:

  • source_path: Current path of the note
  • destination_path: New path for the note (can include new filename)
  • update_links (default: true): Update links if filename changes

Features:

  • Can move to a different folder: move_note("Inbox/Note.md", "Archive/Note.md")
  • Can move AND rename: move_note("Inbox/Old.md", "Archive/New.md")
  • Automatically detects if filename changes and updates all wiki-style links
  • No link updates needed for simple folder moves (Obsidian links work by name)
  • Preserves link aliases when updating

Returns:

{ "success": true, "source": "Inbox/Quick Note.md", "destination": "Projects/Project Plan.md", "renamed": true, "details": { "links_updated": 5, "notes_updated": 3 } }

rename_note

Rename a note and automatically update all references to it throughout your vault.

Parameters:

  • old_path: Current path of the note
  • new_path: New path for the note (must be in same directory)
  • update_links (default: true): Automatically update all wiki-style links

Returns:

{ "success": true, "old_path": "Projects/Old Name.md", "new_path": "Projects/New Name.md", "operation": "renamed", "details": { "links_updated": 12, "notes_updated": 8, "link_update_details": [ {"note": "Daily/2024-01-15.md", "updates": 2}, {"note": "Ideas/Related.md", "updates": 1} ] } }

Features:

  • Automatically finds and updates all [[wiki-style links]] to the renamed note
  • Preserves link aliases (e.g., [[Old Name|Display Text]] โ†’ [[New Name|Display Text]])
  • Handles various link formats: [[Note]], [[Note.md]], [[Note|Alias]]
  • Shows which notes were updated for transparency
  • Can only rename within the same directory (use move_note to change directories)
move_folder

Move an entire folder and all its contents to a new location.

Parameters:

  • source_folder: Current folder path (e.g., "Projects/Old")
  • destination_folder: New folder path (e.g., "Archive/Projects/Old")
  • update_links (default: true): Update links in other notes (future enhancement)

Returns:

{ "source": "Projects/Completed", "destination": "Archive/2024/Projects", "moved": true, "notes_moved": 15, "folders_moved": 3, "links_updated": 0 }

add_tags

Add tags to a note's frontmatter.

Parameters:

  • path: Path to the note
  • tags: List of tags to add (without # prefix)

Supports hierarchical tags:

  • Simple tags: ["project", "urgent"]
  • Hierarchical tags: ["project/web", "work/meetings/standup"]
  • Mixed: ["urgent", "project/mobile", "status/active"]
update_tags

Update tags on a note - either replace all tags or merge with existing.

Parameters:

  • path: Path to the note
  • tags: New tags to set (without # prefix)
  • merge (default: false): If true, adds to existing tags. If false, replaces all tags

Perfect for AI workflows:

User: "Tell me what this note is about and add appropriate tags" AI: [reads note] "This note is about machine learning research..." AI: [uses update_tags to set tags: ["ai", "research", "neural-networks"]]

remove_tags

Remove tags from a note's frontmatter.

Parameters:

  • path: Path to the note
  • tags: List of tags to remove
get_note_info

Get metadata and statistics about a note without retrieving its full content.

Parameters:

  • path: Path to the note

Returns:

{ "path": "Projects/AI Research.md", "exists": true, "metadata": { "tags": ["ai", "research"], "aliases": [], "frontmatter": {} }, "stats": { "size_bytes": 4523, "word_count": 823, "link_count": 12 } }

Image Management

read_image

View an image from your vault. Images are automatically resized to a maximum width of 800px for optimal display in Claude Desktop.

Parameters:

  • path: Path to the image file (e.g., "Attachments/screenshot.png")

Returns:

  • A resized image object that can be viewed directly in Claude Desktop

Supported formats:

  • PNG, JPG/JPEG, GIF, BMP, WebP
view_note_images

Extract and view all images embedded in a note.

Parameters:

  • path: Path to the note containing images

Returns:

{ "note_path": "Projects/Design Mockups.md", "image_count": 3, "images": [ { "path": "Attachments/mockup1.png", "alt_text": "Homepage design", "image": "" } ] }

Use cases:

  • Analyze screenshots and diagrams in your notes
  • Review design mockups and visual documentation
  • Extract visual information for AI analysis
list_tags

List all unique tags used across your vault with usage statistics.

Parameters:

  • include_counts (default: true): Include usage count for each tag
  • sort_by (default: "name"): Sort by "name" or "count"

Returns:

{ "total_tags": 25, "tags": [ {"name": "project", "count": 42}, {"name": "project/web", "count": 15}, {"name": "project/mobile", "count": 8}, {"name": "meeting", "count": 38}, {"name": "idea", "count": 15} ] }

Note: Hierarchical tags are listed as separate entries, showing both parent and full paths.

Performance Notes:

  • Fast for small vaults (<1000 notes)
  • May take several seconds for large vaults
  • Uses concurrent batching for optimization

Link Management

โšก Performance Note: Link management tools have been heavily optimized in v1.1.5:

  • 84x faster link validity checking
  • 96x faster broken link detection
  • 2x faster backlink searches
  • Includes automatic caching and batch processing
get_backlinks

Find all notes that link to a specific note.

Parameters:

  • path: Path to the note to find backlinks for
  • include_context (default: true): Whether to include text context around links
  • context_length (default: 100): Number of characters of context to include

Returns:

{ "target_note": "Projects/AI Research.md", "backlink_count": 5, "backlinks": [ { "source_path": "Daily/2024-01-15.md", "link_text": "AI Research", "link_type": "wiki", "context": "...working on the [[AI Research]] project today..." } ] }

Use cases:

  • Understanding which notes reference a concept or topic
  • Discovering relationships between notes
  • Building a mental map of note connections
get_outgoing_links

List all links from a specific note.

Parameters:

  • path: Path to the note to extract links from
  • check_validity (default: true): Whether to check if linked notes exist and get resolved file paths

Returns:

{ "source_note": "Projects/Overview.md", "link_count": 8, "links": [ { "target": "AI Research", "display_text": "AI Research", "type": "wiki", "exists": true, "file_path": "Projects/AI Research.md" } ] }

Use cases:

  • Understanding what a note references
  • Checking note dependencies before moving/deleting
  • Exploring the structure of index or hub notes
get_backlinks

Find all notes that link to a specific note (incoming links).

Parameters:

  • path: Path to the target note
  • include_context (default: true): Include surrounding text context
  • context_length (default: 100): Characters of context to include

Returns:

{ "target_note": "Projects/My Project.md", "backlink_count": 3, "backlinks": [ { "source_path": "Daily/2024-01-15.md", "target": "My Project", "display_text": "My Project", "link_type": "wiki", "context": "...working on [[My Project]] today..." } ] }

Use cases:

  • Understanding which notes reference a concept or topic
  • Discovering relationships between notes
  • Building a mental map of note connections
find_broken_links

Find all broken links in the vault, a specific directory, or a single note.

Parameters:

  • directory (optional): Specific directory to check (defaults to entire vault)
  • single_note (optional): Check only this specific note for broken links

Returns:

{ "directory": "/", "broken_link_count": 3, "affected_notes": 2, "broken_links": [ { "source_path": "Projects/Overview.md", "broken_link": "Projects/Old Name.md", "display_text": "Old Project", "link_type": "wiki" } ] }

Use cases:

  • After renaming or deleting notes
  • Regular vault maintenance
  • Before reorganizing folder structure

Testing

Running Tests

# Run all tests python tests/run_tests.py # Or with pytest directly pytest tests/

Tests create temporary vaults for isolation and don't require a running Obsidian instance.

Testing with MCP Inspector

  1. Set your vault path:

    export OBSIDIAN_VAULT_PATH="/path/to/your/vault"

  2. Run the MCP Inspector:

    npx @modelcontextprotocol/inspector python -m obsidian_mcp.server

  3. Open the Inspector UI at http://localhost:5173

  4. Test the tools interactively with your actual vault

Integration with Claude Desktop

For development installations, see the Development Installation section above.

Enhanced Error Handling

The server provides detailed, actionable error messages to help AI systems recover from errors:

Example Error Messages

Invalid Path:

Invalid note path: '../../../etc/passwd'. Valid paths must: 1) End with .md or .markdown, 2) Use forward slashes (e.g., 'folder/note.md'), 3) Not contain '..' or start with '/', 4) Not exceed 255 characters. Example: 'Daily/2024-01-15.md' or 'Projects/My Project.md'

Empty Search Query:

Search query cannot be empty. Valid queries: 1) Keywords: 'machine learning', 2) Tags: 'tag:#project', 3) Paths: 'path:Daily/', 4) Combined: 'tag:#urgent TODO'

Invalid Date Parameters:

Invalid date_type: 'invalid'. Must be either 'created' or 'modified'. Use 'created' to find notes by creation date, 'modified' for last edit date

Troubleshooting

"Vault not found" error

  • Ensure the OBSIDIAN_VAULT_PATH environment variable is set correctly
  • Verify the path points to an existing Obsidian vault directory
  • Check that you have read/write permissions for the vault directory

Tags not showing up

  • Ensure tags are properly formatted (with or without # prefix)
  • Tags in frontmatter should be in YAML array format: tags: [tag1, tag2]
  • Inline tags should use the # prefix: #project #urgent
  • Tags inside code blocks are automatically excluded

"File too large" error

  • The server has a 10MB limit for note files and 50MB for images
  • This prevents memory issues with very large files
  • Consider splitting large notes into smaller ones

"Module not found" error

  • Ensure your virtual environment is activated
  • Run from the project root: python -m obsidianpilot.server
  • Verify all dependencies are installed: pip install -r requirements.txt

Empty results when listing notes

  • Specify a directory when using list_notes (e.g., "Daily", "Projects")
  • Root directory listing requires recursive implementation
  • Check if notes are in subdirectories

Tags not updating

  • Ensure notes have YAML frontmatter section for frontmatter tags
  • Frontmatter must include a tags: field (even if empty)
  • The server now properly reads both frontmatter tags and inline hashtags

Best Practices for AI Assistants

Preventing Data Loss

  1. Always read before updating: The update_note tool REPLACES content by default
  2. Use append mode for additions: When adding to existing notes, use merge_strategy="append"
  3. Check note existence: Use read_note to verify a note exists before modifying
  4. Be explicit about overwrites: Only use overwrite=true when intentionally replacing content

Recommended Workflows

Safe note editing:

  1. Read the existing note first
  2. Modify the content as needed
  3. Update with the complete new content

Adding to daily notes:

  • Use merge_strategy="append" to add entries without losing existing content
  • Use edit_note_section to add content to specific sections (like "## Tasks" or "## Notes")

Creating new notes:

  • Use create_note with overwrite=false (default) to prevent accidental overwrites
  • Add relevant tags to maintain organization
  • Use list_tags to see existing tags and avoid creating duplicates

Organizing with tags:

  • Check existing tags with list_tags before creating new ones
  • Maintain consistent naming (e.g., use "project" not "projects")
  • Use tags to enable powerful search and filtering

Security Considerations

  • Vault path access - The server only accesses the specified vault directory
  • The server validates all paths to prevent directory traversal attacks
  • File operations are restricted to the vault directory
  • Large files are rejected to prevent memory exhaustion
  • Path validation prevents access to system files

Development

Code Style

  • Uses FastMCP framework for MCP implementation
  • Pydantic models for type safety and validation
  • Modular architecture with separated concerns
  • Comprehensive error handling and user-friendly messages

Adding New Tools

  1. Create tool function in appropriate module under src/tools/
  2. Add Pydantic models if needed in src/models/
  3. Register the tool in src/server.py with the @mcp.tool() decorator
  4. Include comprehensive docstrings
  5. Add tests in tests/
  6. Test with MCP Inspector before deploying

Changelog

v2.0.3 (2025-06-27)

  • โœ๏ธ Token-efficient section editing - New edit_note_section tool for precise content insertion and updates
  • ๐ŸŽฏ Five edit operations - Insert before/after headings, replace sections, append to sections, or edit headings only
  • ๐Ÿ“ Smart section detection - Case-insensitive markdown heading matching with hierarchy support
  • ๐Ÿ”ง Create missing sections - Optionally create sections if they don't exist
  • ๐Ÿ“ Preserve note structure - Edit specific parts without rewriting entire notes
  • ๐Ÿ” Precise text replacement - New edit_note_content tool for exact text search and replace
  • ๐Ÿ›ก๏ธ Frontmatter preservation - Automatically detects and maintains YAML frontmatter during all edits
  • ๐Ÿ› FastMCP compatibility - Fixed deprecated import warnings and updated dependencies
  • ๐Ÿ“š Windows setup guide - Comprehensive installation instructions for Windows environments

v2.0.2 (2025-01-24)

  • ๐ŸŽฏ Simplified architecture - Removed memory index, SQLite is now the only search method
  • ๐Ÿ” Search transparency - Added metadata to search results (total_count, truncated, limit)
  • โš™๏ธ Configurable search limits - Exposed max_results parameter (1-500, default 50)
  • ๐Ÿงน Reduced tool clutter - Removed unnecessary index management tools
  • ๐Ÿ“ Reasoning-friendly improvements - Enhanced all tools with proper Field annotations and comprehensive docstrings
  • ๐Ÿš€ Better AI reasoning - Added "When to use" and "When NOT to use" sections to all tools
  • โšก Performance notes - Added explicit performance guidance for expensive operations
  • ๐Ÿ”ง Cleaner codebase - Removed ~500 lines of memory index code, reducing maintenance burden

v2.0.0 (2025-01-24)

  • ๐Ÿš€ Complete architecture overhaul - Migrated from REST API to direct filesystem access
  • โšก 5x faster searches with persistent SQLite indexing that survives between sessions
  • ๐Ÿ–ผ๏ธ Image support - View and analyze images from your vault with automatic resizing
  • ๐Ÿ” Regex power search - Find complex patterns with optimized streaming
  • ๐Ÿ—‚๏ธ Property search - Query notes by frontmatter properties with advanced operators
  • ๐ŸŽฏ One-command setup - Auto-configure Claude Desktop with uvx --from ObsidianPilot ObsidianPilot-configure
  • ๐Ÿ“ฆ 90% less memory usage - Efficient streaming architecture
  • ๐Ÿ”„ No plugins required - Works offline without needing Obsidian to be running
  • โœจ Incremental indexing - Only re-indexes changed files
  • ๐Ÿ”ง Migration support - Automatically detects and migrates old REST API configs
  • ๐Ÿท๏ธ Enhanced hierarchical tag support - Full support for Obsidian's nested tag system
    • Search parent tags to find all children (e.g., tag:project finds project/web)
    • Search child tags across any hierarchy (e.g., tag:web finds project/web, design/web)
    • Exact hierarchical matching (e.g., tag:project/web)
  • ๐Ÿ” Improved metadata handling - Better alignment with Obsidian's property system
    • Automatic migration of legacy properties (tagโ†’tags, aliasโ†’aliases)
    • Array/list property searching (find items within arrays)
    • Date property comparisons with ISO format support
    • Numeric comparisons for array lengths
  • ๐Ÿ“ AI-friendly tool definitions - Updated all tool descriptions for better LLM understanding
    • Added hierarchical tag examples to all tag-related tools
    • Enhanced property search documentation
    • Clearer parameter descriptions following MCP best practices

v1.1.8 (2025-01-15)

  • ๐Ÿ”ง Fixed FastMCP compatibility issue that prevented PyPI package from running
  • ๐Ÿ“ฆ Updated to FastMCP 2.8.1 for better stability
  • ๐Ÿ› Fixed Pydantic V2 deprecation warnings (migrated to @field_validator)
  • โœจ Changed FastMCP initialization to use 'instructions' parameter
  • ๐Ÿš€ Improved compatibility with uvx and pipx installation methods

v1.1.7 (2025-01-10)

  • ๐Ÿ”„ Changed default API endpoint to HTTP (http://127.0.0.1:27123) for easier setup
  • ๐Ÿ“ Updated documentation to reflect HTTP as default, HTTPS as optional
  • ๐Ÿ”ง Added note about automatic trailing slash handling in URLs
  • โœจ Improved first-time user experience with zero-configuration setup

v1.1.6 (2025-01-10)

  • ๐Ÿ› Fixed timeout errors when creating or updating large notes
  • โšก Added graceful timeout handling for better reliability with large content
  • ๐Ÿ”ง Improved error reporting to prevent false failures on successful operations

v1.1.5 (2025-01-09)

  • โšก Massive performance optimization for link management:
    • 84x faster link validity checking
    • 96x faster broken link detection
    • 2x faster backlink searches
    • Added automatic caching and batch processing
  • ๐Ÿ”ง Optimized concurrent operations for large vaults
  • ๐Ÿ“ Enhanced documentation for performance considerations

v1.1.4 (2025-01-09)

  • ๐Ÿ”— Added link management tools for comprehensive vault analysis:
    • get_backlinks - Find all notes linking to a specific note
    • get_outgoing_links - List all links from a note with validity checking
    • find_broken_links - Identify broken links for vault maintenance
  • ๐Ÿ”ง Fixed URL construction to support both HTTPS (default) and HTTP endpoints
  • ๐Ÿ“ Enhanced link parsing to handle both wiki-style and markdown links
  • โšก Optimized backlink search to handle various path formats

v1.1.3 (2025-01-09)

  • ๐Ÿ› Fixed search_by_date to properly find notes modified today (days_ago=0)
  • โœจ Added list_folders tool for exploring vault folder structure
  • โœจ Added create_folder tool that creates full folder hierarchies
  • โœจ Added move_folder tool for bulk folder operations
  • โœจ Added update_tags tool for AI-driven tag management
  • ๐Ÿ› Fixed tag reading to properly handle both frontmatter and inline hashtags
  • โœจ Added list_tags tool to discover existing tags with usage statistics
  • โšก Optimized performance with concurrent batching for large vaults
  • ๐Ÿ“ Improved documentation and error messages following MCP best practices
  • ๐ŸŽฏ Enhanced create_note to encourage tag usage for better organization

v1.1.2 (2025-01-09)

  • Fixed PyPI package documentation

v1.1.1 (2025-01-06)

  • Initial PyPI release

Publishing (for maintainers)

To publish a new version to PyPI:

# 1. Update version in pyproject.toml # 2. Clean old builds rm -rf dist/ build/ *.egg-info/ # 3. Build the package python -m build # 4. Check the package twine check dist/* # 5. Upload to PyPI twine upload dist/* -u __token__ -p $PYPI_API_KEY # 6. Create and push git tag git tag -a v2.0.2 -m "Release version 2.0.2" git push origin v2.0.2

Users can then install and run with:

# Using uvx (recommended - no installation needed) uvx ObsidianPilot # Or install globally with pipx pipx install ObsidianPilot ObsidianPilot # Or with pip pip install ObsidianPilot ObsidianPilot

Configuration

Performance and Indexing

The server now includes a persistent search index using SQLite for dramatically improved performance:

Key Features:
  • Instant startup - No need to rebuild index on every server start
  • Incremental updates - Only re-indexes files that have changed
  • 60x faster searches - SQLite queries are much faster than scanning all files
  • Lower memory usage - Files are loaded on-demand rather than all at once
Configuration Options:

Set these environment variables to customize behavior:

# Set logging level (default: INFO, options: DEBUG, INFO, WARNING, ERROR) export OBSIDIAN_LOG_LEVEL=DEBUG

The search index is stored in your vault at .obsidian/mcp-search-index.db.

Performance Notes

  • Search indexing - With persistent index, only changed files are re-indexed
  • Concurrent operations - File operations use async I/O for better performance
  • Large vaults - Incremental indexing makes large vaults (10,000+ notes) usable
  • Image handling - Images are automatically resized to prevent memory issues

Migration from REST API Version

If you were using a previous version that required the Local REST API plugin:

  1. You no longer need the Obsidian Local REST API plugin - This server now uses direct filesystem access
  2. Replace OBSIDIAN_REST_API_KEY with OBSIDIAN_VAULT_PATH in your configuration
  3. Remove any OBSIDIAN_API_URL settings
  4. The new version is significantly faster and more reliable
  5. All features work offline without requiring Obsidian to be running

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-tool)
  3. Write tests for new functionality
  4. Ensure all tests pass
  5. Commit your changes (git commit -m 'Add amazing tool')
  6. Push to the branch (git push origin feature/amazing-tool)
  7. Open a Pull Request

License

MIT License - see LICENSE file for details

Acknowledgments

  • Nate Strong for creating the original obsidian-mcp foundation that made ObsidianPilot possible
  • Anthropic for creating the Model Context Protocol
  • Obsidian team for the amazing note-taking app
  • coddingtonbear for the original Local REST API plugin (no longer required)
  • dsp-ant for the FastMCP framework

About

MCP Server for Obsidian

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Python 95.4%
  • PowerShell 3.4%
  • Shell 1.2%
โšก