mirror of
https://github.com/aaronsb/obsidian-mcp-plugin.git
synced 2026-07-22 16:40:32 +00:00
🎉 MAJOR RELEASE: Full semantic MCP server integration with direct plugin API access ✨ Semantic Tools Integrated (5 tools): - **vault**: File operations (list, read, create, update, delete, search, fragments) - **edit**: Smart editing (window, append, patch, at_line, from_buffer) - **view**: Content viewing (file, window, active, open_in_obsidian) - **workflow**: AI workflow guidance and suggestions - **system**: System operations (info, commands, fetch_web) 🔧 Architecture Achievements: - Replaced HTTP-based ObsidianAPI with direct app.vault/app.workspace calls - Preserved exact ObsidianAPI interface - semantic router unchanged - Integrated fragment retrieval system for large files - Added content buffer manager for edit recovery - Ported workflow configuration and state management 🚀 Performance & Capabilities: - Direct vault access - no HTTP overhead - Rich Obsidian API integration (search, commands, workspace) - Advanced search with fallback implementation - Image processing with Sharp integration - Fetch tool using native fetch API 📦 MCP Resources: - Added vault-info resource (obsidian://vault-info) - Real-time vault metadata and file counts - Active file tracking and plugin status 🛠️ Technical Implementation: - Removed axios dependencies - browser-compatible - Fixed all TypeScript type issues - Maintained proven MCP server patterns from obsidian-semantic-mcp - Updated to v0.3.0 with automatic version sync This completes the core architectural vision: semantic MCP operations with direct Obsidian plugin API integration for maximum performance and capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
89 lines
No EOL
2 KiB
TypeScript
89 lines
No EOL
2 KiB
TypeScript
/**
|
|
* Content buffer manager for storing generated content between edit attempts
|
|
*/
|
|
|
|
export interface BufferedContent {
|
|
content: string;
|
|
timestamp: number;
|
|
filePath?: string;
|
|
searchText?: string;
|
|
}
|
|
|
|
export class ContentBufferManager {
|
|
private static instance: ContentBufferManager;
|
|
private buffer: Map<string, BufferedContent> = new Map();
|
|
private defaultKey = '_last_generated';
|
|
private maxAge = 30 * 60 * 1000; // 30 minutes
|
|
|
|
private constructor() {}
|
|
|
|
static getInstance(): ContentBufferManager {
|
|
if (!ContentBufferManager.instance) {
|
|
ContentBufferManager.instance = new ContentBufferManager();
|
|
}
|
|
return ContentBufferManager.instance;
|
|
}
|
|
|
|
/**
|
|
* Store content in buffer
|
|
*/
|
|
store(content: string, key?: string, metadata?: { filePath?: string; searchText?: string }): void {
|
|
const bufferKey = key || this.defaultKey;
|
|
this.buffer.set(bufferKey, {
|
|
content,
|
|
timestamp: Date.now(),
|
|
...metadata
|
|
});
|
|
|
|
// Clean old entries
|
|
this.cleanOldEntries();
|
|
}
|
|
|
|
/**
|
|
* Retrieve content from buffer
|
|
*/
|
|
retrieve(key?: string): BufferedContent | null {
|
|
const bufferKey = key || this.defaultKey;
|
|
const entry = this.buffer.get(bufferKey);
|
|
|
|
if (!entry) return null;
|
|
|
|
// Check if entry is too old
|
|
if (Date.now() - entry.timestamp > this.maxAge) {
|
|
this.buffer.delete(bufferKey);
|
|
return null;
|
|
}
|
|
|
|
return entry;
|
|
}
|
|
|
|
/**
|
|
* Clear specific buffer or all buffers
|
|
*/
|
|
clear(key?: string): void {
|
|
if (key) {
|
|
this.buffer.delete(key);
|
|
} else {
|
|
this.buffer.clear();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all buffer keys
|
|
*/
|
|
getKeys(): string[] {
|
|
return Array.from(this.buffer.keys());
|
|
}
|
|
|
|
/**
|
|
* Clean entries older than maxAge
|
|
*/
|
|
private cleanOldEntries(): void {
|
|
const now = Date.now();
|
|
for (const [key, entry] of this.buffer.entries()) {
|
|
if (now - entry.timestamp > this.maxAge) {
|
|
this.buffer.delete(key);
|
|
}
|
|
}
|
|
}
|
|
} |