update_memory
Enhance and maintain the accuracy of stored knowledge by updating content, categorization, and metadata in a centralized memory repository. Ensures reliable, up-to-date information for informed decisions.
Instructions
Evolve and refine your stored knowledge with flexible updates to content, categorization, and metadata. Keep your memory repository current and accurate as understanding deepens, ensuring your knowledge base remains a reliable source of up-to-date insights and decisions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | New category for organizing the memory | |
| content | No | New detailed content for the memory (no character limit) | |
| id | Yes | The unique identifier of the memory to update | |
| metadata | No | New metadata as key-value pairs (replaces existing metadata) | |
| title | No | New title for the memory (max 50 characters for better file organization) | |
| workingDirectory | Yes | The full absolute path to the working directory where data is stored. MUST be an absolute path, never relative. Windows: "C:\Users\username\project" or "D:\projects\my-app". Unix/Linux/macOS: "/home/username/project" or "/Users/username/project". Do NOT use: ".", "..", "~", "./folder", "../folder" or any relative paths. Ensure the path exists and is accessible before calling this tool. NOTE: When server is started with --claude flag, this parameter is ignored and a global user directory is used instead. |
Implementation Reference
- The core handler function that implements the 'update_memory' tool logic: input validation, existing memory retrieval, update preparation, storage update call, change detection, and formatted success/error responses.handler: async ({ id, title, content, metadata, category }: { id: string; title?: string; content?: string; metadata?: Record<string, any>; category?: string; }) => { try { // Validate inputs if (!id || id.trim().length === 0) { return { content: [{ type: 'text' as const, text: 'Error: Memory ID is required.' }], isError: true }; } if (content !== undefined && content.trim().length === 0) { return { content: [{ type: 'text' as const, text: 'Error: Content cannot be empty if provided.' }], isError: true }; } if (title && title.trim().length > 50) { return { content: [{ type: 'text' as const, text: `Error: Memory title must be 50 characters or less for better file organization. Current length: ${title.trim().length} characters. Please provide a short, descriptive title instead. For example: - "User prefers dark mode interface" - "Project uses TypeScript and React" - "Database connection timeout is 30s" Use the content field for detailed information.` }], isError: true }; } if (category && category.trim().length > 100) { return { content: [{ type: 'text' as const, text: 'Error: Category must be 100 characters or less.' }], isError: true }; } // Check if at least one field is being updated if (title === undefined && content === undefined && metadata === undefined && category === undefined) { return { content: [{ type: 'text' as const, text: 'Error: At least one field (title, content, metadata, or category) must be provided for update.' }], isError: true }; } // Get the existing memory first const existingMemory = await storage.getMemory(id.trim()); if (!existingMemory) { return { content: [{ type: 'text' as const, text: `❌ Memory not found. **Memory ID:** ${id} The memory with this ID does not exist or may have been deleted.` }], isError: true }; } // Prepare updates const updates: any = {}; if (title !== undefined) { updates.title = title.trim(); } if (content !== undefined) { updates.content = content.trim(); } if (metadata !== undefined) { updates.metadata = metadata; } if (category !== undefined) { updates.category = category.trim(); } const updatedMemory = await storage.updateMemory(id.trim(), updates); if (!updatedMemory) { return { content: [{ type: 'text' as const, text: `❌ Failed to update memory. **Memory ID:** ${id} The memory could not be updated. Please try again.` }], isError: true }; } // Show what changed const changes: string[] = []; if (title !== undefined && title.trim() !== existingMemory.title) { changes.push('Title'); } if (content !== undefined && content.trim() !== existingMemory.content) { changes.push('Content'); } if (metadata !== undefined && JSON.stringify(metadata) !== JSON.stringify(existingMemory.metadata)) { changes.push('Metadata'); } if (category !== undefined && category.trim() !== existingMemory.category) { changes.push('Category'); } return { content: [{ type: 'text' as const, text: `✅ Memory updated successfully! **Memory ID:** ${updatedMemory.id} **Updated Fields:** ${changes.join(', ')} **Title:** ${updatedMemory.title} **Content:** ${updatedMemory.content.substring(0, 200)}${updatedMemory.content.length > 200 ? '...' : ''} **Category:** ${updatedMemory.category || 'Not specified'} **Created:** ${new Date(updatedMemory.createdAt).toLocaleString()} **Updated:** ${new Date(updatedMemory.updatedAt).toLocaleString()} **Metadata:** ${Object.keys(updatedMemory.metadata).length > 0 ? JSON.stringify(updatedMemory.metadata, null, 2) : 'None'}` }] }; } catch (error) { return { content: [{ type: 'text' as const, text: `Error updating memory: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } }
- Zod-based input schema defining parameters for updating a memory: id (required), title/content/metadata/category (optional).inputSchema: { id: z.string(), title: z.string().optional(), content: z.string().optional(), metadata: z.record(z.any()).optional(), category: z.string().optional() },
- src/server.ts:842-875 (registration)MCP server registration of 'update_memory' tool via McpServer.tool(). Wraps the createUpdateMemoryTool handler, adds workingDirectory param and storage creation.server.tool( 'update_memory', 'Evolve and refine your stored knowledge with flexible updates to content, categorization, and metadata. Keep your memory repository current and accurate as understanding deepens, ensuring your knowledge base remains a reliable source of up-to-date insights and decisions.', { workingDirectory: z.string().describe(getWorkingDirectoryDescription(config)), id: z.string().describe('The unique identifier of the memory to update'), title: z.string().optional().describe('New title for the memory (max 50 characters for better file organization)'), content: z.string().optional().describe('New detailed content for the memory (no character limit)'), metadata: z.record(z.any()).optional().describe('New metadata as key-value pairs (replaces existing metadata)'), category: z.string().optional().describe('New category for organizing the memory') }, async ({ workingDirectory, id, title, content, metadata, category }: { workingDirectory: string; id: string; title?: string; content?: string; metadata?: Record<string, any>; category?: string; }) => { try { const storage = await createMemoryStorage(workingDirectory, config); const tool = createUpdateMemoryTool(storage); return await tool.handler({ id, title, content, metadata, category }); } catch (error) { return { content: [{ type: 'text' as const, text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } );
- File storage backend implementation of updateMemory: finds JSON file by ID, parses, merges partial updates, handles category moves, updates timestamp, persists to file.async updateMemory(id: string, updates: Partial<Memory>): Promise<Memory | null> { const filePath = await this.findMemoryFileById(id); if (!filePath) { return null; } try { const content = await fs.readFile(filePath, 'utf-8'); const jsonMemory = JSON.parse(content); // Convert to Memory interface for merging const existingMemory: Memory = { id: jsonMemory.id, title: jsonMemory.title, content: jsonMemory.details, metadata: {}, createdAt: jsonMemory.dateCreated, updatedAt: jsonMemory.dateUpdated, category: jsonMemory.category === 'general' ? undefined : jsonMemory.category }; // Merge updates const updatedMemory: Memory = { ...existingMemory, ...updates, id: existingMemory.id, // Ensure ID doesn't change updatedAt: new Date().toISOString(), }; // If category changed, we need to move the file if (updates.category !== undefined && updates.category !== existingMemory.category) { // Delete old file await fs.unlink(filePath); // Create new file in new category await this.createMemory(updatedMemory); } else { // Update existing file const updatedJsonMemory = { id: updatedMemory.id, title: updatedMemory.title, details: updatedMemory.content, category: updatedMemory.category || 'general', dateCreated: updatedMemory.createdAt, dateUpdated: updatedMemory.updatedAt }; await fs.writeFile(filePath, JSON.stringify(updatedJsonMemory, null, 2), 'utf-8'); } return updatedMemory; } catch (error) { return null; } }