Files
obsidian-mcp-server/IMPLEMENTATION_NOTES_PHASE5.md
Bill 7e5a6a8c3c Phase 5 Complete: Advanced Read Operations with Excalidraw Support
- Enhanced read_note tool with frontmatter parsing options
  - parseFrontmatter option to separate frontmatter from content
  - withFrontmatter and withContent options for flexible responses
  - Returns structured ParsedNote JSON when parsing enabled
  - Backward compatible (default behavior unchanged)

- New read_excalidraw tool for Excalidraw file metadata
  - Detects compressed-json format (Excalidraw's actual format)
  - Returns elementCount, hasCompressedData, metadata fields
  - Handles compressed (base64) and uncompressed formats
  - Preview text extraction from Text Elements section
  - Optional full compressed data inclusion

- New frontmatter-utils.ts for YAML parsing
  - Uses Obsidian's built-in parseYaml
  - Extracts and parses frontmatter
  - Handles edge cases (no frontmatter, malformed YAML)
  - Excalidraw metadata parsing with compression detection

- Enhanced type definitions with JSDoc comments
  - ParsedNote interface for structured note data
  - ExcalidrawMetadata interface with detailed field docs
  - Clear documentation of all fields and their purposes

- Comprehensive documentation
  - IMPLEMENTATION_NOTES_PHASE5.md - Implementation details
  - EXCALIDRAW_FIX_SUMMARY.md - Bug fix documentation
  - EXCALIDRAW_TESTING_GUIDE.md - Testing instructions
  - Updated CHANGELOG.md with all changes
  - Updated ROADMAP.md marking Phase 5 complete

- Known limitation documented
  - elementCount returns 0 for compressed files (expected)
  - Decompression would require pako library (not included)
  - hasCompressedData correctly identifies compressed files
  - Preview text still available without decompression
  - Added to roadmap as future enhancement

All manual tests passed. Phase 5 complete and production-ready.
2025-10-16 23:47:19 -04:00

9.0 KiB

Phase 5 Implementation Notes: Advanced Read Operations

Date: October 16, 2025
Status: Complete (Including Manual Testing)
Estimated Effort: 2-3 days
Actual Effort: ~2.5 hours (implementation + testing refinements)

Overview

Phase 5 adds advanced read capabilities to the Obsidian MCP Server, including frontmatter parsing and specialized Excalidraw file support. This phase enhances the read_note tool and introduces a new read_excalidraw tool.

Goals Achieved

Enhanced read_note tool with frontmatter parsing options
Created frontmatter utilities for YAML parsing
Added specialized Excalidraw file support
Maintained backward compatibility
Added comprehensive type definitions

Implementation Details

1. Frontmatter Utilities (src/utils/frontmatter-utils.ts)

Created a new utility class for handling frontmatter operations:

Key Methods:

  • extractFrontmatter(content: string) - Extracts and parses YAML frontmatter

    • Detects frontmatter delimiters (--- or ...)
    • Separates frontmatter from content
    • Parses YAML using Obsidian's built-in parseYaml
    • Handles malformed YAML gracefully
  • extractFrontmatterSummary(parsedFrontmatter) - Extracts common fields

    • Normalizes title, tags, aliases fields
    • Includes custom fields
    • Returns null if no frontmatter
  • hasFrontmatter(content: string) - Quick check for frontmatter presence

  • parseExcalidrawMetadata(content: string) - Parses Excalidraw files

    • Detects Excalidraw plugin markers
    • Extracts JSON from code blocks
    • Counts drawing elements
    • Identifies compressed data

Edge Cases Handled:

  • Files without frontmatter
  • Malformed YAML (returns null for parsed data)
  • Missing closing delimiter
  • Empty frontmatter blocks
  • Non-Excalidraw files

2. Type Definitions (src/types/mcp-types.ts)

Added new types for Phase 5:

export interface ParsedNote {
  path: string;
  hasFrontmatter: boolean;
  frontmatter?: string;
  parsedFrontmatter?: Record<string, any>;
  content: string;
  contentWithoutFrontmatter?: string;
}

export interface ExcalidrawMetadata {
  path: string;
  isExcalidraw: boolean;
  elementCount?: number;
  hasCompressedData?: boolean;
  metadata?: Record<string, any>;
  preview?: string;
  compressedData?: string;
}

3. Enhanced read_note Tool

New Parameters:

  • withFrontmatter (boolean, default: true) - Include frontmatter in response
  • withContent (boolean, default: true) - Include full content
  • parseFrontmatter (boolean, default: false) - Parse and structure frontmatter

Behavior:

  • Default (parseFrontmatter: false): Returns raw file content as plain text (backward compatible)
  • With parseFrontmatter: true: Returns structured ParsedNote JSON object

Example Usage:

// Simple read (backward compatible)
read_note({ path: "note.md" })
// Returns: raw content as text

// Parse frontmatter
read_note({ 
  path: "note.md", 
  parseFrontmatter: true 
})
// Returns: ParsedNote JSON with separated frontmatter

// Get only frontmatter
read_note({ 
  path: "note.md", 
  parseFrontmatter: true,
  withContent: false 
})
// Returns: ParsedNote with only frontmatter, no content

4. New read_excalidraw Tool

Specialized tool for Excalidraw drawing files.

Parameters:

  • path (string, required) - Path to Excalidraw file
  • includeCompressed (boolean, default: false) - Include full drawing data
  • includePreview (boolean, default: true) - Include text elements preview

Features:

  • Validates file is an Excalidraw drawing
  • Extracts metadata (element count, version, appState)
  • Provides text preview without full data
  • Optional full compressed data inclusion

Example Usage:

// Get metadata and preview
read_excalidraw({ path: "drawing.excalidraw.md" })
// Returns: ExcalidrawMetadata with preview

// Get full drawing data
read_excalidraw({ 
  path: "drawing.excalidraw.md",
  includeCompressed: true 
})
// Returns: ExcalidrawMetadata with full compressed data

5. Tool Registry Updates (src/tools/index.ts)

Updated read_note schema:

  • Added three new optional parameters
  • Updated description to mention frontmatter parsing
  • Maintained backward compatibility

Added read_excalidraw tool:

  • New tool definition with comprehensive schema
  • Added case in callTool switch statement
  • Passes options to readExcalidraw method

Files Modified

  1. Created:

    • src/utils/frontmatter-utils.ts - Frontmatter parsing utilities
  2. Modified:

    • src/types/mcp-types.ts - Added ParsedNote and ExcalidrawMetadata types
    • src/tools/note-tools.ts - Enhanced readNote, added readExcalidraw
    • src/tools/index.ts - Updated tool definitions and callTool
    • ROADMAP.md - Marked Phase 5 as complete
    • CHANGELOG.md - Added Phase 5 changes

Backward Compatibility

Fully backward compatible

  • Default read_note behavior unchanged (returns raw content)
  • Existing clients continue to work without modifications
  • New features are opt-in via parameters

Testing Results

All manual tests completed successfully with the following refinements implemented based on feedback:

Improvements Made Post-Testing

  1. Enhanced Error Handling for Excalidraw Files

    • Non-Excalidraw files now return structured response with isExcalidraw: false
    • Added helpful message: "File is not an Excalidraw drawing. Use read_note instead for regular markdown files."
    • Changed from error response to graceful structured response
  2. Comprehensive Documentation

    • Enhanced tool schema description with all return fields documented
    • Detailed parameter descriptions for includeCompressed and includePreview
    • Clear explanation of what data is included in each field
  3. Full Metadata Exposure Verified

    • elementCount - Count of drawing elements
    • hasCompressedData - Boolean for compressed data presence
    • metadata - Object with appState and version
    • preview - Text elements (when requested)
    • compressedData - Full drawing data (when requested)

Test Cases Validated

Manual testing was performed for:

  1. Frontmatter Parsing:

    • Notes with valid YAML frontmatter
    • Notes without frontmatter
    • Notes with malformed YAML
    • Various YAML formats (arrays, objects, nested)
    • Empty frontmatter blocks
  2. Parameter Combinations:

    • parseFrontmatter: true with various options
    • withFrontmatter: false + withContent: true
    • withFrontmatter: true + withContent: false
    • All parameters at default values
  3. Excalidraw Support:

    • Valid Excalidraw files
    • Non-Excalidraw markdown files (graceful handling)
    • Excalidraw files with/without compressed data
    • Preview text extraction
    • Full data inclusion
    • Metadata field exposure
    • Compressed format detection (compressed-json code fence)
    • ⚠️ Known Limitation: elementCount returns 0 for compressed files
      • Most Excalidraw files use compressed base64 format
      • Decompression would require pako library (not included)
      • Text elements visible in preview but not counted
      • Use hasCompressedData: true to identify compressed files
  4. Edge Cases:

    • Very large Excalidraw files
    • Files with special characters in frontmatter
    • Files with multiple frontmatter blocks (invalid)
    • Unicode content in frontmatter

All test cases passed successfully.

Benefits

  1. Better Frontmatter Handling

    • Separate frontmatter from content for easier processing
    • Parse YAML into structured objects
    • Access metadata without manual parsing
  2. Excalidraw Support

    • First-class support for Excalidraw drawings
    • Extract metadata without parsing full drawing
    • Optional preview and compressed data
  3. Flexibility

    • Choose what data to include in responses
    • Reduce bandwidth for metadata-only requests
    • Maintain backward compatibility
  4. Type Safety

    • Structured responses with proper TypeScript types
    • Clear interfaces for parsed data
    • Better IDE autocomplete and validation

Next Steps

Phase 5 is complete. Recommended next phases:

  1. Phase 6: Powerful Search (P2, 4-5 days)

    • Regex search support
    • Snippet extraction
    • Advanced filtering
  2. Phase 8: Write Operations & Concurrency (P1, 5-6 days)

    • Partial updates (frontmatter, sections)
    • Concurrency control with ETags
    • File rename/move with link updates
  3. Phase 9: Linking & Backlinks (P2, 3-4 days)

    • Wikilink validation
    • Backlink queries
    • Link resolution

Notes

  • Uses Obsidian's built-in parseYaml for YAML parsing
  • Frontmatter extraction follows Obsidian's conventions
  • Excalidraw detection uses plugin markers
  • All error cases return clear error messages
  • Implementation is efficient (no unnecessary file reads)

Version

This implementation is part of version 4.0.0 of the Obsidian MCP Server plugin.