memory_loading
Load architectural decision records into memory for querying entities, exploring relationships, and managing architectural knowledge within a memory-centric system.
Instructions
Advanced memory loading tool for the memory-centric architecture. Query, explore, and manage memory entities and relationships. Load ADRs into memory system and perform intelligent queries.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | No | Memory operation to perform | query_entities |
| query | No | Query parameters for entity search | |
| entityId | No | Entity ID for get_entity and find_related actions | |
| maxDepth | No | Maximum depth for relationship traversal (find_related action) | |
| forceReload | No | Force reload of ADRs (load_adrs action) |
Implementation Reference
- src/tools/memory-loading-tool.ts:56-601 (handler)MemoryLoadingTool class: the main handler implementing the 'memory_loading' tool. The execute method (lines 76-130) handles tool logic via action-based switch (load_adrs, query_entities, get_entity, etc.). Private methods provide supporting functionality for memory operations.export class MemoryLoadingTool { private memoryManager: MemoryEntityManager; private memoryTransformer: MemoryTransformer; private logger: EnhancedLogger; private config: ReturnType<typeof loadConfig>; constructor( memoryManager?: MemoryEntityManager, private adrDiscoveryFn?: typeof discoverAdrsInDirectory ) { this.logger = new EnhancedLogger({}); this.config = loadConfig(); this.memoryManager = memoryManager || new MemoryEntityManager(); this.memoryTransformer = new MemoryTransformer(this.memoryManager); } async initialize(): Promise<void> { await this.memoryManager.initialize(); } async execute(params: MemoryLoadingParams): Promise<{ content: Array<{ type: 'text'; text: string }>; isError?: boolean; }> { try { await this.initialize(); const action = params.action || 'query_entities'; switch (action) { case 'load_adrs': return await this.loadAdrsIntoMemory(params.forceReload || false); case 'query_entities': return await this.queryMemoryEntities(params.query || {}); case 'get_entity': if (!params.entityId) { throw new McpAdrError('entityId required for get_entity action', 'MISSING_PARAMETER'); } return await this.getMemoryEntity(params.entityId); case 'find_related': if (!params.entityId) { throw new McpAdrError('entityId required for find_related action', 'MISSING_PARAMETER'); } return await this.findRelatedEntities(params.entityId, params.maxDepth || 2); case 'get_intelligence': return await this.getMemoryIntelligence(); case 'create_snapshot': return await this.createMemorySnapshot(); default: throw new McpAdrError(`Unknown action: ${action}`, 'INVALID_ACTION'); } } catch (error) { this.logger.error( 'Memory loading tool execution failed', 'MemoryLoadingTool', error instanceof Error ? error : undefined, { params, error } ); return { content: [ { type: 'text', text: `Memory loading failed: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } private async loadAdrsIntoMemory(forceReload: boolean): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { this.logger.info('Loading ADRs into memory system', 'MemoryLoadingTool', { adrDirectory: this.config.adrDirectory, forceReload, }); // Discover ADRs in the configured directory const discoveryFn = this.adrDiscoveryFn || discoverAdrsInDirectory; const adrDiscovery = await discoveryFn(this.config.adrDirectory, this.config.projectPath, { includeContent: true, // Include content for transformation includeTimeline: false, }); if (adrDiscovery.totalAdrs === 0) { return { content: [ { type: 'text', text: JSON.stringify( { status: 'no_adrs_found', message: 'No ADRs found in the configured directory', directory: this.config.adrDirectory, recommendations: adrDiscovery.recommendations, }, null, 2 ), }, ], }; } // Transform ADRs to memory entities const { entities, relationships } = await this.memoryTransformer.transformAdrCollectionToMemories(adrDiscovery.adrs); // Store entities and relationships in memory system const storedEntities = []; for (const entity of entities) { const stored = await this.memoryManager.upsertEntity(entity); storedEntities.push({ id: stored.id, title: stored.title, type: stored.type, confidence: stored.confidence, status: entity.type === 'architectural_decision' ? entity.decisionData.status : 'unknown', }); } const storedRelationships = []; for (const relationship of relationships) { const stored = await this.memoryManager.upsertRelationship(relationship); storedRelationships.push({ id: stored.id, type: stored.type, sourceTitle: storedEntities.find(e => e.id === stored.sourceId)?.title || 'Unknown', targetTitle: storedEntities.find(e => e.id === stored.targetId)?.title || 'Unknown', strength: stored.strength, confidence: stored.confidence, }); } const result = { status: 'success', message: `Successfully loaded ${storedEntities.length} ADRs into memory system`, summary: { totalAdrs: adrDiscovery.totalAdrs, entitiesCreated: storedEntities.length, relationshipsInferred: storedRelationships.length, statusDistribution: adrDiscovery.summary.byStatus, categoryDistribution: adrDiscovery.summary.byCategory, }, entities: storedEntities, relationships: storedRelationships, transformation: { averageConfidence: entities.reduce((sum, e) => sum + e.confidence, 0) / entities.length, technicalStackCoverage: [...new Set(entities.flatMap(e => e.context.technicalStack))], businessDomains: [ ...new Set(entities.map(e => e.context.businessDomain).filter(Boolean)), ], }, }; this.logger.info('ADRs successfully loaded into memory system', 'MemoryLoadingTool', { entitiesCreated: storedEntities.length, relationshipsCreated: storedRelationships.length, }); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to load ADRs into memory: ${error instanceof Error ? error.message : String(error)}`, 'ADR_LOADING_ERROR' ); } } private async queryMemoryEntities(queryParams: MemoryLoadingParams['query'] = {}): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { // Convert string arrays to typed arrays for validation const memoryQuery: MemoryQuery = {}; if (queryParams.entityTypes) memoryQuery.entityTypes = queryParams.entityTypes as MemoryEntity['type'][]; if (queryParams.relationshipTypes) memoryQuery.relationshipTypes = queryParams.relationshipTypes as MemoryRelationship['type'][]; if (queryParams.tags) memoryQuery.tags = queryParams.tags; if (queryParams.textQuery) memoryQuery.textQuery = queryParams.textQuery; if (queryParams.confidenceThreshold !== undefined) memoryQuery.confidenceThreshold = queryParams.confidenceThreshold; if (queryParams.relevanceThreshold !== undefined) memoryQuery.relevanceThreshold = queryParams.relevanceThreshold; if (queryParams.timeRange) memoryQuery.timeRange = queryParams.timeRange; if (queryParams.contextFilters) memoryQuery.contextFilters = queryParams.contextFilters; if (queryParams.limit) memoryQuery.limit = queryParams.limit; if (queryParams.sortBy) memoryQuery.sortBy = queryParams.sortBy; if (queryParams.includeRelated !== undefined) memoryQuery.includeRelated = queryParams.includeRelated; if (queryParams.relationshipDepth) memoryQuery.relationshipDepth = queryParams.relationshipDepth; const queryResult = await this.memoryManager.queryEntities(memoryQuery); const result = { status: 'success', query: { parameters: queryParams, executionTime: queryResult.queryTime, totalResults: queryResult.totalCount, returnedResults: queryResult.entities.length, }, entities: queryResult.entities.map(entity => ({ id: entity.id, type: entity.type, title: entity.title, description: entity.description.length > 200 ? entity.description.substring(0, 197) + '...' : entity.description, confidence: entity.confidence, relevance: entity.relevance, tags: entity.tags, created: entity.created, lastModified: entity.lastModified, accessCount: entity.accessPattern.accessCount, relationshipCount: entity.relationships.length, // Type-specific data preview ...(entity.type === 'architectural_decision' && { adrStatus: entity.decisionData.status, implementationStatus: entity.decisionData.implementationStatus, }), ...(entity.type === 'knowledge_artifact' && { artifactType: entity.artifactData.artifactType, format: entity.artifactData.format, }), })), relationships: queryParams.includeRelated ? queryResult.relationships.map(rel => ({ id: rel.id, type: rel.type, strength: rel.strength, confidence: rel.confidence, sourceId: rel.sourceId, targetId: rel.targetId, context: rel.context, })) : [], aggregations: queryResult.aggregations, intelligence: { patterns: ( await this.memoryManager.getIntelligence() ).patternRecognition.discoveredPatterns.slice(0, 3), recommendations: ( await this.memoryManager.getIntelligence() ).adaptiveRecommendations.nextActions.slice(0, 3), }, }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to query memory entities: ${error instanceof Error ? error.message : String(error)}`, 'QUERY_ERROR' ); } } private async getMemoryEntity(entityId: string): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { const entity = await this.memoryManager.getEntity(entityId); if (!entity) { return { content: [ { type: 'text', text: JSON.stringify( { status: 'not_found', message: `Entity with ID ${entityId} not found`, entityId, }, null, 2 ), }, ], }; } // Get related entities const relatedData = await this.memoryManager.findRelatedEntities(entityId, 2); const result = { status: 'success', entity: { ...entity, // Include full details for the requested entity evolution: entity.evolution, validation: entity.validation, accessPattern: entity.accessPattern, }, relationships: { direct: entity.relationships, extended: relatedData.relationshipPaths.map(path => ({ depth: path.depth, path: path.path, relationships: path.relationships.map(rel => ({ type: rel.type, strength: rel.strength, context: rel.context, })), })), }, relatedEntities: relatedData.entities.map(e => ({ id: e.id, type: e.type, title: e.title, confidence: e.confidence, relevance: e.relevance, })), intelligence: { suggestedActions: ( await this.memoryManager.getIntelligence() ).adaptiveRecommendations.nextActions.filter(action => action.requiredEntities.includes(entityId) ), }, }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to get memory entity: ${error instanceof Error ? error.message : String(error)}`, 'ENTITY_GET_ERROR' ); } } private async findRelatedEntities( entityId: string, maxDepth: number ): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { const relatedData = await this.memoryManager.findRelatedEntities(entityId, maxDepth); const result = { status: 'success', sourceEntityId: entityId, maxDepth, relatedEntities: relatedData.entities.map(entity => ({ id: entity.id, type: entity.type, title: entity.title, description: entity.description.length > 150 ? entity.description.substring(0, 147) + '...' : entity.description, confidence: entity.confidence, relevance: entity.relevance, tags: entity.tags, })), relationshipPaths: relatedData.relationshipPaths.map(path => ({ depth: path.depth, pathLength: path.path.length, entities: path.path, relationshipChain: path.relationships.map(rel => ({ type: rel.type, strength: rel.strength, context: rel.context, })), })), statistics: { totalRelatedEntities: relatedData.entities.length, pathDistribution: relatedData.relationshipPaths.reduce( (acc, path) => { acc[`depth${path.depth}`] = (acc[`depth${path.depth}`] || 0) + 1; return acc; }, {} as Record<string, number> ), relationshipTypes: relatedData.relationshipPaths .flatMap(path => path.relationships.map(rel => rel.type)) .reduce( (acc, type) => { acc[type] = (acc[type] || 0) + 1; return acc; }, {} as Record<string, number> ), }, }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to find related entities: ${error instanceof Error ? error.message : String(error)}`, 'RELATED_ENTITIES_ERROR' ); } } private async getMemoryIntelligence(): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { const intelligence = await this.memoryManager.getIntelligence(); const result = { status: 'success', intelligence: { contextAwareness: { currentContext: intelligence.contextAwareness.currentContext, recentContextChanges: intelligence.contextAwareness.contextHistory.slice(-5), }, patternRecognition: { discoveredPatterns: intelligence.patternRecognition.discoveredPatterns.map(pattern => ({ pattern: pattern.pattern, confidence: pattern.confidence, frequency: pattern.frequency, contexts: pattern.contexts, applicabilityScore: pattern.applicabilityScore, })), patternConfidence: intelligence.patternRecognition.patternConfidence, emergentBehaviors: intelligence.patternRecognition.emergentBehaviors, }, relationshipInference: { suggestedRelationships: intelligence.relationshipInference.suggestedRelationships, weakConnections: intelligence.relationshipInference.weakConnections, conflictDetection: intelligence.relationshipInference.conflictDetection, }, adaptiveRecommendations: intelligence.adaptiveRecommendations, }, }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to get memory intelligence: ${error instanceof Error ? error.message : String(error)}`, 'INTELLIGENCE_ERROR' ); } } private async createMemorySnapshot(): Promise<{ content: Array<{ type: 'text'; text: string }>; }> { try { const snapshot = await this.memoryManager.createSnapshot(); const result = { status: 'success', snapshot: { id: snapshot.id, timestamp: snapshot.timestamp, version: snapshot.version, metadata: snapshot.metadata, entitySummary: { totalEntities: snapshot.entities.length, byType: snapshot.entities.reduce( (acc, entity) => { acc[entity.type] = (acc[entity.type] || 0) + 1; return acc; }, {} as Record<string, number> ), averageConfidence: snapshot.metadata.averageConfidence, }, relationshipSummary: { totalRelationships: snapshot.relationships.length, byType: snapshot.relationships.reduce( (acc, rel) => { acc[rel.type] = (acc[rel.type] || 0) + 1; return acc; }, {} as Record<string, number> ), }, intelligenceSummary: { discoveredPatterns: snapshot.intelligence.patternRecognition.discoveredPatterns.length, suggestedRelationships: snapshot.intelligence.relationshipInference.suggestedRelationships.length, nextActions: snapshot.intelligence.adaptiveRecommendations.nextActions.length, knowledgeGaps: snapshot.intelligence.adaptiveRecommendations.knowledgeGaps.length, }, }, }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { throw new McpAdrError( `Failed to create memory snapshot: ${error instanceof Error ? error.message : String(error)}`, 'SNAPSHOT_ERROR' ); } } }
- MemoryLoadingParams interface: defines the input schema for the tool, including query parameters, actions (load_adrs, query_entities, etc.), and action-specific params.interface MemoryLoadingParams { // Query parameters query?: { entityTypes?: string[]; tags?: string[]; textQuery?: string; relationshipTypes?: string[]; confidenceThreshold?: number; relevanceThreshold?: number; timeRange?: { from: string; to: string; }; contextFilters?: { projectPhase?: string; businessDomain?: string; technicalStack?: string[]; environmentalFactors?: string[]; }; limit?: number; sortBy?: 'relevance' | 'confidence' | 'lastModified' | 'created' | 'accessCount'; includeRelated?: boolean; relationshipDepth?: number; }; // Actions action?: | 'load_adrs' | 'query_entities' | 'get_entity' | 'find_related' | 'get_intelligence' | 'create_snapshot'; // Parameters for specific actions entityId?: string; // For get_entity, find_related maxDepth?: number; // For find_related forceReload?: boolean; // For load_adrs }
- src/tools/tool-catalog.ts:880-898 (registration)Tool registration in central TOOL_CATALOG map, including metadata, category 'memory', simplified inputSchema, and CE-MCP directive flag.TOOL_CATALOG.set('memory_loading', { name: 'memory_loading', shortDescription: 'Load memory context', fullDescription: 'Loads memory context from previous sessions.', category: 'memory', complexity: 'simple', tokenCost: { min: 500, max: 2000 }, hasCEMCPDirective: true, // Phase 4.3: Simple tool - memory retrieval relatedTools: ['expand_memory', 'query_conversation_history'], keywords: ['memory', 'load', 'context', 'session'], requiresAI: false, inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, maxItems: { type: 'number', default: 100 }, }, }, });
- MemorySnapshotsResource uses MemoryLoadingTool.execute() to implement MCP resource operations (adr://memory-snapshots/*), bridging tool to resource URIs.const toolResult = await this.memoryLoadingTool.execute(toolParams); if (toolResult.isError || !toolResult.content || !toolResult.content[0]) { throw new Error(toolResult.content?.[0]?.text || 'Tool execution failed'); } // Extract and format data const memoryData = this.extractMemoryData(toolResult.content[0].text); const formattedContent = this.formatMemoryContent(operation, memoryData, queryParams); const result = { contents: [ { uri, mimeType: 'text/markdown', text: formattedContent, }, ], }; // Cache the result (TTL in seconds) this.cache.set(uri, result, this.CACHE_TTL); return result; } catch (error) { this.logger.error( 'Memory snapshots resource read failed', 'MemorySnapshotsResource', error instanceof Error ? error : undefined, { uri, error } ); // Return error as resource content return { contents: [ { uri, mimeType: 'text/markdown', text: `# Memory Snapshots Error\n\n⚠️ Failed to read memory resource:\n\n\`\`\`\n${error instanceof Error ? error.message : String(error)}\n\`\`\``, }, ], }; } }