Files
obsidian-mcp/specs/001-obsidian-mcp-bundle/data-model.md
Peter.Morton 622b28e42c feat: implement Obsidian MCP Bundle MVP (Phase 1-3)
- Complete project setup with TypeScript, Jest, MCPB manifest
- Implement foundational infrastructure (CLI executor, logger, error handler)
- Add 9 file operation tools for User Story 1
- Full MCP protocol compliance with stdio transport
- Input validation and sanitization for security
- Comprehensive error handling with actionable messages
- Constitutional compliance: all 6 principles satisfied

MVP includes:
- obsidian_create_note, read, append, prepend, delete, move, rename, open, file_info
- Zod validation schemas for all parameters
- 30s timeout configuration with per-command overrides
- Stderr-only logging with sanitized output
- Graceful shutdown handling

Build:  0 errors, 0 vulnerabilities
Tasks: 48/167 complete (MVP milestone)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-22 11:21:38 -05:00

11 KiB

Data Model: Obsidian MCP Bundle

Phase: 1 (Design & Contracts)
Date: 2026-03-22
Purpose: Define data structures and their relationships

Overview

This MCP bundle operates on Obsidian's data model (vault, notes, properties, tasks, links, tags). The bundle does NOT maintain its own data store - it provides a typed interface layer over Obsidian CLI operations.

Core Entities

Vault

Description: An Obsidian knowledge base (collection of markdown files and folders)

Attributes:

  • name (string, required): Vault identifier for user configuration
  • path (string, readonly): Filesystem path to vault root
  • fileCount (number, readonly): Total number of files
  • folderCount (number, readonly): Total number of folders
  • size (number, readonly): Total size in bytes

Validation Rules:

  • Name must match an existing Obsidian vault
  • Path must be accessible with read/write permissions

State Transitions: N/A (vault state managed by Obsidian)

CLI Mapping: obsidian vault, obsidian vaults


Note

Description: A markdown file within the vault

Attributes:

  • name (string, required): File name without extension OR exact path
  • path (string, readonly): Full path relative to vault root
  • content (string): File contents (markdown text)
  • size (number, readonly): File size in bytes
  • created (datetime, readonly): Creation timestamp
  • modified (datetime, readonly): Last modification timestamp
  • properties (Property[], readonly): Frontmatter metadata

Validation Rules:

  • Name must be valid filename (no path separators in name-only mode)
  • Path must be within vault (no directory traversal)
  • Name ambiguity: If multiple files match name, require exact path
  • Content must be valid UTF-8 text

Relationships:

  • HAS_MANY Properties (frontmatter)
  • HAS_MANY Tasks (checkbox items)
  • HAS_MANY Links (outgoing)
  • REFERENCED_BY Links (backlinks)
  • HAS_MANY Tags

State Transitions:

  • Created → Exists
  • Exists → Modified (content/properties changed)
  • Exists → Deleted (moved to trash or permanent delete)
  • Deleted → Restored (from history)

CLI Mapping: obsidian create, obsidian read, obsidian file, obsidian delete


Property

Description: Frontmatter metadata key-value pair

Attributes:

  • name (string, required): Property key (alphanumeric, underscores)
  • value (string|number|boolean|date|array, required): Property value
  • type (enum, readonly): text|number|checkbox|date|datetime|list
  • file (string, required): Note path containing this property

Validation Rules:

  • Name must be valid YAML key
  • Value must match type (enforced by Obsidian)
  • List values must be array of strings
  • Date/datetime must be ISO 8601 format

Relationships:

  • BELONGS_TO Note

CLI Mapping: obsidian property:set, obsidian property:read, obsidian property:remove, obsidian properties


Task

Description: Markdown checkbox item with status tracking

Attributes:

  • ref (string, required): Task reference in format "path:line"
  • file (string, required): Note path containing task
  • line (number, required): Line number in file (1-indexed)
  • text (string, readonly): Task description
  • status (string, required): Empty (""), "x" (done), or custom character
  • done (boolean, computed): True if status is "x"

Validation Rules:

  • Line must exist in file
  • Line must contain checkbox syntax: - [ ] or - [x] or - [char]
  • Status character must be single character or empty

Relationships:

  • BELONGS_TO Note
  • MAY_REFERENCE other Notes (via wikilinks in task text)

State Transitions:

  • todo (status="") → done (status="x")
  • done (status="x") → todo (status="")
  • Any status → custom status (status="char")

CLI Mapping: obsidian tasks, obsidian task


Description: Connection between notes (wikilink or markdown link)

Attributes:

  • source (string, required): Source note path
  • target (string, required): Target note name or path
  • type (enum, readonly): wikilink|markdown|unresolved
  • count (number, optional): Number of occurrences (for aggregation)
  • resolved (boolean, readonly): False if target doesn't exist

Validation Rules:

  • Source must be existing note
  • Target format depends on type (wikilink uses [[name]], markdown uses [text](path))

Relationships:

  • ORIGINATES_FROM Note (source)
  • POINTS_TO Note (target, if resolved)

CLI Mapping: obsidian links, obsidian backlinks, obsidian unresolved


Tag

Description: Categorization marker (e.g., #project, #important)

Attributes:

  • name (string, required): Tag without # prefix
  • count (number, optional): Number of occurrences in vault
  • files (string[], optional): Files containing this tag

Validation Rules:

  • Name must start with letter, can contain letters/numbers/hyphens/underscores
  • Case-sensitive
  • Nested tags use slash (e.g., "project/active")

Relationships:

  • APPEARS_IN many Notes

CLI Mapping: obsidian tags, obsidian tag


Alias

Description: Alternative name for a note (defined in frontmatter)

Attributes:

  • alias (string, required): Alternative name
  • file (string, required): Note path this alias refers to

Validation Rules:

  • Alias must be defined in note's frontmatter aliases property

Relationships:

  • BELONGS_TO Note

CLI Mapping: obsidian aliases


Template

Description: Reusable note template

Attributes:

  • name (string, required): Template name/path
  • content (string, readonly): Template content (may include variables)
  • resolved (string, optional): Template with variables resolved

Validation Rules:

  • Name must match existing template file
  • Variables use {{variable}} syntax

CLI Mapping: obsidian templates, obsidian template:read, obsidian template:insert


DailyNote

Description: Special note type for daily journaling

Attributes:

  • date (date, required): Date for the daily note
  • path (string, readonly): Path to daily note file
  • content (string): Daily note content

Validation Rules:

  • Date must be valid ISO date (YYYY-MM-DD)
  • Path follows Obsidian's daily note configuration

Relationships:

  • IS_A Note (special type)

State Transitions:

  • Not created → Created (on first daily:append or daily:prepend)

CLI Mapping: obsidian daily, obsidian daily:read, obsidian daily:append, obsidian daily:prepend, obsidian daily:path


Plugin

Description: Obsidian plugin (core or community)

Attributes:

  • id (string, required): Plugin identifier
  • name (string, readonly): Display name
  • version (string, readonly): Plugin version
  • enabled (boolean, readonly): Activation status
  • type (enum, readonly): core|community

Validation Rules:

  • ID must match installed plugin

CLI Mapping: obsidian plugins, obsidian plugins:enabled, obsidian plugin


Theme

Description: Obsidian visual theme

Attributes:

  • name (string, required): Theme name
  • version (string, readonly): Theme version
  • active (boolean, readonly): Whether currently active

Validation Rules:

  • Name must match installed theme or be empty string for default

CLI Mapping: obsidian themes, obsidian theme, obsidian theme:set


Bookmark

Description: Saved reference to file, folder, search, or URL

Attributes:

  • title (string, required): Bookmark display name
  • type (enum, readonly): file|folder|search|url
  • target (string, required): File path, folder path, search query, or URL

Validation Rules:

  • File/folder targets must exist
  • URLs must be valid HTTP/HTTPS
  • Search queries must be non-empty

CLI Mapping: obsidian bookmarks, obsidian bookmark


Tool Request/Response Schemas

Each MCP tool accepts parameters matching entity attributes and returns structured results.

Common Patterns

Success Response:

{
  success: true,
  data: { /* entity or array of entities */ }
}

Error Response:

{
  success: false,
  error: {
    code: string,    // e.g., "NOTE_NOT_FOUND"
    message: string, // Human-readable error
    details?: unknown // Additional context
  }
}

Parameter Validation

All tool parameters are validated using Zod schemas before CLI execution:

// Example: Create note parameters
{
  name: string (1-255 chars),
  path?: string (valid path),
  content?: string,
  template?: string,
  overwrite?: boolean,
  open?: boolean,
  newtab?: boolean
}

CLI Output Parsing

Obsidian CLI returns data in various formats. The bundle normalizes to JSON:

Format Mapping

  • JSON output → Direct parse
  • TSV output → Parse to array of objects
  • CSV output → Parse to array of objects
  • Text output → Wrap in { raw: string } object
  • Empty output → Return { success: true }

Special Cases

  • Ambiguous file names: CLI returns multiple paths → Error with path list
  • File not found: CLI exits with error code → Map to NOT_FOUND error
  • Obsidian not running: CLI connection fails → Map to OBSIDIAN_NOT_RUNNING error

Data Flow

AI Assistant
    ↓
MCP Tool Call (JSON-RPC)
    ↓
Input Validation (Zod)
    ↓
Parameter Sanitization
    ↓
CLI Command Construction
    ↓
Obsidian CLI Execution (spawn with timeout)
    ↓
Output Parsing (JSON/TSV/CSV/Text)
    ↓
Error Mapping (if needed)
    ↓
Structured Response (JSON)
    ↓
MCP Tool Result (JSON-RPC)
    ↓
AI Assistant

Concurrency & State

  • No shared state: Each tool call is independent
  • Concurrent file modifications: Rely on Obsidian's built-in conflict detection (per clarification)
  • Vault state: Managed entirely by Obsidian (bundle is stateless)
  • CLI commands: Sequential execution per tool call (no parallel CLI commands from single call)

Error Handling

Errors are categorized and mapped to user-friendly messages:

Error Category Code Message Pattern
Obsidian not running OBSIDIAN_NOT_RUNNING "Obsidian application is not running. Please start Obsidian and try again."
Vault not found VAULT_NOT_FOUND "Vault '{name}' not found. Check your vault name in MCP settings."
File not found FILE_NOT_FOUND "Note '{name}' not found. Use exact path or check spelling."
Ambiguous name AMBIGUOUS_NAME "Multiple notes named '{name}' found: {paths}. Please specify exact path."
Permission denied PERMISSION_DENIED "Cannot access {path}. Check file permissions."
Timeout TIMEOUT "Operation took too long (>30s). Try with smaller scope."
Validation error VALIDATION_ERROR "{field} {constraint}" (e.g., "name must be 1-255 characters")
CLI error CLI_ERROR "{original CLI error message}" (for unexpected errors)