#
tokens: 24485/50000 15/15 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .github
│   ├── copilot-instructions.md
│   └── workflows
│       ├── ci.yml
│       └── sync-spec.yml
├── .gitignore
├── .vscode
│   ├── mcp.json
│   └── tasks.json
├── build
│   ├── index.d.ts
│   ├── index.d.ts.map
│   ├── index.js
│   └── index.js.map
├── bun.lock
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── package.json
├── README.md
├── src
│   ├── index.ts
│   └── openapi.json
├── test
│   ├── ai-native-integration.test.ts
│   └── integration.test.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Obsidian Local REST API MCP Server

An AI-Native MCP (Model Context Protocol) server that provides intelligent, task-oriented tools for interacting with Obsidian vaults through a local REST API.

## 🧠 AI-Native Design Philosophy

This MCP server has been redesigned following AI-Native principles rather than simple API-to-tool mapping. Instead of exposing low-level CRUD operations, it provides high-level, task-oriented tools that LLMs can reason about more effectively.

### Before vs After: The Transformation

| **Old Approach (CRUD-Based)** | **New Approach (AI-Native)** | **Why Better** |
|--------------------------------|-------------------------------|----------------|
| `list_files` (returns everything) | `list_directory(path, limit, offset)` | Prevents context overflow with pagination |
| `create_file` + `update_file` | `write_file(path, content, mode)` | Single tool handles create/update/append |
| `create_note` + `update_note` | `create_or_update_note(path, content, frontmatter)` | Intelligent upsert removes decision complexity |
| `search_notes(query)` | `search_vault(query, scope, path_filter)` | Precise, scopeable search with advanced filtering |
| *(no equivalent)* | `get_daily_note(date)` | High-level abstraction for common workflow |
| *(no equivalent)* | `get_recent_notes(limit)` | Task-oriented recent file access |
| *(no equivalent)* | `find_related_notes(path, on)` | Conceptual relationship discovery |

## 🛠 Available Tools

### Directory & File Operations

#### `list_directory`
**Purpose**: List directory contents with pagination to prevent context overflow
```json
{
  "path": "Projects/",
  "recursive": false,
  "limit": 20,
  "offset": 0
}
```
**AI Benefit**: LLM can explore vault structure incrementally without overwhelming context

#### `read_file`
**Purpose**: Read content of any file in the vault
```json
{"path": "notes/meeting-notes.md"}
```

#### `write_file`
**Purpose**: Write file with multiple modes - replaces separate create/update operations
```json
{
  "path": "notes/summary.md",
  "content": "# Meeting Summary\n...",
  "mode": "append"  // "overwrite", "append", "prepend"
}
```
**AI Benefit**: Single tool handles all write scenarios, removes ambiguity

#### `delete_item`
**Purpose**: Delete any file or directory
```json
{"path": "old-notes/"}
```

### AI-Native Note Operations

#### `create_or_update_note`
**Purpose**: Intelligent upsert - creates if missing, updates if exists
```json
{
  "path": "daily/2024-12-26",
  "content": "## Tasks\n- Review AI-native MCP design",
  "frontmatter": {"tags": ["daily", "tasks"]}
}
```
**AI Benefit**: Eliminates "does this note exist?" decision tree

#### `get_daily_note`
**Purpose**: Smart daily note retrieval with common naming patterns
```json
{"date": "today"}  // or "yesterday", "2024-12-26"
```
**AI Benefit**: Abstracts file system details and naming conventions

#### `get_recent_notes`
**Purpose**: Get recently modified notes
```json
{"limit": 5}
```
**AI Benefit**: Matches natural "what did I work on recently?" queries

### Advanced Search & Discovery

#### `search_vault`
**Purpose**: Multi-scope search with advanced filtering
```json
{
  "query": "machine learning",
  "scope": ["content", "filename", "tags"],
  "path_filter": "research/"
}
```
**AI Benefit**: Precise, targeted search reduces noise

#### `find_related_notes`
**Purpose**: Discover conceptual relationships between notes
```json
{
  "path": "ai-research.md",
  "on": ["tags", "links"]
}
```
**AI Benefit**: Enables relationship-based workflows and serendipitous discovery

### Legacy Tools (Backward Compatibility)

The server maintains backward compatibility with existing tools like `get_note`, `list_notes`, `get_metadata_keys`, etc.

## Prerequisites

- Node.js 18+ or Bun runtime
- [Obsidian Local REST API](https://github.com/j-shelfwood/obsidian-local-rest-api) running locally (default: http://obsidian-local-rest-api.test)

## Installation

### Using npx (Recommended)

```bash
npx obsidian-local-rest-api-mcp
```

### From Source

```bash
# Clone the repository
git clone https://github.com/j-shelfwood/obsidian-local-rest-api-mcp.git
cd obsidian-local-rest-api-mcp

# Install dependencies with bun
bun install

# Build the project
bun run build
```

## Configuration

Set environment variables for API connection:

```bash
export OBSIDIAN_API_URL="http://obsidian-local-rest-api.test"  # Default URL (or http://localhost:8000 for non-Valet setups)
export OBSIDIAN_API_KEY="your-api-key"          # Optional bearer token
```

## Usage

### Running the Server

```bash
# Development mode with auto-reload
bun run dev

# Production mode
bun run start

# Or run directly
node build/index.js
```

### MCP Client Configuration

#### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "obsidian-vault": {
      "command": "npx",
      "args": ["obsidian-local-rest-api-mcp"],
      "env": {
        "OBSIDIAN_API_URL": "http://obsidian-local-rest-api.test",
        "OBSIDIAN_API_KEY": "your-api-key-if-needed"
      }
    }
  }
}
```

#### VS Code with MCP Extension

Use the included `.vscode/mcp.json` configuration file.

## Development

```bash
# Watch mode for development
bun run dev

# Build TypeScript
bun run build

# Type checking
bun run tsc --noEmit
```

## Architecture

- **ObsidianApiClient** - HTTP client wrapper for REST API endpoints
- **ObsidianMcpServer** - MCP server implementation with tool handlers
- **Configuration** - Environment-based configuration with validation

## Error Handling

The server includes comprehensive error handling:

- API connection failures
- Invalid tool parameters
- Network timeouts
- Authentication errors

Errors are returned as MCP tool call responses with descriptive messages.

## Debugging

Enable debug logging by setting environment variables:

```bash
export DEBUG=1
export NODE_ENV=development
```

Server logs are written to stderr to avoid interfering with MCP protocol communication on stdout.

## Troubleshooting

### MCP Server Fails to Start

If your MCP client shows "Start Failed" or similar errors:

1. **Test the server directly**:

   ```bash
   npx obsidian-local-rest-api-mcp --version
   ```

   Should output the version number.

2. **Test MCP protocol**:

   ```bash
   # Run our test script
   node -e "
   const { spawn } = require('child_process');
   const child = spawn('npx', ['obsidian-local-rest-api-mcp'], { stdio: ['pipe', 'pipe', 'pipe'] });
   child.stdout.on('data', d => console.log('OUT:', d.toString()));
   child.stderr.on('data', d => console.log('ERR:', d.toString()));
   setTimeout(() => {
     child.stdin.write(JSON.stringify({jsonrpc:'2.0',id:1,method:'initialize',params:{protocolVersion:'2024-11-05',capabilities:{},clientInfo:{name:'test',version:'1.0.0'}}})+'\n');
     setTimeout(() => child.kill(), 2000);
   }, 500);
   "
   ```

   Should show initialization response.

3. **Check Environment Variables**:

   - Ensure `OBSIDIAN_API_URL` points to a running Obsidian Local REST API
   - Test the API directly: `curl http://obsidian-local-rest-api.test/api/files` (or your configured API URL)

4. **Verify Obsidian Local REST API**:
   - Install and run [Obsidian Local REST API](https://github.com/j-shelfwood/obsidian-local-rest-api)
   - Confirm it's accessible on the configured port
   - Check if authentication is required

### Common Issues

**"Command not found"**: Make sure Node.js/npm is installed and npx is available

**"Connection refused"**: Obsidian Local REST API is not running or wrong URL

**Laravel Valet .test domains**: If using Laravel Valet, ensure your project directory name matches the .test domain (e.g., `obsidian-local-rest-api.test` for a project in `/obsidian-local-rest-api/`)

**"Unauthorized"**: Check if API key is required and properly configured

**"Timeout"**: Increase timeout in client configuration or check network connectivity

### Cherry Studio Configuration

For Cherry Studio, use these exact settings:

- **Name**: `obsidian-vault` (or any name you prefer)
- **Type**: `Standard Input/Output (stdio)`
- **Command**: `npx`
- **Arguments**: `obsidian-local-rest-api-mcp`
- **Environment Variables**:
  - `OBSIDIAN_API_URL`: Your API URL (e.g., `http://obsidian-local-rest-api.test` for Laravel Valet)
  - `OBSIDIAN_API_KEY`: Optional API key if authentication is required
- **Environment Variables**:
  - `OBSIDIAN_API_URL`: `http://obsidian-local-rest-api.test` (or your API URL)
  - `OBSIDIAN_API_KEY`: `your-api-key` (if required)

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make changes with proper TypeScript types
4. Test with your Obsidian vault
5. Submit a pull request

## License

MIT

```

--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------

```markdown
# Contributing

## Development Setup

1. Clone the repository
2. Install dependencies: `bun install`
3. Build the project: `bun run build`
4. Run tests: `bun test`

## Testing

The project uses Bun's built-in test runner. Tests are located in `test/integration.test.ts` and cover:

- Binary compilation and execution
- TypeScript type checking
- Environment configuration
- Server startup behavior
- Package configuration validation

Run tests with: `bun test`

## Publishing

The project is automatically published to npm when a GitHub release is created. To publish manually:

1. Ensure all tests pass: `bun test`
2. Build the project: `bun run build`
3. Publish: `npm publish --access public`

## CI/CD

GitHub Actions workflow runs on:

- Push to main/master branches
- Pull requests
- GitHub releases

The workflow:

- Tests on multiple Bun versions
- Runs linting and tests
- Builds the project
- Publishes to npm on releases (requires NPM_TOKEN secret)

## Architecture

The MCP server implements the Model Context Protocol specification and provides tools for:

- File operations (list, get, create, update, delete)
- Note operations with frontmatter support
- Metadata extraction and search
- Content search across vault

All API calls are made to the Obsidian Local REST API with configurable base URL and authentication.

```

--------------------------------------------------------------------------------
/.vscode/mcp.json:
--------------------------------------------------------------------------------

```json
{
  "servers": {
    "obsidian-vault": {
      "type": "stdio",
      "command": "node",
      "args": ["build/index.js"]
    }
  }
}

```

--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------

```json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build MCP Server",
      "type": "shell",
      "command": "bun",
      "args": ["run", "build"],
      "group": "build",
      "problemMatcher": ["$tsc"],
      "isBackground": false
    }
  ]
}

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build"]
}

```

--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------

```yaml
name: CI/CD

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]
  release:
    types: [published]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        bun-version: ["latest"]

    steps:
      - uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: ${{ matrix.bun-version }}

      - name: Install dependencies
        run: bun install

      - name: Run linting
        run: bun run lint

      - name: Run tests
        run: bun test

      - name: Build project
        run: bun run build

      - name: Verify binary is executable
        run: test -x build/index.js

  publish:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'release' && github.event.action == 'published'

    steps:
      - uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: latest

      - name: Setup Node.js for npm
        uses: actions/setup-node@v4
        with:
          node-version: "18"
          registry-url: "https://registry.npmjs.org"

      - name: Install dependencies
        run: bun install

      - name: Build and test
        run: bun run build && bun test

      - name: Publish to npm
        run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

```

--------------------------------------------------------------------------------
/.github/workflows/sync-spec.yml:
--------------------------------------------------------------------------------

```yaml
name: Sync API Spec

on:
  repository_dispatch:
    types: [api_spec_updated]
  schedule:
    - cron: '*/5 * * * *'
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          persist-credentials: true

      - name: Set up Node (Bun)
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: '1.2.17'

      - name: Fetch OpenAPI spec from source repo
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          repo=${{ github.event.client_payload.spec_repo || 'j-shelfwood/obsidian-local-rest-api' }}
          path=${{ github.event.client_payload.spec_path || 'openapi.json' }}
          curl -sSL \
            -H "Accept: application/vnd.github.raw+json" \
            https://api.github.com/repos/${repo}/contents/${path} > openapi.json
          jq . openapi.json > /dev/null

      - name: Update working tree with new spec
        run: |
          mkdir -p src
          mv openapi.json src/openapi.json

      - name: Install deps
        run: bun install --frozen-lockfile || bun install

      - name: Build
        run: bun run build

      - name: Test
        run: bun test

      - name: Commit and push to main
        env:
          GIT_AUTHOR_NAME: github-actions[bot]
          GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
          GIT_COMMITTER_NAME: github-actions[bot]
          GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
        run: |
          if git diff --quiet --exit-code src/openapi.json; then
            echo "No changes to spec; skipping commit."
            exit 0
          fi
          git add src/openapi.json
          git commit -m "chore: sync API spec (scheduled or dispatch)"
          git push origin HEAD:main

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "obsidian-local-rest-api-mcp",
  "version": "1.1.0",
  "type": "module",
  "main": "build/index.js",
  "bin": {
    "obsidian-local-rest-api-mcp": "build/index.js"
  },
  "scripts": {
    "build": "bun run tsc && chmod +x build/index.js",
    "dev": "bun run --watch src/index.ts",
    "start": "node build/index.js",
    "test": "bun test",
    "test:unit": "echo 'Basic validation passed - integration tests require running Laravel API'",
    "test:integration": "bun run test:integration.ts",
    "lint": "tsc --noEmit",
    "prepublishOnly": "bun run build && bun run test && bun run lint",
    "publish:npm": "npm publish --access public",
    "version:patch": "npm version patch && npm publish --access public",
    "version:minor": "npm version minor && npm publish --access public",
    "version:major": "npm version major && npm publish --access public"
  },
  "keywords": [
    "mcp",
    "obsidian",
    "model-context-protocol",
    "vault",
    "notes",
    "rest-api",
    "llm",
    "ai",
    "ai-native",
    "task-oriented",
    "intelligent-tools",
    "knowledge-management"
  ],
  "author": "shelfwood",
  "license": "MIT",
  "description": "AI-Native MCP server for Obsidian vaults with task-oriented, intelligent tools designed for LLM workflows",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/j-shelfwood/obsidian-local-rest-api-mcp.git"
  },
  "bugs": {
    "url": "https://github.com/j-shelfwood/obsidian-local-rest-api-mcp/issues"
  },
  "homepage": "https://github.com/j-shelfwood/obsidian-local-rest-api-mcp#readme",
  "files": [
    "build/**/*",
    "README.md",
    "package.json"
  ],
  "engines": {
    "node": ">=18.0.0"
  },
  "devDependencies": {
    "typescript": "^5.8.3",
    "@types/bun": "latest"
  },
  "private": false,
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.13.1",
    "zod": "^3.25.67"
  },
  "types": "build/index.d.ts"
}

```

--------------------------------------------------------------------------------
/.github/copilot-instructions.md:
--------------------------------------------------------------------------------

```markdown
<!-- Use this file to provide workspace-specific custom instructions to Copilot. For more details, visit https://code.visualstudio.com/docs/copilot/copilot-customization#_use-a-githubcopilotinstructionsmd-file -->

# Obsidian Local REST API MCP Server

You can find more info and examples at https://modelcontextprotocol.io/llms-full.txt

## Project Context

This is an MCP (Model Context Protocol) server that provides LLM tool calls to interact with an Obsidian vault through a local REST API. The server acts as a bridge between MCP clients (like Claude Desktop, VS Code, etc.) and the Obsidian Local REST API.

## Architecture

- **MCP Server**: Implements the Model Context Protocol server specification
- **API Client**: Wraps the Obsidian Local REST API endpoints
- **Tools**: Exposes vault operations as MCP tools for LLM consumption

## Key Files

- `src/index.ts` - Main MCP server implementation
- `package.json` - Project configuration with bun support
- `tsconfig.json` - TypeScript configuration optimized for Node16 modules

## Available Tools

The server exposes these tools to MCP clients:

### File Operations
- `list_files` - List all files in vault
- `get_file` - Get file content
- `create_file` - Create new file/directory
- `update_file` - Update file content
- `delete_file` - Delete file

### Note Operations  
- `list_notes` - List notes with metadata
- `get_note` - Get note with frontmatter
- `create_note` - Create note with optional frontmatter
- `update_note` - Update note content/frontmatter
- `delete_note` - Delete note
- `search_notes` - Search notes by content

### Metadata Operations
- `get_metadata_keys` - List all frontmatter keys
- `get_metadata_values` - Get unique values for a key

## Configuration

Set environment variables:
- `OBSIDIAN_API_URL` - Base URL of the REST API (default: http://localhost:8000)
- `OBSIDIAN_API_KEY` - Optional bearer token for authentication

## Development Guidelines

- Use TypeScript strict mode
- Follow MCP protocol specifications
- Handle errors gracefully with meaningful messages
- Validate inputs using zod schemas
- Use proper async/await patterns
- Log errors to stderr (stdout reserved for MCP protocol)

```

--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
# Changelog

## [1.1.0] - 2024-12-26

### 🧠 Major: AI-Native Redesign

This release represents a complete philosophical shift from CRUD-based API mappings to truly AI-native, task-oriented tools designed for LLM workflows.

#### ✨ New AI-Native Tools

- **`list_directory`** - Paginated directory listing prevents context overflow
- **`write_file`** - Unified create/update/append operations with mode parameter
- **`create_or_update_note`** - Intelligent upsert eliminates existence checks
- **`search_vault`** - Multi-scope search with advanced filtering (content, filename, tags)
- **`get_daily_note`** - Smart daily note resolution with common naming patterns
- **`get_recent_notes`** - Task-oriented recent file access
- **`find_related_notes`** - Conceptual relationship discovery via tags and links

#### 🔧 Enhanced Backend API

- New `/api/vault/*` endpoints for high-level operations
- Enhanced `/api/files/write` with multi-mode support
- Enhanced `/api/notes/upsert` for intelligent create/update
- Advanced search and relationship discovery endpoints

#### 📊 Performance Improvements

- **Context Efficiency**: Pagination prevents LLM context overflow
- **Decision Reduction**: Upsert operations eliminate existence checks
- **Cognitive Alignment**: Tools match natural language concepts

#### 🔄 Backward Compatibility

- All existing tools (`get_note`, `list_notes`, etc.) remain functional
- Legacy endpoints preserved for existing integrations
- Gradual migration path available

#### 🏗 Architecture

- New `VaultController` for high-level vault operations
- Enhanced `FileController` and `NoteController`
- Improved `LocalVaultService` with additional file system methods

### Breaking Changes

None - this release maintains full backward compatibility while adding the new AI-native capabilities.

### Migration Guide

Existing integrations continue to work unchanged. To take advantage of AI-native features:

1. Use `list_directory` instead of `list_files` for large vaults
2. Replace `create_file`/`update_file` pairs with single `write_file` calls
3. Use `create_or_update_note` for reliable note operations
4. Leverage `search_vault` for precise, scoped searches

---

## [1.0.3] - Previous Release

Legacy CRUD-based implementation with basic file and note operations.

```

--------------------------------------------------------------------------------
/test/integration.test.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env bun

import { test, expect, describe, beforeAll, afterAll } from "bun:test";
import { spawn, ChildProcess } from "child_process";

describe("MCP Server Basic Tests", () => {
  test("Server binary exists and is executable", () => {
    const fs = require("fs");
    const path = require("path");

    const binaryPath = path.join(process.cwd(), "build", "index.js");
    expect(fs.existsSync(binaryPath)).toBe(true);

    const stats = fs.statSync(binaryPath);
    expect(stats.isFile()).toBe(true);
  });

  test("TypeScript compilation succeeds", async () => {
    const buildProcess = spawn("bun", ["run", "tsc", "--noEmit"], {
      stdio: "pipe",
      cwd: process.cwd()
    });

    return new Promise((resolve, reject) => {
      let stderr = "";

      buildProcess.stderr?.on("data", (data) => {
        stderr += data.toString();
      });

      buildProcess.on("close", (code) => {
        if (code === 0) {
          resolve(undefined);
        } else {
          reject(new Error(`TypeScript compilation failed: ${stderr}`));
        }
      });
    });
  });

  test("Environment configuration parsing", () => {
    const originalUrl = process.env.OBSIDIAN_API_URL;
    const originalKey = process.env.OBSIDIAN_API_KEY;

    // Test default values
    delete process.env.OBSIDIAN_API_URL;
    delete process.env.OBSIDIAN_API_KEY;

    // Test custom values
    process.env.OBSIDIAN_API_URL = "http://test.local:9000";
    process.env.OBSIDIAN_API_KEY = "test-key";

    expect(process.env.OBSIDIAN_API_URL).toBe("http://test.local:9000");
    expect(process.env.OBSIDIAN_API_KEY).toBe("test-key");

    // Restore original values
    if (originalUrl) process.env.OBSIDIAN_API_URL = originalUrl;
    else delete process.env.OBSIDIAN_API_URL;
    if (originalKey) process.env.OBSIDIAN_API_KEY = originalKey;
    else delete process.env.OBSIDIAN_API_KEY;
  });

  test("Server startup timeout handling", async () => {
    const serverProcess = spawn("node", ["build/index.js"], {
      stdio: ["pipe", "pipe", "pipe"],
      env: {
        ...process.env,
        OBSIDIAN_API_URL: "http://localhost:8000",
      },
    });

    return new Promise((resolve) => {
      let hasOutput = false;

      // Check stderr for startup message
      serverProcess.stderr?.on("data", (data) => {
        const output = data.toString();
        if (output.includes("running on stdio")) {
          hasOutput = true;
        }
      });

      // Give server time to start and emit startup message
      global.setTimeout(() => {
        serverProcess.kill();
        // Server starting is success (it should run indefinitely)
        expect(hasOutput).toBe(true);
        resolve(undefined);
      }, 2000);

      serverProcess.on("error", () => {
        // Process errors are expected in test environment
        resolve(undefined);
      });
    });
  }, 5000);
});

describe("Package Configuration", () => {
  test("Package.json has required fields for publishing", () => {
    const packageJson = require("../package.json");

    expect(packageJson.name).toBe("obsidian-local-rest-api-mcp");
    expect(packageJson.version).toBeDefined();
    expect(packageJson.description).toBeDefined();
    expect(packageJson.main).toBe("build/index.js");
    expect(packageJson.types).toBe("build/index.d.ts");
    expect(packageJson.license).toBe("MIT");
    expect(packageJson.repository).toBeDefined();
    expect(packageJson.keywords).toBeArray();
    expect(packageJson.files).toContain("build/**/*");
    expect(packageJson.private).toBe(false);
  });

  test("Binary configuration is correct", () => {
    const packageJson = require("../package.json");

    expect(packageJson.bin).toBeDefined();
    expect(packageJson.bin["obsidian-local-rest-api-mcp"]).toBe("build/index.js");
  });

  test("Dependencies are properly specified", () => {
    const packageJson = require("../package.json");

    expect(packageJson.dependencies).toBeDefined();
    expect(packageJson.dependencies["@modelcontextprotocol/sdk"]).toBeDefined();
    expect(packageJson.dependencies["zod"]).toBeDefined();

    expect(packageJson.devDependencies).toBeDefined();
    expect(packageJson.devDependencies["typescript"]).toBeDefined();
  });
});

```

--------------------------------------------------------------------------------
/test/ai-native-integration.test.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

/**
 * Integration test script for the AI-Native MCP tools
 *
 * This script tests the key functionality of the redesigned MCP server
 * to ensure the AI-native tools work as expected.
 */

// Skip in CI environments or when explicitly requested
if (process.env.CI === 'true' || process.env.SKIP_INTEGRATION_TESTS === 'true') {
    console.log('⏭️  Skipping AI-Native MCP integration tests in CI environment.');
    process.exit(0);
}

import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Configuration
interface Config {
    baseUrl: string;
    apiKey?: string;
}

const config: Config = {
    baseUrl: process.env.OBSIDIAN_API_URL || "http://obsidian-local-rest-api.test",
    apiKey: process.env.OBSIDIAN_API_KEY,
};

// Simple API client for testing
class TestApiClient {
    private baseUrl: string;
    private headers: Record<string, string>;

    constructor(config: Config) {
        this.baseUrl = `${config.baseUrl}/api`;
        this.headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
        };

        if (config.apiKey) {
            this.headers.Authorization = `Bearer ${config.apiKey}`;
        }
    }

    private async request(path: string, options: RequestInit = {}): Promise<any> {
        const url = `${this.baseUrl}${path}`;
        try {
            const response = await fetch(url, {
                ...options,
                headers: {
                    ...this.headers,
                    ...options.headers,
                },
            });

            if (!response.ok) {
                throw new Error(`API request failed: ${response.status} ${response.statusText}`);
            }

            return response.json();
        } catch (error) {
            console.error(`Request to ${url} failed:`, error);
            throw error;
        }
    }

    async testListDirectory() {
        console.log("🧪 Testing list_directory...");
        const result = await this.request("/vault/directory?path=.&limit=5");
        console.log(`✅ Found ${result.total_items} items in vault root`);
        return result;
    }

    async testSearchVault() {
        console.log("🧪 Testing search_vault...");
        const result = await this.request("/vault/search?query=test&scope=content,filename");
        console.log(`✅ Search found ${result.total_results} results`);
        return result;
    }

    async testCreateOrUpdateNote() {
        console.log("🧪 Testing create_or_update_note...");
        const testNote = {
            path: "test-ai-native-note",
            content: "This is a test note created by the AI-native MCP tools.",
            front_matter: {
                tags: ["test", "ai-native", "mcp"],
                created: new Date().toISOString(),
            }
        };

        const result = await this.request("/notes/upsert", {
            method: "POST",
            body: JSON.stringify(testNote),
        });
        console.log(`✅ Note upserted successfully: ${result.path}`);
        return result;
    }

    async testWriteFile() {
        console.log("🧪 Testing write_file (append mode)...");
        const result = await this.request("/files/write", {
            method: "POST",
            body: JSON.stringify({
                path: "test-ai-native-note.md",
                content: "\n\n## Additional Content\nThis was appended using the write_file tool.",
                mode: "append"
            }),
        });
        console.log(`✅ File appended successfully`);
        return result;
    }

    async testGetRecentNotes() {
        console.log("🧪 Testing get_recent_notes...");
        const result = await this.request("/vault/notes/recent?limit=3");
        console.log(`✅ Found ${result.length} recent notes`);
        return result;
    }

    async testGetDailyNote() {
        console.log("🧪 Testing get_daily_note...");
        try {
            const result = await this.request("/vault/notes/daily?date=today");
            console.log(`✅ Found daily note: ${result.path}`);
            return result;
        } catch (error) {
            console.log(`ℹ️  No daily note found (this is expected if you don't have daily notes)`);
            return null;
        }
    }

    async testFindRelatedNotes() {
        console.log("🧪 Testing find_related_notes...");
        try {
            const result = await this.request("/vault/notes/related/test-ai-native-note.md?on=tags");
            console.log(`✅ Found ${result.total_found} related notes`);
            return result;
        } catch (error) {
            console.log(`ℹ️  No related notes found or test note doesn't exist yet`);
            return null;
        }
    }
}

// Run tests
async function runTests() {
    console.log("🚀 Starting AI-Native MCP Integration Tests\n");

    const client = new TestApiClient(config);

    try {
        await client.testListDirectory();
        await client.testCreateOrUpdateNote();
        await client.testWriteFile();
        await client.testSearchVault();
        await client.testGetRecentNotes();
        await client.testGetDailyNote();
        await client.testFindRelatedNotes();
        console.log("\n🎉 All tests completed successfully!");
        console.log("\n📋 Summary of AI-Native Improvements:");
        console.log("• list_directory: Paginated directory listing prevents context overflow");
        console.log("• write_file: Unified create/update/append operations");
        console.log("• create_or_update_note: Intelligent upsert removes LLM decision complexity");
        console.log("• search_vault: Advanced search with scope filtering");
        console.log("• get_recent_notes: Task-oriented recent file access");
        console.log("• get_daily_note: Smart daily note resolution");
        console.log("• find_related_notes: Conceptual note relationships");

    } catch (error) {
        console.error("❌ Test failed:", error);
        process.exit(1);
    }
}

if (import.meta.url === `file://${process.argv[1]}`) {
    runTests().catch(console.error);
}

```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';

// Handle CLI arguments
const args = process.argv.slice(2);
if (args.includes('--version') || args.includes('-v')) {
  const __filename = fileURLToPath(import.meta.url);
  const __dirname = dirname(__filename);
  const packagePath = join(__dirname, '..', 'package.json');
  const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
  console.log(packageJson.version);
  process.exit(0);
}

if (args.includes('--help') || args.includes('-h')) {
  console.log(`
Obsidian Local REST API MCP Server

Usage: obsidian-local-rest-api-mcp [options]

Options:
  -v, --version    Show version number
  -h, --help       Show help

Environment Variables:
  OBSIDIAN_API_URL    Base URL for Obsidian REST API (default: http://obsidian-local-rest-api.test)
  OBSIDIAN_API_KEY    Optional bearer token for authentication

This is an MCP server that communicates via stdio. It should be configured
in your MCP client (like Claude Desktop) rather than run directly.

Example Claude Desktop configuration:
{
  "mcpServers": {
    "obsidian-vault": {
      "command": "npx",
      "args": ["obsidian-local-rest-api-mcp"],
      "env": {
        "OBSIDIAN_API_URL": "http://localhost:8000"
      }
    }
  }
}
`);
  process.exit(0);
}

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";

// Configuration schema
const ConfigSchema = z.object({
  baseUrl: z.string().url().default("http://obsidian-local-rest-api.test"),
  apiKey: z.string().optional(),
});

type Config = z.infer<typeof ConfigSchema>;

// API client for Obsidian REST API
class ObsidianApiClient {
  private baseUrl: string;
  private headers: Record<string, string>;

  constructor(config: Config) {
    this.baseUrl = `${config.baseUrl}/api`;
    this.headers = {
      "Content-Type": "application/json",
      "Accept": "application/json",
    };

    if (config.apiKey) {
      this.headers.Authorization = `Bearer ${config.apiKey}`;
    }
  }

  private async request(path: string, options: RequestInit = {}): Promise<any> {
    const url = `${this.baseUrl}${path}`;
    const response = await fetch(url, {
      ...options,
      headers: {
        ...this.headers,
        ...options.headers,
      },
    });

    if (!response.ok) {
      throw new Error(`API request failed: ${response.status} ${response.statusText}`);
    }

    return response.json();
  }

  // Enhanced API client methods for AI-native operations

  // Directory operations
  async listDirectory(path: string = ".", recursive: boolean = false, limit: number = 50, offset: number = 0) {
    const params = new URLSearchParams({
      path,
      recursive: recursive.toString(),
      limit: limit.toString(),
      offset: offset.toString(),
    });
    return this.request(`/vault/directory?${params}`);
  }

  // File operations
  async readFile(path: string) {
    return this.request(`/files/${encodeURIComponent(path)}`);
  }

  async writeFile(path: string, content: string, mode: string = "overwrite") {
    return this.request("/files/write", {
      method: "POST",
      body: JSON.stringify({ path, content, mode }),
    });
  }

  async deleteItem(path: string) {
    return this.request(`/files/${encodeURIComponent(path)}`, {
      method: "DELETE",
    });
  }

  // AI-native note operations
  async createOrUpdateNote(path: string, content: string, frontmatter: Record<string, any> = {}) {
    return this.request("/notes/upsert", {
      method: "POST",
      body: JSON.stringify({
        path,
        content,
        front_matter: frontmatter
      }),
    });
  }

  async getDailyNote(date: string = "today") {
    const params = new URLSearchParams({ date });
    return this.request(`/vault/notes/daily?${params}`);
  }

  async getRecentNotes(limit: number = 5) {
    const params = new URLSearchParams({ limit: limit.toString() });
    return this.request(`/vault/notes/recent?${params}`);
  }

  // Enhanced search
  async searchVault(query: string, scope: string[] = ["content", "filename", "tags"], pathFilter?: string) {
    const params = new URLSearchParams({
      query,
      scope: scope.join(","),
    });
    if (pathFilter) {
      params.append("path_filter", pathFilter);
    }
    return this.request(`/vault/search?${params}`);
  }

  async findRelatedNotes(path: string, on: string[] = ["tags", "links"]) {
    const params = new URLSearchParams({
      on: on.join(","),
    });
    return this.request(`/vault/notes/related/${encodeURIComponent(path)}?${params}`);
  }

  // Legacy methods for backward compatibility
  async listFiles() {
    return this.request("/files");
  }

  async getFile(path: string) {
    return this.request(`/files/${encodeURIComponent(path)}`);
  }

  async createFile(path: string, content: string, type: "file" | "directory" = "file") {
    return this.request("/files", {
      method: "POST",
      body: JSON.stringify({ path, content, type }),
    });
  }

  async updateFile(path: string, content: string) {
    return this.request(`/files/${encodeURIComponent(path)}`, {
      method: "PUT",
      body: JSON.stringify({ content }),
    });
  }

  async deleteFile(path: string) {
    return this.request(`/files/${encodeURIComponent(path)}`, {
      method: "DELETE",
    });
  }

  // Notes endpoints
  async listNotes() {
    return this.request("/notes");
  }

  async getNote(path: string) {
    return this.request(`/notes/${encodeURIComponent(path)}`);
  }

  async createNote(path: string, content: string, frontmatter?: Record<string, any>) {
    const body: any = { path, content };
    if (frontmatter) {
      body.frontmatter = frontmatter;
    }
    return this.request("/notes", {
      method: "POST",
      body: JSON.stringify(body),
    });
  }

  async updateNote(path: string, content?: string, frontmatter?: Record<string, any>) {
    const body: any = {};
    if (content !== undefined) body.content = content;
    if (frontmatter !== undefined) body.frontmatter = frontmatter;

    return this.request(`/notes/${encodeURIComponent(path)}`, {
      method: "PATCH",
      body: JSON.stringify(body),
    });
  }

  async deleteNote(path: string) {
    return this.request(`/notes/${encodeURIComponent(path)}`, {
      method: "DELETE",
    });
  }

  // Search notes
  async searchNotes(query: string) {
    return this.request(`/notes?search=${encodeURIComponent(query)}`);
  }

  // Metadata endpoints
  async getMetadataKeys() {
    return this.request("/metadata/keys");
  }

  async getMetadataValues(key: string) {
    return this.request(`/metadata/values/${encodeURIComponent(key)}`);
  }
}

// MCP Server implementation
class ObsidianMcpServer {
  private server: Server;
  private client: ObsidianApiClient;

  constructor(config: Config) {
    this.client = new ObsidianApiClient(config);
    this.server = new Server({
      name: "obsidian-vault-mcp",
      version: "1.0.0",
    }, {
      capabilities: {
        tools: {},
      },
    });

    this.setupTools();
  }

  private setupTools() {
    // AI-Native Tools Definition
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        // Directory Operations
        {
          name: "list_directory",
          description: "List directory contents with pagination to prevent context overflow. Shows immediate contents by default.",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Directory path to list", default: "." },
              recursive: { type: "boolean", description: "Include subdirectories recursively", default: false },
              limit: { type: "number", description: "Maximum items to return", default: 50 },
              offset: { type: "number", description: "Pagination offset", default: 0 },
            },
          },
        },

        // File Operations
        {
          name: "read_file",
          description: "Read content of a specific file from the vault",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path to the file" },
            },
            required: ["path"],
          },
        },
        {
          name: "write_file",
          description: "Write file content with different modes: overwrite (default), append, or prepend. Handles both create and update operations.",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path to the file" },
              content: { type: "string", description: "Content to write" },
              mode: { type: "string", enum: ["overwrite", "append", "prepend"], description: "Write mode", default: "overwrite" },
            },
            required: ["path", "content"],
          },
        },
        {
          name: "delete_item",
          description: "Delete a file or directory from the vault",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path to the item to delete" },
            },
            required: ["path"],
          },
        },

        // AI-Native Note Operations
        {
          name: "create_or_update_note",
          description: "Create or update a note with content and frontmatter. Performs upsert operation - creates if doesn't exist, updates if it does.",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path for the note (without .md extension)" },
              content: { type: "string", description: "Note content" },
              frontmatter: { type: "object", description: "Frontmatter metadata", default: {} },
            },
            required: ["path", "content"],
          },
        },
        {
          name: "get_daily_note",
          description: "Get daily note for a specific date. Handles common daily note naming conventions and file locations.",
          inputSchema: {
            type: "object",
            properties: {
              date: { type: "string", description: "Date (today, yesterday, tomorrow, or YYYY-MM-DD)", default: "today" },
            },
          },
        },
        {
          name: "get_recent_notes",
          description: "Get recently modified notes, ordered by modification time",
          inputSchema: {
            type: "object",
            properties: {
              limit: { type: "number", description: "Number of recent notes to return", default: 5 },
            },
          },
        },

        // Enhanced Search and Discovery
        {
          name: "search_vault",
          description: "Search vault content across files, filenames, and metadata with advanced filtering",
          inputSchema: {
            type: "object",
            properties: {
              query: { type: "string", description: "Search query" },
              scope: {
                type: "array",
                items: { type: "string", enum: ["content", "filename", "tags"] },
                description: "Search scope - where to look for the query",
                default: ["content", "filename", "tags"]
              },
              path_filter: { type: "string", description: "Limit search to specific path prefix" },
            },
            required: ["query"],
          },
        },
        {
          name: "find_related_notes",
          description: "Find notes related to a given note based on shared tags, links, or backlinks",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path to the source note" },
              on: {
                type: "array",
                items: { type: "string", enum: ["tags", "links"] },
                description: "Relationship criteria to use for finding related notes",
                default: ["tags", "links"]
              },
            },
            required: ["path"],
          },
        },

        // Legacy Tools (for backward compatibility)
        {
          name: "get_note",
          description: "Get a specific note with its content and metadata (legacy)",
          inputSchema: {
            type: "object",
            properties: {
              path: { type: "string", description: "Path to the note" },
            },
            required: ["path"],
          },
        },
        {
          name: "list_notes",
          description: "List all notes in the vault with optional search filter (legacy with search support)",
          inputSchema: {
            type: "object",
            properties: {
              search: { type: "string", description: "Optional search query to filter notes" },
            },
          },
        },
        {
          name: "get_metadata_keys",
          description: "Get all available frontmatter keys from notes",
          inputSchema: {
            type: "object",
            properties: {},
          },
        },
        {
          name: "get_metadata_values",
          description: "Get all unique values for a specific frontmatter key",
          inputSchema: {
            type: "object",
            properties: {
              key: { type: "string", description: "Frontmatter key" },
            },
            required: ["key"],
          },
        },
      ],
    }));

    // Tool call handler
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      try {
        let result: any;

        switch (name) {
          // AI-Native Tools
          case "list_directory":
            result = await this.client.listDirectory(
              args?.path as string,
              args?.recursive as boolean,
              args?.limit as number,
              args?.offset as number
            );
            break;

          case "read_file":
            result = await this.client.readFile(args?.path as string);
            break;

          case "write_file":
            result = await this.client.writeFile(
              args?.path as string,
              args?.content as string,
              args?.mode as string
            );
            break;

          case "delete_item":
            result = await this.client.deleteItem(args?.path as string);
            break;

          case "create_or_update_note":
            result = await this.client.createOrUpdateNote(
              args?.path as string,
              args?.content as string,
              args?.frontmatter as Record<string, any>
            );
            break;

          case "get_daily_note":
            result = await this.client.getDailyNote(args?.date as string);
            break;

          case "get_recent_notes":
            result = await this.client.getRecentNotes(args?.limit as number);
            break;

          case "search_vault":
            result = await this.client.searchVault(
              args?.query as string,
              args?.scope as string[],
              args?.path_filter as string
            );
            break;

          case "find_related_notes":
            result = await this.client.findRelatedNotes(
              args?.path as string,
              args?.on as string[]
            );
            break;

          // Legacy Tools (backward compatibility)
          case "list_notes":
            const searchQuery = args?.search as string;
            if (searchQuery) {
              // Use the enhanced search functionality
              result = await this.client.searchVault(searchQuery, ["content", "filename", "tags"]);
            } else {
              result = await this.client.listNotes();
            }
            break;

          case "get_note":
            result = await this.client.getNote(args?.path as string);
            break;

          case "get_metadata_keys":
            result = await this.client.getMetadataKeys();
            break;

          case "get_metadata_values":
            result = await this.client.getMetadataValues(args?.key as string);
            break;

          default:
            throw new Error(`Unknown tool: ${name}`);
        }

        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    });
  }

  async start() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error("Obsidian MCP Server running on stdio");

    // Keep the process alive
    const keepAlive = () => {
      setTimeout(keepAlive, 1000);
    };
    keepAlive();
  }
}

// Main function
async function main() {
  // Read configuration from environment variables
  const config = ConfigSchema.parse({
    baseUrl: process.env.OBSIDIAN_API_URL || "http://obsidian-local-rest-api.test",
    apiKey: process.env.OBSIDIAN_API_KEY,
  });

  const mcpServer = new ObsidianMcpServer(config);
  await mcpServer.start();
}

// Error handling
process.on('SIGINT', () => {
  process.exit(0);
});

process.on('SIGTERM', () => {
  process.exit(0);
});

// Run the server if this file is executed directly
main().catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});

```

--------------------------------------------------------------------------------
/src/openapi.json:
--------------------------------------------------------------------------------

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Obsidian Vault REST API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://{host}/api",
      "variables": {
        "host": {
          "default": "localhost",
          "description": "Base hostname (change to 127.0.0.1, my-vm.local, etc.)"
        }
      }
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "schemas": {
      "SuccessResponse": {
        "description": "Successful operation",
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "path": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "description": "Error response",
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Note": {
        "description": "A vault note",
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "front_matter": {
            "type": "object",
            "additionalProperties": true
          },
          "content": {
            "type": "string"
          }
        }
      },
      "NoteInput": {
        "description": "Input for creating or replacing a note",
        "type": "object",
        "required": [
          "path"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "front_matter": {
            "type": "object",
            "additionalProperties": true
          },
          "content": {
            "type": "string"
          }
        }
      },
      "NoteUpdate": {
        "description": "Partial update for a note",
        "type": "object",
        "required": [
          "path"
        ],
        "properties": {
          "path": {
            "type": "string"
          },
          "front_matter": {
            "type": "object",
            "additionalProperties": true
          },
          "content": {
            "type": "string"
          }
        }
      },
      "BulkDeleteInput": {
        "description": "Input for deleting multiple notes",
        "type": "object",
        "required": [
          "paths"
        ],
        "properties": {
          "paths": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "BulkDeleteResult": {
        "description": "Result of bulk delete",
        "type": "object",
        "properties": {
          "deleted": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "notFound": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "BulkUpdateInput": {
        "description": "Input for updating multiple notes",
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NoteUpdate"
            }
          }
        }
      },
      "BulkUpdateResult": {
        "description": "Result of bulk update",
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "note": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/files": {
      "get": {
        "tags": [
          "Files"
        ],
        "operationId": "listFiles",
        "summary": "List all files in the vault",
        "responses": {
          "200": {
            "description": "List of file objects, each with path, last_modified, created_at, size, and mime_type",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "path": {
                        "type": "string"
                      },
                      "last_modified": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "created_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "size": {
                        "type": "integer"
                      },
                      "mime_type": {
                        "type": "string",
                        "nullable": true
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Files"
        ],
        "operationId": "createFile",
        "summary": "Create a new file in the vault (legacy)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path"
                ],
                "properties": {
                  "path": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "file",
                      "directory"
                    ]
                  },
                  "content": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "File created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "409": {
            "description": "File already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/files/write": {
      "post": {
        "tags": [
          "Files"
        ],
        "operationId": "writeFileSmart",
        "summary": "Write a file with mode (overwrite, append, prepend)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path",
                  "content"
                ],
                "properties": {
                  "path": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "overwrite",
                      "append",
                      "prepend"
                    ],
                    "default": "overwrite"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Write completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "path": {
                      "type": "string"
                    },
                    "mode": {
                      "type": "string"
                    },
                    "size": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{path}": {
      "get": {
        "tags": [
          "Files"
        ],
        "operationId": "getFile",
        "summary": "Get raw content of a file",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "style": "simple",
            "explode": false,
            "allowReserved": true,
            "required": true,
            "description": "URL-encoded vault-relative path to file"
          }
        ],
        "responses": {
          "200": {
            "description": "Raw file content",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "404": {
            "description": "File not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Files"
        ],
        "operationId": "updateFile",
        "summary": "Update file content (legacy)",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "style": "simple",
            "explode": false,
            "allowReserved": true,
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content"
                ],
                "properties": {
                  "content": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "404": {
            "description": "File not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Files"
        ],
        "operationId": "deleteFile",
        "summary": "Delete a file or directory",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "style": "simple",
            "explode": false,
            "allowReserved": true,
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "File deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "404": {
            "description": "File not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/notes": {
      "get": {
        "tags": [
          "Notes"
        ],
        "operationId": "listNotes",
        "summary": "List all markdown notes with parsed front matter",
        "responses": {
          "200": {
            "description": "List of notes (Laravel Resource)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Note"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Notes"
        ],
        "operationId": "createNote",
        "summary": "Create a new note (legacy)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Note created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          }
        }
      }
    },
    "/notes/upsert": {
      "post": {
        "tags": [
          "Notes"
        ],
        "operationId": "upsertNote",
        "summary": "Create or update a note intelligently",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "path"
                ],
                "properties": {
                  "path": {
                    "type": "string"
                  },
                  "front_matter": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "content": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Note upserted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          }
        }
      }
    },
    "/notes/{path}": {
      "get": {
        "tags": [
          "Notes"
        ],
        "operationId": "getNote",
        "summary": "Retrieve a single note",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "style": "simple",
            "explode": false,
            "allowReserved": true,
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Note object",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "404": {
            "description": "Note not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Notes"
        ],
        "operationId": "replaceNote",
        "summary": "Replace a note (legacy)",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Note replaced",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "404": {
            "description": "Note not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Notes"
        ],
        "operationId": "updateNote",
        "summary": "Update parts of a note (legacy)",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "front_matter": {
                    "type": "object"
                  },
                  "content": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Note updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "404": {
            "description": "Note not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Notes"
        ],
        "operationId": "deleteNote",
        "summary": "Delete a note",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Note deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "404": {
            "description": "Note not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/bulk/notes/delete": {
      "delete": {
        "tags": [
          "Notes"
        ],
        "operationId": "bulkDeleteNotes",
        "summary": "Delete multiple notes",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkDeleteInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk delete result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkDeleteResult"
                }
              }
            }
          }
        }
      }
    },
    "/bulk/notes/update": {
      "patch": {
        "tags": [
          "Notes"
        ],
        "operationId": "bulkUpdateNotes",
        "summary": "Update multiple notes",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkUpdateInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk update result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkUpdateResult"
                }
              }
            }
          }
        }
      }
    },
    "/metadata/keys": {
      "get": {
        "tags": [
          "Metadata"
        ],
        "operationId": "listMetadataKeys",
        "summary": "List all front matter keys across notes",
        "responses": {
          "200": {
            "description": "Unique keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "/metadata/values/{key}": {
        "get": {
          "tags": [
            "Metadata"
          ],
          "operationId": "listMetadataValues",
          "summary": "List unique values for a front matter key",
          "parameters": [
            {
              "in": "path",
              "name": "key",
              "schema": {
                "type": "string"
              },
              "required": true
            }
          ],
          "responses": {
            "200": {
              "description": "Unique values",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "data"
                    ],
                    "properties": {
                      "data": {
                        "type": "array",
                        "items": {
                          "oneOf": [
                            {
                              "type": "string"
                            },
                            {
                              "type": "number"
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "/vault/directory": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "listDirectory",
            "summary": "List directory contents with pagination",
            "parameters": [
              {
                "in": "query",
                "name": "path",
                "schema": {
                  "type": "string",
                  "default": "."
                }
              },
              {
                "in": "query",
                "name": "recursive",
                "schema": {
                  "type": "boolean",
                  "default": false
                }
              },
              {
                "in": "query",
                "name": "limit",
                "schema": {
                  "type": "integer",
                  "default": 50
                }
              },
              {
                "in": "query",
                "name": "offset",
                "schema": {
                  "type": "integer",
                  "default": 0
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Directory listing",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/vault/search": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "searchVault",
            "summary": "Search vault content across content, filenames, and tags",
            "parameters": [
              {
                "in": "query",
                "name": "query",
                "schema": {
                  "type": "string"
                },
                "required": true
              },
              {
                "in": "query",
                "name": "scope",
                "schema": {
                  "type": "string",
                  "description": "Comma-separated: content,filename,tags"
                }
              },
              {
                "in": "query",
                "name": "path_filter",
                "schema": {
                  "type": "string"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Search results",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              },
              "400": {
                "description": "Missing query"
              }
            }
          }
        },
        "/vault/notes/recent": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "getRecentNotes",
            "summary": "Get recently modified notes",
            "parameters": [
              {
                "in": "query",
                "name": "limit",
                "schema": {
                  "type": "integer",
                  "default": 5
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Recent notes",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Note"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "/vault/notes/daily": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "getDailyNote",
            "summary": "Get daily note by date or shortcuts",
            "parameters": [
              {
                "in": "query",
                "name": "date",
                "schema": {
                  "type": "string",
                  "description": "today|yesterday|tomorrow|YYYY-MM-DD"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Daily note",
                "content": {
                  "application/json": {
                    "schema": {
                      "$ref": "#/components/schemas/Note"
                    }
                  }
                }
              },
              "404": {
                "description": "Not found"
              },
              "400": {
                "description": "Invalid date"
              }
            }
          }
        },
        "/vault/notes/related/{path}": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "getRelatedNotes",
            "summary": "Find related notes based on tags and links",
            "parameters": [
              {
                "in": "path",
                "name": "path",
                "schema": {
                  "type": "string"
                },
                "required": true
              },
              {
                "in": "query",
                "name": "on",
                "schema": {
                  "type": "string",
                  "description": "Comma-separated: tags,links"
                }
              },
              {
                "in": "query",
                "name": "limit",
                "schema": {
                  "type": "integer",
                  "default": 10
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Related notes",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              },
              "404": {
                "description": "Source note not found"
              }
            }
          }
        },
        "/vault/overview": {
          "get": {
            "tags": [
              "Vault"
            ],
            "operationId": "getVaultOverview",
            "summary": "Vault overview including README and first two folder levels",
            "responses": {
              "200": {
                "description": "Overview",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/agent/grep": {
          "post": {
            "tags": [
              "Agent"
            ],
            "operationId": "grepVault",
            "summary": "Search vault content with regex and patterns",
            "requestBody": {
              "required": true,
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "pattern"
                    ],
                    "properties": {
                      "pattern": {
                        "type": "string"
                      },
                      "is_regex": {
                        "type": "boolean"
                      },
                      "case_sensitive": {
                        "type": "boolean"
                      },
                      "include_frontmatter": {
                        "type": "boolean"
                      },
                      "file_pattern": {
                        "type": "string"
                      },
                      "max_results": {
                        "type": "integer"
                      },
                      "context_lines": {
                        "type": "integer"
                      }
                    }
                  }
                }
              }
            },
            "responses": {
              "200": {
                "description": "Search summary",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/agent/query-frontmatter": {
          "post": {
            "tags": [
              "Agent"
            ],
            "operationId": "queryFrontmatter",
            "summary": "Query frontmatter fields across notes",
            "requestBody": {
              "required": false,
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "properties": {
                      "fields": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "where": {
                        "type": "object",
                        "additionalProperties": true
                      },
                      "sort_by": {
                        "type": "string"
                      },
                      "sort_direction": {
                        "type": "string",
                        "enum": [
                          "asc",
                          "desc"
                        ]
                      },
                      "limit": {
                        "type": "integer"
                      },
                      "distinct": {
                        "type": "boolean"
                      }
                    }
                  }
                }
              }
            },
            "responses": {
              "200": {
                "description": "Query results",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/agent/backlinks/{note_path}": {
          "get": {
            "tags": [
              "Agent"
            ],
            "operationId": "getBacklinks",
            "summary": "Find backlinks and mentions for a note",
            "parameters": [
              {
                "in": "path",
                "name": "note_path",
                "schema": {
                  "type": "string"
                },
                "required": true
              },
              {
                "in": "query",
                "name": "include_mentions",
                "schema": {
                  "type": "boolean",
                  "default": true
                }
              },
              {
                "in": "query",
                "name": "include_tags",
                "schema": {
                  "type": "boolean",
                  "default": false
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Backlink summary",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/agent/tags": {
          "get": {
            "tags": [
              "Agent"
            ],
            "operationId": "getTags",
            "summary": "List tags across notes",
            "parameters": [
              {
                "in": "query",
                "name": "min_count",
                "schema": {
                  "type": "integer",
                  "default": 1
                }
              },
              {
                "in": "query",
                "name": "include_nested",
                "schema": {
                  "type": "boolean",
                  "default": true
                }
              },
              {
                "in": "query",
                "name": "format",
                "schema": {
                  "type": "string",
                  "enum": [
                    "flat",
                    "hierarchical"
                  ],
                  "default": "flat"
                }
              }
            ],
            "responses": {
              "200": {
                "description": "Tags",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        },
        "/agent/stats": {
          "get": {
            "tags": [
              "Agent"
            ],
            "operationId": "getVaultStats",
            "summary": "Get vault statistics and health metrics",
            "responses": {
              "200": {
                "description": "Stats",
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          }
        }
      },
      "components": {
        "securitySchemes": {
          "bearerAuth": {
            "type": "http",
            "scheme": "bearer",
            "bearerFormat": "JWT"
          }
        },
        "schemas": {
          "SuccessResponse": {
            "description": "Successful operation",
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "path": {
                "type": "string"
              }
            }
          },
          "ErrorResponse": {
            "description": "Error response",
            "type": "object",
            "properties": {
              "error": {
                "type": "string"
              }
            }
          },
          "Note": {
            "description": "A vault note",
            "type": "object",
            "properties": {
              "path": {
                "type": "string"
              },
              "front_matter": {
                "type": "object",
                "additionalProperties": true
              },
              "content": {
                "type": "string"
              }
            }
          },
          "NoteInput": {
            "description": "Input for creating or replacing a note",
            "type": "object",
            "required": [
              "path"
            ],
            "properties": {
              "path": {
                "type": "string"
              },
              "front_matter": {
                "type": "object",
                "additionalProperties": true
              },
              "content": {
                "type": "string"
              }
            }
          },
          "NoteUpdate": {
            "description": "Partial update for a note",
            "type": "object",
            "required": [
              "path"
            ],
            "properties": {
              "path": {
                "type": "string"
              },
              "front_matter": {
                "type": "object",
                "additionalProperties": true
              },
              "content": {
                "type": "string"
              }
            }
          },
          "BulkDeleteInput": {
            "description": "Input for deleting multiple notes",
            "type": "object",
            "required": [
              "paths"
            ],
            "properties": {
              "paths": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "BulkDeleteResult": {
            "description": "Result of bulk delete",
            "type": "object",
            "properties": {
              "deleted": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "notFound": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "BulkUpdateInput": {
            "description": "Input for updating multiple notes",
            "type": "object",
            "required": [
              "items"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/NoteUpdate"
                }
              }
            }
          },
          "BulkUpdateResult": {
            "description": "Result of bulk update",
            "type": "object",
            "properties": {
              "results": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "note": {
                      "$ref": "#/components/schemas/Note"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/metadata/values/{key}": {
      "get": {
        "tags": [
          "Metadata"
        ],
        "operationId": "listMetadataValues",
        "summary": "List unique values for a front matter key",
        "parameters": [
          {
            "in": "path",
            "name": "key",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Unique values",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "string"
                          },
                          {
                            "type": "number"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "/vault/directory": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "listDirectory",
          "summary": "List directory contents with pagination",
          "parameters": [
            {
              "in": "query",
              "name": "path",
              "schema": {
                "type": "string",
                "default": "."
              }
            },
            {
              "in": "query",
              "name": "recursive",
              "schema": {
                "type": "boolean",
                "default": false
              }
            },
            {
              "in": "query",
              "name": "limit",
              "schema": {
                "type": "integer",
                "default": 50
              }
            },
            {
              "in": "query",
              "name": "offset",
              "schema": {
                "type": "integer",
                "default": 0
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Directory listing",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/vault/search": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "searchVault",
          "summary": "Search vault content across content, filenames, and tags",
          "parameters": [
            {
              "in": "query",
              "name": "query",
              "schema": {
                "type": "string"
              },
              "required": true
            },
            {
              "in": "query",
              "name": "scope",
              "schema": {
                "type": "string",
                "description": "Comma-separated: content,filename,tags"
              }
            },
            {
              "in": "query",
              "name": "path_filter",
              "schema": {
                "type": "string"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Search results",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            },
            "400": {
              "description": "Missing query"
            }
          }
        }
      },
      "/vault/notes/recent": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "getRecentNotes",
          "summary": "Get recently modified notes",
          "parameters": [
            {
              "in": "query",
              "name": "limit",
              "schema": {
                "type": "integer",
                "default": 5
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Recent notes",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Note"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "/vault/notes/daily": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "getDailyNote",
          "summary": "Get daily note by date or shortcuts",
          "parameters": [
            {
              "in": "query",
              "name": "date",
              "schema": {
                "type": "string",
                "description": "today|yesterday|tomorrow|YYYY-MM-DD"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Daily note",
              "content": {
                "application/json": {
                  "schema": {
                    "$ref": "#/components/schemas/Note"
                  }
                }
              }
            },
            "404": {
              "description": "Not found"
            },
            "400": {
              "description": "Invalid date"
            }
          }
        }
      },
      "/vault/notes/related/{path}": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "getRelatedNotes",
          "summary": "Find related notes based on tags and links",
          "parameters": [
            {
              "in": "path",
              "name": "path",
              "schema": {
                "type": "string"
              },
              "required": true
            },
            {
              "in": "query",
              "name": "on",
              "schema": {
                "type": "string",
                "description": "Comma-separated: tags,links"
              }
            },
            {
              "in": "query",
              "name": "limit",
              "schema": {
                "type": "integer",
                "default": 10
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Related notes",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            },
            "404": {
              "description": "Source note not found"
            }
          }
        }
      },
      "/vault/overview": {
        "get": {
          "tags": [
            "Vault"
          ],
          "operationId": "getVaultOverview",
          "summary": "Vault overview including README and first two folder levels",
          "responses": {
            "200": {
              "description": "Overview",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/agent/grep": {
        "post": {
          "tags": [
            "Agent"
          ],
          "operationId": "grepVault",
          "summary": "Search vault content with regex and patterns",
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "pattern"
                  ],
                  "properties": {
                    "pattern": {
                      "type": "string"
                    },
                    "is_regex": {
                      "type": "boolean"
                    },
                    "case_sensitive": {
                      "type": "boolean"
                    },
                    "include_frontmatter": {
                      "type": "boolean"
                    },
                    "file_pattern": {
                      "type": "string"
                    },
                    "max_results": {
                      "type": "integer"
                    },
                    "context_lines": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "Search summary",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/agent/query-frontmatter": {
        "post": {
          "tags": [
            "Agent"
          ],
          "operationId": "queryFrontmatter",
          "summary": "Query frontmatter fields across notes",
          "requestBody": {
            "required": false,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "where": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "sort_by": {
                      "type": "string"
                    },
                    "sort_direction": {
                      "type": "string",
                      "enum": [
                        "asc",
                        "desc"
                      ]
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "distinct": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "Query results",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/agent/backlinks/{note_path}": {
        "get": {
          "tags": [
            "Agent"
          ],
          "operationId": "getBacklinks",
          "summary": "Find backlinks and mentions for a note",
          "parameters": [
            {
              "in": "path",
              "name": "note_path",
              "schema": {
                "type": "string"
              },
              "required": true
            },
            {
              "in": "query",
              "name": "include_mentions",
              "schema": {
                "type": "boolean",
                "default": true
              }
            },
            {
              "in": "query",
              "name": "include_tags",
              "schema": {
                "type": "boolean",
                "default": false
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Backlink summary",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/agent/tags": {
        "get": {
          "tags": [
            "Agent"
          ],
          "operationId": "getTags",
          "summary": "List tags across notes",
          "parameters": [
            {
              "in": "query",
              "name": "min_count",
              "schema": {
                "type": "integer",
                "default": 1
              }
            },
            {
              "in": "query",
              "name": "include_nested",
              "schema": {
                "type": "boolean",
                "default": true
              }
            },
            {
              "in": "query",
              "name": "format",
              "schema": {
                "type": "string",
                "enum": [
                  "flat",
                  "hierarchical"
                ],
                "default": "flat"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "Tags",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      },
      "/agent/stats": {
        "get": {
          "tags": [
            "Agent"
          ],
          "operationId": "getVaultStats",
          "summary": "Get vault statistics and health metrics",
          "responses": {
            "200": {
              "description": "Stats",
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/vault/directory": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "listDirectory",
        "summary": "List directory contents with pagination",
        "parameters": [
          {
            "in": "query",
            "name": "path",
            "schema": {
              "type": "string",
              "default": "."
            }
          },
          {
            "in": "query",
            "name": "recursive",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "in": "query",
            "name": "offset",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Directory listing",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/vault/search": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "searchVault",
        "summary": "Search vault content across content, filenames, and tags",
        "parameters": [
          {
            "in": "query",
            "name": "query",
            "schema": {
              "type": "string"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "scope",
            "schema": {
              "type": "string",
              "description": "Comma-separated: content,filename,tags"
            }
          },
          {
            "in": "query",
            "name": "path_filter",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Missing query"
          }
        }
      }
    },
    "/vault/notes/recent": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "getRecentNotes",
        "summary": "Get recently modified notes",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 5
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent notes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Note"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/vault/notes/daily": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "getDailyNote",
        "summary": "Get daily note by date or shortcuts",
        "parameters": [
          {
            "in": "query",
            "name": "date",
            "schema": {
              "type": "string",
              "description": "today|yesterday|tomorrow|YYYY-MM-DD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Daily note",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          },
          "400": {
            "description": "Invalid date"
          }
        }
      }
    },
    "/vault/notes/related/{path}": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "getRelatedNotes",
        "summary": "Find related notes based on tags and links",
        "parameters": [
          {
            "in": "path",
            "name": "path",
            "schema": {
              "type": "string"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "on",
            "schema": {
              "type": "string",
              "description": "Comma-separated: tags,links"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "type": "integer",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Related notes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "Source note not found"
          }
        }
      }
    },
    "/vault/overview": {
      "get": {
        "tags": [
          "Vault"
        ],
        "operationId": "getVaultOverview",
        "summary": "Vault overview including README and first two folder levels",
        "responses": {
          "200": {
            "description": "Overview",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/agent/grep": {
      "post": {
        "tags": [
          "Agent"
        ],
        "operationId": "grepVault",
        "summary": "Search vault content with regex and patterns",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pattern"
                ],
                "properties": {
                  "pattern": {
                    "type": "string"
                  },
                  "is_regex": {
                    "type": "boolean"
                  },
                  "case_sensitive": {
                    "type": "boolean"
                  },
                  "include_frontmatter": {
                    "type": "boolean"
                  },
                  "file_pattern": {
                    "type": "string"
                  },
                  "max_results": {
                    "type": "integer"
                  },
                  "context_lines": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/agent/query-frontmatter": {
      "post": {
        "tags": [
          "Agent"
        ],
        "operationId": "queryFrontmatter",
        "summary": "Query frontmatter fields across notes",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fields": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "where": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "sort_by": {
                    "type": "string"
                  },
                  "sort_direction": {
                    "type": "string",
                    "enum": [
                      "asc",
                      "desc"
                    ]
                  },
                  "limit": {
                    "type": "integer"
                  },
                  "distinct": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/agent/backlinks/{note_path}": {
      "get": {
        "tags": [
          "Agent"
        ],
        "operationId": "getBacklinks",
        "summary": "Find backlinks and mentions for a note",
        "parameters": [
          {
            "in": "path",
            "name": "note_path",
            "schema": {
              "type": "string"
            },
            "required": true
          },
          {
            "in": "query",
            "name": "include_mentions",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "in": "query",
            "name": "include_tags",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Backlink summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/agent/tags": {
      "get": {
        "tags": [
          "Agent"
        ],
        "operationId": "getTags",
        "summary": "List tags across notes",
        "parameters": [
          {
            "in": "query",
            "name": "min_count",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "in": "query",
            "name": "include_nested",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "in": "query",
            "name": "format",
            "schema": {
              "type": "string",
              "enum": [
                "flat",
                "hierarchical"
              ],
              "default": "flat"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/agent/stats": {
      "get": {
        "tags": [
          "Agent"
        ],
        "operationId": "getVaultStats",
        "summary": "Get vault statistics and health metrics",
        "responses": {
          "200": {
            "description": "Stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    }
  }
}

```