memorygraphMCP 0.11.7__py3-none-any.whl

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 (65) hide show
  1. memorygraph/__init__.py +50 -0
  2. memorygraph/__main__.py +12 -0
  3. memorygraph/advanced_tools.py +509 -0
  4. memorygraph/analytics/__init__.py +46 -0
  5. memorygraph/analytics/advanced_queries.py +727 -0
  6. memorygraph/backends/__init__.py +21 -0
  7. memorygraph/backends/base.py +179 -0
  8. memorygraph/backends/cloud.py +75 -0
  9. memorygraph/backends/cloud_backend.py +858 -0
  10. memorygraph/backends/factory.py +577 -0
  11. memorygraph/backends/falkordb_backend.py +749 -0
  12. memorygraph/backends/falkordblite_backend.py +746 -0
  13. memorygraph/backends/ladybugdb_backend.py +242 -0
  14. memorygraph/backends/memgraph_backend.py +327 -0
  15. memorygraph/backends/neo4j_backend.py +298 -0
  16. memorygraph/backends/sqlite_fallback.py +463 -0
  17. memorygraph/backends/turso.py +448 -0
  18. memorygraph/cli.py +743 -0
  19. memorygraph/cloud_database.py +297 -0
  20. memorygraph/config.py +295 -0
  21. memorygraph/database.py +933 -0
  22. memorygraph/graph_analytics.py +631 -0
  23. memorygraph/integration/__init__.py +69 -0
  24. memorygraph/integration/context_capture.py +426 -0
  25. memorygraph/integration/project_analysis.py +583 -0
  26. memorygraph/integration/workflow_tracking.py +492 -0
  27. memorygraph/intelligence/__init__.py +59 -0
  28. memorygraph/intelligence/context_retrieval.py +447 -0
  29. memorygraph/intelligence/entity_extraction.py +386 -0
  30. memorygraph/intelligence/pattern_recognition.py +420 -0
  31. memorygraph/intelligence/temporal.py +374 -0
  32. memorygraph/migration/__init__.py +27 -0
  33. memorygraph/migration/manager.py +579 -0
  34. memorygraph/migration/models.py +142 -0
  35. memorygraph/migration/scripts/__init__.py +17 -0
  36. memorygraph/migration/scripts/bitemporal_migration.py +595 -0
  37. memorygraph/migration/scripts/multitenancy_migration.py +452 -0
  38. memorygraph/migration_tools_module.py +146 -0
  39. memorygraph/models.py +684 -0
  40. memorygraph/proactive/__init__.py +46 -0
  41. memorygraph/proactive/outcome_learning.py +444 -0
  42. memorygraph/proactive/predictive.py +410 -0
  43. memorygraph/proactive/session_briefing.py +399 -0
  44. memorygraph/relationships.py +668 -0
  45. memorygraph/server.py +883 -0
  46. memorygraph/sqlite_database.py +1876 -0
  47. memorygraph/tools/__init__.py +59 -0
  48. memorygraph/tools/activity_tools.py +262 -0
  49. memorygraph/tools/memory_tools.py +315 -0
  50. memorygraph/tools/migration_tools.py +181 -0
  51. memorygraph/tools/relationship_tools.py +147 -0
  52. memorygraph/tools/search_tools.py +406 -0
  53. memorygraph/tools/temporal_tools.py +339 -0
  54. memorygraph/utils/__init__.py +10 -0
  55. memorygraph/utils/context_extractor.py +429 -0
  56. memorygraph/utils/error_handling.py +151 -0
  57. memorygraph/utils/export_import.py +425 -0
  58. memorygraph/utils/graph_algorithms.py +200 -0
  59. memorygraph/utils/pagination.py +149 -0
  60. memorygraph/utils/project_detection.py +133 -0
  61. memorygraphmcp-0.11.7.dist-info/METADATA +970 -0
  62. memorygraphmcp-0.11.7.dist-info/RECORD +65 -0
  63. memorygraphmcp-0.11.7.dist-info/WHEEL +4 -0
  64. memorygraphmcp-0.11.7.dist-info/entry_points.txt +2 -0
  65. memorygraphmcp-0.11.7.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,50 @@
1
+ """
2
+ Claude Code Memory Server
3
+
4
+ A graph-based MCP server that provides intelligent memory capabilities for Claude Code,
5
+ enabling persistent knowledge tracking, relationship mapping, and contextual development assistance.
6
+
7
+ Supports multiple backends: SQLite (default), Neo4j, and Memgraph.
8
+ """
9
+
10
+ __version__ = "0.11.7"
11
+ __author__ = "Gregory Dickson"
12
+ __email__ = "gregory.d.dickson@gmail.com"
13
+
14
+ from .server import ClaudeMemoryServer
15
+ from .models import (
16
+ Memory,
17
+ MemoryType,
18
+ Relationship,
19
+ RelationshipType,
20
+ MemoryNode,
21
+ MemoryContext,
22
+ MemoryError,
23
+ MemoryNotFoundError,
24
+ RelationshipError,
25
+ ValidationError,
26
+ DatabaseConnectionError,
27
+ SchemaError,
28
+ NotFoundError,
29
+ BackendError,
30
+ ConfigurationError,
31
+ )
32
+
33
+ __all__ = [
34
+ "ClaudeMemoryServer",
35
+ "Memory",
36
+ "MemoryType",
37
+ "Relationship",
38
+ "RelationshipType",
39
+ "MemoryNode",
40
+ "MemoryContext",
41
+ "MemoryError",
42
+ "MemoryNotFoundError",
43
+ "RelationshipError",
44
+ "ValidationError",
45
+ "DatabaseConnectionError",
46
+ "SchemaError",
47
+ "NotFoundError",
48
+ "BackendError",
49
+ "ConfigurationError",
50
+ ]
@@ -0,0 +1,12 @@
1
+ """
2
+ Entry point for running MemoryGraph as a module.
3
+
4
+ Usage:
5
+ python -m memorygraph
6
+ """
7
+
8
+ import asyncio
9
+ from .server import main
10
+
11
+ if __name__ == "__main__":
12
+ asyncio.run(main())
@@ -0,0 +1,509 @@
1
+ """
2
+ Advanced MCP tool handlers for relationship management and graph analytics.
3
+
4
+ This module provides tool definitions and handlers for Phase 4's
5
+ advanced relationship functionality.
6
+ """
7
+
8
+ from typing import Any, Dict, List
9
+ import logging
10
+ import json
11
+
12
+ from mcp.types import Tool, TextContent, CallToolResult
13
+
14
+ from .models import (
15
+ RelationshipType,
16
+ MemoryType,
17
+ Memory,
18
+ )
19
+ from .relationships import relationship_manager, RelationshipCategory
20
+ from .graph_analytics import graph_analyzer
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ # Tool definitions for advanced relationship features
26
+ ADVANCED_RELATIONSHIP_TOOLS = [
27
+ Tool(
28
+ name="find_memory_path",
29
+ description="Find the shortest path between two memories through relationships",
30
+ inputSchema={
31
+ "type": "object",
32
+ "properties": {
33
+ "from_memory_id": {
34
+ "type": "string",
35
+ "description": "Starting memory ID"
36
+ },
37
+ "to_memory_id": {
38
+ "type": "string",
39
+ "description": "Target memory ID"
40
+ },
41
+ "max_depth": {
42
+ "type": "integer",
43
+ "minimum": 1,
44
+ "maximum": 10,
45
+ "default": 5,
46
+ "description": "Maximum path length to search"
47
+ },
48
+ "relationship_types": {
49
+ "type": "array",
50
+ "items": {
51
+ "type": "string",
52
+ "enum": [t.value for t in RelationshipType]
53
+ },
54
+ "description": "Filter by specific relationship types"
55
+ }
56
+ },
57
+ "required": ["from_memory_id", "to_memory_id"]
58
+ }
59
+ ),
60
+ Tool(
61
+ name="analyze_memory_clusters",
62
+ description="Detect clusters of densely connected memories",
63
+ inputSchema={
64
+ "type": "object",
65
+ "properties": {
66
+ "min_cluster_size": {
67
+ "type": "integer",
68
+ "minimum": 2,
69
+ "default": 3,
70
+ "description": "Minimum memories per cluster"
71
+ },
72
+ "min_density": {
73
+ "type": "number",
74
+ "minimum": 0.0,
75
+ "maximum": 1.0,
76
+ "default": 0.3,
77
+ "description": "Minimum cluster density (0.0-1.0)"
78
+ }
79
+ }
80
+ }
81
+ ),
82
+ Tool(
83
+ name="find_bridge_memories",
84
+ description="Find memories that connect different clusters (knowledge bridges)",
85
+ inputSchema={
86
+ "type": "object",
87
+ "properties": {}
88
+ }
89
+ ),
90
+ Tool(
91
+ name="suggest_relationship_type",
92
+ description="Get intelligent suggestions for relationship types between two memories",
93
+ inputSchema={
94
+ "type": "object",
95
+ "properties": {
96
+ "from_memory_id": {
97
+ "type": "string",
98
+ "description": "Source memory ID"
99
+ },
100
+ "to_memory_id": {
101
+ "type": "string",
102
+ "description": "Target memory ID"
103
+ }
104
+ },
105
+ "required": ["from_memory_id", "to_memory_id"]
106
+ }
107
+ ),
108
+ Tool(
109
+ name="reinforce_relationship",
110
+ description="Reinforce a relationship based on successful usage",
111
+ inputSchema={
112
+ "type": "object",
113
+ "properties": {
114
+ "from_memory_id": {
115
+ "type": "string",
116
+ "description": "Source memory ID"
117
+ },
118
+ "to_memory_id": {
119
+ "type": "string",
120
+ "description": "Target memory ID"
121
+ },
122
+ "success": {
123
+ "type": "boolean",
124
+ "default": True,
125
+ "description": "Whether this was a successful use"
126
+ }
127
+ },
128
+ "required": ["from_memory_id", "to_memory_id"]
129
+ }
130
+ ),
131
+ Tool(
132
+ name="get_relationship_types_by_category",
133
+ description="List all relationship types in a specific category",
134
+ inputSchema={
135
+ "type": "object",
136
+ "properties": {
137
+ "category": {
138
+ "type": "string",
139
+ "enum": [c.value for c in RelationshipCategory],
140
+ "description": "Relationship category to query"
141
+ }
142
+ },
143
+ "required": ["category"]
144
+ }
145
+ ),
146
+ Tool(
147
+ name="analyze_graph_metrics",
148
+ description="Get comprehensive graph analytics and metrics",
149
+ inputSchema={
150
+ "type": "object",
151
+ "properties": {}
152
+ }
153
+ ),
154
+ ]
155
+
156
+
157
+ class AdvancedRelationshipHandlers:
158
+ """Handlers for advanced relationship tools."""
159
+
160
+ def __init__(self, memory_db):
161
+ """Initialize handlers with database reference."""
162
+ self.memory_db = memory_db
163
+
164
+ async def handle_find_memory_path(self, arguments: Dict[str, Any]) -> CallToolResult:
165
+ """Find shortest path between two memories."""
166
+ try:
167
+ from_id = arguments["from_memory_id"]
168
+ to_id = arguments["to_memory_id"]
169
+ max_depth = arguments.get("max_depth", 5)
170
+ rel_types = arguments.get("relationship_types")
171
+
172
+ # Convert string types to enums if provided
173
+ relationship_types = None
174
+ if rel_types:
175
+ relationship_types = [RelationshipType(t) for t in rel_types]
176
+
177
+ # Get all memories and relationships
178
+ # (In production, this should be optimized to only fetch relevant subset)
179
+ all_memories = []
180
+ all_relationships = []
181
+
182
+ # For now, we'll use the related memories query as an approximation
183
+ related = await self.memory_db.get_related_memories(
184
+ from_id,
185
+ relationship_types=relationship_types,
186
+ max_depth=max_depth
187
+ )
188
+
189
+ if not related:
190
+ return CallToolResult(
191
+ content=[TextContent(
192
+ type="text",
193
+ text=f"No path found between {from_id} and {to_id}"
194
+ )]
195
+ )
196
+
197
+ # Check if target is in related memories
198
+ found_target = any(m.id == to_id for m, _ in related)
199
+
200
+ if found_target:
201
+ path_info = {
202
+ "found": True,
203
+ "from_memory_id": from_id,
204
+ "to_memory_id": to_id,
205
+ "hops": len([m for m, _ in related if m.id == to_id]),
206
+ "related_memories": len(related)
207
+ }
208
+ else:
209
+ path_info = {
210
+ "found": False,
211
+ "from_memory_id": from_id,
212
+ "to_memory_id": to_id,
213
+ "searched_depth": max_depth
214
+ }
215
+
216
+ return CallToolResult(
217
+ content=[TextContent(
218
+ type="text",
219
+ text=json.dumps(path_info, indent=2)
220
+ )]
221
+ )
222
+
223
+ except Exception as e:
224
+ logger.error(f"Error finding memory path: {e}")
225
+ return CallToolResult(
226
+ content=[TextContent(
227
+ type="text",
228
+ text=f"Error finding path: {str(e)}"
229
+ )],
230
+ isError=True
231
+ )
232
+
233
+ async def handle_analyze_memory_clusters(self, arguments: Dict[str, Any]) -> CallToolResult:
234
+ """Analyze memory clusters."""
235
+ try:
236
+ # Note: This is a simplified implementation
237
+ # In production, we'd need to fetch all memories and relationships
238
+ # from the database to perform proper cluster analysis
239
+
240
+ stats = await self.memory_db.get_memory_statistics()
241
+
242
+ cluster_info = {
243
+ "analysis_type": "cluster_detection",
244
+ "total_memories": stats.get("total_memories", 0),
245
+ "total_relationships": stats.get("total_relationships", 0),
246
+ "note": "Full cluster analysis requires loading entire graph. Use get_memory_statistics for overview."
247
+ }
248
+
249
+ return CallToolResult(
250
+ content=[TextContent(
251
+ type="text",
252
+ text=json.dumps(cluster_info, indent=2)
253
+ )]
254
+ )
255
+
256
+ except Exception as e:
257
+ logger.error(f"Error analyzing clusters: {e}")
258
+ return CallToolResult(
259
+ content=[TextContent(
260
+ type="text",
261
+ text=f"Error analyzing clusters: {str(e)}"
262
+ )],
263
+ isError=True
264
+ )
265
+
266
+ async def handle_find_bridge_memories(self, arguments: Dict[str, Any]) -> CallToolResult:
267
+ """Find bridge memories connecting clusters."""
268
+ try:
269
+ stats = await self.memory_db.get_memory_statistics()
270
+
271
+ bridge_info = {
272
+ "analysis_type": "bridge_detection",
273
+ "total_memories": stats.get("total_memories", 0),
274
+ "note": "Full bridge analysis requires loading entire graph. Use get_memory_statistics for overview."
275
+ }
276
+
277
+ return CallToolResult(
278
+ content=[TextContent(
279
+ type="text",
280
+ text=json.dumps(bridge_info, indent=2)
281
+ )]
282
+ )
283
+
284
+ except Exception as e:
285
+ logger.error(f"Error finding bridges: {e}")
286
+ return CallToolResult(
287
+ content=[TextContent(
288
+ type="text",
289
+ text=f"Error finding bridges: {str(e)}"
290
+ )],
291
+ isError=True
292
+ )
293
+
294
+ async def handle_suggest_relationship_type(self, arguments: Dict[str, Any]) -> CallToolResult:
295
+ """Suggest relationship types between memories."""
296
+ try:
297
+ from_id = arguments["from_memory_id"]
298
+ to_id = arguments["to_memory_id"]
299
+
300
+ # Get the memories
301
+ from_memory = await self.memory_db.get_memory(from_id, include_relationships=False)
302
+ to_memory = await self.memory_db.get_memory(to_id, include_relationships=False)
303
+
304
+ if not from_memory or not to_memory:
305
+ return CallToolResult(
306
+ content=[TextContent(
307
+ type="text",
308
+ text="One or both memories not found"
309
+ )],
310
+ isError=True
311
+ )
312
+
313
+ # Get suggestions
314
+ suggestions = relationship_manager.suggest_relationship_type(
315
+ from_memory,
316
+ to_memory
317
+ )
318
+
319
+ suggestion_list = [
320
+ {
321
+ "type": rel_type.value,
322
+ "confidence": confidence,
323
+ "category": relationship_manager.get_relationship_category(rel_type).value,
324
+ "description": relationship_manager.get_relationship_metadata(rel_type).description
325
+ }
326
+ for rel_type, confidence in suggestions
327
+ ]
328
+
329
+ result = {
330
+ "from_memory": {
331
+ "id": from_memory.id,
332
+ "type": from_memory.type.value,
333
+ "title": from_memory.title
334
+ },
335
+ "to_memory": {
336
+ "id": to_memory.id,
337
+ "type": to_memory.type.value,
338
+ "title": to_memory.title
339
+ },
340
+ "suggestions": suggestion_list
341
+ }
342
+
343
+ return CallToolResult(
344
+ content=[TextContent(
345
+ type="text",
346
+ text=json.dumps(result, indent=2)
347
+ )]
348
+ )
349
+
350
+ except Exception as e:
351
+ logger.error(f"Error suggesting relationship: {e}")
352
+ return CallToolResult(
353
+ content=[TextContent(
354
+ type="text",
355
+ text=f"Error: {str(e)}"
356
+ )],
357
+ isError=True
358
+ )
359
+
360
+ async def handle_reinforce_relationship(self, arguments: Dict[str, Any]) -> CallToolResult:
361
+ """Reinforce a relationship."""
362
+ try:
363
+ from_id = arguments["from_memory_id"]
364
+ to_id = arguments["to_memory_id"]
365
+ success = arguments.get("success", True)
366
+
367
+ # Get the existing relationship to find its type and current properties
368
+ related = await self.memory_db.get_related_memories(from_id, max_depth=1)
369
+
370
+ # Find the relationship to the target memory
371
+ target_rel = None
372
+ for memory, rel in related:
373
+ if memory.id == to_id:
374
+ target_rel = rel
375
+ break
376
+
377
+ if not target_rel:
378
+ return CallToolResult(
379
+ content=[TextContent(
380
+ type="text",
381
+ text=f"No relationship found between {from_id} and {to_id}"
382
+ )],
383
+ isError=True
384
+ )
385
+
386
+ # Reinforce the relationship properties
387
+ new_props = relationship_manager.reinforce_relationship_properties(
388
+ target_rel.properties,
389
+ success=success
390
+ )
391
+
392
+ # Update the relationship in the database
393
+ await self.memory_db.update_relationship_properties(
394
+ from_id,
395
+ to_id,
396
+ target_rel.type,
397
+ new_props
398
+ )
399
+
400
+ result = {
401
+ "from_memory_id": from_id,
402
+ "to_memory_id": to_id,
403
+ "relationship_type": target_rel.type.value,
404
+ "success": success,
405
+ "updated_properties": {
406
+ "strength": new_props.strength,
407
+ "confidence": new_props.confidence,
408
+ "evidence_count": new_props.evidence_count,
409
+ "success_rate": new_props.success_rate
410
+ }
411
+ }
412
+
413
+ return CallToolResult(
414
+ content=[TextContent(
415
+ type="text",
416
+ text=json.dumps(result, indent=2)
417
+ )]
418
+ )
419
+
420
+ except Exception as e:
421
+ logger.error(f"Error reinforcing relationship: {e}")
422
+ return CallToolResult(
423
+ content=[TextContent(
424
+ type="text",
425
+ text=f"Error: {str(e)}"
426
+ )],
427
+ isError=True
428
+ )
429
+
430
+ async def handle_get_relationship_types_by_category(
431
+ self,
432
+ arguments: Dict[str, Any]
433
+ ) -> CallToolResult:
434
+ """Get all relationship types in a category."""
435
+ try:
436
+ category = RelationshipCategory(arguments["category"])
437
+
438
+ types = relationship_manager.get_types_by_category(category)
439
+
440
+ type_list = [
441
+ {
442
+ "type": rel_type.value,
443
+ "description": relationship_manager.get_relationship_metadata(rel_type).description,
444
+ "default_strength": relationship_manager.get_relationship_metadata(rel_type).default_strength,
445
+ "bidirectional": relationship_manager.get_relationship_metadata(rel_type).bidirectional
446
+ }
447
+ for rel_type in types
448
+ ]
449
+
450
+ result = {
451
+ "category": category.value,
452
+ "relationship_types": type_list,
453
+ "count": len(type_list)
454
+ }
455
+
456
+ return CallToolResult(
457
+ content=[TextContent(
458
+ type="text",
459
+ text=json.dumps(result, indent=2)
460
+ )]
461
+ )
462
+
463
+ except Exception as e:
464
+ logger.error(f"Error getting relationship types: {e}")
465
+ return CallToolResult(
466
+ content=[TextContent(
467
+ type="text",
468
+ text=f"Error: {str(e)}"
469
+ )],
470
+ isError=True
471
+ )
472
+
473
+ async def handle_analyze_graph_metrics(self, arguments: Dict[str, Any]) -> CallToolResult:
474
+ """Get comprehensive graph metrics."""
475
+ try:
476
+ # Get database statistics
477
+ stats = await self.memory_db.get_memory_statistics()
478
+
479
+ # Enhance with relationship metadata
480
+ result = {
481
+ "database_statistics": stats,
482
+ "relationship_system": {
483
+ "total_relationship_types": 35,
484
+ "categories": [
485
+ {
486
+ "name": cat.value,
487
+ "types_count": len(relationship_manager.get_types_by_category(cat))
488
+ }
489
+ for cat in RelationshipCategory
490
+ ]
491
+ }
492
+ }
493
+
494
+ return CallToolResult(
495
+ content=[TextContent(
496
+ type="text",
497
+ text=json.dumps(result, indent=2)
498
+ )]
499
+ )
500
+
501
+ except Exception as e:
502
+ logger.error(f"Error getting graph metrics: {e}")
503
+ return CallToolResult(
504
+ content=[TextContent(
505
+ type="text",
506
+ text=f"Error: {str(e)}"
507
+ )],
508
+ isError=True
509
+ )
@@ -0,0 +1,46 @@
1
+ """
2
+ Advanced Analytics for Claude Code Memory Server.
3
+
4
+ Provides advanced graph analytics and visualization capabilities:
5
+ - Graph visualization data export
6
+ - Solution similarity matching
7
+ - Learning path recommendations
8
+ - Knowledge gap identification
9
+ - Memory effectiveness tracking (ROI)
10
+
11
+ Phase 7 Implementation - Advanced Analytics
12
+ """
13
+
14
+ from .advanced_queries import (
15
+ get_memory_graph_visualization,
16
+ analyze_solution_similarity,
17
+ predict_solution_effectiveness,
18
+ recommend_learning_paths,
19
+ identify_knowledge_gaps,
20
+ track_memory_roi,
21
+ GraphVisualizationData,
22
+ SimilarSolution,
23
+ LearningPath,
24
+ KnowledgeGap,
25
+ MemoryROI,
26
+ )
27
+
28
+ __all__ = [
29
+ # Visualization
30
+ "get_memory_graph_visualization",
31
+ "GraphVisualizationData",
32
+ # Similarity
33
+ "analyze_solution_similarity",
34
+ "SimilarSolution",
35
+ # Prediction
36
+ "predict_solution_effectiveness",
37
+ # Learning
38
+ "recommend_learning_paths",
39
+ "LearningPath",
40
+ # Gap analysis
41
+ "identify_knowledge_gaps",
42
+ "KnowledgeGap",
43
+ # ROI tracking
44
+ "track_memory_roi",
45
+ "MemoryROI",
46
+ ]