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.
- memorygraph/__init__.py +50 -0
- memorygraph/__main__.py +12 -0
- memorygraph/advanced_tools.py +509 -0
- memorygraph/analytics/__init__.py +46 -0
- memorygraph/analytics/advanced_queries.py +727 -0
- memorygraph/backends/__init__.py +21 -0
- memorygraph/backends/base.py +179 -0
- memorygraph/backends/cloud.py +75 -0
- memorygraph/backends/cloud_backend.py +858 -0
- memorygraph/backends/factory.py +577 -0
- memorygraph/backends/falkordb_backend.py +749 -0
- memorygraph/backends/falkordblite_backend.py +746 -0
- memorygraph/backends/ladybugdb_backend.py +242 -0
- memorygraph/backends/memgraph_backend.py +327 -0
- memorygraph/backends/neo4j_backend.py +298 -0
- memorygraph/backends/sqlite_fallback.py +463 -0
- memorygraph/backends/turso.py +448 -0
- memorygraph/cli.py +743 -0
- memorygraph/cloud_database.py +297 -0
- memorygraph/config.py +295 -0
- memorygraph/database.py +933 -0
- memorygraph/graph_analytics.py +631 -0
- memorygraph/integration/__init__.py +69 -0
- memorygraph/integration/context_capture.py +426 -0
- memorygraph/integration/project_analysis.py +583 -0
- memorygraph/integration/workflow_tracking.py +492 -0
- memorygraph/intelligence/__init__.py +59 -0
- memorygraph/intelligence/context_retrieval.py +447 -0
- memorygraph/intelligence/entity_extraction.py +386 -0
- memorygraph/intelligence/pattern_recognition.py +420 -0
- memorygraph/intelligence/temporal.py +374 -0
- memorygraph/migration/__init__.py +27 -0
- memorygraph/migration/manager.py +579 -0
- memorygraph/migration/models.py +142 -0
- memorygraph/migration/scripts/__init__.py +17 -0
- memorygraph/migration/scripts/bitemporal_migration.py +595 -0
- memorygraph/migration/scripts/multitenancy_migration.py +452 -0
- memorygraph/migration_tools_module.py +146 -0
- memorygraph/models.py +684 -0
- memorygraph/proactive/__init__.py +46 -0
- memorygraph/proactive/outcome_learning.py +444 -0
- memorygraph/proactive/predictive.py +410 -0
- memorygraph/proactive/session_briefing.py +399 -0
- memorygraph/relationships.py +668 -0
- memorygraph/server.py +883 -0
- memorygraph/sqlite_database.py +1876 -0
- memorygraph/tools/__init__.py +59 -0
- memorygraph/tools/activity_tools.py +262 -0
- memorygraph/tools/memory_tools.py +315 -0
- memorygraph/tools/migration_tools.py +181 -0
- memorygraph/tools/relationship_tools.py +147 -0
- memorygraph/tools/search_tools.py +406 -0
- memorygraph/tools/temporal_tools.py +339 -0
- memorygraph/utils/__init__.py +10 -0
- memorygraph/utils/context_extractor.py +429 -0
- memorygraph/utils/error_handling.py +151 -0
- memorygraph/utils/export_import.py +425 -0
- memorygraph/utils/graph_algorithms.py +200 -0
- memorygraph/utils/pagination.py +149 -0
- memorygraph/utils/project_detection.py +133 -0
- memorygraphmcp-0.11.7.dist-info/METADATA +970 -0
- memorygraphmcp-0.11.7.dist-info/RECORD +65 -0
- memorygraphmcp-0.11.7.dist-info/WHEEL +4 -0
- memorygraphmcp-0.11.7.dist-info/entry_points.txt +2 -0
- memorygraphmcp-0.11.7.dist-info/licenses/LICENSE +21 -0
memorygraph/__init__.py
ADDED
|
@@ -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
|
+
]
|
memorygraph/__main__.py
ADDED
|
@@ -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
|
+
]
|