@danielsimonjr/memory-mcp 0.41.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/file-path.test.js +6 -2
- package/dist/__tests__/performance/benchmarks.test.js +151 -149
- package/dist/core/KnowledgeGraphManager.js +43 -20
- package/dist/features/AnalyticsManager.js +11 -11
- package/dist/features/CompressionManager.js +1 -20
- package/dist/features/index.js +1 -1
- package/dist/index.js +4 -37
- package/dist/memory-saved-searches.jsonl +0 -0
- package/dist/memory-tag-aliases.jsonl +0 -0
- package/dist/memory.jsonl +23 -222
- package/dist/search/BasicSearch.js +21 -51
- package/dist/search/BooleanSearch.js +9 -30
- package/dist/search/FuzzySearch.js +11 -30
- package/dist/search/RankedSearch.js +4 -20
- package/dist/search/SearchFilterChain.js +187 -0
- package/dist/search/index.js +4 -0
- package/dist/server/MCPServer.js +5 -842
- package/dist/server/toolDefinitions.js +732 -0
- package/dist/server/toolHandlers.js +117 -0
- package/dist/types/import-export.types.js +1 -1
- package/dist/utils/constants.js +3 -2
- package/dist/utils/entityUtils.js +108 -0
- package/dist/utils/filterUtils.js +155 -0
- package/dist/utils/index.js +26 -0
- package/dist/utils/paginationUtils.js +81 -0
- package/dist/utils/responseFormatter.js +55 -0
- package/dist/utils/tagUtils.js +107 -0
- package/dist/utils/validationHelper.js +99 -0
- package/package.json +34 -2
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag Normalization and Matching Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralizes tag operations to eliminate duplicate normalization logic
|
|
5
|
+
* across the codebase. All tags are normalized to lowercase for consistent matching.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Normalizes a single tag to lowercase and trimmed.
|
|
9
|
+
*
|
|
10
|
+
* @param tag - Tag to normalize
|
|
11
|
+
* @returns Normalized tag
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeTag(tag) {
|
|
14
|
+
return tag.toLowerCase().trim();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Normalizes an array of tags to lowercase.
|
|
18
|
+
* Handles undefined/null input gracefully.
|
|
19
|
+
*
|
|
20
|
+
* @param tags - Array of tags to normalize, or undefined
|
|
21
|
+
* @returns Normalized tags array, or empty array if input is undefined/null
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeTags(tags) {
|
|
24
|
+
if (!tags || tags.length === 0)
|
|
25
|
+
return [];
|
|
26
|
+
return tags.map(tag => tag.toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Checks if an entity's tags include any of the specified search tags.
|
|
30
|
+
* Both inputs are normalized before comparison.
|
|
31
|
+
*
|
|
32
|
+
* @param entityTags - Tags on the entity (may be undefined)
|
|
33
|
+
* @param searchTags - Tags to search for (may be undefined)
|
|
34
|
+
* @returns true if any search tag matches any entity tag, false if no match or either is empty
|
|
35
|
+
*/
|
|
36
|
+
export function hasMatchingTag(entityTags, searchTags) {
|
|
37
|
+
if (!entityTags || entityTags.length === 0)
|
|
38
|
+
return false;
|
|
39
|
+
if (!searchTags || searchTags.length === 0)
|
|
40
|
+
return false;
|
|
41
|
+
const normalizedEntity = normalizeTags(entityTags);
|
|
42
|
+
const normalizedSearch = normalizeTags(searchTags);
|
|
43
|
+
return normalizedSearch.some(tag => normalizedEntity.includes(tag));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Checks if entity tags include ALL of the specified required tags.
|
|
47
|
+
*
|
|
48
|
+
* @param entityTags - Tags on the entity (may be undefined)
|
|
49
|
+
* @param requiredTags - All tags that must be present
|
|
50
|
+
* @returns true if all required tags are present
|
|
51
|
+
*/
|
|
52
|
+
export function hasAllTags(entityTags, requiredTags) {
|
|
53
|
+
if (!entityTags || entityTags.length === 0)
|
|
54
|
+
return false;
|
|
55
|
+
if (requiredTags.length === 0)
|
|
56
|
+
return true;
|
|
57
|
+
const normalizedEntity = normalizeTags(entityTags);
|
|
58
|
+
return normalizeTags(requiredTags).every(tag => normalizedEntity.includes(tag));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Filters entities by tag match.
|
|
62
|
+
* Returns all entities if searchTags is empty or undefined.
|
|
63
|
+
*
|
|
64
|
+
* @param entities - Array of entities with optional tags property
|
|
65
|
+
* @param searchTags - Tags to filter by
|
|
66
|
+
* @returns Filtered entities that have at least one matching tag
|
|
67
|
+
*/
|
|
68
|
+
export function filterByTags(entities, searchTags) {
|
|
69
|
+
if (!searchTags || searchTags.length === 0) {
|
|
70
|
+
return entities;
|
|
71
|
+
}
|
|
72
|
+
const normalizedSearch = normalizeTags(searchTags);
|
|
73
|
+
return entities.filter(entity => {
|
|
74
|
+
if (!entity.tags || entity.tags.length === 0)
|
|
75
|
+
return false;
|
|
76
|
+
const normalizedEntity = normalizeTags(entity.tags);
|
|
77
|
+
return normalizedSearch.some(tag => normalizedEntity.includes(tag));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Adds new tags to an existing tag array, avoiding duplicates.
|
|
82
|
+
* All tags are normalized to lowercase.
|
|
83
|
+
*
|
|
84
|
+
* @param existingTags - Current tags (may be undefined)
|
|
85
|
+
* @param newTags - Tags to add
|
|
86
|
+
* @returns Combined tags array with no duplicates
|
|
87
|
+
*/
|
|
88
|
+
export function addUniqueTags(existingTags, newTags) {
|
|
89
|
+
const existing = normalizeTags(existingTags);
|
|
90
|
+
const toAdd = normalizeTags(newTags);
|
|
91
|
+
const uniqueNew = toAdd.filter(tag => !existing.includes(tag));
|
|
92
|
+
return [...existing, ...uniqueNew];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Removes specified tags from an existing tag array.
|
|
96
|
+
* Comparison is case-insensitive.
|
|
97
|
+
*
|
|
98
|
+
* @param existingTags - Current tags (may be undefined)
|
|
99
|
+
* @param tagsToRemove - Tags to remove
|
|
100
|
+
* @returns Tags array with specified tags removed
|
|
101
|
+
*/
|
|
102
|
+
export function removeTags(existingTags, tagsToRemove) {
|
|
103
|
+
if (!existingTags || existingTags.length === 0)
|
|
104
|
+
return [];
|
|
105
|
+
const toRemoveNormalized = normalizeTags(tagsToRemove);
|
|
106
|
+
return existingTags.filter(tag => !toRemoveNormalized.includes(tag.toLowerCase()));
|
|
107
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod Schema Validation Helper
|
|
3
|
+
*
|
|
4
|
+
* Centralizes Zod validation patterns to eliminate redundant error formatting
|
|
5
|
+
* and validation logic across the codebase.
|
|
6
|
+
*/
|
|
7
|
+
import { ValidationError } from './errors.js';
|
|
8
|
+
/**
|
|
9
|
+
* Formats Zod errors into human-readable strings.
|
|
10
|
+
*
|
|
11
|
+
* @param error - Zod error object
|
|
12
|
+
* @returns Array of formatted error messages
|
|
13
|
+
*/
|
|
14
|
+
export function formatZodErrors(error) {
|
|
15
|
+
return error.issues.map(issue => {
|
|
16
|
+
const path = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
|
|
17
|
+
return `${path}${issue.message}`;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validates data against a Zod schema and returns the typed result.
|
|
22
|
+
* Throws ValidationError with formatted error messages on failure.
|
|
23
|
+
*
|
|
24
|
+
* @param data - The data to validate
|
|
25
|
+
* @param schema - The Zod schema to validate against
|
|
26
|
+
* @param errorMessage - Custom error message prefix (default: 'Validation failed')
|
|
27
|
+
* @returns The validated and typed data
|
|
28
|
+
* @throws ValidationError if validation fails
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const entities = validateWithSchema(
|
|
33
|
+
* input,
|
|
34
|
+
* BatchCreateEntitiesSchema,
|
|
35
|
+
* 'Invalid entity data'
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function validateWithSchema(data, schema, errorMessage = 'Validation failed') {
|
|
40
|
+
const result = schema.safeParse(data);
|
|
41
|
+
if (!result.success) {
|
|
42
|
+
const errors = formatZodErrors(result.error);
|
|
43
|
+
throw new ValidationError(errorMessage, errors);
|
|
44
|
+
}
|
|
45
|
+
return result.data;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validates data and returns a result object instead of throwing.
|
|
49
|
+
* Useful when you want to handle validation errors gracefully.
|
|
50
|
+
*
|
|
51
|
+
* @param data - The data to validate
|
|
52
|
+
* @param schema - The Zod schema to validate against
|
|
53
|
+
* @returns Result object with success status and either data or errors
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const result = validateSafe(input, EntitySchema);
|
|
58
|
+
* if (result.success) {
|
|
59
|
+
* console.log(result.data);
|
|
60
|
+
* } else {
|
|
61
|
+
* console.error(result.errors);
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function validateSafe(data, schema) {
|
|
66
|
+
const result = schema.safeParse(data);
|
|
67
|
+
if (result.success) {
|
|
68
|
+
return { success: true, data: result.data };
|
|
69
|
+
}
|
|
70
|
+
return { success: false, errors: formatZodErrors(result.error) };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Validates an array of items against a schema.
|
|
74
|
+
* Returns detailed information about which items failed validation.
|
|
75
|
+
*
|
|
76
|
+
* @param items - Array of items to validate
|
|
77
|
+
* @param schema - Zod schema for individual items
|
|
78
|
+
* @param errorMessage - Custom error message prefix
|
|
79
|
+
* @returns Array of validated items
|
|
80
|
+
* @throws ValidationError if any item fails validation
|
|
81
|
+
*/
|
|
82
|
+
export function validateArrayWithSchema(items, schema, errorMessage = 'Array validation failed') {
|
|
83
|
+
const errors = [];
|
|
84
|
+
const validated = [];
|
|
85
|
+
for (let i = 0; i < items.length; i++) {
|
|
86
|
+
const result = schema.safeParse(items[i]);
|
|
87
|
+
if (result.success) {
|
|
88
|
+
validated.push(result.data);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const itemErrors = formatZodErrors(result.error);
|
|
92
|
+
errors.push(...itemErrors.map(e => `[${i}] ${e}`));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (errors.length > 0) {
|
|
96
|
+
throw new ValidationError(errorMessage, errors);
|
|
97
|
+
}
|
|
98
|
+
return validated;
|
|
99
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielsimonjr/memory-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Enhanced MCP memory server with hierarchies, compression, archiving, and
|
|
3
|
+
"version": "0.48.0",
|
|
4
|
+
"description": "Enhanced MCP memory server with hierarchies, compression, archiving, and 47 advanced tools",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Daniel Simon Jr. (https://github.com/danielsimonjr)",
|
|
7
7
|
"homepage": "https://github.com/danielsimonjr/memory-mcp",
|
|
@@ -23,6 +23,38 @@
|
|
|
23
23
|
"analytics"
|
|
24
24
|
],
|
|
25
25
|
"type": "module",
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./types": {
|
|
34
|
+
"types": "./dist/types/index.d.ts",
|
|
35
|
+
"import": "./dist/types/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./utils": {
|
|
38
|
+
"types": "./dist/utils/index.d.ts",
|
|
39
|
+
"import": "./dist/utils/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./core": {
|
|
42
|
+
"types": "./dist/core/index.d.ts",
|
|
43
|
+
"import": "./dist/core/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./search": {
|
|
46
|
+
"types": "./dist/search/index.d.ts",
|
|
47
|
+
"import": "./dist/search/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./features": {
|
|
50
|
+
"types": "./dist/features/index.d.ts",
|
|
51
|
+
"import": "./dist/features/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./server": {
|
|
54
|
+
"types": "./dist/server/MCPServer.d.ts",
|
|
55
|
+
"import": "./dist/server/MCPServer.js"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
26
58
|
"bin": {
|
|
27
59
|
"mcp-server-memory": "dist/index.js"
|
|
28
60
|
},
|