mongodb-memory-bank-mcp
Version:
FIXED: MongoDB Memory Bank MCP with bulletproof error handling, smart operations, and session state management. Eliminates [object Object] errors and user confusion.
155 lines (154 loc) • 6.62 kB
JavaScript
import { getTemplate, TEMPLATE_HIERARCHY } from '../../../domain/entities/memory-templates.js';
/**
* Implementation of structured memory storage use case
* Combines universal project detection with structured template validation
* Perfect harmony with existing MongoDB memory system
*/
export class MemoryStoreStructuredImpl {
memoryRepository;
projectContextDetection;
constructor(memoryRepository, projectContextDetection) {
this.memoryRepository = memoryRepository;
this.projectContextDetection = projectContextDetection;
}
async execute(params) {
// 1. Detect project context using existing universal detection
const projectContext = await this.projectContextDetection.detectProjectContext({
forceDetection: params.forceDetection,
validateIsolation: params.validateIsolation,
workingDirectory: params.workingDirectory,
preferredProjectName: params.preferredProjectName
});
const projectName = params.projectName || projectContext.result?.projectName || 'unknown-project';
// 2. Validate content against template
const validation = await this.memoryRepository.validateTemplate(params.content, params.memoryType, params.fileName);
// 3. Generate relationships based on template dependencies
const relationships = await this.generateRelationships(params.memoryType, projectName, params.fileName);
// 4. Create structured memory object
const template = getTemplate(params.memoryType);
const structuredMemory = {
projectName,
fileName: params.fileName,
content: params.content,
tags: this.generateTags(params.content, params.memoryType),
lastModified: new Date(),
wordCount: this.countWords(params.content),
memoryType: params.memoryType,
templateVersion: template.version,
relationships,
structuredData: {}
};
// 5. Store the structured memory
const storedMemory = await this.memoryRepository.storeStructured(structuredMemory);
return {
memory: storedMemory,
validation,
projectContext: {
projectName: projectContext.result?.projectName || 'unknown-project',
detectionMethod: projectContext.result?.detectionMethod || 'hybrid',
confidence: projectContext.result?.confidence || 0.5,
isNewProject: !projectContext.result?.existsInMemoryBank
}
};
}
/**
* Generate relationships based on template dependencies and existing memories
*/
async generateRelationships(memoryType, projectName, fileName) {
const template = getTemplate(memoryType);
const hierarchyLevel = TEMPLATE_HIERARCHY[memoryType];
// Get existing memories to establish relationships
const existingMemories = await this.memoryRepository.listByProject(projectName);
const dependsOn = [];
const influences = [];
const relatedTo = [];
// Add template-defined dependencies
for (const depType of template.relationships.requiredDependencies) {
const depMemory = existingMemories.find(m => m.memoryType === depType || m.fileName === `${depType}.md`);
if (depMemory) {
dependsOn.push(depMemory.fileName);
}
}
// Add optional dependencies if they exist
for (const depType of template.relationships.optionalDependencies) {
const depMemory = existingMemories.find(m => m.memoryType === depType || m.fileName === `${depType}.md`);
if (depMemory) {
relatedTo.push(depMemory.fileName);
}
}
// Add influences based on template relationships
for (const influenceType of template.relationships.influences) {
const influenceMemory = existingMemories.find(m => m.memoryType === influenceType || m.fileName === `${influenceType}.md`);
if (influenceMemory) {
influences.push(influenceMemory.fileName);
}
}
// Add hierarchical relationships
const lowerLevelMemories = existingMemories.filter(m => {
const memoryLevel = m.memoryType ? TEMPLATE_HIERARCHY[m.memoryType] : 1;
return memoryLevel > hierarchyLevel;
});
for (const memory of lowerLevelMemories) {
if (!influences.includes(memory.fileName)) {
influences.push(memory.fileName);
}
}
return {
dependsOn,
influences,
relatedTo,
hierarchyLevel
};
}
/**
* Generate tags for structured memory
*/
generateTags(content, memoryType) {
const template = getTemplate(memoryType);
const baseTags = [
memoryType,
'structured',
`template-v${template.version}`,
`hierarchy-${TEMPLATE_HIERARCHY[memoryType]}`
];
// Extract content-based tags
const contentTags = this.extractContentTags(content);
// Combine and deduplicate
const allTags = [...baseTags, ...contentTags];
return [...new Set(allTags)].slice(0, 12); // Limit to 12 tags
}
/**
* Extract tags from content
*/
extractContentTags(content) {
const tags = [];
const words = content.toLowerCase().match(/\b\w{3,}\b/g) || [];
// Common technical terms
const techTerms = [
'api', 'database', 'mongodb', 'react', 'node', 'typescript', 'javascript',
'architecture', 'pattern', 'design', 'implementation', 'testing', 'deployment',
'security', 'performance', 'scalability', 'microservice', 'frontend', 'backend'
];
for (const term of techTerms) {
if (words.includes(term)) {
tags.push(term);
}
}
// Extract section-based tags
const sections = content.match(/^#+\s+(.+)$/gm) || [];
for (const section of sections) {
const sectionName = section.replace(/^#+\s+/, '').toLowerCase();
const tag = sectionName.replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
if (tag.length > 2) {
tags.push(tag);
}
}
return tags.slice(0, 8); // Limit content tags
}
/**
* Count words in content
*/
countWords(content) {
return content.trim().split(/\s+/).length;
}
}