turbovault-tools
MCP Tools Layer - The bridge between AI agents and Obsidian vault operations.
This crate implements the Model Context Protocol (MCP) tools that enable AI agents to discover, query, analyze, and manage Obsidian vaults through a structured, type-safe API. It orchestrates all vault operations by integrating the parser, graph, vault, batch, and export crates into a cohesive agent-friendly interface.
Architecture Overview
AI Agent (Claude, GPT, etc.)
↓
MCP Protocol
↓
┌────────────────────────────────────────┐
│ turbovault-tools (THIS CRATE) │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Search Engine (Tantivy) │ │
│ │ - Full-text search │ │
│ │ - TF-IDF ranking │ │
│ │ - Tag & metadata filtering │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────┐ │
│ │ Template Engine │ │
│ │ - Pre-built templates │ │
│ │ - Field validation │ │
│ │ - Note generation │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────┐ │
│ │ 11 Tool Categories │ │
│ │ - File ops │ │
│ │ - Search & discovery │ │
│ │ - Graph analysis │ │
│ │ - Batch operations │ │
│ │ - Export & reporting │ │
│ │ - Templates │ │
│ │ - Validation │ │
│ │ - Metadata queries │ │
│ │ - Relationships │ │
│ │ - Vault lifecycle │ │
│ │ - Analysis tools │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
↓
┌────────────────────────────────────────┐
│ Integration with Other Crates │
│ │
│ turbovault-vault ─ File I/O │
│ turbovault-parser ─ OFM parsing │
│ turbovault-graph ─ Link analysis │
│ turbovault-batch ─ Transactions │
│ turbovault-export ─ Data export │
│ turbovault-core ─ Types & errors │
└────────────────────────────────────────┘
What This Crate Provides
1. Agent-Optimized API Surface
Every tool is designed with AI agents in mind:
- Discoverable: Tools describe themselves with clear names and parameters
- Structured Output: JSON-serializable results for easy parsing
- Error Friendly: Errors include suggestions and context for recovery
- Batching Support: Coordinate multiple operations atomically
- Search First: Rich search and discovery to find relevant notes
2. Production-Grade Search Engine
Built on Tantivy (Apache Lucene-inspired):
- Full-text indexing of all markdown content
- TF-IDF relevance scoring
- Field-specific search (content, title, tags, frontmatter)
- Advanced filtering (tags, metadata, exclusions)
- Related note recommendations
- Fuzzy matching support
3. Template System for Consistent Note Creation
Pre-built templates for common patterns:
- Documentation: Standard docs with sections and cross-references
- Tasks: Action items with priority, status, due dates
- Research: Findings with sources and related notes
Field types with validation:
- Text, LongText, Date (ISO 8601)
- Select (dropdown), MultiSelect (tags)
- Number, Boolean
- Custom examples and defaults
4. Comprehensive Vault Analysis
Health monitoring and metrics:
- Vault health scoring (0-100)
- Hub note detection (highly-connected nodes)
- Orphan and dead-end identification
- Broken link detection with suggestions
- Cycle detection in link graph
- Connectivity metrics and density
Tool Categories
FileTools (6 operations)
Basic file lifecycle management:
use FileTools;
let tools = new;
// Read note content
let content = tools.read_file.await?;
// Write/create note (atomic, creates directories)
tools.write_file.await?;
// Move/rename (updates all backlinks)
tools.move_file.await?;
// Copy with metadata preservation
tools.copy_file.await?;
// Safe deletion (validates path traversal)
tools.delete_file.await?;
Key Features:
- Path traversal protection (all paths validated against vault root)
- Atomic writes via temp files
- Automatic directory creation
- Safe error handling with rollback
SearchTools (4 operations)
Relationship discovery and navigation:
use SearchTools;
let tools = new;
// Find all notes linking to this note
let backlinks = tools.find_backlinks.await?;
// Find all notes this note links to
let forward_links = tools.find_forward_links.await?;
// Find notes within N hops in link graph
let related = tools.find_related_notes.await?;
// Simple filename search
let matching = tools.search_files.await?;
Key Features:
- Graph-based relationship tracking
- Hop distance limiting for performance
- Wikilink and embed support
- Bidirectional link traversal
SearchEngine (5 operations)
Full-text search powered by Tantivy:
use ;
let engine = new.await?;
// Simple keyword search
let results = engine.search.await?;
// Returns: Vec<SearchResultInfo> with scores, snippets, metadata
// Advanced search with filters
let query = new
.with_tags
.with_frontmatter
.exclude
.limit;
let results = engine.advanced_search.await?;
// Search by tags only
let tagged = engine.search_by_tags.await?;
// Find similar notes (content-based)
let similar = engine.find_related.await?;
// Get recommendations for an agent
let recommendations = engine.recommend_related.await?;
SearchResultInfo Structure:
Performance: Indexes on creation (~1000 files/sec), searches in <100ms for 10k+ note vaults.
TemplateEngine (4 operations)
Structured note creation for agents:
use ;
use HashMap;
let engine = new;
// List all available templates
let templates = engine.list_templates;
// Returns: ["doc", "task", "research"]
// Get template details
let task_template = engine.get_template.unwrap;
println!;
// Create note from template
let mut fields = new;
fields.insert;
fields.insert;
fields.insert;
let created = engine.create_from_template.await?;
// Result: CreatedNoteInfo with path, preview, template_id
// Find all notes created from a template
let task_notes = engine.find_notes_from_template.await?;
Built-in Templates:
-
doc (Documentation):
- Fields: title, summary, tags (architecture/security/guide)
- Structure: Overview, Details, Links sections
- Use case: Technical documentation, guides, explanations
-
task (Action Item):
- Fields: title, priority (low/medium/high/critical), due_date
- Structure: Priority, Description, Checklist
- Use case: Task tracking, TODOs, action items
-
research (Research Note):
- Fields: topic, date_researched
- Structure: Key Findings, Sources, Related notes
- Use case: Research findings, literature notes, investigations
Field Validation Examples:
// Date validation
template.validate_field?; // OK
template.validate_field?; // Error: Invalid date format
// Select validation
template.validate_field?; // OK
template.validate_field?; // Error: Invalid option
// Required field check
template.validate_field?; // Error: Field is required
AnalysisTools (4 operations)
Vault-wide statistics and metrics:
use AnalysisTools;
let tools = new;
// Get overall vault statistics
let stats = tools.get_vault_stats.await?;
// Returns: VaultStats {
// total_files, total_links, orphaned_files, average_links_per_file
// }
// Find orphaned notes (no incoming or outgoing links)
let orphans = tools.list_orphaned_notes.await?;
// Detect cycles (mutual reference chains)
let cycles = tools.detect_cycles.await?;
// Returns: Vec<Vec<String>> - each cycle is a loop of file paths
// Calculate link density (actual links / possible links)
let density = tools.get_link_density.await?;
// Returns: f64 (0.0 = no links, 1.0 = fully connected)
// Get comprehensive connectivity metrics
let metrics = tools.get_connectivity_metrics.await?;
// Returns: JSON with all metrics combined
GraphTools (7 operations)
Link graph analysis and health monitoring:
use GraphTools;
let tools = new;
// Quick health check (fast, essential metrics only)
let health = tools.quick_health_check.await?;
// Returns: HealthInfo {
// health_score: 85,
// total_notes: 1250,
// broken_links_count: 3,
// is_healthy: true
// }
// Full health analysis (comprehensive, slower)
let full = tools.full_health_analysis.await?;
// Includes: hub_notes, dead_end_notes, isolated_clusters
// Get broken links with suggestions
let broken = tools.get_broken_links.await?;
// Returns: Vec<BrokenLinkInfo> with suggestions for fixes
// Find hub notes (highly connected)
let hubs = tools.get_hub_notes.await?;
// Returns: Top 10 notes by link count
// Find dead-end notes (no outgoing links)
let dead_ends = tools.get_dead_end_notes.await?;
// Detect cycles in link graph
let cycles = tools.detect_cycles.await?;
// Get connected components (isolated groups)
let components = tools.get_connected_components.await?;
// Find isolated clusters (small disconnected groups)
let clusters = tools.get_isolated_clusters.await?;
Health Score Calculation:
- 100: Perfect (no broken links, no orphans)
- 80-99: Good (minor issues)
- 60-79: Fair (needs attention)
- 0-59: Poor (critical issues)
BatchTools (1 operation)
Atomic multi-file operations:
use BatchOperation;
use BatchTools;
let tools = new;
let operations = vec!;
// Execute atomically: all succeed or all fail
let result = tools.batch_execute.await?;
// Returns: BatchResult {
// success: true,
// executed: 3,
// total: 3,
// transaction_id: "uuid",
// duration_ms: 45,
// changes: ["Created: new/note.md", "Moved: old/path.md → new/path.md", ...]
// }
Batch Operation Types:
CreateFile: Create new file with contentWriteFile: Write/overwrite existing fileDeleteFile: Remove fileMoveFile: Rename/move fileUpdateLinks: Find and replace link targets
Transaction Guarantees:
- Conflict detection (operations on same file)
- Validation before execution
- Stop-on-first-error with detailed error reporting
- Transaction ID for tracking
ExportTools (4 operations)
Data export for downstream processing:
use ExportTools;
let tools = new;
// Export health report
let json = tools.export_health_report.await?;
let csv = tools.export_health_report.await?;
// Export broken links
let broken_json = tools.export_broken_links.await?;
// Export vault statistics
let stats_csv = tools.export_vault_stats.await?;
// Export comprehensive analysis report
let analysis = tools.export_analysis_report.await?;
Export Formats:
- JSON: Pretty-printed, nested structure, easy to parse
- CSV: Flattened, compatible with spreadsheets and databases
Use Cases:
- Time-series tracking of vault health
- External reporting and dashboards
- Integration with BI tools
- Historical trend analysis
ValidationTools (3 operations)
Content validation and quality checks:
use ValidationTools;
let tools = new;
// Validate single note with default rules
let report = tools.validate_note.await?;
// Returns: ValidationReportInfo {
// passed: true,
// total_issues: 2,
// warning_count: 2,
// issues: [...]
// }
// Validate with custom rules
let report = tools.validate_note_with_rules.await?;
// Validate entire vault
let vault_report = tools.validate_vault.await?;
// Quick validation with issue limit (for large vaults)
let quick = tools.validate_vault_quick.await?;
Validation Rules:
- Frontmatter presence and required fields
- Link validity (broken link detection)
- Content length minimums
- Custom validators can be added
Severity Levels:
- Info: Informational, not blocking
- Warning: Should fix but not critical
- Error: Important issue to address
- Critical: Blocks deployment or causes failures
MetadataTools (2 operations)
Frontmatter querying and extraction:
use MetadataTools;
let tools = new;
// Query files by metadata pattern
let results = tools.query_metadata.await?;
let results = tools.query_metadata.await?;
let results = tools.query_metadata.await?;
let results = tools.query_metadata.await?;
// Get specific metadata value (supports dot notation)
let value = tools.get_metadata_value.await?;
let nested = tools.get_metadata_value.await?;
Query Syntax:
key: "value"- Exact matchkey > number- Greater thankey < number- Less thankey: contains("substring")- String contains
Returns: JSON with matched files and their metadata
RelationshipTools (3 operations)
Link strength analysis and suggestions:
use RelationshipTools;
let tools = new;
// Calculate link strength between two files
let strength = tools.get_link_strength.await?;
// Returns: {
// strength: 0.75,
// components: {
// direct_links: 2,
// backlinks: 1,
// shared_references: 3
// },
// interpretation: "Strong - frequently connected"
// }
// Get link suggestions for a file
let suggestions = tools.suggest_links.await?;
// Returns: Top 5 suggested links with reasons
// Get centrality ranking (importance scores)
let rankings = tools.get_centrality_ranking.await?;
// Returns: All files ranked by betweenness, closeness, eigenvector centrality
Link Strength Calculation:
strength = (direct_links * 1.0) + (backlinks * 0.7) + (shared_references * 0.3)
normalized to 0.0-1.0
Centrality Metrics:
- Betweenness: How often this note bridges other notes
- Closeness: How quickly this note can reach others
- Eigenvector: Importance based on connections to important notes
VaultLifecycleTools (7 operations)
Multi-vault management and lifecycle:
use VaultLifecycleTools;
use Path;
let tools = new;
// Create new vault with template
let vault_info = tools.create_vault.await?;
// Add existing vault
let vault_info = tools.add_vault_from_path.await?;
// List all registered vaults
let vaults = tools.list_vaults.await?;
// Get active vault
let active = tools.get_active_vault.await?;
// Switch to different vault
tools.set_active_vault.await?;
// Remove vault from registry (doesn't delete files)
tools.remove_vault.await?;
// Validate vault structure
let validation = tools.validate_vault.await?;
Vault Templates:
- default: Areas, Projects, Resources, Archive (PARA method)
- research: Literature, Theory, Findings, Hypotheses
- team: Team, Projects, Decisions, Documentation
Practical Agent Workflows
Workflow 1: Finding and Analyzing Notes
Agent Goal: "Find all high-priority tasks that are overdue"
// Step 1: Search by metadata
let results = metadata_tools.query_metadata.await?;
// Step 2: Filter by date
let mut overdue = Vecnew;
for file in results.as_array.unwrap
// Step 3: Get task details
for path in overdue
Workflow 2: Vault Health Analysis
Agent Goal: "Analyze vault health and generate improvement report"
// Step 1: Quick health check
let health = graph_tools.quick_health_check.await?;
if health.health_score < 70
Workflow 3: Bulk Organization
Agent Goal: "Reorganize project notes into archive"
// Step 1: Find completed project notes
let completed = metadata_tools.query_metadata.await?;
// Step 2: Build batch operations
let mut operations = Vecnew;
for file in completed
// Step 3: Execute atomically
let result = batch_tools.batch_execute.await?;
if result.success
Workflow 4: Knowledge Discovery
Agent Goal: "Find notes related to current topic for context"
let current_note = "concepts/async-programming.md";
// Step 1: Get direct relationships
let backlinks = search_tools.find_backlinks.await?;
let forward_links = search_tools.find_forward_links.await?;
// Step 2: Get semantically similar notes
let similar = search_engine.find_related.await?;
// Step 3: Get notes within 2 hops in graph
let nearby = search_tools.find_related_notes.await?;
// Step 4: Search for related tags
let vault_file = vault_manager.parse_file.await?;
if let Some = vault_file.frontmatter
// Agent synthesizes: "I found 25 related notes:
// - 5 direct references
// - 10 semantically similar (by content)
// - 8 nearby in your knowledge graph
// - 12 with shared tags"
Workflow 5: Template-Based Note Creation
Agent Goal: "Create a new research note about Rust concurrency"
// Step 1: List available templates
let templates = template_engine.list_templates;
// Step 2: Select appropriate template
let research = template_engine.get_template.unwrap;
// Step 3: Fill in fields
let mut fields = new;
fields.insert;
fields.insert;
// Step 4: Create note from template
let created = template_engine.create_from_template.await?;
// Step 5: Find related notes to link
let related = search_engine.search.await?;
// Step 6: Update note with links
let mut content = file_tools.read_file.await?;
content.push_str;
for result in related.iter.take
file_tools.write_file.await?;
// Agent reports: "Created research note and linked to 5 related topics"
Integration with turbovault-server
The tools are registered with the MCP server via turbomcp macros:
// From crates/turbovault-server/src/tools.rs
use *;
use *;
Performance and Scaling
Memory Usage
- Base: ~50MB for server infrastructure
- Search Index: ~1MB per 1000 notes (in-memory Tantivy index)
- Link Graph: ~500KB per 1000 notes (in-memory graph structure)
- File Cache: Configurable, TTL-based eviction
Total for 10,000 note vault: ~80MB
Latency Characteristics
| Operation | Typical Latency | Notes |
|---|---|---|
| File Read | <10ms | Direct filesystem access |
| File Write | <20ms | Atomic write via temp file |
| Simple Search | <50ms | In-memory index lookup |
| Advanced Search | <100ms | With filters and ranking |
| Graph Analysis | <200ms | Full vault traversal |
| Health Check | <300ms | Comprehensive metrics |
| Batch Operation | 50ms * ops | Sequential with validation |
Throughput
- File Scanning: 1000+ files/second
- Search Indexing: 800+ files/second
- Concurrent Reads: Limited by filesystem
- Graph Building: 500+ files/second
Scaling Strategies
For Large Vaults (10k+ notes):
- Use
validate_vault_quick()instead ofvalidate_vault() - Limit search results with
.limit() - Cache frequently accessed notes
- Use batch operations for bulk updates
- Enable link graph persistence (future)
For Multiple Vaults:
- Use
VaultLifecycleToolsto manage multiple vaults - Only one vault active at a time (switch with
set_active_vault) - Each vault has independent index and graph
- Resource usage scales linearly with number of vaults
Error Handling from Agent Perspective
All tools return Result<T, Error> which maps to MCP errors:
Common Error Patterns
// File not found
Err
// → Agent receives: "NotFound" error, can suggest creating file
// Path traversal attempt
Err
// → Agent receives: "InvalidPath" error, understands security boundary
// Validation failure
Err
// → Agent receives: error with suggestion to add field
// Batch conflict
Err
// → Agent receives: error explaining operations need to be sequential
Error Recovery Strategies
For Agents:
- Parse error messages: Contain actionable information
- Use suggestions: Broken links include similar filenames
- Validate before batch: Call
validate()beforebatch_execute() - Check file existence: Use metadata query before operations
- Handle partial failures: BatchResult indicates which operation failed
Example Agent Error Handling:
match file_tools.read_file.await
Tool Input/Output Schema Patterns
Input Patterns
Simple String Arguments:
read_file
search
validate_note
Structured Options:
validate_note_with_rules
Builder Pattern for Complex Queries:
let query = new
.with_tags
.with_frontmatter
.limit;
Batch Operations (Enum-based):
vec!
Output Patterns
Simple Values:
String // File content
// List of paths
bool // Success/failure
f64 // Metrics
Structured Results:
VaultStats
SearchResultInfo
BatchResult
JSON Values (for flexibility):
Value // Metadata queries, metrics
Development and Testing
Running Tests
# Run all tests in this crate
# Run with output
# Run specific test
# Run with test coverage
Adding New Tools
- Create tool module (e.g.,
src/my_tools.rs):
use VaultManager;
use Arc;
- Export from lib.rs:
pub use MyTools;
- Register in server (in turbovault-server):
async
Testing Patterns
Unit Tests (in tool modules):
Integration Tests (require vault setup):
async
Dependencies
This crate integrates all other TurboVault crates:
[]
# Internal crates (ordered by dependency)
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
= { = true }
# MCP integration (turbomcp)
= { = "2.0.2", = ["full"] }
= "2.0.2"
= "2.0.2"
# Search engine (Apache Lucene-inspired)
= "0.22"
# Core async/serde/etc
= { = true }
= { = true }
= { = true }
= { = true, = ["serde"] }
Architecture Design Choices
Why Tantivy for Search?
- Production-grade: Used in production systems, battle-tested
- Lucene-inspired: Proven search architecture and algorithms
- Fast: Sub-100ms searches on 10k+ note vaults
- Memory-efficient: In-memory index with reasonable memory footprint
- Rust-native: No C dependencies, excellent safety and performance
Alternatives Considered:
- MeiliSearch: Too heavy, requires separate service
- Sonic: Limited query features
- Simple grep: No ranking, too slow for large vaults
- SQLite FTS5: Considered, but Tantivy has better Rust integration
Why Separate Tool Modules?
Single Responsibility:
- Each module focuses on one domain (search, files, graphs)
- Easy to understand and maintain
- Clear boundaries for testing
Composability:
- Tools can be used independently
- Agent can choose appropriate tools for task
- Easy to extend with new tool categories
Performance:
- Only create what you need (lazy initialization)
- Can optimize each domain separately
- Clear performance boundaries
Why Arc Everywhere?
Shared State:
- All tools need access to vault manager
- Vault manager maintains cache, graph, file locks
- Single source of truth for vault state
Thread Safety:
- Arc enables sharing across async tasks
- VaultManager uses internal locking (RwLock, DashMap)
- Safe concurrent access from multiple tools
Lifetime Simplicity:
- No lifetime annotations needed
- Tools can be moved freely
- Simplifies async code significantly
References to Other Documentation
For deeper dives into specific areas:
- Core Types and Errors: See
crates/turbovault-core/README.md - OFM Parsing: See
crates/turbovault-parser/README.md - Link Graph Analysis: See
crates/turbovault-graph/README.md - File Operations: See
crates/turbovault-vault/README.md - Batch Transactions: See
crates/turbovault-batch/README.md - Export Formats: See
crates/turbovault-export/README.md - MCP Server: See
crates/turbovault-server/README.md - Deployment: See
/docs/deployment/index.md(project root) - Code Quality: See
/DILIGENCE_PASS_COMPLETE.md(project root)
Future Enhancements
Potential additions (not yet implemented):
- Persistent Search Index: Save/load index to avoid rebuilding
- Incremental Indexing: Update index on file changes, not full rebuild
- Advanced Tantivy Features: Fuzzy search, phrase queries, boosting
- Custom Validators: Plugin system for validation rules
- More Templates: Code snippets, meeting notes, project templates
- Link Refactoring: Rename note and update all backlinks atomically
- Snapshot/Restore: Point-in-time vault backups
- Diff/Merge Tools: For concurrent edits and conflict resolution
- Real-time Collaboration: Multi-user editing support
- Graph Visualization: Export graph data for visualization tools
License
Part of the TurboVault project. See project root for license information.