ac-framework 1.7.0 → 1.9.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/README.md +26 -0
- package/bin/postinstall.js +21 -1
- package/framework/.agent/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.agent/workflows/ac-lite.md +192 -0
- package/framework/.agent/workflows/ac.md +40 -0
- package/framework/.amazonq/prompts/ac-lite.md +192 -0
- package/framework/.amazonq/prompts/ac.md +40 -0
- package/framework/.amazonq/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.antigravity/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.antigravity/workflows/ac-lite.md +192 -0
- package/framework/.antigravity/workflows/ac.md +40 -0
- package/framework/.augment/commands/ac-lite.md +192 -0
- package/framework/.augment/commands/ac.md +40 -0
- package/framework/.augment/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.claude/commands/opsx/ac-lite.md +192 -0
- package/framework/.claude/commands/opsx/ac.md +40 -0
- package/framework/.claude/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.cline/commands/opsx/ac-lite.md +192 -0
- package/framework/.cline/commands/opsx/ac.md +40 -0
- package/framework/.cline/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.clinerules/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.clinerules/workflows/ac-lite.md +192 -0
- package/framework/.clinerules/workflows/ac.md +40 -0
- package/framework/.codebuddy/commands/opsx/ac-lite.md +192 -0
- package/framework/.codebuddy/commands/opsx/ac.md +40 -0
- package/framework/.codebuddy/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.codex/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.continue/prompts/ac-lite.md +192 -0
- package/framework/.continue/prompts/ac.md +40 -0
- package/framework/.continue/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.cospec/openspec/commands/ac-lite.md +192 -0
- package/framework/.cospec/openspec/commands/ac.md +40 -0
- package/framework/.cospec/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.crush/commands/opsx/ac-lite.md +192 -0
- package/framework/.crush/commands/opsx/ac.md +40 -0
- package/framework/.crush/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.cursor/commands/ac-lite.md +192 -0
- package/framework/.cursor/commands/ac.md +40 -0
- package/framework/.cursor/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.factory/commands/ac-lite.md +192 -0
- package/framework/.factory/commands/ac.md +40 -0
- package/framework/.factory/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.gemini/commands/opsx/ac-lite.md +192 -0
- package/framework/.gemini/commands/opsx/ac.md +40 -0
- package/framework/.gemini/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.github/prompts/ac-lite.md +192 -0
- package/framework/.github/prompts/ac.md +40 -0
- package/framework/.github/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.iflow/commands/ac-lite.md +192 -0
- package/framework/.iflow/commands/ac.md +40 -0
- package/framework/.iflow/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.kilocode/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.kilocode/workflows/ac-lite.md +192 -0
- package/framework/.kilocode/workflows/ac.md +40 -0
- package/framework/.kimi/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.kimi/workflows/ac-lite.md +192 -0
- package/framework/.kimi/workflows/ac.md +40 -0
- package/framework/.opencode/command/ac-lite.md +192 -0
- package/framework/.opencode/command/ac.md +40 -0
- package/framework/.opencode/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.qoder/commands/opsx/ac-lite.md +192 -0
- package/framework/.qoder/commands/opsx/ac.md +40 -0
- package/framework/.qoder/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.qwen/commands/ac-lite.md +192 -0
- package/framework/.qwen/commands/ac.md +40 -0
- package/framework/.qwen/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.roo/commands/ac-lite.md +192 -0
- package/framework/.roo/commands/ac.md +40 -0
- package/framework/.roo/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.trae/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.windsurf/skills/acfm-memory/SKILL.md +312 -0
- package/framework/.windsurf/workflows/ac-lite.md +192 -0
- package/framework/.windsurf/workflows/ac.md +40 -0
- package/framework/AGENTS.md +39 -0
- package/framework/CLAUDE.md +39 -0
- package/framework/GEMINI.md +39 -0
- package/framework/copilot-instructions.md +39 -0
- package/package.json +5 -2
- package/src/cli.js +2 -0
- package/src/commands/init.js +98 -0
- package/src/commands/memory.js +833 -0
- package/src/index.js +46 -0
- package/src/mcp/server.js +345 -0
- package/src/mcp/server.js.bak +727 -0
- package/src/memory/autosave.js +382 -0
- package/src/memory/database.js +178 -0
- package/src/memory/engine.js +727 -0
- package/src/memory/index.js +62 -0
- package/src/memory/utils.js +128 -0
- package/src/services/mcp-installer.js +194 -0
- package/src/services/spec-engine.js +69 -1
|
@@ -0,0 +1,727 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MCP Server for AC Framework Memory System
|
|
5
|
+
* Exposes memory system functionality via Model Context Protocol
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import {
|
|
11
|
+
initDatabase,
|
|
12
|
+
isDatabaseInitialized,
|
|
13
|
+
saveMemory,
|
|
14
|
+
searchMemories,
|
|
15
|
+
getContext,
|
|
16
|
+
getTimeline,
|
|
17
|
+
getMemory,
|
|
18
|
+
updateMemory,
|
|
19
|
+
deleteMemory,
|
|
20
|
+
startSession,
|
|
21
|
+
endSession,
|
|
22
|
+
getStats,
|
|
23
|
+
findPatterns,
|
|
24
|
+
getConnections,
|
|
25
|
+
anticipateNeeds,
|
|
26
|
+
exportMemories,
|
|
27
|
+
importMemories,
|
|
28
|
+
pruneMemories,
|
|
29
|
+
MEMORY_TYPES,
|
|
30
|
+
IMPORTANCE_LEVELS
|
|
31
|
+
} from "../memory/index.js";
|
|
32
|
+
|
|
33
|
+
class MCPMemoryServer {
|
|
34
|
+
constructor() {
|
|
35
|
+
this.server = new Server(
|
|
36
|
+
{
|
|
37
|
+
name: "ac-framework-memory",
|
|
38
|
+
version: "1.0.0",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
capabilities: {
|
|
42
|
+
resources: {},
|
|
43
|
+
tools: {},
|
|
44
|
+
prompts: {},
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
this.setupHandlers();
|
|
50
|
+
|
|
51
|
+
// Initialize database if not already done
|
|
52
|
+
if (!isDatabaseInitialized()) {
|
|
53
|
+
initDatabase();
|
|
54
|
+
console.error("Memory system initialized for MCP server");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setupHandlers() {
|
|
59
|
+
// Register tools
|
|
60
|
+
this.server.setRequestHandler("tools/list", async () => ({
|
|
61
|
+
tools: [
|
|
62
|
+
{
|
|
63
|
+
name: "memory_save",
|
|
64
|
+
description: "Save a memory observation",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
type: "object",
|
|
67
|
+
properties: {
|
|
68
|
+
content: { type: "string", description: "Content to save in memory" },
|
|
69
|
+
type: {
|
|
70
|
+
type: "string",
|
|
71
|
+
enum: MEMORY_TYPES,
|
|
72
|
+
default: "general_insight",
|
|
73
|
+
description: "Type of memory"
|
|
74
|
+
},
|
|
75
|
+
importance: {
|
|
76
|
+
type: "string",
|
|
77
|
+
enum: IMPORTANCE_LEVELS,
|
|
78
|
+
default: "medium",
|
|
79
|
+
description: "Importance level"
|
|
80
|
+
},
|
|
81
|
+
tags: {
|
|
82
|
+
type: "array",
|
|
83
|
+
items: { type: "string" },
|
|
84
|
+
description: "Tags for categorization"
|
|
85
|
+
},
|
|
86
|
+
projectPath: { type: "string", description: "Associated project path" },
|
|
87
|
+
changeName: { type: "string", description: "Associated change name" },
|
|
88
|
+
confidence: {
|
|
89
|
+
type: "number",
|
|
90
|
+
minimum: 0,
|
|
91
|
+
maximum: 1,
|
|
92
|
+
description: "Confidence score (0-1)"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
required: ["content"]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "memory_search",
|
|
100
|
+
description: "Search memories using full-text search",
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {
|
|
104
|
+
query: { type: "string", description: "Search query" },
|
|
105
|
+
limit: { type: "number", default: 10, description: "Maximum results" },
|
|
106
|
+
type: {
|
|
107
|
+
type: "string",
|
|
108
|
+
enum: MEMORY_TYPES,
|
|
109
|
+
description: "Filter by memory type"
|
|
110
|
+
},
|
|
111
|
+
importance: {
|
|
112
|
+
type: "string",
|
|
113
|
+
enum: IMPORTANCE_LEVELS,
|
|
114
|
+
description: "Filter by importance"
|
|
115
|
+
},
|
|
116
|
+
projectPath: { type: "string", description: "Filter by project path" },
|
|
117
|
+
minConfidence: {
|
|
118
|
+
type: "number",
|
|
119
|
+
minimum: 0,
|
|
120
|
+
maximum: 1,
|
|
121
|
+
default: 0,
|
|
122
|
+
description: "Minimum confidence score"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
required: ["query"]
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: "memory_recall",
|
|
130
|
+
description: "Recall relevant context for a task or project",
|
|
131
|
+
inputSchema: {
|
|
132
|
+
type: "object",
|
|
133
|
+
properties: {
|
|
134
|
+
task: { type: "string", description: "Specific task to recall context for" },
|
|
135
|
+
projectPath: { type: "string", description: "Project path" },
|
|
136
|
+
changeName: { type: "string", description: "Change name" },
|
|
137
|
+
limit: { type: "number", default: 5, description: "Number of memories to return" },
|
|
138
|
+
days: { type: "number", default: 30, description: "Days to look back" }
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "memory_get",
|
|
144
|
+
description: "Get a specific memory by ID",
|
|
145
|
+
inputSchema: {
|
|
146
|
+
type: "object",
|
|
147
|
+
properties: {
|
|
148
|
+
id: { type: "number", description: "Memory ID" }
|
|
149
|
+
},
|
|
150
|
+
required: ["id"]
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "memory_timeline",
|
|
155
|
+
description: "Get timeline around a specific memory",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties: {
|
|
159
|
+
id: { type: "number", description: "Memory ID" },
|
|
160
|
+
window: { type: "number", default: 3, description: "Number of memories before/after" }
|
|
161
|
+
},
|
|
162
|
+
required: ["id"]
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "memory_stats",
|
|
167
|
+
description: "Get memory system statistics",
|
|
168
|
+
inputSchema: {
|
|
169
|
+
type: "object",
|
|
170
|
+
properties: {
|
|
171
|
+
projectPath: { type: "string", description: "Filter by project path" },
|
|
172
|
+
since: { type: "string", description: "ISO date string to filter from" }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: "memory_patterns",
|
|
178
|
+
description: "Find patterns in memories",
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
type: {
|
|
183
|
+
type: "string",
|
|
184
|
+
enum: MEMORY_TYPES,
|
|
185
|
+
description: "Filter by memory type"
|
|
186
|
+
},
|
|
187
|
+
minFrequency: {
|
|
188
|
+
type: "number",
|
|
189
|
+
default: 2,
|
|
190
|
+
description: "Minimum frequency for pattern detection"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "memory_anticipate",
|
|
197
|
+
description: "Anticipate memories needed for a future task",
|
|
198
|
+
inputSchema: {
|
|
199
|
+
type: "object",
|
|
200
|
+
properties: {
|
|
201
|
+
task: { type: "string", description: "Task to anticipate needs for" },
|
|
202
|
+
projectPath: { type: "string", description: "Project path" },
|
|
203
|
+
limit: { type: "number", default: 5, description: "Number of suggestions" }
|
|
204
|
+
},
|
|
205
|
+
required: ["task"]
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "memory_export",
|
|
210
|
+
description: "Export memories to JSON",
|
|
211
|
+
inputSchema: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
filePath: { type: "string", description: "File path to export to (optional)" },
|
|
215
|
+
shareableOnly: { type: "boolean", default: true, description: "Only export shareable memories" },
|
|
216
|
+
projectPath: { type: "string", description: "Filter by project path" },
|
|
217
|
+
since: { type: "string", description: "ISO date string to filter from" }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: "memory_import",
|
|
223
|
+
description: "Import memories from JSON",
|
|
224
|
+
inputSchema: {
|
|
225
|
+
type: "object",
|
|
226
|
+
properties: {
|
|
227
|
+
filePath: { type: "string", description: "File path to import from" },
|
|
228
|
+
merge: { type: "boolean", default: true, description: "Merge with existing memories" }
|
|
229
|
+
},
|
|
230
|
+
required: ["filePath"]
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: "memory_prune",
|
|
235
|
+
description: "Prune obsolete memories",
|
|
236
|
+
inputSchema: {
|
|
237
|
+
type: "object",
|
|
238
|
+
properties: {
|
|
239
|
+
olderThanDays: {
|
|
240
|
+
type: "number",
|
|
241
|
+
default: 90,
|
|
242
|
+
description: "Delete memories older than this many days"
|
|
243
|
+
},
|
|
244
|
+
dryRun: { type: "boolean", default: false, description: "Show what would be pruned without actually deleting" }
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
}));
|
|
250
|
+
|
|
251
|
+
this.server.setRequestHandler("tools/call", async (request) => {
|
|
252
|
+
try {
|
|
253
|
+
switch (request.params.name) {
|
|
254
|
+
case "memory_save": {
|
|
255
|
+
const result = await saveMemory({
|
|
256
|
+
content: request.params.arguments.content,
|
|
257
|
+
type: request.params.arguments.type,
|
|
258
|
+
importance: request.params.arguments.importance,
|
|
259
|
+
tags: request.params.arguments.tags,
|
|
260
|
+
projectPath: request.params.arguments.projectPath,
|
|
261
|
+
changeName: request.params.arguments.changeName,
|
|
262
|
+
confidence: request.params.arguments.confidence
|
|
263
|
+
});
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: "text",
|
|
268
|
+
text: JSON.stringify({
|
|
269
|
+
success: true,
|
|
270
|
+
id: result.id,
|
|
271
|
+
operation: result.operation,
|
|
272
|
+
revisionCount: result.revisionCount
|
|
273
|
+
}, null, 2)
|
|
274
|
+
}
|
|
275
|
+
]
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
case "memory_search": {
|
|
279
|
+
const results = await searchMemories(
|
|
280
|
+
request.params.arguments.query,
|
|
281
|
+
{
|
|
282
|
+
limit: request.params.arguments.limit,
|
|
283
|
+
type: request.params.arguments.type,
|
|
284
|
+
importance: request.params.arguments.importance,
|
|
285
|
+
projectPath: request.params.arguments.projectPath,
|
|
286
|
+
minConfidence: request.params.arguments.minConfidence
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
return {
|
|
290
|
+
content: [
|
|
291
|
+
{
|
|
292
|
+
type: "text",
|
|
293
|
+
text: JSON.stringify({
|
|
294
|
+
query: request.params.arguments.query,
|
|
295
|
+
count: results.length,
|
|
296
|
+
results: results
|
|
297
|
+
}, null, 2)
|
|
298
|
+
}
|
|
299
|
+
]
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
case "memory_recall": {
|
|
303
|
+
const results = await getContext({
|
|
304
|
+
projectPath: request.params.arguments.projectPath,
|
|
305
|
+
changeName: request.params.arguments.changeName,
|
|
306
|
+
currentTask: request.params.arguments.task,
|
|
307
|
+
limit: request.params.arguments.limit,
|
|
308
|
+
lookbackDays: request.params.arguments.days
|
|
309
|
+
});
|
|
310
|
+
return {
|
|
311
|
+
content: [
|
|
312
|
+
{
|
|
313
|
+
type: "text",
|
|
314
|
+
text: JSON.stringify({
|
|
315
|
+
task: request.params.arguments.task || null,
|
|
316
|
+
projectPath: request.params.arguments.projectPath,
|
|
317
|
+
count: results.length,
|
|
318
|
+
memories: results
|
|
319
|
+
}, null, 2)
|
|
320
|
+
}
|
|
321
|
+
]
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
case "memory_get": {
|
|
325
|
+
const memory = await getMemory(request.params.arguments.id);
|
|
326
|
+
if (!memory) {
|
|
327
|
+
return {
|
|
328
|
+
content: [
|
|
329
|
+
{
|
|
330
|
+
type: "text",
|
|
331
|
+
text: JSON.stringify({ error: "Memory not found" })
|
|
332
|
+
}
|
|
333
|
+
],
|
|
334
|
+
isError: true
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
content: [
|
|
339
|
+
{
|
|
340
|
+
type: "text",
|
|
341
|
+
text: JSON.stringify({ memory }, null, 2)
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
case "memory_timeline": {
|
|
347
|
+
const timeline = await getTimeline(
|
|
348
|
+
request.params.arguments.id,
|
|
349
|
+
{
|
|
350
|
+
window: request.params.arguments.window
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
if (!timeline) {
|
|
354
|
+
return {
|
|
355
|
+
content: [
|
|
356
|
+
{
|
|
357
|
+
type: "text",
|
|
358
|
+
text: JSON.stringify({ error: "Memory not found" })
|
|
359
|
+
}
|
|
360
|
+
],
|
|
361
|
+
isError: true
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
content: [
|
|
366
|
+
{
|
|
367
|
+
type: "text",
|
|
368
|
+
text: JSON.stringify(timeline, null, 2)
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
case "memory_stats": {
|
|
374
|
+
const stats = await getStats({
|
|
375
|
+
projectPath: request.params.arguments.projectPath,
|
|
376
|
+
since: request.params.arguments.since
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
content: [
|
|
380
|
+
{
|
|
381
|
+
type: "text",
|
|
382
|
+
text: JSON.stringify(stats, null, 2)
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
case "memory_patterns": {
|
|
388
|
+
const patterns = await findPatterns({
|
|
389
|
+
type: request.params.arguments.type,
|
|
390
|
+
minFrequency: request.params.arguments.minFrequency
|
|
391
|
+
});
|
|
392
|
+
return {
|
|
393
|
+
content: [
|
|
394
|
+
{
|
|
395
|
+
type: "text",
|
|
396
|
+
text: JSON.stringify({ patterns }, null, 2)
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
case "memory_anticipate": {
|
|
402
|
+
const memories = await anticipateNeeds(
|
|
403
|
+
request.params.arguments.task,
|
|
404
|
+
request.params.arguments.projectPath
|
|
405
|
+
);
|
|
406
|
+
return {
|
|
407
|
+
content: [
|
|
408
|
+
{
|
|
409
|
+
type: "text",
|
|
410
|
+
text: JSON.stringify({
|
|
411
|
+
task: request.params.arguments.task,
|
|
412
|
+
suggestions: memories.slice(0, request.params.arguments.limit || 5)
|
|
413
|
+
}, null, 2)
|
|
414
|
+
}
|
|
415
|
+
]
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
case "memory_export": {
|
|
419
|
+
const memories = await exportMemories({
|
|
420
|
+
shareableOnly: request.params.arguments.shareableOnly,
|
|
421
|
+
projectPath: request.params.arguments.projectPath,
|
|
422
|
+
since: request.params.arguments.since
|
|
423
|
+
});
|
|
424
|
+
const exportData = {
|
|
425
|
+
exportedAt: new Date().toISOString(),
|
|
426
|
+
count: memories.length,
|
|
427
|
+
memories: memories
|
|
428
|
+
};
|
|
429
|
+
if (request.params.arguments.filePath) {
|
|
430
|
+
const fs = await import("node:fs");
|
|
431
|
+
const { writeFileSync } = fs;
|
|
432
|
+
writeFileSync(
|
|
433
|
+
request.params.arguments.filePath,
|
|
434
|
+
JSON.stringify(exportData, null, 2)
|
|
435
|
+
);
|
|
436
|
+
return {
|
|
437
|
+
content: [
|
|
438
|
+
{
|
|
439
|
+
type: "text",
|
|
440
|
+
text: JSON.stringify({
|
|
441
|
+
success: true,
|
|
442
|
+
message: `Exported ${memories.length} memories to ${request.params.arguments.filePath}`
|
|
443
|
+
}, null, 2)
|
|
444
|
+
}
|
|
445
|
+
]
|
|
446
|
+
};
|
|
447
|
+
} else {
|
|
448
|
+
return {
|
|
449
|
+
content: [
|
|
450
|
+
{
|
|
451
|
+
type: "text",
|
|
452
|
+
text: JSON.stringify(exportData, null, 2)
|
|
453
|
+
}
|
|
454
|
+
]
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
case "memory_import": {
|
|
459
|
+
const fs = await import("node:fs");
|
|
460
|
+
const { readFileSync } = fs;
|
|
461
|
+
const data = JSON.parse(readFileSync(request.params.arguments.filePath, "utf-8"));
|
|
462
|
+
const memories = data.memories || data;
|
|
463
|
+
const results = await importMemories(memories, { merge: request.params.arguments.merge });
|
|
464
|
+
const success = results.filter(r => r.success);
|
|
465
|
+
const failed = results.filter(r => !r.success);
|
|
466
|
+
return {
|
|
467
|
+
content: [
|
|
468
|
+
{
|
|
469
|
+
type: "text",
|
|
470
|
+
text: JSON.stringify({
|
|
471
|
+
imported: success.length,
|
|
472
|
+
failed: failed.length,
|
|
473
|
+
results: results
|
|
474
|
+
}, null, 2)
|
|
475
|
+
}
|
|
476
|
+
]
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
case "memory_prune": {
|
|
480
|
+
const result = await pruneMemories({
|
|
481
|
+
olderThanDays: request.params.arguments.olderThanDays,
|
|
482
|
+
dryRun: request.params.arguments.dryRun
|
|
483
|
+
});
|
|
484
|
+
return {
|
|
485
|
+
content: [
|
|
486
|
+
{
|
|
487
|
+
type: "text",
|
|
488
|
+
text: JSON.stringify(result, null, 2)
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
default:
|
|
494
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
495
|
+
}
|
|
496
|
+
} catch (error) {
|
|
497
|
+
return {
|
|
498
|
+
content: [
|
|
499
|
+
{
|
|
500
|
+
type: "text",
|
|
501
|
+
text: JSON.stringify({ error: error.message })
|
|
502
|
+
}
|
|
503
|
+
],
|
|
504
|
+
isError: true
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// Register resources
|
|
510
|
+
this.server.setRequestHandler("resources/list", async () => ({
|
|
511
|
+
resources: [
|
|
512
|
+
{
|
|
513
|
+
uri: "memory://stats",
|
|
514
|
+
name: "Memory Statistics",
|
|
515
|
+
description: "Current memory system statistics",
|
|
516
|
+
mimeType: "application/json"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
uri: "memory://types",
|
|
520
|
+
name: "Memory Types",
|
|
521
|
+
description: "Available memory types and their descriptions",
|
|
522
|
+
mimeType: "application/json"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
uri: "memory://patterns",
|
|
526
|
+
name: "Memory Patterns",
|
|
527
|
+
description: "Detected patterns in memory system",
|
|
528
|
+
mimeType: "application/json"
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
}));
|
|
532
|
+
|
|
533
|
+
this.server.setRequestHandler("resources/read", async (request) => {
|
|
534
|
+
try {
|
|
535
|
+
switch (request.params.uri) {
|
|
536
|
+
case "memory://stats": {
|
|
537
|
+
const stats = await getStats();
|
|
538
|
+
return {
|
|
539
|
+
contents: [
|
|
540
|
+
{
|
|
541
|
+
uri: request.params.uri,
|
|
542
|
+
mimeType: "application/json",
|
|
543
|
+
text: JSON.stringify(stats, null, 2)
|
|
544
|
+
}
|
|
545
|
+
]
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
case "memory://types": {
|
|
549
|
+
const types = MEMORY_TYPES.map(type => ({
|
|
550
|
+
type,
|
|
551
|
+
description: getMemoryTypeDescription(type)
|
|
552
|
+
}));
|
|
553
|
+
return {
|
|
554
|
+
contents: [
|
|
555
|
+
{
|
|
556
|
+
uri: request.params.uri,
|
|
557
|
+
mimeType: "application/json",
|
|
558
|
+
text: JSON.stringify({ types }, null, 2)
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
case "memory://patterns": {
|
|
564
|
+
const patterns = await findPatterns({ minFrequency: 2 });
|
|
565
|
+
return {
|
|
566
|
+
contents: [
|
|
567
|
+
{
|
|
568
|
+
uri: request.params.uri,
|
|
569
|
+
mimeType: "application/json",
|
|
570
|
+
text: JSON.stringify({ patterns }, null, 2)
|
|
571
|
+
}
|
|
572
|
+
]
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
default:
|
|
576
|
+
throw new Error(`Unknown resource: ${request.params.uri}`);
|
|
577
|
+
}
|
|
578
|
+
} catch (error) {
|
|
579
|
+
return {
|
|
580
|
+
contents: [
|
|
581
|
+
{
|
|
582
|
+
uri: request.params.uri,
|
|
583
|
+
mimeType: "application/json",
|
|
584
|
+
text: JSON.stringify({ error: error.message })
|
|
585
|
+
}
|
|
586
|
+
],
|
|
587
|
+
isError: true
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// Register prompts
|
|
593
|
+
this.server.setRequestHandler("prompts/list", async () => ({
|
|
594
|
+
prompts: [
|
|
595
|
+
{
|
|
596
|
+
name: "memory_recall_prompt",
|
|
597
|
+
description: "Prompt to recall relevant memories before starting work",
|
|
598
|
+
arguments: [
|
|
599
|
+
{
|
|
600
|
+
name: "task",
|
|
601
|
+
description: "Task description to recall context for",
|
|
602
|
+
required: true
|
|
603
|
+
}
|
|
604
|
+
]
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
name: "memory_search_prompt",
|
|
608
|
+
description: "Prompt to search for specific memories",
|
|
609
|
+
arguments: [
|
|
610
|
+
{
|
|
611
|
+
name: "query",
|
|
612
|
+
description: "Search query",
|
|
613
|
+
required: true
|
|
614
|
+
}
|
|
615
|
+
]
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
name: "memory_anticipate_prompt",
|
|
619
|
+
description: "Prompt to anticipate memories needed for future work",
|
|
620
|
+
arguments: [
|
|
621
|
+
{
|
|
622
|
+
name: "task",
|
|
623
|
+
description: "Future task to anticipate needs for",
|
|
624
|
+
required: true
|
|
625
|
+
}
|
|
626
|
+
]
|
|
627
|
+
}
|
|
628
|
+
]
|
|
629
|
+
}));
|
|
630
|
+
|
|
631
|
+
this.server.setRequestHandler("prompts/get", async (request) => {
|
|
632
|
+
try {
|
|
633
|
+
switch (request.params.name) {
|
|
634
|
+
case "memory_recall_prompt": {
|
|
635
|
+
return {
|
|
636
|
+
description: "Recall relevant memories for the specified task",
|
|
637
|
+
messages: [
|
|
638
|
+
{
|
|
639
|
+
role: "user",
|
|
640
|
+
content: {
|
|
641
|
+
type: "text",
|
|
642
|
+
text: `Please recall relevant memories for this task: ${request.params.arguments.task}`
|
|
643
|
+
}
|
|
644
|
+
]
|
|
645
|
+
];
|
|
646
|
+
}
|
|
647
|
+
case "memory_search_prompt": {
|
|
648
|
+
return {
|
|
649
|
+
description: "Search for memories matching the query",
|
|
650
|
+
messages: [
|
|
651
|
+
{
|
|
652
|
+
role: "user",
|
|
653
|
+
content: {
|
|
654
|
+
type: "text",
|
|
655
|
+
text: `Please search memories for: ${request.params.arguments.query}`
|
|
656
|
+
}
|
|
657
|
+
]
|
|
658
|
+
];
|
|
659
|
+
}
|
|
660
|
+
case "memory_anticipate_prompt": {
|
|
661
|
+
return {
|
|
662
|
+
description: "Anticipate memories that will be needed for future work",
|
|
663
|
+
messages: [
|
|
664
|
+
{
|
|
665
|
+
role: "user",
|
|
666
|
+
content: {
|
|
667
|
+
type: "text",
|
|
668
|
+
text: `Please anticipate what memories will be needed for: ${request.params.arguments.task}`
|
|
669
|
+
}
|
|
670
|
+
]
|
|
671
|
+
];
|
|
672
|
+
}
|
|
673
|
+
default:
|
|
674
|
+
throw new Error(`Unknown prompt: ${request.params.name}`);
|
|
675
|
+
}
|
|
676
|
+
} catch (error) {
|
|
677
|
+
return {
|
|
678
|
+
description: "Error loading prompt",
|
|
679
|
+
messages: [
|
|
680
|
+
{
|
|
681
|
+
role: "user",
|
|
682
|
+
content: {
|
|
683
|
+
type: "text",
|
|
684
|
+
text: `Error: ${error.message}`
|
|
685
|
+
}
|
|
686
|
+
]
|
|
687
|
+
];
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
async run() {
|
|
694
|
+
const transport = new StdioServerTransport();
|
|
695
|
+
await this.server.connect(transport);
|
|
696
|
+
console.error("AC Framework Memory MCP Server running on stdio");
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function getMemoryTypeDescription(type) {
|
|
701
|
+
const descriptions = {
|
|
702
|
+
architectural_decision: "Major design decisions about system architecture",
|
|
703
|
+
bugfix_pattern: "Solutions to bugs and issues encountered",
|
|
704
|
+
api_pattern: "Patterns and best practices for API design",
|
|
705
|
+
performance_insight: "Learnings from performance optimization work",
|
|
706
|
+
security_fix: "Security vulnerability fixes and patches",
|
|
707
|
+
refactor_technique: "Successful code refactoring patterns",
|
|
708
|
+
dependency_note: "Notes about project dependencies and versions",
|
|
709
|
+
workaround: "Temporary solutions to problems",
|
|
710
|
+
convention: "Established project conventions and standards",
|
|
711
|
+
context_boundary: "Defined system boundaries and limitations",
|
|
712
|
+
general_insight: "General insights and learnings",
|
|
713
|
+
session_summary: "Summary of work completed in a session"
|
|
714
|
+
};
|
|
715
|
+
return descriptions[type] || "Memory type description not available";
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Start server if called directly
|
|
719
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
720
|
+
const server = new MCPMemoryServer();
|
|
721
|
+
server.run().catch(error => {
|
|
722
|
+
console.error("Failed to start MCP server:", error);
|
|
723
|
+
process.exit(1);
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export default MCPMemoryServer;
|