Skip to main content
Glama
memory-expand-resource.ts7.54 kB
/** * Memory Expand Resource - Detailed view of a specific memory entity * URI Pattern: adr://memory/{key} */ import { URLSearchParams } from 'url'; import { McpAdrError } from '../types/index.js'; import { resourceCache, generateETag } from './resource-cache.js'; import { ResourceGenerationResult } from './index.js'; import { resourceRouter } from './resource-router.js'; import type { MemoryEntityManager } from '../utils/memory-entity-manager.js'; export interface MemoryExpandData { key: string; entity: { id: string; type: string; name: string; content: any; metadata: Record<string, any>; tags: string[]; confidence: number; lastModified: string; created: string; accessCount: number; } | null; relationships: Array<{ targetId: string; targetName: string; relationshipType: string; strength: number; }>; relatedEntities: Array<{ id: string; name: string; type: string; relevance: number; }>; timestamp: string; found: boolean; } /** * Generate memory expand resource showing detailed entity information. * * Returns complete details about a specific memory entity including: * - Full entity content and metadata * - All relationships to other entities * - Related entities by relevance * - Access statistics * * **URI Pattern:** `adr://memory/{key}` * * **Query Parameters:** * - `includeRelated`: Include related entities (default: true) * - `relationshipDepth`: Depth of relationships to traverse (default: 2) * - `maxRelated`: Maximum related entities to return (default: 10) * * @param params - URL path parameters containing: * - key: Memory entity key/ID * @param searchParams - URL query parameters for customization * @param memoryManager - Optional memory entity manager instance * * @returns Promise resolving to resource generation result containing: * - data: Complete memory entity data with relationships * - contentType: "application/json" * - lastModified: ISO timestamp of generation * - cacheKey: Unique identifier "memory-expand:{key}" * - ttl: Cache duration (60 seconds / 1 minute) * - etag: Entity tag for cache validation * * @throws {McpAdrError} When memory expansion fails * * @example * ```typescript * // Get expanded memory entity * const memory = await generateMemoryExpandResource( * { key: 'adr-001' }, * new URLSearchParams() * ); * * console.log(`Entity type: ${memory.data.entity?.type}`); * console.log(`Relationships: ${memory.data.relationships.length}`); * * // With custom depth * const deep = await generateMemoryExpandResource( * { key: 'architecture-context' }, * new URLSearchParams('relationshipDepth=3&maxRelated=20') * ); * ``` * * @since v2.2.0 * @see {@link MemoryEntityManager} for memory management */ export async function generateMemoryExpandResource( params: Record<string, string>, searchParams: URLSearchParams, memoryManager?: MemoryEntityManager ): Promise<ResourceGenerationResult> { const key = params['key']; if (!key) { throw new McpAdrError('Missing required parameter: key', 'INVALID_PARAMS'); } const includeRelated = searchParams.get('includeRelated') !== 'false'; const relationshipDepth = parseInt(searchParams.get('relationshipDepth') || '2', 10); const maxRelated = parseInt(searchParams.get('maxRelated') || '10', 10); const cacheKey = `memory-expand:${key}`; // Check cache const cached = await resourceCache.get<ResourceGenerationResult>(cacheKey); if (cached) { return cached; } try { // If no memory manager provided, return a not-found response if (!memoryManager) { const notFoundData: MemoryExpandData = { key, entity: null, relationships: [], relatedEntities: [], timestamp: new Date().toISOString(), found: false, }; const result: ResourceGenerationResult = { data: notFoundData, contentType: 'application/json', lastModified: new Date().toISOString(), cacheKey, ttl: 30, // Short cache for not-found etag: generateETag(notFoundData), }; return result; } // Try to get the entity from memory manager let entity = null; let relationships: MemoryExpandData['relationships'] = []; let relatedEntities: MemoryExpandData['relatedEntities'] = []; try { // Attempt to get entity by ID using queryEntities const queryResult = await memoryManager.queryEntities({ textQuery: key, limit: 1, }); const foundEntity = queryResult.entities?.[0]; if (foundEntity) { entity = { id: foundEntity.id, type: foundEntity.type, name: foundEntity.title, // MemoryEntity uses 'title' not 'name' content: foundEntity.description, // MemoryEntity uses 'description' not 'content' metadata: foundEntity.context || {}, // MemoryEntity uses 'context' object tags: foundEntity.tags || [], confidence: foundEntity.confidence || 1.0, lastModified: foundEntity.lastModified || new Date().toISOString(), created: foundEntity.created || new Date().toISOString(), accessCount: foundEntity.accessPattern?.accessCount || 0, // Nested in accessPattern }; // Get relationships if requested if (includeRelated) { try { const related = await memoryManager.findRelatedEntities( foundEntity.id, relationshipDepth ); // Map relationshipPaths to our relationships format relationships = related.relationshipPaths ?.flatMap( (path: any) => path.relationships?.map((rel: any) => ({ targetId: rel.targetId, targetName: rel.targetId, relationshipType: rel.type || 'related', strength: rel.strength || 0.5, })) || [] ) .slice(0, maxRelated) || []; relatedEntities = related.entities?.slice(0, maxRelated).map((ent: any) => ({ id: ent.id, name: ent.title || ent.id, // MemoryEntity uses 'title' not 'name' type: ent.type, relevance: ent.relevance || 0.5, // Use relevance if available })) || []; } catch { // Relationships not available } } } } catch { // Entity not found } const expandData: MemoryExpandData = { key, entity, relationships, relatedEntities: relatedEntities.slice(0, maxRelated), timestamp: new Date().toISOString(), found: entity !== null, }; const result: ResourceGenerationResult = { data: expandData, contentType: 'application/json', lastModified: new Date().toISOString(), cacheKey, ttl: 60, // 1 minute cache etag: generateETag(expandData), }; // Cache result resourceCache.set(cacheKey, result, result.ttl); return result; } catch (error) { throw new McpAdrError( `Failed to expand memory entity: ${error instanceof Error ? error.message : String(error)}`, 'RESOURCE_GENERATION_ERROR' ); } } // Register route resourceRouter.register( '/memory/{key}', generateMemoryExpandResource, 'Detailed view of a specific memory entity' );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tosin2013/mcp-adr-analysis-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server