agentdb 1.1.8 → 1.2.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.
@@ -428,6 +428,64 @@ class AgentDBCLI {
428
428
  // ============================================================================
429
429
  // CLI Entry Point
430
430
  // ============================================================================
431
+ async function handleMcpCommands(subcommand, args) {
432
+ if (!subcommand || subcommand === 'start') {
433
+ // Start the actual MCP server
434
+ const { spawn } = await import('child_process');
435
+ const mcpServerPath = path.join(__dirname, '../mcp/agentdb-mcp-server.js');
436
+
437
+ const proc = spawn('node', [mcpServerPath], {
438
+ stdio: 'inherit',
439
+ env: {
440
+ ...process.env,
441
+ AGENTDB_PATH: process.env.AGENTDB_PATH || './agentdb.db'
442
+ }
443
+ });
444
+
445
+ proc.on('exit', (code) => {
446
+ process.exit(code || 0);
447
+ });
448
+
449
+ // Handle termination signals
450
+ process.on('SIGINT', () => {
451
+ proc.kill('SIGINT');
452
+ });
453
+
454
+ process.on('SIGTERM', () => {
455
+ proc.kill('SIGTERM');
456
+ });
457
+ }
458
+ else if (subcommand === 'list' || subcommand === 'tools') {
459
+ console.log('\nšŸ“¦ AgentDB MCP Tools (15 total)\n');
460
+ console.log('Reflexion Memory:');
461
+ console.log(' 1. reflexion_store - Store episodes with critique');
462
+ console.log(' 2. reflexion_retrieve - Retrieve relevant episodes');
463
+ console.log(' 3. reflexion_critique_summary - Get critique lessons\n');
464
+ console.log('Skill Library:');
465
+ console.log(' 4. skill_create - Create reusable skill');
466
+ console.log(' 5. skill_search - Search skills');
467
+ console.log(' 6. skill_consolidate - Auto-create from episodes\n');
468
+ console.log('Causal Memory:');
469
+ console.log(' 7. causal_add_edge - Add causal edge');
470
+ console.log(' 8. causal_query - Query causal effects');
471
+ console.log(' 9. causal_experiment_create - Create A/B test');
472
+ console.log(' 10. causal_experiment_calculate - Calculate uplift\n');
473
+ console.log('Causal Recall:');
474
+ console.log(' 11. recall_with_certificate - Retrieve with provenance\n');
475
+ console.log('Nightly Learner:');
476
+ console.log(' 12. learner_discover - Auto-discover patterns');
477
+ console.log(' 13. learner_prune - Clean low-quality edges\n');
478
+ console.log('Database:');
479
+ console.log(' 14. db_stats - Database statistics');
480
+ console.log(' 15. db_export - Export data\n');
481
+ }
482
+ else {
483
+ log.error(`Unknown mcp subcommand: ${subcommand}`);
484
+ console.log('\nUsage:');
485
+ console.log(' agentdb mcp [start] - Start MCP server (stdio)');
486
+ console.log(' agentdb mcp list - List available MCP tools');
487
+ }
488
+ }
431
489
  async function main() {
432
490
  const args = process.argv.slice(2);
433
491
  if (args.length === 0 || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
@@ -458,6 +516,9 @@ async function main() {
458
516
  else if (command === 'db') {
459
517
  await handleDbCommands(cli, subcommand, args.slice(2));
460
518
  }
519
+ else if (command === 'mcp') {
520
+ await handleMcpCommands(subcommand, args.slice(2));
521
+ }
461
522
  else {
462
523
  log.error(`Unknown command: ${command}`);
463
524
  printHelp();
@@ -700,6 +761,13 @@ ${colors.bright}DATABASE COMMANDS:${colors.reset}
700
761
  agentdb db stats
701
762
  Show database statistics
702
763
 
764
+ ${colors.bright}MCP INTEGRATION:${colors.reset}
765
+ agentdb mcp [start]
766
+ Start MCP server for Claude Desktop integration
767
+
768
+ agentdb mcp list
769
+ List all available MCP tools
770
+
703
771
  ${colors.bright}ENVIRONMENT:${colors.reset}
704
772
  AGENTDB_PATH Database file path (default: ./agentdb.db)
705
773
 
@@ -0,0 +1,417 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentDB MCP Server
4
+ * Production-ready MCP server for Claude Desktop integration
5
+ * Exposes AgentDB frontier memory features via MCP protocol
6
+ */
7
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import {
10
+ CallToolRequestSchema,
11
+ ListToolsRequestSchema,
12
+ } from '@modelcontextprotocol/sdk/types.js';
13
+ import Database from 'better-sqlite3';
14
+ import { CausalMemoryGraph } from '../controllers/CausalMemoryGraph.js';
15
+ import { CausalRecall } from '../controllers/CausalRecall.js';
16
+ import { ReflexionMemory } from '../controllers/ReflexionMemory.js';
17
+ import { SkillLibrary } from '../controllers/SkillLibrary.js';
18
+ import { NightlyLearner } from '../controllers/NightlyLearner.js';
19
+ import { EmbeddingService } from '../controllers/EmbeddingService.js';
20
+ import * as path from 'path';
21
+
22
+ // ============================================================================
23
+ // Initialize AgentDB Controllers
24
+ // ============================================================================
25
+ const dbPath = process.env.AGENTDB_PATH || './agentdb.db';
26
+ const db = new Database(dbPath);
27
+
28
+ // Initialize embedding service
29
+ const embeddingService = new EmbeddingService({
30
+ model: 'Xenova/all-MiniLM-L6-v2',
31
+ cacheDir: './.agentdb/embeddings'
32
+ });
33
+ await embeddingService.initialize();
34
+
35
+ // Initialize all controllers
36
+ const causalGraph = new CausalMemoryGraph(db);
37
+ const causalRecall = new CausalRecall(db, embeddingService);
38
+ const reflexion = new ReflexionMemory(db, embeddingService);
39
+ const skills = new SkillLibrary(db, embeddingService);
40
+ const learner = new NightlyLearner(db, causalGraph, reflexion);
41
+
42
+ // ============================================================================
43
+ // MCP Server Setup
44
+ // ============================================================================
45
+ const server = new Server(
46
+ {
47
+ name: 'agentdb',
48
+ version: '1.2.0',
49
+ },
50
+ {
51
+ capabilities: {
52
+ tools: {},
53
+ },
54
+ }
55
+ );
56
+
57
+ // ============================================================================
58
+ // Tool Definitions
59
+ // ============================================================================
60
+ const tools = [
61
+ {
62
+ name: 'reflexion_store',
63
+ description: 'Store an episode with self-critique for reflexion-based learning',
64
+ inputSchema: {
65
+ type: 'object',
66
+ properties: {
67
+ session_id: { type: 'string', description: 'Session identifier' },
68
+ task: { type: 'string', description: 'Task description' },
69
+ reward: { type: 'number', description: 'Task reward (0-1)' },
70
+ success: { type: 'boolean', description: 'Whether task succeeded' },
71
+ critique: { type: 'string', description: 'Self-critique reflection' },
72
+ input: { type: 'string', description: 'Task input' },
73
+ output: { type: 'string', description: 'Task output' },
74
+ latency_ms: { type: 'number', description: 'Execution latency' },
75
+ tokens: { type: 'number', description: 'Tokens used' },
76
+ },
77
+ required: ['session_id', 'task', 'reward', 'success'],
78
+ },
79
+ },
80
+ {
81
+ name: 'reflexion_retrieve',
82
+ description: 'Retrieve relevant past episodes for learning from experience',
83
+ inputSchema: {
84
+ type: 'object',
85
+ properties: {
86
+ task: { type: 'string', description: 'Task to find similar episodes for' },
87
+ k: { type: 'number', description: 'Number of episodes to retrieve', default: 5 },
88
+ only_failures: { type: 'boolean', description: 'Only retrieve failures' },
89
+ only_successes: { type: 'boolean', description: 'Only retrieve successes' },
90
+ min_reward: { type: 'number', description: 'Minimum reward threshold' },
91
+ },
92
+ required: ['task'],
93
+ },
94
+ },
95
+ {
96
+ name: 'skill_create',
97
+ description: 'Create a reusable skill in the skill library',
98
+ inputSchema: {
99
+ type: 'object',
100
+ properties: {
101
+ name: { type: 'string', description: 'Skill name' },
102
+ description: { type: 'string', description: 'What the skill does' },
103
+ code: { type: 'string', description: 'Skill implementation code' },
104
+ success_rate: { type: 'number', description: 'Initial success rate' },
105
+ },
106
+ required: ['name', 'description'],
107
+ },
108
+ },
109
+ {
110
+ name: 'skill_search',
111
+ description: 'Search for applicable skills by semantic similarity',
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ task: { type: 'string', description: 'Task to find skills for' },
116
+ k: { type: 'number', description: 'Number of skills to return', default: 10 },
117
+ min_success_rate: { type: 'number', description: 'Minimum success rate filter' },
118
+ },
119
+ required: ['task'],
120
+ },
121
+ },
122
+ {
123
+ name: 'causal_add_edge',
124
+ description: 'Add a causal relationship between actions and outcomes',
125
+ inputSchema: {
126
+ type: 'object',
127
+ properties: {
128
+ cause: { type: 'string', description: 'Causal action/intervention' },
129
+ effect: { type: 'string', description: 'Observed effect/outcome' },
130
+ uplift: { type: 'number', description: 'Causal uplift magnitude' },
131
+ confidence: { type: 'number', description: 'Confidence in causal claim (0-1)', default: 0.95 },
132
+ sample_size: { type: 'number', description: 'Number of observations', default: 0 },
133
+ },
134
+ required: ['cause', 'effect', 'uplift'],
135
+ },
136
+ },
137
+ {
138
+ name: 'causal_query',
139
+ description: 'Query causal effects to understand what actions cause what outcomes',
140
+ inputSchema: {
141
+ type: 'object',
142
+ properties: {
143
+ cause: { type: 'string', description: 'Filter by cause (optional)' },
144
+ effect: { type: 'string', description: 'Filter by effect (optional)' },
145
+ min_confidence: { type: 'number', description: 'Minimum confidence', default: 0.5 },
146
+ min_uplift: { type: 'number', description: 'Minimum uplift', default: 0.0 },
147
+ limit: { type: 'number', description: 'Maximum results', default: 10 },
148
+ },
149
+ },
150
+ },
151
+ {
152
+ name: 'recall_with_certificate',
153
+ description: 'Retrieve memories with causal utility scoring and provenance certificate',
154
+ inputSchema: {
155
+ type: 'object',
156
+ properties: {
157
+ query: { type: 'string', description: 'Query for memory retrieval' },
158
+ k: { type: 'number', description: 'Number of results', default: 12 },
159
+ alpha: { type: 'number', description: 'Similarity weight', default: 0.7 },
160
+ beta: { type: 'number', description: 'Causal uplift weight', default: 0.2 },
161
+ gamma: { type: 'number', description: 'Recency weight', default: 0.1 },
162
+ },
163
+ required: ['query'],
164
+ },
165
+ },
166
+ {
167
+ name: 'learner_discover',
168
+ description: 'Automatically discover causal patterns from episode history',
169
+ inputSchema: {
170
+ type: 'object',
171
+ properties: {
172
+ min_attempts: { type: 'number', description: 'Minimum attempts required', default: 3 },
173
+ min_success_rate: { type: 'number', description: 'Minimum success rate', default: 0.6 },
174
+ min_confidence: { type: 'number', description: 'Minimum statistical confidence', default: 0.7 },
175
+ dry_run: { type: 'boolean', description: 'Preview without storing', default: false },
176
+ },
177
+ },
178
+ },
179
+ {
180
+ name: 'db_stats',
181
+ description: 'Get database statistics showing record counts',
182
+ inputSchema: {
183
+ type: 'object',
184
+ properties: {},
185
+ },
186
+ },
187
+ ];
188
+
189
+ // ============================================================================
190
+ // Tool Handlers
191
+ // ============================================================================
192
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
193
+ return { tools };
194
+ });
195
+
196
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
197
+ const { name, arguments: args } = request.params;
198
+
199
+ try {
200
+ switch (name) {
201
+ case 'reflexion_store': {
202
+ const episodeId = await reflexion.storeEpisode({
203
+ sessionId: args.session_id,
204
+ task: args.task,
205
+ reward: args.reward,
206
+ success: args.success,
207
+ critique: args.critique || '',
208
+ input: args.input || '',
209
+ output: args.output || '',
210
+ latencyMs: args.latency_ms || 0,
211
+ tokens: args.tokens || 0,
212
+ });
213
+ return {
214
+ content: [
215
+ {
216
+ type: 'text',
217
+ text: `āœ… Stored episode #${episodeId}\nTask: ${args.task}\nReward: ${args.reward}\nSuccess: ${args.success}`,
218
+ },
219
+ ],
220
+ };
221
+ }
222
+
223
+ case 'reflexion_retrieve': {
224
+ const episodes = await reflexion.retrieveRelevant({
225
+ task: args.task,
226
+ k: args.k || 5,
227
+ onlyFailures: args.only_failures,
228
+ onlySuccesses: args.only_successes,
229
+ minReward: args.min_reward,
230
+ });
231
+ return {
232
+ content: [
233
+ {
234
+ type: 'text',
235
+ text: `šŸ” Retrieved ${episodes.length} episodes:\n\n` +
236
+ episodes.map((ep, i) =>
237
+ `${i + 1}. Episode ${ep.id}\n Task: ${ep.task}\n Reward: ${ep.reward.toFixed(2)}\n Similarity: ${ep.similarity?.toFixed(3) || 'N/A'}`
238
+ ).join('\n\n'),
239
+ },
240
+ ],
241
+ };
242
+ }
243
+
244
+ case 'skill_create': {
245
+ const skillId = await skills.createSkill({
246
+ name: args.name,
247
+ description: args.description,
248
+ signature: { inputs: {}, outputs: {} },
249
+ code: args.code || '',
250
+ successRate: args.success_rate || 0.0,
251
+ uses: 0,
252
+ avgReward: 0.0,
253
+ avgLatencyMs: 0.0,
254
+ });
255
+ return {
256
+ content: [
257
+ {
258
+ type: 'text',
259
+ text: `āœ… Created skill #${skillId}: ${args.name}`,
260
+ },
261
+ ],
262
+ };
263
+ }
264
+
265
+ case 'skill_search': {
266
+ const foundSkills = await skills.searchSkills({
267
+ task: args.task,
268
+ k: args.k || 10,
269
+ minSuccessRate: args.min_success_rate || 0.0,
270
+ });
271
+ return {
272
+ content: [
273
+ {
274
+ type: 'text',
275
+ text: `šŸ” Found ${foundSkills.length} skills:\n\n` +
276
+ foundSkills.map((skill, i) =>
277
+ `${i + 1}. ${skill.name}\n ${skill.description}\n Success: ${(skill.successRate * 100).toFixed(1)}%`
278
+ ).join('\n\n'),
279
+ },
280
+ ],
281
+ };
282
+ }
283
+
284
+ case 'causal_add_edge': {
285
+ const edgeId = causalGraph.addCausalEdge({
286
+ fromMemoryId: 0,
287
+ fromMemoryType: args.cause,
288
+ toMemoryId: 0,
289
+ toMemoryType: args.effect,
290
+ similarity: 0,
291
+ uplift: args.uplift,
292
+ confidence: args.confidence || 0.95,
293
+ sampleSize: args.sample_size || 0,
294
+ evidenceIds: [],
295
+ });
296
+ return {
297
+ content: [
298
+ {
299
+ type: 'text',
300
+ text: `āœ… Added causal edge #${edgeId}\n${args.cause} → ${args.effect}\nUplift: ${args.uplift}`,
301
+ },
302
+ ],
303
+ };
304
+ }
305
+
306
+ case 'causal_query': {
307
+ const edges = causalGraph.queryCausalEffects({
308
+ interventionMemoryId: 0,
309
+ interventionMemoryType: args.cause || '',
310
+ outcomeMemoryId: args.effect ? 0 : undefined,
311
+ minConfidence: args.min_confidence || 0.5,
312
+ minUplift: args.min_uplift || 0.0,
313
+ });
314
+ const limited = edges.slice(0, args.limit || 10);
315
+ return {
316
+ content: [
317
+ {
318
+ type: 'text',
319
+ text: `šŸ” Found ${edges.length} causal edges:\n\n` +
320
+ limited.map((edge, i) =>
321
+ `${i + 1}. ${edge.cause} → ${edge.effect}\n Uplift: ${edge.uplift.toFixed(3)} (confidence: ${edge.confidence.toFixed(2)})`
322
+ ).join('\n\n'),
323
+ },
324
+ ],
325
+ };
326
+ }
327
+
328
+ case 'recall_with_certificate': {
329
+ const result = await causalRecall.recall(
330
+ 'mcp-' + Date.now(),
331
+ args.query,
332
+ args.k || 12,
333
+ undefined,
334
+ 'internal'
335
+ );
336
+ return {
337
+ content: [
338
+ {
339
+ type: 'text',
340
+ text: `šŸ” Retrieved ${result.candidates.length} results:\n\n` +
341
+ result.candidates.slice(0, 5).map((r, i) =>
342
+ `${i + 1}. ${r.type} ${r.id}\n Similarity: ${r.similarity.toFixed(3)}\n Uplift: ${r.uplift?.toFixed(3) || '0.000'}`
343
+ ).join('\n\n') +
344
+ `\n\nšŸ“œ Certificate ID: ${result.certificate.id}`,
345
+ },
346
+ ],
347
+ };
348
+ }
349
+
350
+ case 'learner_discover': {
351
+ const discovered = await learner.discover({
352
+ minAttempts: args.min_attempts || 3,
353
+ minSuccessRate: args.min_success_rate || 0.6,
354
+ minConfidence: args.min_confidence || 0.7,
355
+ dryRun: args.dry_run || false,
356
+ });
357
+ return {
358
+ content: [
359
+ {
360
+ type: 'text',
361
+ text: `šŸŒ™ Discovered ${discovered.length} causal patterns:\n\n` +
362
+ discovered.slice(0, 10).map((edge, i) =>
363
+ `${i + 1}. ${edge.cause} → ${edge.effect}\n Uplift: ${edge.uplift.toFixed(3)} (n=${edge.sampleSize})`
364
+ ).join('\n\n'),
365
+ },
366
+ ],
367
+ };
368
+ }
369
+
370
+ case 'db_stats': {
371
+ const stats = {
372
+ causal_edges: db.prepare('SELECT COUNT(*) as count FROM causal_edges').get().count,
373
+ causal_experiments: db.prepare('SELECT COUNT(*) as count FROM causal_experiments').get().count,
374
+ causal_observations: db.prepare('SELECT COUNT(*) as count FROM causal_observations').get().count,
375
+ episodes: db.prepare('SELECT COUNT(*) as count FROM episodes').get().count,
376
+ };
377
+ return {
378
+ content: [
379
+ {
380
+ type: 'text',
381
+ text: `šŸ“Š Database Statistics:\n\n` +
382
+ `Causal Edges: ${stats.causal_edges}\n` +
383
+ `Experiments: ${stats.causal_experiments}\n` +
384
+ `Observations: ${stats.causal_observations}\n` +
385
+ `Episodes: ${stats.episodes}`,
386
+ },
387
+ ],
388
+ };
389
+ }
390
+
391
+ default:
392
+ throw new Error(`Unknown tool: ${name}`);
393
+ }
394
+ } catch (error) {
395
+ return {
396
+ content: [
397
+ {
398
+ type: 'text',
399
+ text: `āŒ Error: ${error.message}`,
400
+ },
401
+ ],
402
+ isError: true,
403
+ };
404
+ }
405
+ });
406
+
407
+ // ============================================================================
408
+ // Start Server
409
+ // ============================================================================
410
+ async function main() {
411
+ const transport = new StdioServerTransport();
412
+ await server.connect(transport);
413
+ console.error('šŸš€ AgentDB MCP Server running on stdio');
414
+ console.error('šŸ“¦ 9 tools available for Claude Desktop');
415
+ }
416
+
417
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentdb",
3
- "version": "1.1.8",
4
- "description": "AgentDB - Frontier Memory Features: Causal reasoning, reflexion memory, skill library, explainable recall, and automated learning for AI agents. 150x faster vector search with HNSW indexing.",
3
+ "version": "1.2.0",
4
+ "description": "AgentDB - Frontier Memory Features with MCP Integration: Causal reasoning, reflexion memory, skill library, and automated learning. 150x faster vector search. Full Claude Desktop support via Model Context Protocol.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -55,10 +55,12 @@
55
55
  },
56
56
  "homepage": "https://agentdb.ruv.io",
57
57
  "dependencies": {
58
+ "@modelcontextprotocol/sdk": "^1.20.1",
58
59
  "@xenova/transformers": "^2.17.2",
59
60
  "better-sqlite3": "^11.7.0",
60
61
  "chalk": "^5.3.0",
61
- "commander": "^12.1.0"
62
+ "commander": "^12.1.0",
63
+ "zod": "^3.25.76"
62
64
  },
63
65
  "devDependencies": {
64
66
  "@types/better-sqlite3": "^7.6.11",