@lesgo/memory-mcp 1.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { z } from 'zod';
6
+ import { GitHubClient } from './github.js';
7
+ import { cache } from './cache.js';
8
+ import { AsyncWriter } from './writer.js';
9
+ import { parseIndex } from './index-gen.js';
10
+ import { log } from './logger.js';
11
+ // Configuration schema - passed via MCP settings
12
+ const ConfigSchema = z.object({
13
+ repo: z.string().regex(/^[^/]+\/[^/]+$/, 'Must be in format "owner/repo"'),
14
+ token: z.string().min(1, 'GitHub token is required'),
15
+ });
16
+ // Tool input schemas
17
+ const ReadMemorySchema = z.object({
18
+ path: z.string().describe('Path to the memory file (e.g., "templates/user-story.md")'),
19
+ });
20
+ const SaveMemorySchema = z.object({
21
+ category: z.string().describe('Category folder (e.g., "templates", "standards", "knowledge"). Will be created if it does not exist.'),
22
+ name: z.string().describe('File name (e.g., "user-story.md" or "user-story")'),
23
+ content: z.string().describe('Content of the memory file'),
24
+ });
25
+ const DeleteMemorySchema = z.object({
26
+ path: z.string().describe('Path to the memory file to delete'),
27
+ });
28
+ const SearchMemorySchema = z.object({
29
+ query: z.string().describe('Search query (searches paths and content)'),
30
+ });
31
+ // Tool definitions
32
+ const TOOLS = [
33
+ {
34
+ name: 'list_knowledge',
35
+ description: 'List all available memory files organized by category. Returns the index of templates, standards, and knowledge files.',
36
+ inputSchema: {
37
+ type: 'object',
38
+ properties: {},
39
+ required: [],
40
+ },
41
+ },
42
+ {
43
+ name: 'read_memory',
44
+ description: 'Read the content of a specific memory file. Fast cached reads.',
45
+ inputSchema: {
46
+ type: 'object',
47
+ properties: {
48
+ path: {
49
+ type: 'string',
50
+ description: 'Path to the memory file (e.g., "templates/user-story.md")',
51
+ },
52
+ },
53
+ required: ['path'],
54
+ },
55
+ },
56
+ {
57
+ name: 'save_memory',
58
+ description: 'Create or update a memory file. Saves are async and non-blocking. Category folders are auto-created.',
59
+ inputSchema: {
60
+ type: 'object',
61
+ properties: {
62
+ category: {
63
+ type: 'string',
64
+ description: 'Category folder (e.g., "templates", "standards", "knowledge")',
65
+ },
66
+ name: {
67
+ type: 'string',
68
+ description: 'File name (e.g., "user-story.md")',
69
+ },
70
+ content: {
71
+ type: 'string',
72
+ description: 'Content of the memory file',
73
+ },
74
+ },
75
+ required: ['category', 'name', 'content'],
76
+ },
77
+ },
78
+ {
79
+ name: 'delete_memory',
80
+ description: 'Delete a memory file. Deletes are async and non-blocking.',
81
+ inputSchema: {
82
+ type: 'object',
83
+ properties: {
84
+ path: {
85
+ type: 'string',
86
+ description: 'Path to the memory file to delete',
87
+ },
88
+ },
89
+ required: ['path'],
90
+ },
91
+ },
92
+ {
93
+ name: 'search_memory',
94
+ description: 'Search across all memory files by keyword. Searches both file paths and content.',
95
+ inputSchema: {
96
+ type: 'object',
97
+ properties: {
98
+ query: {
99
+ type: 'string',
100
+ description: 'Search query',
101
+ },
102
+ },
103
+ required: ['query'],
104
+ },
105
+ },
106
+ ];
107
+ class MemoryMCPServer {
108
+ server;
109
+ github = null;
110
+ writer = null;
111
+ config = null;
112
+ constructor() {
113
+ this.server = new Server({
114
+ name: 'memory-mcp',
115
+ version: '1.0.0',
116
+ }, {
117
+ capabilities: {
118
+ tools: {},
119
+ },
120
+ });
121
+ this.setupHandlers();
122
+ }
123
+ setupHandlers() {
124
+ // List available tools
125
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
126
+ return { tools: TOOLS };
127
+ });
128
+ // Handle tool calls
129
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
130
+ const { name, arguments: args } = request.params;
131
+ try {
132
+ switch (name) {
133
+ case 'list_knowledge':
134
+ return await this.handleListKnowledge();
135
+ case 'read_memory':
136
+ return await this.handleReadMemory(args);
137
+ case 'save_memory':
138
+ return await this.handleSaveMemory(args);
139
+ case 'delete_memory':
140
+ return await this.handleDeleteMemory(args);
141
+ case 'search_memory':
142
+ return await this.handleSearchMemory(args);
143
+ default:
144
+ return {
145
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
146
+ isError: true,
147
+ };
148
+ }
149
+ }
150
+ catch (error) {
151
+ const message = error instanceof Error ? error.message : String(error);
152
+ return {
153
+ content: [{ type: 'text', text: `Error: ${message}` }],
154
+ isError: true,
155
+ };
156
+ }
157
+ });
158
+ }
159
+ async handleListKnowledge() {
160
+ const indexEntry = cache.get('index.json');
161
+ if (indexEntry) {
162
+ const index = parseIndex(indexEntry.content);
163
+ return {
164
+ content: [{
165
+ type: 'text',
166
+ text: JSON.stringify(index, null, 2),
167
+ }],
168
+ };
169
+ }
170
+ // Generate index from cache if index.json doesn't exist
171
+ const files = cache.keys()
172
+ .filter((path) => path !== 'index.json')
173
+ .map((path) => {
174
+ const parts = path.split('/');
175
+ return { path, category: parts.length > 1 ? parts[0] : 'root' };
176
+ });
177
+ const categories = [...new Set(files.map((f) => f.category))].sort();
178
+ return {
179
+ content: [{
180
+ type: 'text',
181
+ text: JSON.stringify({ categories, files, lastUpdated: new Date().toISOString() }, null, 2),
182
+ }],
183
+ };
184
+ }
185
+ async handleReadMemory(args) {
186
+ const { path } = ReadMemorySchema.parse(args);
187
+ // Try cache first (fast path)
188
+ let entry = cache.get(path);
189
+ if (!entry && this.github) {
190
+ // Cache miss - fetch from GitHub
191
+ const file = await this.github.getFile(path);
192
+ if (!file) {
193
+ return {
194
+ content: [{ type: 'text', text: `File not found: ${path}` }],
195
+ isError: true,
196
+ };
197
+ }
198
+ cache.set(path, file.content, file.sha);
199
+ entry = { content: file.content, sha: file.sha };
200
+ }
201
+ if (!entry) {
202
+ return {
203
+ content: [{ type: 'text', text: `File not found: ${path}` }],
204
+ isError: true,
205
+ };
206
+ }
207
+ return {
208
+ content: [{ type: 'text', text: entry.content }],
209
+ };
210
+ }
211
+ async handleSaveMemory(args) {
212
+ const { category, name, content } = SaveMemorySchema.parse(args);
213
+ if (!this.writer) {
214
+ return {
215
+ content: [{ type: 'text', text: 'Server not initialized' }],
216
+ isError: true,
217
+ };
218
+ }
219
+ const result = await this.writer.save(category, name, content);
220
+ if (!result.success) {
221
+ return {
222
+ content: [{ type: 'text', text: result.error ?? 'Save failed' }],
223
+ isError: true,
224
+ };
225
+ }
226
+ return {
227
+ content: [{ type: 'text', text: `Saved: ${result.path}` }],
228
+ };
229
+ }
230
+ async handleDeleteMemory(args) {
231
+ const { path } = DeleteMemorySchema.parse(args);
232
+ if (!this.writer) {
233
+ return {
234
+ content: [{ type: 'text', text: 'Server not initialized' }],
235
+ isError: true,
236
+ };
237
+ }
238
+ const result = await this.writer.delete(path);
239
+ if (!result.success) {
240
+ return {
241
+ content: [{ type: 'text', text: result.error ?? 'Delete failed' }],
242
+ isError: true,
243
+ };
244
+ }
245
+ return {
246
+ content: [{ type: 'text', text: `Deleted: ${path}` }],
247
+ };
248
+ }
249
+ async handleSearchMemory(args) {
250
+ const { query } = SearchMemorySchema.parse(args);
251
+ const results = cache.search(query);
252
+ if (results.length === 0) {
253
+ return {
254
+ content: [{ type: 'text', text: `No results found for: "${query}"` }],
255
+ };
256
+ }
257
+ const formatted = results
258
+ .map((r) => `**${r.path}**\n${r.snippet}`)
259
+ .join('\n\n---\n\n');
260
+ return {
261
+ content: [{ type: 'text', text: formatted }],
262
+ };
263
+ }
264
+ async initialize(config) {
265
+ log('init', `Initializing with repo: ${config.repo}`);
266
+ this.config = config;
267
+ this.github = new GitHubClient(config);
268
+ this.writer = new AsyncWriter(this.github);
269
+ // Validate GitHub access
270
+ const hasAccess = await this.github.validateAccess();
271
+ if (!hasAccess) {
272
+ throw new Error(`Cannot access repository: ${config.repo}. Check token permissions.`);
273
+ }
274
+ // Fetch full tree and populate cache
275
+ log('init', 'Fetching repository contents...');
276
+ const tree = await this.github.listTree();
277
+ log('init', `Found ${tree.length} files in repository`);
278
+ // Fetch content for all files
279
+ for (const { path, sha } of tree) {
280
+ try {
281
+ const file = await this.github.getFile(path);
282
+ if (file) {
283
+ cache.set(path, file.content, file.sha);
284
+ }
285
+ }
286
+ catch (error) {
287
+ log('init', `Failed to fetch ${path}: ${error}`);
288
+ }
289
+ }
290
+ log('init', `Cache populated with ${cache.size} files`);
291
+ // Drain any pending writes from previous session
292
+ await this.writer.drainQueue();
293
+ log('init', 'Server ready');
294
+ }
295
+ async run() {
296
+ const transport = new StdioServerTransport();
297
+ await this.server.connect(transport);
298
+ log('server', 'MCP server running on stdio');
299
+ }
300
+ }
301
+ // Main entry point
302
+ async function main() {
303
+ // Parse config from environment or command line
304
+ // MCP clients pass config via environment variables
305
+ const repo = process.env.MEMORY_MCP_REPO;
306
+ const token = process.env.MEMORY_MCP_TOKEN;
307
+ if (!repo || !token) {
308
+ console.error('Error: MEMORY_MCP_REPO and MEMORY_MCP_TOKEN environment variables are required.');
309
+ console.error('Configure these in your MCP client settings.');
310
+ process.exit(1);
311
+ }
312
+ try {
313
+ const config = ConfigSchema.parse({ repo, token });
314
+ const server = new MemoryMCPServer();
315
+ await server.initialize(config);
316
+ await server.run();
317
+ }
318
+ catch (error) {
319
+ console.error('Fatal error:', error);
320
+ process.exit(1);
321
+ }
322
+ }
323
+ main();
324
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ type LogCategory = 'init' | 'cache' | 'github' | 'queue' | 'writer' | 'server';
2
+ /**
3
+ * Log to stderr with category prefix
4
+ * MCP servers communicate via stdio, so all logging must go to stderr
5
+ */
6
+ export declare function log(category: LogCategory, message: string): void;
7
+ export {};
8
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhE"}
package/dist/logger.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Log to stderr with category prefix
3
+ * MCP servers communicate via stdio, so all logging must go to stderr
4
+ */
5
+ export function log(category, message) {
6
+ const timestamp = new Date().toISOString();
7
+ console.error(`[${timestamp}] [${category}] ${message}`);
8
+ }
9
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,QAAqB,EAAE,OAAe;IACxD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,49 @@
1
+ export interface QueueItem {
2
+ path: string;
3
+ content: string;
4
+ operation: 'save' | 'delete';
5
+ timestamp: number;
6
+ retryCount: number;
7
+ }
8
+ /**
9
+ * Persistent write queue for failed GitHub operations
10
+ * Stores pending writes to disk and retries on next operation
11
+ */
12
+ export declare class WriteQueue {
13
+ private items;
14
+ constructor();
15
+ /**
16
+ * Load queue from disk
17
+ */
18
+ private load;
19
+ /**
20
+ * Persist queue to disk
21
+ */
22
+ private save;
23
+ /**
24
+ * Add an item to the queue
25
+ */
26
+ enqueue(path: string, content: string, operation: 'save' | 'delete'): void;
27
+ /**
28
+ * Get all pending items
29
+ */
30
+ getAll(): QueueItem[];
31
+ /**
32
+ * Remove an item from the queue (after successful sync)
33
+ */
34
+ remove(path: string): void;
35
+ /**
36
+ * Increment retry count and remove if max retries exceeded
37
+ */
38
+ incrementRetry(path: string): boolean;
39
+ /**
40
+ * Check if queue is empty
41
+ */
42
+ get isEmpty(): boolean;
43
+ /**
44
+ * Get queue size
45
+ */
46
+ get size(): number;
47
+ }
48
+ export declare const writeQueue: WriteQueue;
49
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAKD;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAmB;;IAMhC;;OAEG;IACH,OAAO,CAAC,IAAI;IAaZ;;OAEG;IACH,OAAO,CAAC,IAAI;IAQZ;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAgB1E;;OAEG;IACH,MAAM,IAAI,SAAS,EAAE;IAIrB;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU1B;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAkBrC;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
package/dist/queue.js ADDED
@@ -0,0 +1,109 @@
1
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+ import { log } from './logger.js';
5
+ const QUEUE_FILE = join(homedir(), '.memory-mcp-queue.json');
6
+ const MAX_RETRIES = 3;
7
+ /**
8
+ * Persistent write queue for failed GitHub operations
9
+ * Stores pending writes to disk and retries on next operation
10
+ */
11
+ export class WriteQueue {
12
+ items = [];
13
+ constructor() {
14
+ this.load();
15
+ }
16
+ /**
17
+ * Load queue from disk
18
+ */
19
+ load() {
20
+ try {
21
+ if (existsSync(QUEUE_FILE)) {
22
+ const data = readFileSync(QUEUE_FILE, 'utf-8');
23
+ this.items = JSON.parse(data);
24
+ log('queue', `Loaded ${this.items.length} pending items from queue`);
25
+ }
26
+ }
27
+ catch (error) {
28
+ log('queue', `Failed to load queue file: ${error}`);
29
+ this.items = [];
30
+ }
31
+ }
32
+ /**
33
+ * Persist queue to disk
34
+ */
35
+ save() {
36
+ try {
37
+ writeFileSync(QUEUE_FILE, JSON.stringify(this.items, null, 2));
38
+ }
39
+ catch (error) {
40
+ log('queue', `Failed to save queue file: ${error}`);
41
+ }
42
+ }
43
+ /**
44
+ * Add an item to the queue
45
+ */
46
+ enqueue(path, content, operation) {
47
+ // Remove any existing item for the same path
48
+ this.items = this.items.filter((item) => item.path !== path);
49
+ this.items.push({
50
+ path,
51
+ content,
52
+ operation,
53
+ timestamp: Date.now(),
54
+ retryCount: 0,
55
+ });
56
+ this.save();
57
+ log('queue', `Enqueued ${operation} for: ${path}`);
58
+ }
59
+ /**
60
+ * Get all pending items
61
+ */
62
+ getAll() {
63
+ return [...this.items];
64
+ }
65
+ /**
66
+ * Remove an item from the queue (after successful sync)
67
+ */
68
+ remove(path) {
69
+ const before = this.items.length;
70
+ this.items = this.items.filter((item) => item.path !== path);
71
+ if (this.items.length < before) {
72
+ this.save();
73
+ log('queue', `Removed from queue: ${path}`);
74
+ }
75
+ }
76
+ /**
77
+ * Increment retry count and remove if max retries exceeded
78
+ */
79
+ incrementRetry(path) {
80
+ const item = this.items.find((i) => i.path === path);
81
+ if (!item)
82
+ return false;
83
+ item.retryCount++;
84
+ if (item.retryCount >= MAX_RETRIES) {
85
+ this.items = this.items.filter((i) => i.path !== path);
86
+ log('queue', `Max retries reached, dropping: ${path}`);
87
+ this.save();
88
+ return false;
89
+ }
90
+ this.save();
91
+ log('queue', `Retry ${item.retryCount}/${MAX_RETRIES} for: ${path}`);
92
+ return true;
93
+ }
94
+ /**
95
+ * Check if queue is empty
96
+ */
97
+ get isEmpty() {
98
+ return this.items.length === 0;
99
+ }
100
+ /**
101
+ * Get queue size
102
+ */
103
+ get size() {
104
+ return this.items.length;
105
+ }
106
+ }
107
+ // Global queue instance
108
+ export const writeQueue = new WriteQueue();
109
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { GitHubClient } from './github.js';
2
+ /**
3
+ * Async writer manager - handles non-blocking GitHub operations
4
+ * Updates cache immediately, returns to agent, syncs GitHub in background
5
+ */
6
+ export declare class AsyncWriter {
7
+ private github;
8
+ private pendingWrites;
9
+ constructor(github: GitHubClient);
10
+ /**
11
+ * Save a file - updates cache immediately, syncs GitHub async
12
+ * Returns immediately after cache update
13
+ */
14
+ save(category: string, name: string, content: string): Promise<{
15
+ success: boolean;
16
+ path: string;
17
+ error?: string;
18
+ }>;
19
+ /**
20
+ * Delete a file - removes from cache immediately, syncs GitHub async
21
+ */
22
+ delete(path: string): Promise<{
23
+ success: boolean;
24
+ error?: string;
25
+ }>;
26
+ /**
27
+ * Sync a file to GitHub (async, non-blocking)
28
+ */
29
+ private syncToGitHub;
30
+ /**
31
+ * Delete a file from GitHub (async, non-blocking)
32
+ */
33
+ private deleteFromGitHub;
34
+ /**
35
+ * Update index without blocking on errors
36
+ */
37
+ private updateIndexSafe;
38
+ /**
39
+ * Drain the write queue - called on startup and after successful operations
40
+ */
41
+ drainQueue(): Promise<void>;
42
+ }
43
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../src/writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAS3C;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAA0B;gBAEnC,MAAM,EAAE,YAAY;IAIhC;;;OAGG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAgCxH;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAgBzE;;OAEG;YACW,YAAY;IAiC1B;;OAEG;YACW,gBAAgB;IA4B9B;;OAEG;YACW,eAAe;IAQ7B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAiClC"}