UNPKG

@notbnull/mcp-cursor-taskmaster

Version:

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

151 lines (150 loc) 5.39 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")); const os_1 = __importDefault(require("os")); class MemoryStore { db; dataDir; constructor(projectDir = process.cwd()) { // Ensure we have a valid project directory const validProjectDir = this.validateProjectDir(projectDir); this.dataDir = path_1.default.join(validProjectDir, ".taskmaster"); } validateProjectDir(projectDir) { // If projectDir is empty, root, or invalid, use a safe fallback if (!projectDir || projectDir === "/" || projectDir === "\\") { // Use home directory as fallback const fallbackDir = path_1.default.join(os_1.default.homedir(), ".cursor-taskmaster-projects", "default"); console.error(`Warning: Invalid project directory "${projectDir}", using fallback: ${fallbackDir}`); return fallbackDir; } // Resolve to absolute path to avoid relative path issues return path_1.default.resolve(projectDir); } 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