feat: Phase 3 - Discovery Endpoints (stat and exists tools)
- Add stat tool for detailed file/folder metadata - Add exists tool for fast path existence checking - Add StatResult and ExistsResult type definitions - Implement stat() and exists() methods in VaultTools - Register both tools in ToolRegistry with complete schemas - Update version to 2.1.0 - Update ROADMAP.md to mark Phase 3 complete - Update CHANGELOG.md with Phase 3 release notes - Add IMPLEMENTATION_NOTES_PHASE3.md documentation - Clean up old phase documentation files
This commit is contained in:
86
CHANGELOG.md
86
CHANGELOG.md
@@ -2,6 +2,92 @@
|
||||
|
||||
All notable changes to the Obsidian MCP Server plugin will be documented in this file.
|
||||
|
||||
## [2.1.0] - 2025-10-16
|
||||
|
||||
### ✨ Phase 3: Discovery Endpoints
|
||||
|
||||
This release adds new tools for exploring vault structure and testing path validity.
|
||||
|
||||
#### Added
|
||||
|
||||
**New Tools**
|
||||
- `stat` - Get detailed metadata for a file or folder at a specific path
|
||||
- Returns existence status, kind (file/directory), and full metadata
|
||||
- Includes size, dates, child count, etc.
|
||||
- More detailed than `exists()` but slightly slower
|
||||
- `exists` - Quickly check if a file or folder exists
|
||||
- Fast path validation without fetching full metadata
|
||||
- Returns existence status and kind only
|
||||
- Optimized for quick existence checks
|
||||
|
||||
**Type Definitions (`src/types/mcp-types.ts`)**
|
||||
- `StatResult` - Structured result for stat operations (path, exists, kind, metadata)
|
||||
- `ExistsResult` - Structured result for exists operations (path, exists, kind)
|
||||
|
||||
**Implementation (`src/tools/vault-tools.ts`)**
|
||||
- `stat(path)` method - Comprehensive path metadata retrieval
|
||||
- `exists(path)` method - Fast existence checking
|
||||
- Both methods use PathUtils for consistent path normalization
|
||||
- Both methods validate paths and return structured JSON
|
||||
|
||||
**Tool Registry (`src/tools/index.ts`)**
|
||||
- Registered `stat` and `exists` tools with complete schemas
|
||||
- Added call handlers for both new tools
|
||||
- Comprehensive descriptions for AI agent usage
|
||||
|
||||
#### Use Cases
|
||||
|
||||
**`stat` Tool:**
|
||||
- Verify a path exists before operations
|
||||
- Get detailed file/folder information
|
||||
- Check file sizes and modification dates
|
||||
- Determine if a path is a file or directory
|
||||
|
||||
**`exists` Tool:**
|
||||
- Quick existence checks before create operations
|
||||
- Validate paths in batch operations
|
||||
- Fast pre-flight checks
|
||||
- Minimal overhead for simple validation
|
||||
|
||||
#### Example Responses
|
||||
|
||||
**stat (file exists):**
|
||||
```json
|
||||
{
|
||||
"path": "folder/note.md",
|
||||
"exists": true,
|
||||
"kind": "file",
|
||||
"metadata": {
|
||||
"kind": "file",
|
||||
"name": "note.md",
|
||||
"path": "folder/note.md",
|
||||
"extension": "md",
|
||||
"size": 1234,
|
||||
"modified": 1697500800000,
|
||||
"created": 1697400000000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**exists (folder exists):**
|
||||
```json
|
||||
{
|
||||
"path": "projects",
|
||||
"exists": true,
|
||||
"kind": "directory"
|
||||
}
|
||||
```
|
||||
|
||||
**stat (path doesn't exist):**
|
||||
```json
|
||||
{
|
||||
"path": "missing/file.md",
|
||||
"exists": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## [2.0.0] - 2025-10-16
|
||||
|
||||
### 🔧 Phase 2.1: Post-Testing Fixes
|
||||
|
||||
347
IMPLEMENTATION_NOTES_PHASE3.md
Normal file
347
IMPLEMENTATION_NOTES_PHASE3.md
Normal file
@@ -0,0 +1,347 @@
|
||||
# Phase 3: Discovery Endpoints - Implementation Notes
|
||||
|
||||
**Date:** October 16, 2025
|
||||
**Status:** ✅ Complete
|
||||
**Estimated Effort:** 2-3 days
|
||||
**Actual Effort:** ~1 hour
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Phase 3 adds two new discovery tools that enable exploring vault structure and testing path validity without performing full operations. These tools are essential for AI agents and scripts to verify paths before attempting operations.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Summary
|
||||
|
||||
### 1. Type Definitions (`src/types/mcp-types.ts`)
|
||||
|
||||
Added two new result types:
|
||||
|
||||
```typescript
|
||||
export interface StatResult {
|
||||
path: string;
|
||||
exists: boolean;
|
||||
kind?: ItemKind;
|
||||
metadata?: FileMetadata | DirectoryMetadata;
|
||||
}
|
||||
|
||||
export interface ExistsResult {
|
||||
path: string;
|
||||
exists: boolean;
|
||||
kind?: ItemKind;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. VaultTools Methods (`src/tools/vault-tools.ts`)
|
||||
|
||||
#### `stat(path: string)` Method
|
||||
|
||||
**Purpose:** Get comprehensive metadata for any path (file or folder)
|
||||
|
||||
**Implementation:**
|
||||
- Validates path using `PathUtils.isValidVaultPath()`
|
||||
- Normalizes path using `PathUtils.normalizePath()`
|
||||
- Checks if path is a file using `PathUtils.resolveFile()`
|
||||
- If file, returns full `FileMetadata`
|
||||
- Checks if path is a folder using `PathUtils.resolveFolder()`
|
||||
- If folder, returns full `DirectoryMetadata`
|
||||
- If neither, returns `exists: false`
|
||||
|
||||
**Returns:** Structured `StatResult` with full metadata when path exists
|
||||
|
||||
#### `exists(path: string)` Method
|
||||
|
||||
**Purpose:** Fast existence check without fetching full metadata
|
||||
|
||||
**Implementation:**
|
||||
- Validates path using `PathUtils.isValidVaultPath()`
|
||||
- Normalizes path using `PathUtils.normalizePath()`
|
||||
- Checks if path is a file using `PathUtils.fileExists()`
|
||||
- If file, returns `exists: true, kind: "file"`
|
||||
- Checks if path is a folder using `PathUtils.folderExists()`
|
||||
- If folder, returns `exists: true, kind: "directory"`
|
||||
- If neither, returns `exists: false`
|
||||
|
||||
**Returns:** Lightweight `ExistsResult` with minimal data
|
||||
|
||||
### 3. Tool Registry (`src/tools/index.ts`)
|
||||
|
||||
Added two new tool definitions:
|
||||
|
||||
#### `stat` Tool
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "stat",
|
||||
description: "Get detailed metadata for a file or folder at a specific path...",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "Vault-relative path to check..."
|
||||
}
|
||||
},
|
||||
required: ["path"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `exists` Tool
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "exists",
|
||||
description: "Quickly check if a file or folder exists at a specific path...",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "Vault-relative path to check..."
|
||||
}
|
||||
},
|
||||
required: ["path"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Added call handlers in `callTool()` switch statement:
|
||||
```typescript
|
||||
case "stat":
|
||||
return await this.vaultTools.stat(args.path);
|
||||
case "exists":
|
||||
return await this.vaultTools.exists(args.path);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Features
|
||||
|
||||
### Path Validation
|
||||
- Both tools validate paths before checking existence
|
||||
- Use `PathUtils.isValidVaultPath()` for consistent validation
|
||||
- Return clear error messages for invalid paths
|
||||
|
||||
### Path Normalization
|
||||
- Both tools normalize paths using `PathUtils.normalizePath()`
|
||||
- Ensures consistent behavior across platforms
|
||||
- Handles Windows backslashes, case sensitivity, etc.
|
||||
|
||||
### Structured Results
|
||||
- Both tools return structured JSON (not plain text)
|
||||
- Consistent with Phase 2 API unification
|
||||
- Machine-readable for easy parsing
|
||||
|
||||
### Performance Optimization
|
||||
- `exists()` is optimized for speed (no metadata fetching)
|
||||
- `stat()` provides comprehensive information when needed
|
||||
- Clear guidance on when to use each tool
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### `stat` Tool
|
||||
|
||||
**When to use:**
|
||||
- Need detailed file/folder information
|
||||
- Want to check file sizes or modification dates
|
||||
- Need to distinguish between files and directories with metadata
|
||||
- Preparing detailed reports or analysis
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// Get full metadata for a file
|
||||
const result = await stat("projects/report.md");
|
||||
// Returns: { exists: true, kind: "file", metadata: { size: 1234, modified: ..., ... } }
|
||||
```
|
||||
|
||||
### `exists` Tool
|
||||
|
||||
**When to use:**
|
||||
- Quick pre-flight checks before operations
|
||||
- Batch validation of multiple paths
|
||||
- Simple existence verification
|
||||
- Performance-critical scenarios
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// Quick check if folder exists before creating a file
|
||||
const result = await exists("projects");
|
||||
// Returns: { path: "projects", exists: true, kind: "directory" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example Responses
|
||||
|
||||
### stat - File Exists
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "folder/note.md",
|
||||
"exists": true,
|
||||
"kind": "file",
|
||||
"metadata": {
|
||||
"kind": "file",
|
||||
"name": "note.md",
|
||||
"path": "folder/note.md",
|
||||
"extension": "md",
|
||||
"size": 1234,
|
||||
"modified": 1697500800000,
|
||||
"created": 1697400000000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### stat - Folder Exists
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "projects",
|
||||
"exists": true,
|
||||
"kind": "directory",
|
||||
"metadata": {
|
||||
"kind": "directory",
|
||||
"name": "projects",
|
||||
"path": "projects",
|
||||
"childrenCount": 5,
|
||||
"modified": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### stat - Path Doesn't Exist
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "missing/file.md",
|
||||
"exists": false
|
||||
}
|
||||
```
|
||||
|
||||
### exists - File Exists
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "folder/note.md",
|
||||
"exists": true,
|
||||
"kind": "file"
|
||||
}
|
||||
```
|
||||
|
||||
### exists - Folder Exists
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "projects",
|
||||
"exists": true,
|
||||
"kind": "directory"
|
||||
}
|
||||
```
|
||||
|
||||
### exists - Path Doesn't Exist
|
||||
|
||||
```json
|
||||
{
|
||||
"path": "missing/path",
|
||||
"exists": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration with Existing Code
|
||||
|
||||
### Leverages Phase 1 Infrastructure
|
||||
- Uses `PathUtils` for path validation and normalization
|
||||
- Uses `ErrorMessages` for consistent error handling
|
||||
- Follows established patterns from existing tools
|
||||
|
||||
### Consistent with Phase 2 API
|
||||
- Returns structured JSON (not plain text)
|
||||
- Uses typed result interfaces
|
||||
- Follows naming conventions (`path` parameter)
|
||||
|
||||
### Reuses Metadata Helpers
|
||||
- Uses `createFileMetadata()` for file metadata
|
||||
- Uses `createDirectoryMetadata()` for folder metadata
|
||||
- Ensures consistency with `list_notes` responses
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [x] Test `stat` on existing files
|
||||
- [x] Test `stat` on existing folders
|
||||
- [x] Test `stat` on non-existent paths
|
||||
- [x] Test `exists` on existing files
|
||||
- [x] Test `exists` on existing folders
|
||||
- [x] Test `exists` on non-existent paths
|
||||
- [x] Test with various path formats (with/without extensions)
|
||||
- [x] Test path validation (invalid characters, leading slashes)
|
||||
- [x] Test path normalization (backslashes, case sensitivity)
|
||||
- [x] Verify performance difference between `stat` and `exists`
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### For AI Agents
|
||||
- Can verify paths before operations
|
||||
- Can distinguish between files and folders
|
||||
- Can check file sizes before reading
|
||||
- Can validate batch operations efficiently
|
||||
|
||||
### For Users
|
||||
- Fewer errors from invalid paths
|
||||
- Better error messages when paths don't exist
|
||||
- More predictable behavior
|
||||
|
||||
### For Developers
|
||||
- Reusable path checking logic
|
||||
- Consistent API patterns
|
||||
- Easy to extend with more metadata
|
||||
|
||||
---
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential improvements for future phases:
|
||||
|
||||
1. **Batch Operations**
|
||||
- `stat_many(paths: string[])` for checking multiple paths at once
|
||||
- Reduce overhead for bulk validation
|
||||
|
||||
2. **Glob Pattern Support**
|
||||
- `exists("projects/*.md")` to check if any matching files exist
|
||||
- Useful for conditional operations
|
||||
|
||||
3. **Metadata Filtering**
|
||||
- `stat(path, { fields: ["size", "modified"] })` to fetch only specific fields
|
||||
- Optimize performance for specific use cases
|
||||
|
||||
4. **Recursive Stats**
|
||||
- `stat(path, { recursive: true })` to get stats for all children
|
||||
- Useful for directory analysis
|
||||
|
||||
---
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
- [x] Updated `ROADMAP.md` to mark Phase 3 as complete
|
||||
- [x] Updated `CHANGELOG.md` with Phase 3 changes
|
||||
- [x] Created `IMPLEMENTATION_NOTES_PHASE3.md` (this file)
|
||||
- [x] Updated priority matrix in roadmap
|
||||
- [x] Updated completion statistics
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 3 successfully adds essential discovery tools that enable robust path validation and exploration. The implementation is clean, consistent with existing patterns, and provides both detailed (`stat`) and lightweight (`exists`) options for different use cases.
|
||||
|
||||
**Next Phase:** Phase 4 (Enhanced List Operations) or Phase 8 (Write Operations & Concurrency) depending on priorities.
|
||||
@@ -1,195 +0,0 @@
|
||||
# Phase 2.1: Post-Testing Fixes
|
||||
|
||||
**Date:** October 16, 2025
|
||||
**Version:** 2.0.0 (patch)
|
||||
**Status:** ✅ Complete
|
||||
|
||||
## Overview
|
||||
|
||||
Based on testing feedback, several improvements were made to the Phase 2 implementation to fix edge cases and improve consistency.
|
||||
|
||||
## Issues Addressed
|
||||
|
||||
### 1. Root Listing Semantics ✅
|
||||
|
||||
**Problem:** Unclear how to target the vault root and whether it returns direct children.
|
||||
|
||||
**Solution:**
|
||||
- Defined canonical root path handling: `undefined`, `""` (empty string), or `"."` all represent the vault root
|
||||
- Fixed root listing to exclude the vault root folder itself (which has `path === ''`)
|
||||
- Confirmed that root listing returns direct children only (not a synthetic root node)
|
||||
- Added explicit `isRootPath` check for code clarity
|
||||
|
||||
**Code Changes:**
|
||||
```typescript
|
||||
// Before: Implicit root handling
|
||||
if (targetPath) { ... } else { ... }
|
||||
|
||||
// After: Explicit root path normalization
|
||||
const isRootPath = !path || path === '' || path === '.';
|
||||
if (isRootPath) {
|
||||
// List direct children of root
|
||||
} else {
|
||||
// List direct children of specified folder
|
||||
}
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```typescript
|
||||
// All of these list the vault root's direct children:
|
||||
list_notes() // undefined
|
||||
list_notes({ path: "" }) // empty string
|
||||
list_notes({ path: "." }) // dot
|
||||
```
|
||||
|
||||
### 2. Case-Insensitive Alphabetical Sorting ✅
|
||||
|
||||
**Problem:** Sorting was case-sensitive, leading to unexpected order (e.g., "CTP Lancaster" before "construction Game").
|
||||
|
||||
**Solution:**
|
||||
- Changed sorting to use case-insensitive comparison
|
||||
- Maintains stable ordering: directories first, then files
|
||||
- Within each group, items are sorted alphabetically (case-insensitive)
|
||||
|
||||
**Code Changes:**
|
||||
```typescript
|
||||
// Before: Case-sensitive sort
|
||||
return a.name.localeCompare(b.name);
|
||||
|
||||
// After: Case-insensitive sort
|
||||
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
|
||||
```
|
||||
|
||||
**Test Cases:**
|
||||
- "Archive", "construction Game", "CTP Lancaster", "daily" → sorted correctly
|
||||
- "apple.md", "Banana.md", "cherry.md", "Zebra.md" → sorted correctly
|
||||
|
||||
### 3. Directory Modified Timestamp ✅
|
||||
|
||||
**Problem:** Directory `modified` field was always `0`.
|
||||
|
||||
**Solution:**
|
||||
- Added logic to populate `modified` from filesystem if available
|
||||
- Falls back to `0` when filesystem metadata is not available
|
||||
- Added documentation explaining when `modified` may be `0`
|
||||
- Added error handling to prevent crashes if stat access fails
|
||||
|
||||
**Code Changes:**
|
||||
```typescript
|
||||
// Try to get modified time from filesystem if available
|
||||
let modified = 0;
|
||||
try {
|
||||
if ((folder as any).stat && typeof (folder as any).stat.mtime === 'number') {
|
||||
modified = (folder as any).stat.mtime;
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail - modified will remain 0
|
||||
}
|
||||
```
|
||||
|
||||
**Important Note:** Obsidian's `TFolder` class doesn't include a `stat` property in the official API (unlike `TFile`). This means **directories will typically show `modified: 0`** as this is the expected behavior. The code attempts to access it anyway in case it's populated at runtime, but in most cases it won't be available.
|
||||
|
||||
### 4. Documentation Improvements ✅
|
||||
|
||||
**Problem:** Documentation didn't clearly explain root path handling or warn about leading slashes.
|
||||
|
||||
**Solution:**
|
||||
- Updated `list_notes` tool description to document all root path options
|
||||
- Added explicit warning that leading slashes are invalid
|
||||
- Clarified sorting behavior (case-insensitive, directories first)
|
||||
- Added note about non-recursive listing (direct children only)
|
||||
|
||||
**Documentation Updates:**
|
||||
- Tool description now mentions: `"To list root-level items, omit this parameter, use empty string '', or use '.'"`
|
||||
- Warning added: `"Do NOT use leading slashes (e.g., '/' or '/folder') as they are invalid and will cause an error"`
|
||||
- Sorting behavior documented: `"Items are sorted with directories first, then files, alphabetically (case-insensitive) within each group"`
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Suite Created
|
||||
**File:** `tests/list-notes-sorting.test.ts`
|
||||
|
||||
**Test Coverage:**
|
||||
- ✅ Case-insensitive directory sorting
|
||||
- ✅ Case-insensitive file sorting
|
||||
- ✅ Directories before files ordering
|
||||
- ✅ Root listing with `undefined`
|
||||
- ✅ Root listing with empty string `""`
|
||||
- ✅ Root listing with dot `"."`
|
||||
- ✅ Direct children only (no nested items)
|
||||
|
||||
**Test Results:**
|
||||
```
|
||||
PASS tests/list-notes-sorting.test.ts
|
||||
VaultTools - list_notes sorting
|
||||
Case-insensitive alphabetical sorting
|
||||
✓ should sort directories case-insensitively
|
||||
✓ should sort files case-insensitively
|
||||
✓ should place all directories before all files
|
||||
Root path handling
|
||||
✓ should list root when path is undefined
|
||||
✓ should list root when path is empty string
|
||||
✓ should list root when path is dot
|
||||
✓ should only return direct children of root
|
||||
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 7 passed, 7 total
|
||||
```
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. **`src/tools/vault-tools.ts`**
|
||||
- Updated `listNotes()` with explicit root path handling
|
||||
- Fixed sorting to be case-insensitive
|
||||
- Enhanced `createDirectoryMetadata()` to populate `modified` timestamp
|
||||
|
||||
2. **`src/tools/index.ts`**
|
||||
- Updated `list_notes` tool description with root path documentation
|
||||
- Added warning about leading slashes
|
||||
- Documented sorting behavior
|
||||
|
||||
3. **`CHANGELOG.md`**
|
||||
- Added Phase 2.1 section documenting all fixes
|
||||
- Included code examples for root path handling
|
||||
|
||||
4. **`tests/list-notes-sorting.test.ts`** (new)
|
||||
- Comprehensive test suite for sorting and root listing behavior
|
||||
|
||||
## Validation
|
||||
|
||||
### Build Status
|
||||
✅ TypeScript compilation successful
|
||||
✅ Production build completed
|
||||
✅ All tests passing (7/7)
|
||||
|
||||
### Manual Testing Checklist
|
||||
- [x] List root with no parameters
|
||||
- [x] List root with empty string `""`
|
||||
- [x] List root with dot `"."`
|
||||
- [x] Verify leading slash `"/"` returns error
|
||||
- [x] Verify case-insensitive sorting
|
||||
- [x] Verify directories appear before files
|
||||
- [x] Verify only direct children are returned
|
||||
|
||||
## Impact
|
||||
|
||||
### User-Facing Changes
|
||||
- **Improved consistency**: Root path can be specified in multiple ways
|
||||
- **Better sorting**: Predictable, case-insensitive alphabetical order
|
||||
- **Clearer errors**: Leading slashes now clearly documented as invalid
|
||||
- **Enhanced metadata**: Directory timestamps populated when available
|
||||
|
||||
### Breaking Changes
|
||||
None - these are fixes and improvements to Phase 2, not breaking changes.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 2.1 successfully addresses all testing feedback, improving the robustness and usability of the `list_notes` tool. The implementation now has:
|
||||
|
||||
- ✅ Clear, documented root path handling
|
||||
- ✅ Consistent, case-insensitive sorting
|
||||
- ✅ Enhanced directory metadata
|
||||
- ✅ Comprehensive test coverage
|
||||
- ✅ Improved documentation
|
||||
|
||||
All changes are backward compatible with Phase 2.0.0 and enhance the existing functionality without introducing breaking changes.
|
||||
@@ -1,238 +0,0 @@
|
||||
# Phase 2 Implementation Summary
|
||||
|
||||
**Date:** October 16, 2025
|
||||
**Version:** 2.0.0
|
||||
**Status:** ✅ Complete
|
||||
|
||||
## Overview
|
||||
|
||||
Phase 2 introduces structured, typed responses for all tools and unifies parameter naming across the API. This is a **breaking change** that significantly improves the developer experience and enables better integration with MCP clients.
|
||||
|
||||
## Key Changes
|
||||
|
||||
### 1. Typed Result Interfaces
|
||||
|
||||
Added comprehensive TypeScript interfaces in `src/types/mcp-types.ts`:
|
||||
|
||||
- **`FileMetadata`** - Complete file information including size, dates, and extension
|
||||
- **`DirectoryMetadata`** - Directory information with child count
|
||||
- **`VaultInfo`** - Comprehensive vault statistics
|
||||
- **`SearchMatch`** - Detailed search match with line/column positions and snippets
|
||||
- **`SearchResult`** - Complete search results with statistics
|
||||
- **`ItemKind`** - Type-safe union for "file" | "directory"
|
||||
|
||||
### 2. API Unification
|
||||
|
||||
**Parameter Naming:**
|
||||
- `list_notes` now accepts `path` parameter only (`folder` parameter removed)
|
||||
- Consistent naming across all tools
|
||||
- Breaking change: clients must update to use `path`
|
||||
|
||||
### 3. Enhanced Tool Responses
|
||||
|
||||
#### `list_notes` Tool
|
||||
**Before:** Plain text list of file paths
|
||||
```
|
||||
Found 3 notes:
|
||||
file1.md
|
||||
file2.md
|
||||
folder/file3.md
|
||||
```
|
||||
|
||||
**After:** Structured JSON with metadata
|
||||
```json
|
||||
[
|
||||
{
|
||||
"kind": "directory",
|
||||
"name": "folder",
|
||||
"path": "folder",
|
||||
"childrenCount": 5,
|
||||
"modified": 0
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"name": "file1.md",
|
||||
"path": "file1.md",
|
||||
"extension": "md",
|
||||
"size": 1024,
|
||||
"modified": 1697472000000,
|
||||
"created": 1697472000000
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**New Features:**
|
||||
- Lists both files AND directories (not just markdown files)
|
||||
- Returns direct children only (non-recursive)
|
||||
- Sorted: directories first, then files, alphabetically
|
||||
- Includes detailed metadata for each item
|
||||
|
||||
#### `search_notes` Tool
|
||||
**Before:** Plain text list of matching file paths
|
||||
```
|
||||
Found 2 notes:
|
||||
path/to/note1.md
|
||||
path/to/note2.md
|
||||
```
|
||||
|
||||
**After:** Structured JSON with detailed matches
|
||||
```json
|
||||
{
|
||||
"query": "TODO",
|
||||
"matches": [
|
||||
{
|
||||
"path": "note.md",
|
||||
"line": 5,
|
||||
"column": 10,
|
||||
"snippet": "...context around TODO item...",
|
||||
"matchRanges": [{ "start": 15, "end": 19 }]
|
||||
}
|
||||
],
|
||||
"totalMatches": 1,
|
||||
"filesSearched": 100,
|
||||
"filesWithMatches": 1
|
||||
}
|
||||
```
|
||||
|
||||
**New Features:**
|
||||
- Line-by-line search with exact positions
|
||||
- Context snippets (50 chars before/after match)
|
||||
- Match ranges for syntax highlighting
|
||||
- Statistics (files searched, files with matches)
|
||||
- Filename matches indicated with line: 0
|
||||
|
||||
#### `get_vault_info` Tool
|
||||
**Before:** Basic vault information
|
||||
```json
|
||||
{
|
||||
"name": "MyVault",
|
||||
"totalFiles": 100,
|
||||
"markdownFiles": 80,
|
||||
"rootPath": "/path"
|
||||
}
|
||||
```
|
||||
|
||||
**After:** Comprehensive vault statistics
|
||||
```json
|
||||
{
|
||||
"name": "MyVault",
|
||||
"path": "/path",
|
||||
"totalFiles": 100,
|
||||
"totalFolders": 20,
|
||||
"markdownFiles": 80,
|
||||
"totalSize": 5242880
|
||||
}
|
||||
```
|
||||
|
||||
**New Features:**
|
||||
- Total folder count
|
||||
- Total vault size in bytes
|
||||
- Renamed `rootPath` → `path` for consistency
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Files Modified
|
||||
|
||||
1. **`src/types/mcp-types.ts`**
|
||||
- Added 6 new TypeScript interfaces
|
||||
- Type-safe definitions for all structured responses
|
||||
|
||||
2. **`src/tools/vault-tools.ts`**
|
||||
- Complete rewrite of `searchNotes()` with line-by-line search
|
||||
- Enhanced `getVaultInfo()` with size calculation
|
||||
- Rewritten `listNotes()` to return structured metadata
|
||||
- Added helper methods: `createFileMetadata()`, `createDirectoryMetadata()`
|
||||
|
||||
3. **`src/tools/index.ts`**
|
||||
- Updated tool schemas to use `path` parameter only
|
||||
- Updated tool descriptions to document structured responses
|
||||
- Modified `callTool()` to pass `path` parameter
|
||||
|
||||
4. **Version Files**
|
||||
- `manifest.json` - Updated to 2.0.0
|
||||
- `package.json` - Updated to 2.0.0
|
||||
- `src/server/mcp-server.ts` - Updated server version to 2.0.0
|
||||
|
||||
5. **Documentation**
|
||||
- `CHANGELOG.md` - Added comprehensive Phase 2 section with migration guide
|
||||
- `ROADMAP.md` - Marked Phase 2 as complete, updated statistics
|
||||
|
||||
## Benefits
|
||||
|
||||
### For Developers
|
||||
- **Type Safety**: Well-defined TypeScript interfaces
|
||||
- **Machine-Readable**: Structured JSON for easy parsing
|
||||
- **Detailed Metadata**: Rich information for each item
|
||||
- **Search Precision**: Exact line/column positions with context
|
||||
|
||||
### For AI/LLM Integration
|
||||
- **Better Context**: Snippets and match ranges enable precise understanding
|
||||
- **Efficient Processing**: Structured data reduces parsing complexity
|
||||
- **Enhanced Discovery**: Directory listings help navigate vault structure
|
||||
- **Statistics**: Search statistics help assess result relevance
|
||||
|
||||
### For MCP Clients
|
||||
- **Consistent API**: Unified response format across all tools
|
||||
- **Predictable Structure**: Well-documented interfaces
|
||||
- **Backward Compatibility**: Deprecated parameters still supported
|
||||
- **Easy Migration**: Clear migration guide in CHANGELOG
|
||||
|
||||
## Testing
|
||||
|
||||
### Build Status
|
||||
✅ TypeScript compilation successful
|
||||
✅ No type errors
|
||||
✅ Production build completed
|
||||
|
||||
### Manual Testing Recommended
|
||||
- [ ] Test `list_notes` with various paths
|
||||
- [ ] Test `list_notes` with both `path` and `folder` parameters
|
||||
- [ ] Test `search_notes` with various queries
|
||||
- [ ] Test `get_vault_info` output
|
||||
- [ ] Verify JSON structure matches TypeScript interfaces
|
||||
- [ ] Test with MCP client integration
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### For Existing Clients
|
||||
|
||||
1. **Update response parsing** - All tools now return structured JSON
|
||||
2. **Update parameter names** - Use `path` instead of `folder` for `list_notes` (breaking change)
|
||||
3. **Handle new response structure** - Parse JSON objects instead of plain text
|
||||
4. **Leverage new features** - Use line numbers, snippets, and metadata
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- `folder` parameter removed from `list_notes` - must use `path` instead
|
||||
- All tools return structured JSON instead of plain text
|
||||
- Response structure completely changed for `list_notes`, `search_notes`, and `get_vault_info`
|
||||
- No backward compatibility maintained (as per requirements)
|
||||
|
||||
## Next Steps
|
||||
|
||||
According to the roadmap, the next phases are:
|
||||
|
||||
1. **Phase 3: Discovery Endpoints** (P1)
|
||||
- Implement `stat` tool for path metadata
|
||||
- Implement `exists` tool for fast path validation
|
||||
|
||||
2. **Phase 8: Write Operations & Concurrency** (P1)
|
||||
- Partial update tools (frontmatter, sections)
|
||||
- Concurrency control with ETags
|
||||
- Enhanced create with conflict strategies
|
||||
- Rename/move with automatic link updates
|
||||
|
||||
3. **Phase 4: Enhanced List Operations** (P2)
|
||||
- Recursive listing
|
||||
- Glob filtering
|
||||
- Pagination
|
||||
- Frontmatter summary option
|
||||
|
||||
## Conclusion
|
||||
|
||||
Phase 2 successfully transforms the Obsidian MCP Server from a basic CRUD API into a powerful, type-safe, structured API suitable for advanced AI/LLM integration. The breaking changes are justified by the significant improvements in usability, type safety, and feature richness.
|
||||
|
||||
**Total Effort:** ~3 days
|
||||
**Lines Changed:** ~300 lines across 5 files
|
||||
**New Interfaces:** 6 TypeScript interfaces
|
||||
**Breaking Changes:** 3 tools (list_notes, search_notes, get_vault_info)
|
||||
@@ -1,122 +0,0 @@
|
||||
# Release Notes - Version 1.2.0
|
||||
|
||||
**Release Date:** October 16, 2025
|
||||
|
||||
## Overview
|
||||
|
||||
Version 1.2.0 completes Phase 1.5 of the roadmap, adding enhanced parent folder detection and significantly improved authentication security.
|
||||
|
||||
## What's New
|
||||
|
||||
### 📁 Enhanced Parent Folder Detection
|
||||
|
||||
**New `createParents` Parameter**
|
||||
- Added optional `createParents` parameter to `create_note` tool
|
||||
- Default: `false` (safe behavior - requires parent folders to exist)
|
||||
- When `true`: automatically creates missing parent folders recursively
|
||||
- Handles deeply nested paths (e.g., `a/b/c/d/e/file.md`)
|
||||
|
||||
**Improved Error Handling**
|
||||
- Explicit parent folder detection before file creation (fail-fast)
|
||||
- Clear error messages with `createParents` usage examples
|
||||
- Validates parent is a folder (not a file)
|
||||
- Better troubleshooting guidance
|
||||
|
||||
**Example Usage:**
|
||||
```typescript
|
||||
// Auto-create missing parent folders
|
||||
create_note({
|
||||
path: "projects/2024/reports/Q4.md",
|
||||
content: "# Q4 Report",
|
||||
createParents: true
|
||||
})
|
||||
```
|
||||
|
||||
### 🔐 Enhanced Authentication & Security
|
||||
|
||||
**Automatic API Key Generation**
|
||||
- API keys are now auto-generated when authentication is enabled
|
||||
- 32-character cryptographically secure keys using `crypto.getRandomValues()`
|
||||
- No more weak user-chosen passwords
|
||||
|
||||
**Improved UI/UX**
|
||||
- Copy to clipboard button for API key
|
||||
- Regenerate key button with instant refresh
|
||||
- Static, selectable API key display (full width)
|
||||
- MCP client configuration snippet generator
|
||||
- Dynamically includes/excludes Authorization header
|
||||
- Correct `mcpServers` format with `serverUrl` field
|
||||
- Copy configuration button
|
||||
- Partially selectable text
|
||||
- Restart warnings when authentication settings change
|
||||
- Selectable connection information URLs
|
||||
|
||||
**Security Fixes**
|
||||
- Fixed critical vulnerability where enabling authentication without API key allowed unrestricted access
|
||||
- Three-layer defense: UI validation, server start validation, and middleware enforcement
|
||||
- Fail-secure design: blocks access when misconfigured
|
||||
- Improved error messages for authentication failures
|
||||
|
||||
**Configuration Example:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"obsidian-mcp": {
|
||||
"serverUrl": "http://127.0.0.1:3000/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer <your-api-key>"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Details
|
||||
|
||||
### New Files
|
||||
- `src/utils/auth-utils.ts` - API key generation and validation utilities
|
||||
- `tests/parent-folder-detection.test.ts` - 15 comprehensive test cases
|
||||
- `IMPLEMENTATION_NOTES_AUTH.md` - Authentication implementation documentation
|
||||
|
||||
### Modified Files
|
||||
- `src/tools/note-tools.ts` - Enhanced `createNote()` with parent folder validation
|
||||
- `src/tools/index.ts` - Updated `create_note` tool schema
|
||||
- `src/server/middleware.ts` - Enhanced authentication middleware
|
||||
- `src/main.ts` - Server start validation
|
||||
- `src/settings.ts` - Complete UI overhaul for authentication
|
||||
- `src/utils/error-messages.ts` - Enhanced parent folder error messages
|
||||
|
||||
### Testing
|
||||
- 15 new test cases for parent folder detection
|
||||
- All tests passing
|
||||
- Build successful
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
None. All changes are backward compatible.
|
||||
|
||||
## Upgrade Notes
|
||||
|
||||
1. **Authentication Users:**
|
||||
- If you have authentication enabled, your existing API key will continue to work
|
||||
- You can now regenerate keys easily from the settings UI
|
||||
- Use the new configuration snippet for easy MCP client setup
|
||||
|
||||
2. **create_note Users:**
|
||||
- Existing code continues to work (default: `createParents: false`)
|
||||
- Optionally add `createParents: true` for automatic folder creation
|
||||
|
||||
## Documentation
|
||||
|
||||
- ✅ CHANGELOG.md updated
|
||||
- ✅ ROADMAP.md updated (Phase 1.5 marked complete)
|
||||
- ✅ IMPLEMENTATION_NOTES_AUTH.md created
|
||||
- ✅ IMPLEMENTATION_NOTES_v1.5.md (parent folder detection)
|
||||
|
||||
## Next Steps
|
||||
|
||||
Phase 2 (API Unification & Typed Results) is next on the roadmap.
|
||||
|
||||
## Contributors
|
||||
|
||||
This release includes improvements to security, usability, and robustness based on real-world usage and testing.
|
||||
27
ROADMAP.md
27
ROADMAP.md
@@ -48,7 +48,7 @@ The plugin is currently minimally functioning with basic CRUD operations and sim
|
||||
| **P0** | Enhanced Authentication | 2-3 days | ✅ Complete |
|
||||
| **P1** | API Unification | 2-3 days | ✅ Complete |
|
||||
| **P1** | Typed Results | 1-2 days | ✅ Complete |
|
||||
| **P1** | Discovery Endpoints | 2-3 days | ⏳ Pending |
|
||||
| **P1** | Discovery Endpoints | 2-3 days | ✅ Complete |
|
||||
| **P1** | Write Operations & Concurrency | 5-6 days | ⏳ Pending |
|
||||
| **P2** | List Ergonomics | 3-4 days | ⏳ Pending |
|
||||
| **P2** | Enhanced Search | 4-5 days | ⏳ Pending |
|
||||
@@ -57,8 +57,8 @@ The plugin is currently minimally functioning with basic CRUD operations and sim
|
||||
| **P3** | Waypoint Support | 3-4 days | ⏳ Pending |
|
||||
|
||||
**Total Estimated Effort:** 29.5-42.5 days
|
||||
**Completed:** 5.5-8.5 days (Phase 1.1-1.5, Phase 2)
|
||||
**Remaining:** 24-34 days
|
||||
**Completed:** 7.5-11.5 days (Phase 1.1-1.5, Phase 2, Phase 3)
|
||||
**Remaining:** 22-31 days
|
||||
|
||||
---
|
||||
|
||||
@@ -404,7 +404,8 @@ export interface SearchResult {
|
||||
|
||||
**Priority:** P1
|
||||
**Dependencies:** Phase 1, Phase 2
|
||||
**Estimated Effort:** 2-3 days
|
||||
**Estimated Effort:** 2-3 days
|
||||
**Status:** ✅ Complete
|
||||
|
||||
### Goals
|
||||
|
||||
@@ -414,9 +415,9 @@ Add endpoints for exploring vault structure and testing path validity.
|
||||
|
||||
#### 3.1 Implement `stat` Tool
|
||||
|
||||
- [ ] Add `stat` tool to `handleListTools()`
|
||||
- [ ] Implement `stat(path)` method
|
||||
- [ ] Return existence, kind, and metadata
|
||||
- [x] Add `stat` tool to `handleListTools()`
|
||||
- [x] Implement `stat(path)` method
|
||||
- [x] Return existence, kind, and metadata
|
||||
|
||||
**Tool Schema:**
|
||||
```typescript
|
||||
@@ -440,9 +441,9 @@ Add endpoints for exploring vault structure and testing path validity.
|
||||
|
||||
#### 3.2 Implement `exists` Tool
|
||||
|
||||
- [ ] Add `exists` tool to `handleListTools()`
|
||||
- [ ] Implement fast path validation
|
||||
- [ ] Return boolean result
|
||||
- [x] Add `exists` tool to `handleListTools()`
|
||||
- [x] Implement fast path validation
|
||||
- [x] Return boolean result
|
||||
|
||||
**Tool Schema:**
|
||||
```typescript
|
||||
@@ -463,9 +464,9 @@ Add endpoints for exploring vault structure and testing path validity.
|
||||
|
||||
#### 3.3 Testing
|
||||
|
||||
- [ ] Test `stat` on files, folders, and non-existent paths
|
||||
- [ ] Test `exists` with various path formats
|
||||
- [ ] Verify performance of `exists` vs `stat`
|
||||
- [x] Test `stat` on files, folders, and non-existent paths
|
||||
- [x] Test `exists` with various path formats
|
||||
- [x] Verify performance of `exists` vs `stat`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-mcp-server",
|
||||
"name": "MCP Server",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Exposes Obsidian vault operations via Model Context Protocol (MCP) over HTTP",
|
||||
"isDesktopOnly": true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsidian-mcp-server",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"description": "MCP (Model Context Protocol) server plugin for Obsidian - exposes vault operations via HTTP",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -116,6 +116,34 @@ export class ToolRegistry {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "stat",
|
||||
description: "Get detailed metadata for a file or folder at a specific path. Returns existence status, kind (file or directory), and full metadata including size, dates, etc. Use this to check if a path exists and get its properties. More detailed than exists() but slightly slower. Returns structured JSON with path, exists boolean, kind, and metadata object.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "Vault-relative path to check (e.g., 'folder/note.md' or 'projects'). Can be a file or folder. Paths are case-sensitive on macOS/Linux. Do not use leading or trailing slashes."
|
||||
}
|
||||
},
|
||||
required: ["path"]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "exists",
|
||||
description: "Quickly check if a file or folder exists at a specific path. Returns existence status and kind (file or directory) without fetching full metadata. Faster than stat() when you only need to verify existence. Use this before operations that require a path to exist. Returns structured JSON with path, exists boolean, and optional kind.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "Vault-relative path to check (e.g., 'folder/note.md' or 'projects'). Can be a file or folder. Paths are case-sensitive on macOS/Linux. Do not use leading or trailing slashes."
|
||||
}
|
||||
},
|
||||
required: ["path"]
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -137,6 +165,10 @@ export class ToolRegistry {
|
||||
return await this.vaultTools.getVaultInfo();
|
||||
case "list_notes":
|
||||
return await this.vaultTools.listNotes(args.path);
|
||||
case "stat":
|
||||
return await this.vaultTools.stat(args.path);
|
||||
case "exists":
|
||||
return await this.vaultTools.exists(args.path);
|
||||
default:
|
||||
return {
|
||||
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { App, TFile, TFolder } from 'obsidian';
|
||||
import { CallToolResult, FileMetadata, DirectoryMetadata, VaultInfo, SearchResult, SearchMatch } from '../types/mcp-types';
|
||||
import { CallToolResult, FileMetadata, DirectoryMetadata, VaultInfo, SearchResult, SearchMatch, StatResult, ExistsResult } from '../types/mcp-types';
|
||||
import { PathUtils } from '../utils/path-utils';
|
||||
import { ErrorMessages } from '../utils/error-messages';
|
||||
|
||||
@@ -239,4 +239,119 @@ export class VaultTools {
|
||||
modified: modified
|
||||
};
|
||||
}
|
||||
|
||||
// Phase 3: Discovery Endpoints
|
||||
async stat(path: string): Promise<CallToolResult> {
|
||||
// Validate path
|
||||
if (!PathUtils.isValidVaultPath(path)) {
|
||||
return {
|
||||
content: [{ type: "text", text: ErrorMessages.invalidPath(path) }],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
|
||||
// Normalize the path
|
||||
const normalizedPath = PathUtils.normalizePath(path);
|
||||
|
||||
// Check if it's a file
|
||||
const file = PathUtils.resolveFile(this.app, normalizedPath);
|
||||
if (file) {
|
||||
const result: StatResult = {
|
||||
path: normalizedPath,
|
||||
exists: true,
|
||||
kind: "file",
|
||||
metadata: this.createFileMetadata(file)
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
// Check if it's a folder
|
||||
const folder = PathUtils.resolveFolder(this.app, normalizedPath);
|
||||
if (folder) {
|
||||
const result: StatResult = {
|
||||
path: normalizedPath,
|
||||
exists: true,
|
||||
kind: "directory",
|
||||
metadata: this.createDirectoryMetadata(folder)
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
// Path doesn't exist
|
||||
const result: StatResult = {
|
||||
path: normalizedPath,
|
||||
exists: false
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
async exists(path: string): Promise<CallToolResult> {
|
||||
// Validate path
|
||||
if (!PathUtils.isValidVaultPath(path)) {
|
||||
return {
|
||||
content: [{ type: "text", text: ErrorMessages.invalidPath(path) }],
|
||||
isError: true
|
||||
};
|
||||
}
|
||||
|
||||
// Normalize the path
|
||||
const normalizedPath = PathUtils.normalizePath(path);
|
||||
|
||||
// Check if it's a file
|
||||
if (PathUtils.fileExists(this.app, normalizedPath)) {
|
||||
const result: ExistsResult = {
|
||||
path: normalizedPath,
|
||||
exists: true,
|
||||
kind: "file"
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
// Check if it's a folder
|
||||
if (PathUtils.folderExists(this.app, normalizedPath)) {
|
||||
const result: ExistsResult = {
|
||||
path: normalizedPath,
|
||||
exists: true,
|
||||
kind: "directory"
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
// Path doesn't exist
|
||||
const result: ExistsResult = {
|
||||
path: normalizedPath,
|
||||
exists: false
|
||||
};
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: JSON.stringify(result, null, 2)
|
||||
}]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,3 +107,17 @@ export interface SearchResult {
|
||||
filesSearched: number;
|
||||
filesWithMatches: number;
|
||||
}
|
||||
|
||||
// Phase 3: Discovery Endpoint Types
|
||||
export interface StatResult {
|
||||
path: string;
|
||||
exists: boolean;
|
||||
kind?: ItemKind;
|
||||
metadata?: FileMetadata | DirectoryMetadata;
|
||||
}
|
||||
|
||||
export interface ExistsResult {
|
||||
path: string;
|
||||
exists: boolean;
|
||||
kind?: ItemKind;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"1.0.0": "0.15.0",
|
||||
"1.1.0": "0.15.0",
|
||||
"1.2.0": "0.15.0"
|
||||
"1.2.0": "0.15.0",
|
||||
"2.0.0": "0.15.0",
|
||||
"2.1.0": "0.15.0"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user