@danielsimonjr/memory-mcp 0.48.0 → 9.8.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.
Files changed (209) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +2000 -194
  3. package/dist/__tests__/file-path.test.js +7 -11
  4. package/dist/__tests__/knowledge-graph.test.js +3 -8
  5. package/dist/core/EntityManager.d.ts +266 -0
  6. package/dist/core/EntityManager.d.ts.map +1 -0
  7. package/dist/core/EntityManager.js +85 -133
  8. package/dist/core/GraphEventEmitter.d.ts +202 -0
  9. package/dist/core/GraphEventEmitter.d.ts.map +1 -0
  10. package/dist/core/GraphEventEmitter.js +346 -0
  11. package/dist/core/GraphStorage.d.ts +395 -0
  12. package/dist/core/GraphStorage.d.ts.map +1 -0
  13. package/dist/core/GraphStorage.js +643 -31
  14. package/dist/core/GraphTraversal.d.ts +141 -0
  15. package/dist/core/GraphTraversal.d.ts.map +1 -0
  16. package/dist/core/GraphTraversal.js +573 -0
  17. package/dist/core/HierarchyManager.d.ts +111 -0
  18. package/dist/core/HierarchyManager.d.ts.map +1 -0
  19. package/dist/{features → core}/HierarchyManager.js +14 -9
  20. package/dist/core/ManagerContext.d.ts +72 -0
  21. package/dist/core/ManagerContext.d.ts.map +1 -0
  22. package/dist/core/ManagerContext.js +118 -0
  23. package/dist/core/ObservationManager.d.ts +85 -0
  24. package/dist/core/ObservationManager.d.ts.map +1 -0
  25. package/dist/core/ObservationManager.js +51 -57
  26. package/dist/core/RelationManager.d.ts +131 -0
  27. package/dist/core/RelationManager.d.ts.map +1 -0
  28. package/dist/core/RelationManager.js +31 -7
  29. package/dist/core/SQLiteStorage.d.ts +354 -0
  30. package/dist/core/SQLiteStorage.d.ts.map +1 -0
  31. package/dist/core/SQLiteStorage.js +917 -0
  32. package/dist/core/StorageFactory.d.ts +45 -0
  33. package/dist/core/StorageFactory.d.ts.map +1 -0
  34. package/dist/core/StorageFactory.js +64 -0
  35. package/dist/core/TransactionManager.d.ts +464 -0
  36. package/dist/core/TransactionManager.d.ts.map +1 -0
  37. package/dist/core/TransactionManager.js +490 -13
  38. package/dist/core/index.d.ts +17 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +12 -2
  41. package/dist/features/AnalyticsManager.d.ts +44 -0
  42. package/dist/features/AnalyticsManager.d.ts.map +1 -0
  43. package/dist/features/AnalyticsManager.js +3 -2
  44. package/dist/features/ArchiveManager.d.ts +133 -0
  45. package/dist/features/ArchiveManager.d.ts.map +1 -0
  46. package/dist/features/ArchiveManager.js +221 -14
  47. package/dist/features/CompressionManager.d.ts +117 -0
  48. package/dist/features/CompressionManager.d.ts.map +1 -0
  49. package/dist/features/CompressionManager.js +189 -20
  50. package/dist/features/IOManager.d.ts +225 -0
  51. package/dist/features/IOManager.d.ts.map +1 -0
  52. package/dist/features/IOManager.js +1041 -0
  53. package/dist/features/StreamingExporter.d.ts +123 -0
  54. package/dist/features/StreamingExporter.d.ts.map +1 -0
  55. package/dist/features/StreamingExporter.js +203 -0
  56. package/dist/features/TagManager.d.ts +147 -0
  57. package/dist/features/TagManager.d.ts.map +1 -0
  58. package/dist/features/index.d.ts +12 -0
  59. package/dist/features/index.d.ts.map +1 -0
  60. package/dist/features/index.js +5 -6
  61. package/dist/index.d.ts +9 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +10 -10
  64. package/dist/memory.jsonl +1 -26
  65. package/dist/search/BasicSearch.d.ts +51 -0
  66. package/dist/search/BasicSearch.d.ts.map +1 -0
  67. package/dist/search/BasicSearch.js +9 -3
  68. package/dist/search/BooleanSearch.d.ts +98 -0
  69. package/dist/search/BooleanSearch.d.ts.map +1 -0
  70. package/dist/search/BooleanSearch.js +156 -9
  71. package/dist/search/EmbeddingService.d.ts +178 -0
  72. package/dist/search/EmbeddingService.d.ts.map +1 -0
  73. package/dist/search/EmbeddingService.js +358 -0
  74. package/dist/search/FuzzySearch.d.ts +118 -0
  75. package/dist/search/FuzzySearch.d.ts.map +1 -0
  76. package/dist/search/FuzzySearch.js +241 -25
  77. package/dist/search/QueryCostEstimator.d.ts +111 -0
  78. package/dist/search/QueryCostEstimator.d.ts.map +1 -0
  79. package/dist/search/QueryCostEstimator.js +355 -0
  80. package/dist/search/RankedSearch.d.ts +71 -0
  81. package/dist/search/RankedSearch.d.ts.map +1 -0
  82. package/dist/search/RankedSearch.js +54 -6
  83. package/dist/search/SavedSearchManager.d.ts +79 -0
  84. package/dist/search/SavedSearchManager.d.ts.map +1 -0
  85. package/dist/search/SearchFilterChain.d.ts +120 -0
  86. package/dist/search/SearchFilterChain.d.ts.map +1 -0
  87. package/dist/search/SearchFilterChain.js +2 -4
  88. package/dist/search/SearchManager.d.ts +326 -0
  89. package/dist/search/SearchManager.d.ts.map +1 -0
  90. package/dist/search/SearchManager.js +148 -0
  91. package/dist/search/SearchSuggestions.d.ts +27 -0
  92. package/dist/search/SearchSuggestions.d.ts.map +1 -0
  93. package/dist/search/SearchSuggestions.js +1 -1
  94. package/dist/search/SemanticSearch.d.ts +149 -0
  95. package/dist/search/SemanticSearch.d.ts.map +1 -0
  96. package/dist/search/SemanticSearch.js +323 -0
  97. package/dist/search/TFIDFEventSync.d.ts +85 -0
  98. package/dist/search/TFIDFEventSync.d.ts.map +1 -0
  99. package/dist/search/TFIDFEventSync.js +133 -0
  100. package/dist/search/TFIDFIndexManager.d.ts +151 -0
  101. package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
  102. package/dist/search/TFIDFIndexManager.js +232 -17
  103. package/dist/search/VectorStore.d.ts +235 -0
  104. package/dist/search/VectorStore.d.ts.map +1 -0
  105. package/dist/search/VectorStore.js +311 -0
  106. package/dist/search/index.d.ts +21 -0
  107. package/dist/search/index.d.ts.map +1 -0
  108. package/dist/search/index.js +12 -0
  109. package/dist/server/MCPServer.d.ts +21 -0
  110. package/dist/server/MCPServer.d.ts.map +1 -0
  111. package/dist/server/MCPServer.js +4 -4
  112. package/dist/server/responseCompressor.d.ts +94 -0
  113. package/dist/server/responseCompressor.d.ts.map +1 -0
  114. package/dist/server/responseCompressor.js +127 -0
  115. package/dist/server/toolDefinitions.d.ts +27 -0
  116. package/dist/server/toolDefinitions.d.ts.map +1 -0
  117. package/dist/server/toolDefinitions.js +188 -17
  118. package/dist/server/toolHandlers.d.ts +41 -0
  119. package/dist/server/toolHandlers.d.ts.map +1 -0
  120. package/dist/server/toolHandlers.js +467 -75
  121. package/dist/types/index.d.ts +13 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +1 -1
  124. package/dist/types/types.d.ts +1654 -0
  125. package/dist/types/types.d.ts.map +1 -0
  126. package/dist/types/types.js +9 -0
  127. package/dist/utils/compressedCache.d.ts +192 -0
  128. package/dist/utils/compressedCache.d.ts.map +1 -0
  129. package/dist/utils/compressedCache.js +309 -0
  130. package/dist/utils/compressionUtil.d.ts +214 -0
  131. package/dist/utils/compressionUtil.d.ts.map +1 -0
  132. package/dist/utils/compressionUtil.js +247 -0
  133. package/dist/utils/constants.d.ts +245 -0
  134. package/dist/utils/constants.d.ts.map +1 -0
  135. package/dist/utils/constants.js +124 -0
  136. package/dist/utils/entityUtils.d.ts +321 -0
  137. package/dist/utils/entityUtils.d.ts.map +1 -0
  138. package/dist/utils/entityUtils.js +434 -4
  139. package/dist/utils/errors.d.ts +95 -0
  140. package/dist/utils/errors.d.ts.map +1 -0
  141. package/dist/utils/errors.js +24 -0
  142. package/dist/utils/formatters.d.ts +145 -0
  143. package/dist/utils/formatters.d.ts.map +1 -0
  144. package/dist/utils/{paginationUtils.js → formatters.js} +54 -3
  145. package/dist/utils/index.d.ts +23 -0
  146. package/dist/utils/index.d.ts.map +1 -0
  147. package/dist/utils/index.js +69 -31
  148. package/dist/utils/indexes.d.ts +270 -0
  149. package/dist/utils/indexes.d.ts.map +1 -0
  150. package/dist/utils/indexes.js +526 -0
  151. package/dist/utils/logger.d.ts +24 -0
  152. package/dist/utils/logger.d.ts.map +1 -0
  153. package/dist/utils/operationUtils.d.ts +124 -0
  154. package/dist/utils/operationUtils.d.ts.map +1 -0
  155. package/dist/utils/operationUtils.js +175 -0
  156. package/dist/utils/parallelUtils.d.ts +72 -0
  157. package/dist/utils/parallelUtils.d.ts.map +1 -0
  158. package/dist/utils/parallelUtils.js +169 -0
  159. package/dist/utils/schemas.d.ts +374 -0
  160. package/dist/utils/schemas.d.ts.map +1 -0
  161. package/dist/utils/schemas.js +302 -2
  162. package/dist/utils/searchAlgorithms.d.ts +99 -0
  163. package/dist/utils/searchAlgorithms.d.ts.map +1 -0
  164. package/dist/utils/searchAlgorithms.js +167 -0
  165. package/dist/utils/searchCache.d.ts +108 -0
  166. package/dist/utils/searchCache.d.ts.map +1 -0
  167. package/dist/utils/taskScheduler.d.ts +290 -0
  168. package/dist/utils/taskScheduler.d.ts.map +1 -0
  169. package/dist/utils/taskScheduler.js +466 -0
  170. package/dist/workers/index.d.ts +12 -0
  171. package/dist/workers/index.d.ts.map +1 -0
  172. package/dist/workers/index.js +9 -0
  173. package/dist/workers/levenshteinWorker.d.ts +60 -0
  174. package/dist/workers/levenshteinWorker.d.ts.map +1 -0
  175. package/dist/workers/levenshteinWorker.js +98 -0
  176. package/package.json +17 -4
  177. package/dist/__tests__/edge-cases/edge-cases.test.js +0 -406
  178. package/dist/__tests__/integration/workflows.test.js +0 -449
  179. package/dist/__tests__/performance/benchmarks.test.js +0 -413
  180. package/dist/__tests__/unit/core/EntityManager.test.js +0 -334
  181. package/dist/__tests__/unit/core/GraphStorage.test.js +0 -205
  182. package/dist/__tests__/unit/core/RelationManager.test.js +0 -274
  183. package/dist/__tests__/unit/features/CompressionManager.test.js +0 -350
  184. package/dist/__tests__/unit/search/BasicSearch.test.js +0 -311
  185. package/dist/__tests__/unit/search/BooleanSearch.test.js +0 -432
  186. package/dist/__tests__/unit/search/FuzzySearch.test.js +0 -448
  187. package/dist/__tests__/unit/search/RankedSearch.test.js +0 -379
  188. package/dist/__tests__/unit/utils/levenshtein.test.js +0 -77
  189. package/dist/core/KnowledgeGraphManager.js +0 -423
  190. package/dist/features/BackupManager.js +0 -311
  191. package/dist/features/ExportManager.js +0 -305
  192. package/dist/features/ImportExportManager.js +0 -50
  193. package/dist/features/ImportManager.js +0 -328
  194. package/dist/memory-saved-searches.jsonl +0 -0
  195. package/dist/memory-tag-aliases.jsonl +0 -0
  196. package/dist/types/analytics.types.js +0 -6
  197. package/dist/types/entity.types.js +0 -7
  198. package/dist/types/import-export.types.js +0 -7
  199. package/dist/types/search.types.js +0 -7
  200. package/dist/types/tag.types.js +0 -6
  201. package/dist/utils/dateUtils.js +0 -89
  202. package/dist/utils/filterUtils.js +0 -155
  203. package/dist/utils/levenshtein.js +0 -62
  204. package/dist/utils/pathUtils.js +0 -115
  205. package/dist/utils/responseFormatter.js +0 -55
  206. package/dist/utils/tagUtils.js +0 -107
  207. package/dist/utils/tfidf.js +0 -90
  208. package/dist/utils/validationHelper.js +0 -99
  209. package/dist/utils/validationUtils.js +0 -109
@@ -1,117 +1,509 @@
1
1
  /**
2
2
  * MCP Tool Handlers
3
3
  *
4
- * Extracted from MCPServer.ts to reduce file size and improve maintainability.
5
- * Contains handler functions for all 45 Knowledge Graph tools.
4
+ * Contains handler functions for all 51 Knowledge Graph tools.
5
+ * Handlers call managers directly via ManagerContext.
6
+ * Phase 4: Updated to use specialized managers for single responsibility.
7
+ * Phase 4 Sprint 9: Added 4 graph algorithm tools (find_shortest_path, find_all_paths, get_connected_components, get_centrality).
8
+ * Phase 6: Updated to use Zod validation instead of type assertions.
9
+ * Phase 3 Sprint 4: Added response compression for large payloads.
6
10
  *
7
11
  * @module server/toolHandlers
8
12
  */
9
- import { formatToolResponse, formatTextResponse, formatRawResponse } from '../utils/responseFormatter.js';
13
+ import { formatToolResponse, formatTextResponse, formatRawResponse, validateWithSchema, BatchCreateEntitiesSchema, BatchCreateRelationsSchema, EntityNamesSchema, DeleteRelationsSchema, AddObservationsInputSchema, DeleteObservationsInputSchema, ArchiveCriteriaSchema, SavedSearchInputSchema, SavedSearchUpdateSchema, ImportFormatSchema, ExtendedExportFormatSchema, MergeStrategySchema, ExportFilterSchema, SearchQuerySchema, } from '../utils/index.js';
14
+ import { z } from 'zod';
15
+ import { maybeCompressResponse } from './responseCompressor.js';
16
+ /**
17
+ * Wrapper to apply automatic response compression for large tool responses.
18
+ *
19
+ * Responses exceeding 256KB are automatically compressed with brotli
20
+ * and base64-encoded for transport. The compressed response includes
21
+ * metadata about the compression (original size, compressed size, ratio).
22
+ *
23
+ * @param handler - The original handler function
24
+ * @returns A wrapped handler that may compress the response
25
+ */
26
+ async function withCompression(handler) {
27
+ const result = await handler();
28
+ // Only compress text responses
29
+ const textContent = result.content[0];
30
+ if (textContent?.type !== 'text') {
31
+ return result;
32
+ }
33
+ const compressed = await maybeCompressResponse(textContent.text);
34
+ // If compression was applied, wrap the response
35
+ if (compressed.compressed) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: 'text',
40
+ text: JSON.stringify(compressed),
41
+ },
42
+ ],
43
+ };
44
+ }
45
+ // Return original if no compression needed
46
+ return result;
47
+ }
10
48
  /**
11
49
  * Registry of all tool handlers keyed by tool name.
50
+ * Handlers call managers directly for reduced abstraction layers.
51
+ *
52
+ * Note: Large-response tools (read_graph, search_nodes, get_subtree, open_nodes)
53
+ * are wrapped with automatic response compression for payloads >256KB.
12
54
  */
13
55
  export const toolHandlers = {
14
56
  // ==================== ENTITY HANDLERS ====================
15
- create_entities: async (manager, args) => formatToolResponse(await manager.createEntities(args.entities)),
16
- delete_entities: async (manager, args) => {
17
- await manager.deleteEntities(args.entityNames);
18
- return formatTextResponse(`Deleted ${args.entityNames.length} entities`);
57
+ create_entities: async (ctx, args) => {
58
+ const entities = validateWithSchema(args.entities, BatchCreateEntitiesSchema, 'Invalid entities data');
59
+ return formatToolResponse(await ctx.entityManager.createEntities(entities));
60
+ },
61
+ delete_entities: async (ctx, args) => {
62
+ const entityNames = validateWithSchema(args.entityNames, EntityNamesSchema, 'Invalid entity names');
63
+ await ctx.entityManager.deleteEntities(entityNames);
64
+ return formatTextResponse(`Deleted ${entityNames.length} entities`);
65
+ },
66
+ read_graph: async (ctx) => withCompression(async () => formatToolResponse(await ctx.storage.loadGraph())),
67
+ open_nodes: async (ctx, args) => {
68
+ const names = args.names !== undefined
69
+ ? validateWithSchema(args.names, z.array(z.string()), 'Invalid entity names')
70
+ : [];
71
+ return withCompression(async () => formatToolResponse(await ctx.searchManager.openNodes(names)));
19
72
  },
20
- read_graph: async (manager) => formatToolResponse(await manager.readGraph()),
21
- open_nodes: async (manager, args) => formatToolResponse(await manager.openNodes(args.names)),
22
73
  // ==================== RELATION HANDLERS ====================
23
- create_relations: async (manager, args) => formatToolResponse(await manager.createRelations(args.relations)),
24
- delete_relations: async (manager, args) => {
25
- await manager.deleteRelations(args.relations);
26
- return formatTextResponse(`Deleted ${args.relations.length} relations`);
74
+ create_relations: async (ctx, args) => {
75
+ const relations = validateWithSchema(args.relations, BatchCreateRelationsSchema, 'Invalid relations data');
76
+ return formatToolResponse(await ctx.relationManager.createRelations(relations));
77
+ },
78
+ delete_relations: async (ctx, args) => {
79
+ const relations = validateWithSchema(args.relations, DeleteRelationsSchema, 'Invalid relations data');
80
+ await ctx.relationManager.deleteRelations(relations);
81
+ return formatTextResponse(`Deleted ${relations.length} relations`);
27
82
  },
28
83
  // ==================== OBSERVATION HANDLERS ====================
29
- add_observations: async (manager, args) => formatToolResponse(await manager.addObservations(args.observations)),
30
- delete_observations: async (manager, args) => {
31
- await manager.deleteObservations(args.deletions);
84
+ add_observations: async (ctx, args) => {
85
+ const observations = validateWithSchema(args.observations, AddObservationsInputSchema, 'Invalid observations data');
86
+ return formatToolResponse(await ctx.observationManager.addObservations(observations));
87
+ },
88
+ delete_observations: async (ctx, args) => {
89
+ const deletions = validateWithSchema(args.deletions, DeleteObservationsInputSchema, 'Invalid deletion data');
90
+ await ctx.observationManager.deleteObservations(deletions);
32
91
  return formatTextResponse('Observations deleted successfully');
33
92
  },
34
93
  // ==================== SEARCH HANDLERS ====================
35
- search_nodes: async (manager, args) => formatToolResponse(await manager.searchNodes(args.query, args.tags, args.minImportance, args.maxImportance)),
36
- search_by_date_range: async (manager, args) => formatToolResponse(await manager.searchByDateRange(args.startDate, args.endDate, args.entityType, args.tags)),
37
- search_nodes_ranked: async (manager, args) => formatToolResponse(await manager.searchNodesRanked(args.query, args.tags, args.minImportance, args.maxImportance, args.limit)),
38
- boolean_search: async (manager, args) => formatToolResponse(await manager.booleanSearch(args.query, args.tags, args.minImportance, args.maxImportance)),
39
- fuzzy_search: async (manager, args) => formatToolResponse(await manager.fuzzySearch(args.query, args.threshold, args.tags, args.minImportance, args.maxImportance)),
40
- get_search_suggestions: async (manager, args) => formatToolResponse(await manager.getSearchSuggestions(args.query, args.maxSuggestions)),
94
+ search_nodes: async (ctx, args) => {
95
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
96
+ const tags = args.tags !== undefined ? validateWithSchema(args.tags, z.array(z.string()), 'Invalid tags') : undefined;
97
+ const minImportance = args.minImportance !== undefined ? validateWithSchema(args.minImportance, z.number().min(0).max(10), 'Invalid minImportance') : undefined;
98
+ const maxImportance = args.maxImportance !== undefined ? validateWithSchema(args.maxImportance, z.number().min(0).max(10), 'Invalid maxImportance') : undefined;
99
+ return withCompression(async () => formatToolResponse(await ctx.searchManager.searchNodes(query, tags, minImportance, maxImportance)));
100
+ },
101
+ search_by_date_range: async (ctx, args) => {
102
+ const startDate = args.startDate !== undefined ? validateWithSchema(args.startDate, z.string(), 'Invalid startDate') : undefined;
103
+ const endDate = args.endDate !== undefined ? validateWithSchema(args.endDate, z.string(), 'Invalid endDate') : undefined;
104
+ const entityType = args.entityType !== undefined ? validateWithSchema(args.entityType, z.string(), 'Invalid entityType') : undefined;
105
+ const tags = args.tags !== undefined ? validateWithSchema(args.tags, z.array(z.string()), 'Invalid tags') : undefined;
106
+ return formatToolResponse(await ctx.searchManager.searchByDateRange(startDate, endDate, entityType, tags));
107
+ },
108
+ search_nodes_ranked: async (ctx, args) => {
109
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
110
+ const tags = args.tags !== undefined ? validateWithSchema(args.tags, z.array(z.string()), 'Invalid tags') : undefined;
111
+ const minImportance = args.minImportance !== undefined ? validateWithSchema(args.minImportance, z.number().min(0).max(10), 'Invalid minImportance') : undefined;
112
+ const maxImportance = args.maxImportance !== undefined ? validateWithSchema(args.maxImportance, z.number().min(0).max(10), 'Invalid maxImportance') : undefined;
113
+ const limit = args.limit !== undefined ? validateWithSchema(args.limit, z.number().int().positive(), 'Invalid limit') : undefined;
114
+ return formatToolResponse(await ctx.searchManager.searchNodesRanked(query, tags, minImportance, maxImportance, limit));
115
+ },
116
+ boolean_search: async (ctx, args) => {
117
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
118
+ const tags = args.tags !== undefined ? validateWithSchema(args.tags, z.array(z.string()), 'Invalid tags') : undefined;
119
+ const minImportance = args.minImportance !== undefined ? validateWithSchema(args.minImportance, z.number().min(0).max(10), 'Invalid minImportance') : undefined;
120
+ const maxImportance = args.maxImportance !== undefined ? validateWithSchema(args.maxImportance, z.number().min(0).max(10), 'Invalid maxImportance') : undefined;
121
+ return formatToolResponse(await ctx.searchManager.booleanSearch(query, tags, minImportance, maxImportance));
122
+ },
123
+ fuzzy_search: async (ctx, args) => {
124
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
125
+ const threshold = args.threshold !== undefined ? validateWithSchema(args.threshold, z.number().min(0).max(1), 'Invalid threshold') : undefined;
126
+ const tags = args.tags !== undefined ? validateWithSchema(args.tags, z.array(z.string()), 'Invalid tags') : undefined;
127
+ const minImportance = args.minImportance !== undefined ? validateWithSchema(args.minImportance, z.number().min(0).max(10), 'Invalid minImportance') : undefined;
128
+ const maxImportance = args.maxImportance !== undefined ? validateWithSchema(args.maxImportance, z.number().min(0).max(10), 'Invalid maxImportance') : undefined;
129
+ return formatToolResponse(await ctx.searchManager.fuzzySearch(query, threshold, tags, minImportance, maxImportance));
130
+ },
131
+ get_search_suggestions: async (ctx, args) => {
132
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
133
+ const maxSuggestions = args.maxSuggestions !== undefined ? validateWithSchema(args.maxSuggestions, z.number().int().positive(), 'Invalid maxSuggestions') : undefined;
134
+ return formatToolResponse(await ctx.searchManager.getSearchSuggestions(query, maxSuggestions));
135
+ },
136
+ // Phase 10 Sprint 4: Automatic search method selection
137
+ search_auto: async (ctx, args) => {
138
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
139
+ const limit = args.limit !== undefined ? validateWithSchema(args.limit, z.number().int().positive().max(200), 'Invalid limit') : undefined;
140
+ return formatToolResponse(await ctx.searchManager.autoSearch(query, limit));
141
+ },
41
142
  // ==================== SAVED SEARCH HANDLERS ====================
42
- save_search: async (manager, args) => formatToolResponse(await manager.saveSearch(args)),
43
- execute_saved_search: async (manager, args) => formatToolResponse(await manager.executeSavedSearch(args.name)),
44
- list_saved_searches: async (manager) => formatToolResponse(await manager.listSavedSearches()),
45
- delete_saved_search: async (manager, args) => {
46
- const deleted = await manager.deleteSavedSearch(args.name);
143
+ save_search: async (ctx, args) => {
144
+ const searchInput = validateWithSchema(args, SavedSearchInputSchema, 'Invalid saved search data');
145
+ return formatToolResponse(await ctx.searchManager.saveSearch(searchInput));
146
+ },
147
+ execute_saved_search: async (ctx, args) => {
148
+ const name = validateWithSchema(args.name, z.string().min(1), 'Invalid search name');
149
+ return formatToolResponse(await ctx.searchManager.executeSavedSearch(name));
150
+ },
151
+ list_saved_searches: async (ctx) => formatToolResponse(await ctx.searchManager.listSavedSearches()),
152
+ delete_saved_search: async (ctx, args) => {
153
+ const name = validateWithSchema(args.name, z.string().min(1), 'Invalid search name');
154
+ const deleted = await ctx.searchManager.deleteSavedSearch(name);
47
155
  return formatTextResponse(deleted
48
- ? `Saved search "${args.name}" deleted successfully`
49
- : `Saved search "${args.name}" not found`);
156
+ ? `Saved search "${name}" deleted successfully`
157
+ : `Saved search "${name}" not found`);
158
+ },
159
+ update_saved_search: async (ctx, args) => {
160
+ const name = validateWithSchema(args.name, z.string().min(1), 'Invalid search name');
161
+ const updates = validateWithSchema(args.updates, SavedSearchUpdateSchema, 'Invalid update data');
162
+ return formatToolResponse(await ctx.searchManager.updateSavedSearch(name, updates));
50
163
  },
51
- update_saved_search: async (manager, args) => formatToolResponse(await manager.updateSavedSearch(args.name, args.updates)),
52
164
  // ==================== TAG HANDLERS ====================
53
- add_tags: async (manager, args) => formatToolResponse(await manager.addTags(args.entityName, args.tags)),
54
- remove_tags: async (manager, args) => formatToolResponse(await manager.removeTags(args.entityName, args.tags)),
55
- set_importance: async (manager, args) => formatToolResponse(await manager.setImportance(args.entityName, args.importance)),
56
- add_tags_to_multiple_entities: async (manager, args) => formatToolResponse(await manager.addTagsToMultipleEntities(args.entityNames, args.tags)),
57
- replace_tag: async (manager, args) => formatToolResponse(await manager.replaceTag(args.oldTag, args.newTag)),
58
- merge_tags: async (manager, args) => formatToolResponse(await manager.mergeTags(args.tag1, args.tag2, args.targetTag)),
165
+ add_tags: async (ctx, args) => {
166
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
167
+ const tags = validateWithSchema(args.tags, z.array(z.string().min(1)), 'Invalid tags');
168
+ return formatToolResponse(await ctx.entityManager.addTags(entityName, tags));
169
+ },
170
+ remove_tags: async (ctx, args) => {
171
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
172
+ const tags = validateWithSchema(args.tags, z.array(z.string().min(1)), 'Invalid tags');
173
+ return formatToolResponse(await ctx.entityManager.removeTags(entityName, tags));
174
+ },
175
+ set_importance: async (ctx, args) => {
176
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
177
+ const importance = validateWithSchema(args.importance, z.number().min(0).max(10), 'Invalid importance');
178
+ return formatToolResponse(await ctx.entityManager.setImportance(entityName, importance));
179
+ },
180
+ add_tags_to_multiple_entities: async (ctx, args) => {
181
+ const entityNames = validateWithSchema(args.entityNames, z.array(z.string().min(1)), 'Invalid entity names');
182
+ const tags = validateWithSchema(args.tags, z.array(z.string().min(1)), 'Invalid tags');
183
+ return formatToolResponse(await ctx.entityManager.addTagsToMultipleEntities(entityNames, tags));
184
+ },
185
+ replace_tag: async (ctx, args) => {
186
+ const oldTag = validateWithSchema(args.oldTag, z.string().min(1), 'Invalid old tag');
187
+ const newTag = validateWithSchema(args.newTag, z.string().min(1), 'Invalid new tag');
188
+ return formatToolResponse(await ctx.entityManager.replaceTag(oldTag, newTag));
189
+ },
190
+ merge_tags: async (ctx, args) => {
191
+ const tag1 = validateWithSchema(args.tag1, z.string().min(1), 'Invalid first tag');
192
+ const tag2 = validateWithSchema(args.tag2, z.string().min(1), 'Invalid second tag');
193
+ const targetTag = validateWithSchema(args.targetTag, z.string().min(1), 'Invalid target tag');
194
+ return formatToolResponse(await ctx.entityManager.mergeTags(tag1, tag2, targetTag));
195
+ },
59
196
  // ==================== TAG ALIAS HANDLERS ====================
60
- add_tag_alias: async (manager, args) => formatToolResponse(await manager.addTagAlias(args.alias, args.canonical, args.description)),
61
- list_tag_aliases: async (manager) => formatToolResponse(await manager.listTagAliases()),
62
- remove_tag_alias: async (manager, args) => {
63
- const removed = await manager.removeTagAlias(args.alias);
197
+ add_tag_alias: async (ctx, args) => {
198
+ const alias = validateWithSchema(args.alias, z.string().min(1), 'Invalid alias');
199
+ const canonical = validateWithSchema(args.canonical, z.string().min(1), 'Invalid canonical tag');
200
+ const description = args.description !== undefined ? validateWithSchema(args.description, z.string(), 'Invalid description') : undefined;
201
+ return formatToolResponse(await ctx.tagManager.addTagAlias(alias, canonical, description));
202
+ },
203
+ list_tag_aliases: async (ctx) => formatToolResponse(await ctx.tagManager.listTagAliases()),
204
+ remove_tag_alias: async (ctx, args) => {
205
+ const alias = validateWithSchema(args.alias, z.string().min(1), 'Invalid alias');
206
+ const removed = await ctx.tagManager.removeTagAlias(alias);
64
207
  return formatTextResponse(removed
65
- ? `Tag alias "${args.alias}" removed successfully`
66
- : `Tag alias "${args.alias}" not found`);
67
- },
68
- get_aliases_for_tag: async (manager, args) => formatToolResponse(await manager.getAliasesForTag(args.canonicalTag)),
69
- resolve_tag: async (manager, args) => formatToolResponse({
70
- tag: args.tag,
71
- resolved: await manager.resolveTag(args.tag),
72
- }),
208
+ ? `Tag alias "${alias}" removed successfully`
209
+ : `Tag alias "${alias}" not found`);
210
+ },
211
+ get_aliases_for_tag: async (ctx, args) => {
212
+ const canonicalTag = validateWithSchema(args.canonicalTag, z.string().min(1), 'Invalid canonical tag');
213
+ return formatToolResponse(await ctx.tagManager.getAliasesForTag(canonicalTag));
214
+ },
215
+ resolve_tag: async (ctx, args) => {
216
+ const tag = validateWithSchema(args.tag, z.string().min(1), 'Invalid tag');
217
+ return formatToolResponse({
218
+ tag,
219
+ resolved: await ctx.tagManager.resolveTag(tag),
220
+ });
221
+ },
73
222
  // ==================== HIERARCHY HANDLERS ====================
74
- set_entity_parent: async (manager, args) => formatToolResponse(await manager.setEntityParent(args.entityName, args.parentName)),
75
- get_children: async (manager, args) => formatToolResponse(await manager.getChildren(args.entityName)),
76
- get_parent: async (manager, args) => formatToolResponse(await manager.getParent(args.entityName)),
77
- get_ancestors: async (manager, args) => formatToolResponse(await manager.getAncestors(args.entityName)),
78
- get_descendants: async (manager, args) => formatToolResponse(await manager.getDescendants(args.entityName)),
79
- get_subtree: async (manager, args) => formatToolResponse(await manager.getSubtree(args.entityName)),
80
- get_root_entities: async (manager) => formatToolResponse(await manager.getRootEntities()),
81
- get_entity_depth: async (manager, args) => formatToolResponse({
82
- entityName: args.entityName,
83
- depth: await manager.getEntityDepth(args.entityName),
84
- }),
85
- move_entity: async (manager, args) => formatToolResponse(await manager.moveEntity(args.entityName, args.newParentName)),
223
+ set_entity_parent: async (ctx, args) => {
224
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
225
+ const parentName = args.parentName !== undefined ? validateWithSchema(args.parentName, z.string().min(1).nullable(), 'Invalid parent name') : null;
226
+ return formatToolResponse(await ctx.hierarchyManager.setEntityParent(entityName, parentName));
227
+ },
228
+ get_children: async (ctx, args) => {
229
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
230
+ return formatToolResponse(await ctx.hierarchyManager.getChildren(entityName));
231
+ },
232
+ get_parent: async (ctx, args) => {
233
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
234
+ return formatToolResponse(await ctx.hierarchyManager.getParent(entityName));
235
+ },
236
+ get_ancestors: async (ctx, args) => {
237
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
238
+ return formatToolResponse(await ctx.hierarchyManager.getAncestors(entityName));
239
+ },
240
+ get_descendants: async (ctx, args) => {
241
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
242
+ return formatToolResponse(await ctx.hierarchyManager.getDescendants(entityName));
243
+ },
244
+ get_subtree: async (ctx, args) => {
245
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
246
+ return withCompression(async () => formatToolResponse(await ctx.hierarchyManager.getSubtree(entityName)));
247
+ },
248
+ get_root_entities: async (ctx) => formatToolResponse(await ctx.hierarchyManager.getRootEntities()),
249
+ get_entity_depth: async (ctx, args) => {
250
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
251
+ return formatToolResponse({
252
+ entityName,
253
+ depth: await ctx.hierarchyManager.getEntityDepth(entityName),
254
+ });
255
+ },
256
+ move_entity: async (ctx, args) => {
257
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
258
+ const newParentName = args.newParentName !== undefined ? validateWithSchema(args.newParentName, z.string().min(1).nullable(), 'Invalid new parent name') : null;
259
+ return formatToolResponse(await ctx.hierarchyManager.moveEntity(entityName, newParentName));
260
+ },
86
261
  // ==================== ANALYTICS HANDLERS ====================
87
- get_graph_stats: async (manager) => formatToolResponse(await manager.getGraphStats()),
88
- validate_graph: async (manager) => formatToolResponse(await manager.validateGraph()),
262
+ get_graph_stats: async (ctx) => formatToolResponse(await ctx.analyticsManager.getGraphStats()),
263
+ validate_graph: async (ctx) => formatToolResponse(await ctx.analyticsManager.validateGraph()),
89
264
  // ==================== COMPRESSION HANDLERS ====================
90
- find_duplicates: async (manager, args) => formatToolResponse(await manager.findDuplicates(args.threshold)),
91
- merge_entities: async (manager, args) => formatToolResponse(await manager.mergeEntities(args.entityNames, args.targetName)),
92
- compress_graph: async (manager, args) => formatToolResponse(await manager.compressGraph(args.threshold, args.dryRun)),
93
- archive_entities: async (manager, args) => formatToolResponse(await manager.archiveEntities({
94
- olderThan: args.olderThan,
95
- importanceLessThan: args.importanceLessThan,
96
- tags: args.tags,
97
- }, args.dryRun)),
265
+ find_duplicates: async (ctx, args) => {
266
+ const threshold = args.threshold !== undefined ? validateWithSchema(args.threshold, z.number().min(0).max(1), 'Invalid threshold') : undefined;
267
+ return formatToolResponse(await ctx.compressionManager.findDuplicates(threshold));
268
+ },
269
+ merge_entities: async (ctx, args) => {
270
+ const entityNames = validateWithSchema(args.entityNames, z.array(z.string().min(1)).min(2), 'Invalid entity names');
271
+ const targetName = args.targetName !== undefined ? validateWithSchema(args.targetName, z.string().min(1), 'Invalid target name') : undefined;
272
+ return formatToolResponse(await ctx.compressionManager.mergeEntities(entityNames, targetName));
273
+ },
274
+ compress_graph: async (ctx, args) => {
275
+ const threshold = args.threshold !== undefined ? validateWithSchema(args.threshold, z.number().min(0).max(1), 'Invalid threshold') : undefined;
276
+ const dryRun = args.dryRun !== undefined ? validateWithSchema(args.dryRun, z.boolean(), 'Invalid dryRun value') : undefined;
277
+ return formatToolResponse(await ctx.compressionManager.compressGraph(threshold, dryRun));
278
+ },
279
+ archive_entities: async (ctx, args) => {
280
+ const criteria = validateWithSchema({
281
+ olderThan: args.olderThan,
282
+ importanceLessThan: args.importanceLessThan,
283
+ tags: args.tags,
284
+ }, ArchiveCriteriaSchema, 'Invalid archive criteria');
285
+ const dryRun = args.dryRun !== undefined ? validateWithSchema(args.dryRun, z.boolean(), 'Invalid dryRun value') : undefined;
286
+ return formatToolResponse(await ctx.archiveManager.archiveEntities(criteria, dryRun));
287
+ },
288
+ // ==================== GRAPH ALGORITHM HANDLERS (Phase 4 Sprint 9) ====================
289
+ find_shortest_path: async (ctx, args) => {
290
+ const source = validateWithSchema(args.source, z.string().min(1), 'Invalid source entity');
291
+ const target = validateWithSchema(args.target, z.string().min(1), 'Invalid target entity');
292
+ const direction = args.direction !== undefined
293
+ ? validateWithSchema(args.direction, z.enum(['outgoing', 'incoming', 'both']), 'Invalid direction')
294
+ : undefined;
295
+ const relationTypes = args.relationTypes !== undefined
296
+ ? validateWithSchema(args.relationTypes, z.array(z.string()), 'Invalid relation types')
297
+ : undefined;
298
+ const result = await ctx.graphTraversal.findShortestPath(source, target, { direction, relationTypes });
299
+ if (!result) {
300
+ return formatTextResponse(`No path found between "${source}" and "${target}"`);
301
+ }
302
+ return formatToolResponse(result);
303
+ },
304
+ find_all_paths: async (ctx, args) => {
305
+ const source = validateWithSchema(args.source, z.string().min(1), 'Invalid source entity');
306
+ const target = validateWithSchema(args.target, z.string().min(1), 'Invalid target entity');
307
+ const maxDepth = args.maxDepth !== undefined
308
+ ? validateWithSchema(args.maxDepth, z.number().int().min(1).max(10), 'Invalid maxDepth (1-10)')
309
+ : 5;
310
+ const direction = args.direction !== undefined
311
+ ? validateWithSchema(args.direction, z.enum(['outgoing', 'incoming', 'both']), 'Invalid direction')
312
+ : undefined;
313
+ const relationTypes = args.relationTypes !== undefined
314
+ ? validateWithSchema(args.relationTypes, z.array(z.string()), 'Invalid relation types')
315
+ : undefined;
316
+ const results = await ctx.graphTraversal.findAllPaths(source, target, maxDepth, { direction, relationTypes });
317
+ return formatToolResponse({ paths: results, count: results.length });
318
+ },
319
+ get_connected_components: async (ctx) => {
320
+ const result = await ctx.graphTraversal.findConnectedComponents();
321
+ return formatToolResponse(result);
322
+ },
323
+ get_centrality: async (ctx, args) => {
324
+ const algorithm = args.algorithm !== undefined
325
+ ? validateWithSchema(args.algorithm, z.enum(['degree', 'betweenness', 'pagerank']), 'Invalid algorithm')
326
+ : 'degree';
327
+ const topN = args.topN !== undefined
328
+ ? validateWithSchema(args.topN, z.number().int().min(1).max(100), 'Invalid topN (1-100)')
329
+ : 10;
330
+ let result;
331
+ if (algorithm === 'degree') {
332
+ const direction = args.direction !== undefined
333
+ ? validateWithSchema(args.direction, z.enum(['in', 'out', 'both']), 'Invalid direction')
334
+ : 'both';
335
+ result = await ctx.graphTraversal.calculateDegreeCentrality(direction, topN);
336
+ }
337
+ else if (algorithm === 'betweenness') {
338
+ const approximate = args.approximate !== undefined
339
+ ? validateWithSchema(args.approximate, z.boolean(), 'Invalid approximate value')
340
+ : false;
341
+ const sampleRate = args.sampleRate !== undefined
342
+ ? validateWithSchema(args.sampleRate, z.number().min(0.01).max(1.0), 'Invalid sample rate (0.01-1.0)')
343
+ : 0.2;
344
+ result = await ctx.graphTraversal.calculateBetweennessCentrality({
345
+ topN,
346
+ approximate,
347
+ sampleRate,
348
+ });
349
+ }
350
+ else {
351
+ const dampingFactor = args.dampingFactor !== undefined
352
+ ? validateWithSchema(args.dampingFactor, z.number().min(0).max(1), 'Invalid damping factor (0-1)')
353
+ : 0.85;
354
+ result = await ctx.graphTraversal.calculatePageRank(dampingFactor, 100, 1e-6, topN);
355
+ }
356
+ // Convert Map to object for JSON serialization
357
+ return formatToolResponse({
358
+ algorithm: result.algorithm,
359
+ topEntities: result.topEntities,
360
+ totalEntities: result.scores.size,
361
+ ...(algorithm === 'betweenness' && args.approximate ? { approximate: true } : {}),
362
+ });
363
+ },
98
364
  // ==================== IMPORT/EXPORT HANDLERS ====================
99
- import_graph: async (manager, args) => formatToolResponse(await manager.importGraph(args.format, args.data, args.mergeStrategy, args.dryRun)),
100
- export_graph: async (manager, args) => formatRawResponse(await manager.exportGraph(args.format, args.filter)),
365
+ import_graph: async (ctx, args) => {
366
+ const format = validateWithSchema(args.format, ImportFormatSchema, 'Invalid import format');
367
+ const data = validateWithSchema(args.data, z.string().min(1), 'Invalid import data');
368
+ const mergeStrategy = args.mergeStrategy !== undefined ? validateWithSchema(args.mergeStrategy, MergeStrategySchema, 'Invalid merge strategy') : undefined;
369
+ const dryRun = args.dryRun !== undefined ? validateWithSchema(args.dryRun, z.boolean(), 'Invalid dryRun value') : undefined;
370
+ return formatToolResponse(await ctx.ioManager.importGraph(format, data, mergeStrategy, dryRun));
371
+ },
372
+ export_graph: async (ctx, args) => {
373
+ const format = validateWithSchema(args.format, ExtendedExportFormatSchema, 'Invalid export format');
374
+ const filter = args.filter !== undefined ? validateWithSchema(args.filter, ExportFilterSchema, 'Invalid export filter') : undefined;
375
+ const compress = args.compress !== undefined ? validateWithSchema(args.compress, z.boolean(), 'Invalid compress value') : undefined;
376
+ const compressionQuality = args.compressionQuality !== undefined
377
+ ? validateWithSchema(args.compressionQuality, z.number().int().min(0).max(11), 'Invalid compression quality (must be 0-11)')
378
+ : undefined;
379
+ const streaming = args.streaming !== undefined ? validateWithSchema(args.streaming, z.boolean(), 'Invalid streaming value') : undefined;
380
+ const outputPath = args.outputPath !== undefined ? validateWithSchema(args.outputPath, z.string(), 'Invalid outputPath value') : undefined;
381
+ // Get filtered or full graph
382
+ let graph;
383
+ if (filter) {
384
+ graph = await ctx.searchManager.searchByDateRange(filter.startDate, filter.endDate, filter.entityType, filter.tags);
385
+ }
386
+ else {
387
+ graph = await ctx.storage.loadGraph();
388
+ }
389
+ // Export with optional compression and streaming
390
+ const result = await ctx.ioManager.exportGraphWithCompression(graph, format, {
391
+ filter,
392
+ compress,
393
+ compressionQuality,
394
+ streaming,
395
+ outputPath,
396
+ });
397
+ // Return streamed result with metadata
398
+ if (result.streamed) {
399
+ return formatToolResponse({
400
+ format: result.format,
401
+ entityCount: result.entityCount,
402
+ relationCount: result.relationCount,
403
+ compressed: result.compressed,
404
+ encoding: result.encoding,
405
+ originalSize: result.originalSize,
406
+ compressedSize: result.compressedSize,
407
+ compressionRatio: `${(result.compressionRatio * 100).toFixed(1)}%`,
408
+ streamed: true,
409
+ outputPath: result.outputPath,
410
+ message: result.content,
411
+ });
412
+ }
413
+ // Return compressed result with metadata, or raw content for uncompressed
414
+ if (result.compressed) {
415
+ return formatToolResponse({
416
+ format: result.format,
417
+ entityCount: result.entityCount,
418
+ relationCount: result.relationCount,
419
+ compressed: true,
420
+ encoding: result.encoding,
421
+ originalSize: result.originalSize,
422
+ compressedSize: result.compressedSize,
423
+ compressionRatio: `${(result.compressionRatio * 100).toFixed(1)}%`,
424
+ data: result.content,
425
+ });
426
+ }
427
+ // Uncompressed: return raw content for backward compatibility
428
+ return formatRawResponse(result.content);
429
+ },
430
+ // ==================== SEMANTIC SEARCH HANDLERS (Phase 4 Sprint 12) ====================
431
+ semantic_search: async (ctx, args) => {
432
+ const semanticSearch = ctx.semanticSearch;
433
+ if (!semanticSearch) {
434
+ return formatTextResponse('Semantic search is not available. Set MEMORY_EMBEDDING_PROVIDER environment variable to "openai" or "local".');
435
+ }
436
+ const query = validateWithSchema(args.query, SearchQuerySchema, 'Invalid search query');
437
+ const limit = args.limit !== undefined
438
+ ? validateWithSchema(args.limit, z.number().int().min(1).max(100), 'Invalid limit (1-100)')
439
+ : undefined;
440
+ const minSimilarity = args.minSimilarity !== undefined
441
+ ? validateWithSchema(args.minSimilarity, z.number().min(0).max(1), 'Invalid minSimilarity (0-1)')
442
+ : undefined;
443
+ const graph = await ctx.storage.loadGraph();
444
+ const results = await semanticSearch.search(graph, query, limit, minSimilarity);
445
+ return formatToolResponse({
446
+ query,
447
+ results: results.map(r => ({
448
+ entity: r.entity,
449
+ similarity: r.similarity,
450
+ })),
451
+ count: results.length,
452
+ });
453
+ },
454
+ find_similar_entities: async (ctx, args) => {
455
+ const semanticSearch = ctx.semanticSearch;
456
+ if (!semanticSearch) {
457
+ return formatTextResponse('Semantic search is not available. Set MEMORY_EMBEDDING_PROVIDER environment variable to "openai" or "local".');
458
+ }
459
+ const entityName = validateWithSchema(args.entityName, z.string().min(1), 'Invalid entity name');
460
+ const limit = args.limit !== undefined
461
+ ? validateWithSchema(args.limit, z.number().int().min(1).max(100), 'Invalid limit (1-100)')
462
+ : undefined;
463
+ const minSimilarity = args.minSimilarity !== undefined
464
+ ? validateWithSchema(args.minSimilarity, z.number().min(0).max(1), 'Invalid minSimilarity (0-1)')
465
+ : undefined;
466
+ const graph = await ctx.storage.loadGraph();
467
+ const results = await semanticSearch.findSimilar(graph, entityName, limit, minSimilarity);
468
+ return formatToolResponse({
469
+ entityName,
470
+ similarEntities: results.map(r => ({
471
+ entity: r.entity,
472
+ similarity: r.similarity,
473
+ })),
474
+ count: results.length,
475
+ });
476
+ },
477
+ index_embeddings: async (ctx, args) => {
478
+ const semanticSearch = ctx.semanticSearch;
479
+ if (!semanticSearch) {
480
+ return formatTextResponse('Semantic search is not available. Set MEMORY_EMBEDDING_PROVIDER environment variable to "openai" or "local".');
481
+ }
482
+ const forceReindex = args.forceReindex !== undefined
483
+ ? validateWithSchema(args.forceReindex, z.boolean(), 'Invalid forceReindex value')
484
+ : false;
485
+ const graph = await ctx.storage.loadGraph();
486
+ const result = await semanticSearch.indexAll(graph, { forceReindex });
487
+ return formatToolResponse({
488
+ ...result,
489
+ totalEntities: graph.entities.length,
490
+ stats: semanticSearch.getStats(),
491
+ });
492
+ },
101
493
  };
102
494
  /**
103
495
  * Handle a tool call by dispatching to the appropriate handler.
104
496
  *
105
497
  * @param name - Tool name to call
106
498
  * @param args - Tool arguments
107
- * @param manager - Knowledge graph manager instance
499
+ * @param ctx - Manager context with all manager instances
108
500
  * @returns Tool response
109
501
  * @throws Error if tool name is unknown
110
502
  */
111
- export async function handleToolCall(name, args, manager) {
503
+ export async function handleToolCall(name, args, ctx) {
112
504
  const handler = toolHandlers[name];
113
505
  if (!handler) {
114
506
  throw new Error(`Unknown tool: ${name}`);
115
507
  }
116
- return handler(manager, args);
508
+ return handler(ctx, args);
117
509
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Types Module - Barrel Export
3
+ *
4
+ * Central export point for all type definitions used throughout the
5
+ * Memory MCP Server. All types are consolidated in types.ts (Phase 5 cleanup).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { Entity, Relation, KnowledgeGraph, SearchResult } from './types/index.js';
10
+ * ```
11
+ */
12
+ export type { Entity, Relation, KnowledgeGraph, ReadonlyKnowledgeGraph, SearchResult, SavedSearch, BooleanQueryNode, DocumentVector, TFIDFIndex, FuzzyCacheKey, BooleanCacheEntry, PaginatedCacheEntry, TokenizedEntity, GraphStats, ValidationReport, ValidationIssue, ValidationWarning, CacheCompressionStats, ArchiveResultExtended, ExportFilter, ExportOptions, ExportResult, ImportResult, CompressionResult, BackupOptions, BackupResult, RestoreResult, BackupMetadataExtended, BackupInfoExtended, TagAlias, IGraphStorage, StorageConfig, LowercaseData, TraversalOptions, TraversalResult, PathResult, ConnectedComponentsResult, CentralityResult, WeightedRelation, EmbeddingService, SemanticSearchResult, IVectorStore, VectorSearchResult, EmbeddingConfig, SemanticIndexOptions, LongRunningOperationOptions, BatchOperationType, BatchOperation, BatchResult, BatchOptions, GraphEventType, GraphEventBase, EntityCreatedEvent, EntityUpdatedEvent, EntityDeletedEvent, RelationCreatedEvent, RelationDeletedEvent, ObservationAddedEvent, ObservationDeletedEvent, GraphSavedEvent, GraphLoadedEvent, GraphEvent, GraphEventListener, GraphEventMap, SearchMethod, QueryCostEstimate, AutoSearchResult, QueryCostEstimatorOptions, } from './types.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EAEV,MAAM,EACN,QAAQ,EACR,cAAc,EACd,sBAAsB,EAEtB,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,UAAU,EAEV,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EAEf,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EAErB,qBAAqB,EAErB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,iBAAiB,EAEjB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAElB,QAAQ,EAER,aAAa,EACb,aAAa,EACb,aAAa,EAEb,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAEhB,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EAEpB,2BAA2B,EAE3B,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,YAAY,EAEZ,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,aAAa,EAEb,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,YAAY,CAAC"}
@@ -2,7 +2,7 @@
2
2
  * Types Module - Barrel Export
3
3
  *
4
4
  * Central export point for all type definitions used throughout the
5
- * Memory MCP Server. Import from this file to access any type.
5
+ * Memory MCP Server. All types are consolidated in types.ts (Phase 5 cleanup).
6
6
  *
7
7
  * @example
8
8
  * ```typescript