mcp-memory-keeper 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +433 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1051 -0
  4. package/bin/mcp-memory-keeper +52 -0
  5. package/dist/__tests__/helpers/database-test-helper.js +160 -0
  6. package/dist/__tests__/helpers/test-server.js +92 -0
  7. package/dist/__tests__/integration/advanced-features.test.js +614 -0
  8. package/dist/__tests__/integration/backward-compatibility.test.js +245 -0
  9. package/dist/__tests__/integration/batchOperationsE2E.test.js +396 -0
  10. package/dist/__tests__/integration/batchOperationsHandler.test.js +1230 -0
  11. package/dist/__tests__/integration/channelManagementHandler.test.js +1291 -0
  12. package/dist/__tests__/integration/channels.test.js +376 -0
  13. package/dist/__tests__/integration/checkpoint.test.js +251 -0
  14. package/dist/__tests__/integration/concurrent-access.test.js +190 -0
  15. package/dist/__tests__/integration/context-operations.test.js +243 -0
  16. package/dist/__tests__/integration/contextDiff.test.js +852 -0
  17. package/dist/__tests__/integration/contextDiffHandler.test.js +976 -0
  18. package/dist/__tests__/integration/contextExportHandler.test.js +510 -0
  19. package/dist/__tests__/integration/contextGetPaginationDefaults.test.js +298 -0
  20. package/dist/__tests__/integration/contextReassignChannelHandler.test.js +908 -0
  21. package/dist/__tests__/integration/contextRelationshipsHandler.test.js +1151 -0
  22. package/dist/__tests__/integration/contextSearch.test.js +938 -0
  23. package/dist/__tests__/integration/contextSearchHandler.test.js +552 -0
  24. package/dist/__tests__/integration/contextWatchActual.test.js +165 -0
  25. package/dist/__tests__/integration/contextWatchHandler.test.js +1500 -0
  26. package/dist/__tests__/integration/cross-session-sharing.test.js +302 -0
  27. package/dist/__tests__/integration/database-initialization.test.js +134 -0
  28. package/dist/__tests__/integration/enhanced-context-operations.test.js +1082 -0
  29. package/dist/__tests__/integration/enhancedContextGetHandler.test.js +915 -0
  30. package/dist/__tests__/integration/enhancedContextTimelineHandler.test.js +716 -0
  31. package/dist/__tests__/integration/error-cases.test.js +407 -0
  32. package/dist/__tests__/integration/export-import.test.js +367 -0
  33. package/dist/__tests__/integration/feature-flags.test.js +542 -0
  34. package/dist/__tests__/integration/file-operations.test.js +264 -0
  35. package/dist/__tests__/integration/git-integration.test.js +237 -0
  36. package/dist/__tests__/integration/index-tools.test.js +496 -0
  37. package/dist/__tests__/integration/issue11-actual-bug-demo.test.js +304 -0
  38. package/dist/__tests__/integration/issue11-search-filters-bug.test.js +561 -0
  39. package/dist/__tests__/integration/issue12-checkpoint-restore-behavior.test.js +621 -0
  40. package/dist/__tests__/integration/issue13-key-validation.test.js +433 -0
  41. package/dist/__tests__/integration/knowledge-graph.test.js +338 -0
  42. package/dist/__tests__/integration/migrations.test.js +528 -0
  43. package/dist/__tests__/integration/multi-agent.test.js +546 -0
  44. package/dist/__tests__/integration/pagination-critical-fix.test.js +296 -0
  45. package/dist/__tests__/integration/paginationDefaultsHandler.test.js +600 -0
  46. package/dist/__tests__/integration/project-directory.test.js +283 -0
  47. package/dist/__tests__/integration/resource-cleanup.test.js +149 -0
  48. package/dist/__tests__/integration/retention.test.js +513 -0
  49. package/dist/__tests__/integration/search.test.js +333 -0
  50. package/dist/__tests__/integration/semantic-search.test.js +266 -0
  51. package/dist/__tests__/integration/server-initialization.test.js +307 -0
  52. package/dist/__tests__/integration/session-management.test.js +219 -0
  53. package/dist/__tests__/integration/simplified-sharing.test.js +346 -0
  54. package/dist/__tests__/integration/smart-compaction.test.js +230 -0
  55. package/dist/__tests__/integration/summarization.test.js +308 -0
  56. package/dist/__tests__/integration/watcher-migration-validation.test.js +544 -0
  57. package/dist/__tests__/security/input-validation.test.js +115 -0
  58. package/dist/__tests__/utils/agents.test.js +473 -0
  59. package/dist/__tests__/utils/database.test.js +177 -0
  60. package/dist/__tests__/utils/git.test.js +122 -0
  61. package/dist/__tests__/utils/knowledge-graph.test.js +297 -0
  62. package/dist/__tests__/utils/migrationHealthCheck.test.js +302 -0
  63. package/dist/__tests__/utils/project-directory-messages.test.js +188 -0
  64. package/dist/__tests__/utils/timezone-safe-dates.js +119 -0
  65. package/dist/__tests__/utils/validation.test.js +200 -0
  66. package/dist/__tests__/utils/vector-store.test.js +231 -0
  67. package/dist/handlers/contextWatchHandlers.js +206 -0
  68. package/dist/index.js +4310 -0
  69. package/dist/index.phase1.backup.js +410 -0
  70. package/dist/index.phase2.backup.js +704 -0
  71. package/dist/migrations/003_add_channels.js +174 -0
  72. package/dist/migrations/004_add_context_watch.js +151 -0
  73. package/dist/migrations/005_add_context_watch.js +98 -0
  74. package/dist/migrations/simplify-sharing.js +117 -0
  75. package/dist/repositories/BaseRepository.js +30 -0
  76. package/dist/repositories/CheckpointRepository.js +140 -0
  77. package/dist/repositories/ContextRepository.js +1873 -0
  78. package/dist/repositories/FileRepository.js +104 -0
  79. package/dist/repositories/RepositoryManager.js +62 -0
  80. package/dist/repositories/SessionRepository.js +66 -0
  81. package/dist/repositories/WatcherRepository.js +252 -0
  82. package/dist/repositories/index.js +15 -0
  83. package/dist/server.js +384 -0
  84. package/dist/test-helpers/database-helper.js +128 -0
  85. package/dist/types/entities.js +3 -0
  86. package/dist/utils/agents.js +791 -0
  87. package/dist/utils/channels.js +150 -0
  88. package/dist/utils/database.js +731 -0
  89. package/dist/utils/feature-flags.js +476 -0
  90. package/dist/utils/git.js +145 -0
  91. package/dist/utils/knowledge-graph.js +264 -0
  92. package/dist/utils/migrationHealthCheck.js +373 -0
  93. package/dist/utils/migrations.js +452 -0
  94. package/dist/utils/retention.js +460 -0
  95. package/dist/utils/timestamps.js +112 -0
  96. package/dist/utils/validation.js +296 -0
  97. package/dist/utils/vector-store.js +247 -0
  98. package/package.json +84 -0
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Memory Keeper CLI
5
+ * This wrapper ensures the server runs correctly when invoked via npx
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const path = require('path');
10
+ const fs = require('fs');
11
+ const os = require('os');
12
+
13
+ // Determine the data directory
14
+ const DATA_DIR = process.env.DATA_DIR || path.join(os.homedir(), 'mcp-data', 'memory-keeper');
15
+
16
+ // Ensure data directory exists
17
+ if (!fs.existsSync(DATA_DIR)) {
18
+ fs.mkdirSync(DATA_DIR, { recursive: true });
19
+ }
20
+
21
+ // Set environment variable for the server
22
+ process.env.DATA_DIR = DATA_DIR;
23
+
24
+ // Get the path to the actual server
25
+ const serverPath = path.join(__dirname, '..', 'dist', 'index.js');
26
+
27
+ // Check if the server is built
28
+ if (!fs.existsSync(serverPath)) {
29
+ console.error('Error: Server not built. This should not happen with the npm package.');
30
+ console.error('Please report this issue at: https://github.com/mkreyman/mcp-memory-keeper/issues');
31
+ process.exit(1);
32
+ }
33
+
34
+ // Change to data directory (where context.db will be created)
35
+ process.chdir(DATA_DIR);
36
+
37
+ // Spawn the server
38
+ const child = spawn(process.execPath, [serverPath, ...process.argv.slice(2)], {
39
+ stdio: 'inherit',
40
+ env: process.env
41
+ });
42
+
43
+ // Handle exit
44
+ child.on('exit', (code) => {
45
+ process.exit(code);
46
+ });
47
+
48
+ // Handle errors
49
+ child.on('error', (err) => {
50
+ console.error('Failed to start memory-keeper server:', err);
51
+ process.exit(1);
52
+ });
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseTestHelper = void 0;
4
+ /**
5
+ * Helper utilities for managing database behavior in tests
6
+ */
7
+ class DatabaseTestHelper {
8
+ db;
9
+ originalTriggers = new Map();
10
+ constructor(db) {
11
+ this.db = db;
12
+ }
13
+ /**
14
+ * Disable timestamp update triggers to prevent unexpected timestamp updates
15
+ * during tests that are sensitive to update counts.
16
+ */
17
+ disableTimestampTriggers() {
18
+ const triggerNames = [
19
+ 'update_context_items_timestamp',
20
+ 'update_sessions_timestamp',
21
+ 'update_retention_policies_timestamp',
22
+ 'update_feature_flags_timestamp',
23
+ 'increment_sequence_update',
24
+ ];
25
+ for (const triggerName of triggerNames) {
26
+ // Get the trigger definition before dropping it
27
+ const triggerDef = this.db
28
+ .prepare(`SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = ?`)
29
+ .get(triggerName);
30
+ if (triggerDef && triggerDef.sql) {
31
+ this.originalTriggers.set(triggerName, triggerDef.sql);
32
+ // Drop the trigger
33
+ this.db.exec(`DROP TRIGGER IF EXISTS ${triggerName}`);
34
+ }
35
+ }
36
+ }
37
+ /**
38
+ * Re-enable timestamp update triggers after tests
39
+ */
40
+ enableTimestampTriggers() {
41
+ for (const [triggerName, sql] of this.originalTriggers) {
42
+ if (sql) {
43
+ try {
44
+ this.db.exec(sql);
45
+ }
46
+ catch (error) {
47
+ console.warn(`Failed to recreate trigger ${triggerName}:`, error);
48
+ }
49
+ }
50
+ }
51
+ this.originalTriggers.clear();
52
+ }
53
+ /**
54
+ * Normalize timestamps for comparison in tests.
55
+ * Sets all timestamps to a fixed value to avoid timestamp-based failures.
56
+ */
57
+ normalizeTimestamps(items) {
58
+ const fixedTimestamp = '2024-01-01T00:00:00.000Z';
59
+ return items.map(item => ({
60
+ ...item,
61
+ created_at: fixedTimestamp,
62
+ updated_at: fixedTimestamp,
63
+ }));
64
+ }
65
+ /**
66
+ * Update an item without triggering timestamp updates.
67
+ * Useful for tests that need to control timestamps precisely.
68
+ */
69
+ updateWithoutTimestamp(table, updates, where) {
70
+ // Build the UPDATE statement
71
+ const setClauses = Object.keys(updates)
72
+ .map(key => `${key} = ?`)
73
+ .join(', ');
74
+ const whereClauses = Object.keys(where)
75
+ .map(key => `${key} = ?`)
76
+ .join(' AND ');
77
+ const sql = `UPDATE ${table} SET ${setClauses} WHERE ${whereClauses}`;
78
+ const values = [...Object.values(updates), ...Object.values(where)];
79
+ // Temporarily disable triggers
80
+ this.disableTimestampTriggers();
81
+ try {
82
+ this.db.prepare(sql).run(...values);
83
+ }
84
+ finally {
85
+ // Re-enable triggers
86
+ this.enableTimestampTriggers();
87
+ }
88
+ }
89
+ /**
90
+ * Get counts of items by their modification status
91
+ * Useful for tests that check added vs modified items
92
+ */
93
+ getModificationCounts(sessionId, sinceTimestamp) {
94
+ const added = this.db
95
+ .prepare(`SELECT COUNT(*) as count FROM context_items
96
+ WHERE session_id = ? AND created_at > ?`)
97
+ .get(sessionId, sinceTimestamp);
98
+ const modified = this.db
99
+ .prepare(`SELECT COUNT(*) as count FROM context_items
100
+ WHERE session_id = ?
101
+ AND created_at <= ?
102
+ AND updated_at > ?`)
103
+ .get(sessionId, sinceTimestamp, sinceTimestamp);
104
+ return {
105
+ added: added.count,
106
+ modified: modified.count,
107
+ };
108
+ }
109
+ /**
110
+ * Create a test item with controlled timestamps
111
+ */
112
+ createTestItem(params) {
113
+ const { id, sessionId, key, value, createdAt = new Date().toISOString(), updatedAt = createdAt, category = null, priority = 'normal', channel = 'general', } = params;
114
+ // Temporarily disable triggers to control timestamps
115
+ this.disableTimestampTriggers();
116
+ try {
117
+ this.db
118
+ .prepare(`INSERT INTO context_items
119
+ (id, session_id, key, value, category, priority, channel, created_at, updated_at)
120
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
121
+ .run(id, sessionId, key, value, category, priority, channel, createdAt, updatedAt);
122
+ }
123
+ finally {
124
+ this.enableTimestampTriggers();
125
+ }
126
+ }
127
+ /**
128
+ * Helper to check if change tracking triggers are affecting counts
129
+ */
130
+ getChangeTrackingCount(sessionId, sinceSequence = 0) {
131
+ try {
132
+ const result = this.db
133
+ .prepare(`SELECT COUNT(*) as count FROM context_changes
134
+ WHERE session_id = ? AND sequence_id > ?`)
135
+ .get(sessionId, sinceSequence);
136
+ return result.count;
137
+ }
138
+ catch {
139
+ // Table might not exist in all test environments
140
+ return 0;
141
+ }
142
+ }
143
+ /**
144
+ * Clear all change tracking data for a clean test state
145
+ */
146
+ clearChangeTracking(sessionId) {
147
+ try {
148
+ if (sessionId) {
149
+ this.db.prepare('DELETE FROM context_changes WHERE session_id = ?').run(sessionId);
150
+ }
151
+ else {
152
+ this.db.prepare('DELETE FROM context_changes').run();
153
+ }
154
+ }
155
+ catch {
156
+ // Table might not exist in all test environments
157
+ }
158
+ }
159
+ }
160
+ exports.DatabaseTestHelper = DatabaseTestHelper;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TestServer = void 0;
37
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
38
+ const database_js_1 = require("../../utils/database.js");
39
+ const git_js_1 = require("../../utils/git.js");
40
+ const os = __importStar(require("os"));
41
+ const path = __importStar(require("path"));
42
+ const fs = __importStar(require("fs"));
43
+ class TestServer {
44
+ server;
45
+ dbManager;
46
+ gitOps;
47
+ tempDbPath;
48
+ constructor() {
49
+ // Create temporary database for testing
50
+ this.tempDbPath = path.join(os.tmpdir(), `test-mcp-${Date.now()}.db`);
51
+ this.dbManager = new database_js_1.DatabaseManager({
52
+ filename: this.tempDbPath,
53
+ maxSize: 10 * 1024 * 1024, // 10MB
54
+ walMode: true,
55
+ });
56
+ this.gitOps = new git_js_1.GitOperations(os.tmpdir());
57
+ // Import and configure the server logic here
58
+ // For now, we'll create a minimal server for testing
59
+ this.server = new index_js_1.Server({
60
+ name: 'test-memory-keeper',
61
+ version: '1.0.0',
62
+ }, {
63
+ capabilities: {
64
+ tools: {},
65
+ },
66
+ });
67
+ }
68
+ async callTool(name, args) {
69
+ // This would call the actual tool handler
70
+ // For now, returning a mock response
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: `Called ${name} with ${JSON.stringify(args)}`,
76
+ },
77
+ ],
78
+ };
79
+ }
80
+ cleanup() {
81
+ this.dbManager.close();
82
+ try {
83
+ fs.unlinkSync(this.tempDbPath);
84
+ fs.unlinkSync(`${this.tempDbPath}-wal`);
85
+ fs.unlinkSync(`${this.tempDbPath}-shm`);
86
+ }
87
+ catch (_e) {
88
+ // Ignore
89
+ }
90
+ }
91
+ }
92
+ exports.TestServer = TestServer;