Files
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

13 KiB

Tool Schemas

Purpose: Define input/output schemas for all MCP tools exposed by the Obsidian bundle

Tool Naming Convention

All tools use prefix obsidian_ followed by the operation:

  • obsidian_create_note
  • obsidian_search
  • obsidian_list_tasks

This prevents naming conflicts with other MCP servers.

Priority 1 Tools: File Operations (15 tools)

obsidian_create_note

Description: Create a new note in the vault

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Note name (without .md extension) or exact path",
      "minLength": 1,
      "maxLength": 255
    },
    "path": {
      "type": "string",
      "description": "Optional: Directory path within vault"
    },
    "content": {
      "type": "string",
      "description": "Initial note content (markdown)"
    },
    "template": {
      "type": "string",
      "description": "Template name to use"
    },
    "overwrite": {
      "type": "boolean",
      "description": "Overwrite if file exists (default: false)"
    },
    "open": {
      "type": "boolean",
      "description": "Open file after creating (default: false)"
    }
  },
  "required": ["name"]
}

Output Example:

{
  "success": true,
  "data": {
    "path": "Projects/Meeting Notes.md",
    "created": true,
    "opened": false
  }
}

obsidian_read_note

Description: Read the contents of a note

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {
      "type": "string",
      "description": "Note name (wikilink-style resolution)"
    },
    "path": {
      "type": "string",
      "description": "Exact path to note"
    }
  },
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

Output Example:

{
  "success": true,
  "data": {
    "path": "Projects/Meeting Notes.md",
    "content": "# Meeting Notes\n\n- Agenda item 1\n- Agenda item 2",
    "size": 52,
    "modified": "2026-03-22T15:30:00Z"
  }
}

obsidian_append_to_note

Description: Append content to a note

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string"},
    "path": {"type": "string"},
    "content": {
      "type": "string",
      "description": "Content to append (required)"
    },
    "inline": {
      "type": "boolean",
      "description": "Append without newline (default: false)"
    }
  },
  "required": ["content"],
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

obsidian_delete_note

Description: Delete a note (moves to trash by default)

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string"},
    "path": {"type": "string"},
    "permanent": {
      "type": "boolean",
      "description": "Skip trash, delete permanently (default: false)"
    }
  },
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

obsidian_move_note

Description: Move or rename a note

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string"},
    "path": {"type": "string"},
    "to": {
      "type": "string",
      "description": "Destination folder or full path (required)"
    }
  },
  "required": ["to"],
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

Priority 2 Tools: Search & Discovery (20 tools)

Description: Search vault for text

Input Schema:

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Search query (required)"
    },
    "folder": {
      "type": "string",
      "description": "Limit search to specific folder"
    },
    "limit": {
      "type": "number",
      "description": "Maximum number of results"
    },
    "caseSensitive": {
      "type": "boolean",
      "description": "Case-sensitive search (default: false)"
    }
  },
  "required": ["query"]
}

Output Example:

{
  "success": true,
  "data": {
    "query": "machine learning",
    "matchCount": 5,
    "files": [
      {"path": "Research/AI Notes.md", "matches": 3},
      {"path": "Projects/ML Project.md", "matches": 2}
    ]
  }
}

Description: List backlinks to a note

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string"},
    "path": {"type": "string"},
    "counts": {
      "type": "boolean",
      "description": "Include link counts (default: false)"
    }
  },
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

Output Example:

{
  "success": true,
  "data": {
    "target": "Projects/ML Project.md",
    "backlinks": [
      {"source": "Research/AI Notes.md", "count": 2},
      {"source": "Weekly Review.md", "count": 1}
    ],
    "totalBacklinks": 2
  }
}

obsidian_list_tags

Description: List tags in the vault or specific file

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string", "description": "Limit to specific file"},
    "path": {"type": "string", "description": "Limit to specific path"},
    "counts": {
      "type": "boolean",
      "description": "Include occurrence counts (default: false)"
    },
    "sortBy": {
      "type": "string",
      "enum": ["name", "count"],
      "description": "Sort order (default: name)"
    }
  }
}

Output Example:

{
  "success": true,
  "data": {
    "tags": [
      {"name": "project", "count": 15},
      {"name": "important", "count": 8},
      {"name": "todo", "count": 5}
    ],
    "totalTags": 3
  }
}

Priority 3 Tools: Tasks & Properties (15 tools)

obsidian_list_tasks

Description: List tasks in the vault or specific file

Input Schema:

{
  "type": "object",
  "properties": {
    "file": {"type": "string"},
    "path": {"type": "string"},
    "status": {
      "type": "string",
      "enum": ["todo", "done", "all"],
      "description": "Filter by status (default: all)"
    },
    "verbose": {
      "type": "boolean",
      "description": "Group by file with line numbers (default: false)"
    }
  }
}

Output Example:

{
  "success": true,
  "data": {
    "tasks": [
      {
        "ref": "Projects/TODO.md:5",
        "file": "Projects/TODO.md",
        "line": 5,
        "text": "Finish documentation",
        "status": "",
        "done": false
      },
      {
        "ref": "Weekly Review.md:12",
        "file": "Weekly Review.md",
        "line": 12,
        "text": "Review PRs",
        "status": "x",
        "done": true
      }
    ],
    "totalTasks": 2
  }
}

obsidian_toggle_task

Description: Toggle a task's completion status

Input Schema:

{
  "type": "object",
  "properties": {
    "ref": {
      "type": "string",
      "description": "Task reference (path:line)"
    },
    "file": {"type": "string"},
    "path": {"type": "string"},
    "line": {
      "type": "number",
      "description": "Line number (1-indexed)"
    }
  },
  "oneOf": [
    {"required": ["ref"]},
    {"required": ["file", "line"]},
    {"required": ["path", "line"]}
  ]
}

obsidian_set_property

Description: Set a property value on a note

Input Schema:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Property name (required)"
    },
    "value": {
      "description": "Property value (required, type: string|number|boolean|array)"
    },
    "type": {
      "type": "string",
      "enum": ["text", "number", "checkbox", "date", "datetime", "list"],
      "description": "Property type (optional, inferred from value)"
    },
    "file": {"type": "string"},
    "path": {"type": "string"}
  },
  "required": ["name", "value"],
  "oneOf": [{"required": ["file"]}, {"required": ["path"]}]
}

Priority 4 Tools: Vault Navigation (15 tools)

obsidian_list_files

Description: List files in the vault

Input Schema:

{
  "type": "object",
  "properties": {
    "folder": {
      "type": "string",
      "description": "Filter by folder"
    },
    "extension": {
      "type": "string",
      "description": "Filter by extension (e.g., 'md')"
    }
  }
}

obsidian_get_vault_info

Description: Get vault statistics

Input Schema:

{
  "type": "object",
  "properties": {
    "info": {
      "type": "string",
      "enum": ["name", "path", "files", "folders", "size", "all"],
      "description": "Specific info to return (default: all)"
    }
  }
}

Output Example:

{
  "success": true,
  "data": {
    "name": "My Vault",
    "path": "/Users/user/Documents/Obsidian/My Vault",
    "fileCount": 1234,
    "folderCount": 56,
    "totalSize": 5242880
  }
}

Priority 5 Tools: Advanced Features (30 tools)

obsidian_daily_append

Description: Append content to today's daily note

Input Schema:

{
  "type": "object",
  "properties": {
    "content": {
      "type": "string",
      "description": "Content to append (required)"
    },
    "inline": {
      "type": "boolean",
      "description": "Append without newline (default: false)"
    },
    "open": {
      "type": "boolean",
      "description": "Open daily note after appending (default: false)"
    }
  },
  "required": ["content"]
}

obsidian_list_templates

Description: List available templates

Input Schema:

{
  "type": "object",
  "properties": {}
}

obsidian_list_plugins

Description: List installed plugins

Input Schema:

{
  "type": "object",
  "properties": {
    "filter": {
      "type": "string",
      "enum": ["core", "community", "all"],
      "description": "Filter by plugin type (default: all)"
    },
    "enabledOnly": {
      "type": "boolean",
      "description": "Show only enabled plugins (default: false)"
    },
    "includeVersions": {
      "type": "boolean",
      "description": "Include version numbers (default: false)"
    }
  }
}

Complete Tool List (95 tools)

File Operations (15)

  1. obsidian_create_note
  2. obsidian_read_note
  3. obsidian_append_to_note
  4. obsidian_prepend_to_note
  5. obsidian_delete_note
  6. obsidian_move_note
  7. obsidian_rename_note
  8. obsidian_open_note
  9. obsidian_get_file_info
  10. obsidian_list_recents
  11. obsidian_get_outline
  12. obsidian_get_wordcount
  13. obsidian_random_note
  14. obsidian_open_file
  15. obsidian_list_orphans

Search & Discovery (20)

  1. obsidian_search
  2. obsidian_search_with_context
  3. obsidian_get_backlinks
  4. obsidian_get_outgoing_links
  5. obsidian_list_unresolved_links
  6. obsidian_list_tags
  7. obsidian_get_tag_info
  8. obsidian_list_aliases
  9. obsidian_list_properties
  10. obsidian_get_property_count
  11. obsidian_list_deadends
  12. obsidian_list_files
  13. obsidian_list_folders
  14. obsidian_get_folder_info
  15. obsidian_get_vault_info
  16. obsidian_list_vaults
  17. obsidian_open_search
  18. obsidian_get_version
  19. obsidian_reload_vault
  20. obsidian_list_workspace_tabs

Tasks & Properties (15)

  1. obsidian_list_tasks
  2. obsidian_toggle_task
  3. obsidian_mark_task_done
  4. obsidian_mark_task_todo
  5. obsidian_update_task_status
  6. obsidian_get_property
  7. obsidian_set_property
  8. obsidian_remove_property
  9. obsidian_list_note_properties
  10. obsidian_list_vault_properties
  11. obsidian_daily_tasks
  12. obsidian_active_file_tasks
  13. obsidian_active_file_properties
  14. obsidian_active_file_tags
  15. obsidian_active_file_aliases

Daily Notes (6)

  1. obsidian_open_daily_note
  2. obsidian_daily_append
  3. obsidian_daily_prepend
  4. obsidian_daily_read
  5. obsidian_daily_path
  6. obsidian_random_read

Templates & Bookmarks (8)

  1. obsidian_list_templates
  2. obsidian_read_template
  3. obsidian_insert_template
  4. obsidian_create_bookmark
  5. obsidian_list_bookmarks
  6. obsidian_bookmark_file
  7. obsidian_bookmark_search
  8. obsidian_bookmark_url

Plugins & Themes (12)

  1. obsidian_list_plugins
  2. obsidian_list_enabled_plugins
  3. obsidian_get_plugin_info
  4. obsidian_enable_plugin
  5. obsidian_disable_plugin
  6. obsidian_list_themes
  7. obsidian_get_active_theme
  8. obsidian_set_theme
  9. obsidian_list_css_snippets
  10. obsidian_enable_snippet
  11. obsidian_disable_snippet
  12. obsidian_restricted_mode_status

File History & Sync (12)

  1. obsidian_list_file_versions
  2. obsidian_read_version
  3. obsidian_restore_version
  4. obsidian_list_files_with_history
  5. obsidian_open_history
  6. obsidian_list_sync_versions
  7. obsidian_read_sync_version
  8. obsidian_restore_sync_version
  9. obsidian_get_sync_status
  10. obsidian_pause_sync
  11. obsidian_resume_sync
  12. obsidian_list_sync_deleted

Bases & Commands (7)

  1. obsidian_list_bases
  2. obsidian_list_base_views
  3. obsidian_query_base
  4. obsidian_create_base_item
  5. obsidian_list_commands
  6. obsidian_execute_command
  7. obsidian_get_hotkey

Error Response Format

All tools return errors in consistent structure:

{
  "success": false,
  "error": {
    "code": "OBSIDIAN_NOT_RUNNING",
    "message": "Obsidian application is not running. Please start Obsidian and try again.",
    "details": {
      "attempted": "create_note",
      "file": "Meeting Notes.md"
    }
  }
}

Validation Rules

All input schemas enforce:

  • String min/max lengths
  • Required fields
  • Enum constraints for predefined values
  • Type coercion where safe
  • Sanitization of special characters before CLI execution