UNPKG

@notbnull/mcp-cursor-taskmaster

Version:

A project-scoped MCP server requiring explicit --project-dir configuration for task management, memory retrieval, and agentic workflows

138 lines (137 loc) 4.68 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MemoryStore = void 0; const better_sqlite3_1 = __importDefault(require("better-sqlite3")); const path_1 = __importDefault(require("path")); const promises_1 = __importDefault(require("fs/promises")); const crypto_1 = __importDefault(require("crypto")); class MemoryStore { db; dataDir; constructor(projectDir) { // Use the provided project directory directly - it's validated upstream this.dataDir = path_1.default.join(path_1.default.resolve(projectDir), ".taskmaster"); } async initialize() { try { // Ensure data directory exists console.error(`MemoryStore: Creating directory ${this.dataDir}`); await promises_1.default.mkdir(this.dataDir, { recursive: true }); // Initialize SQLite database const dbPath = path_1.default.join(this.dataDir, "memories.db"); this.db = new better_sqlite3_1.default(dbPath); // Create tables if they don't exist this.db.exec(` CREATE TABLE IF NOT EXISTS memories ( id TEXT PRIMARY KEY, key TEXT UNIQUE NOT NULL, content TEXT NOT NULL, metadata TEXT, timestamp TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_memories_key ON memories(key); CREATE INDEX IF NOT EXISTS idx_memories_timestamp ON memories(timestamp); `); console.error(`MemoryStore: Successfully initialized in ${this.dataDir}`); } catch (error) { console.error(`MemoryStore: Failed to initialize in ${this.dataDir}:`, error); throw new Error(`Failed to initialize MemoryStore: ${error instanceof Error ? error.message : "Unknown error"}`); } } async set(key, content, metadata) { const id = crypto_1.default.randomUUID(); const timestamp = new Date().toISOString(); const stmt = this.db.prepare(` INSERT OR REPLACE INTO memories (id, key, content, metadata, timestamp) VALUES (?, ?, ?, ?, ?) `); stmt.run(id, key, content, metadata ? JSON.stringify(metadata) : null, timestamp); return { id, key, content, metadata, timestamp, }; } async get(key) { const stmt = this.db.prepare(` SELECT * FROM memories WHERE key = ? `); const row = stmt.get(key); if (!row) return null; return { id: row.id, key: row.key, content: row.content, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, timestamp: row.timestamp, }; } async getById(id) { const stmt = this.db.prepare(` SELECT * FROM memories WHERE id = ? `); const row = stmt.get(id); if (!row) return null; return { id: row.id, key: row.key, content: row.content, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, timestamp: row.timestamp, }; } async delete(key) { const stmt = this.db.prepare(` DELETE FROM memories WHERE key = ? `); const result = stmt.run(key); return result.changes > 0; } async list(limit = 100, offset = 0) { const stmt = this.db.prepare(` SELECT * FROM memories ORDER BY timestamp DESC LIMIT ? OFFSET ? `); const rows = stmt.all(limit, offset); return rows.map((row) => ({ id: row.id, key: row.key, content: row.content, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, timestamp: row.timestamp, })); } async search(query) { const stmt = this.db.prepare(` SELECT * FROM memories WHERE content LIKE ? OR key LIKE ? ORDER BY timestamp DESC LIMIT 20 `); const searchPattern = `%${query}%`; const rows = stmt.all(searchPattern, searchPattern); return rows.map((row) => ({ id: row.id, key: row.key, content: row.content, metadata: row.metadata ? JSON.parse(row.metadata) : undefined, timestamp: row.timestamp, })); } close() { if (this.db) { this.db.close(); } } } exports.MemoryStore = MemoryStore; //# sourceMappingURL=memory-store.js.map