move_list_item
Move items between sections in structured memory documents to reorganize information and maintain context for better project management.
Instructions
Move an item from one section to another
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| memory_id | Yes | The ID of the memory document to update | |
| from_section | Yes | The source section containing the item | |
| to_section | Yes | The destination section for the item | |
| item_identifier | Yes | Identifier for the item to move (e.g., company name) | |
| reason | No | Optional reason for the move (stored as metadata) |
Implementation Reference
- src/tools/moveListItem.ts:11-77 (handler)The main handler function `moveListItemTool` that implements the core logic for moving a list item between sections in a memory document.export async function moveListItemTool( storageManager: StorageManager, args: any ): Promise<any> { const params = args as MoveListItemParams; if (!params.memory_id || !params.from_section || !params.to_section || !params.item_identifier) { throw new Error('memory_id, from_section, to_section, and item_identifier are required'); } // Read the memory document const memory = await storageManager.readMemory(params.memory_id); if (!memory) { throw new Error(`Memory document '${params.memory_id}' not found`); } // Find both sections const fromSection = storageManager.findSection(memory.content, params.from_section); if (!fromSection) { throw new Error(`Source section '${params.from_section}' not found in memory document '${params.memory_id}'`); } const toSection = storageManager.findSection(memory.content, params.to_section); const toSectionExists = toSection !== null; // Parse the from section to find and extract the item const fromLines = fromSection.content.split('\n'); const boundaries = findItemBoundaries(fromLines, params.item_identifier); if (!boundaries) { throw new Error(`Item '${params.item_identifier}' not found in section '${params.from_section}'`); } // Extract the item let extractedItem = extractItemLines(fromLines, boundaries); // Add reason as metadata if provided if (params.reason) { extractedItem = addReasonToItem(extractedItem, params.reason, params.from_section); } // Remove item from source section const remainingFromLines = removeItemFromLines(fromLines, boundaries); const newFromContent = remainingFromLines.join('\n'); // Add item to destination section const existingToContent = toSectionExists && toSection ? toSection.content : null; const newToContent = prepareDestinationContent(extractedItem, existingToContent); // Update both sections await storageManager.updateSection(params.memory_id, params.from_section, newFromContent, 'replace'); await storageManager.updateSection(params.memory_id, params.to_section, newToContent, 'replace'); return { content: [{ type: 'text', text: `Successfully moved item '${params.item_identifier}' from '${params.from_section}' to '${params.to_section}' in memory document '${params.memory_id}': **Item**: ${params.item_identifier} **From**: ${params.from_section} **To**: ${params.to_section}${params.reason ? `\n**Reason**: ${params.reason}` : ''} **Destination Section**: ${toSectionExists ? 'Updated existing section' : 'Created new section'} The item has been moved successfully. You can view both sections using the get_section tool.` }] }; }
- src/index.ts:198-233 (registration)Tool registration in the list of available tools, defining name, description, and input schema for MCP protocol.{ name: "move_list_item", description: "Move an item from one section to another", inputSchema: { type: "object", properties: { memory_id: { type: "string", description: "The ID of the memory document to update", }, from_section: { type: "string", description: "The source section containing the item", }, to_section: { type: "string", description: "The destination section for the item", }, item_identifier: { type: "string", description: "Identifier for the item to move (e.g., company name)", }, reason: { type: "string", description: "Optional reason for the move (stored as metadata)", }, }, required: [ "memory_id", "from_section", "to_section", "item_identifier", ], }, },
- src/types/memory.ts:75-81 (schema)TypeScript interface defining the parameters for the move_list_item tool.export interface MoveListItemParams { memory_id: string; from_section: string; to_section: string; item_identifier: string; reason?: string; }
- Supporting helper functions for identifying, extracting, removing, and inserting list items.// Helper functions for moveListItem tool export interface ItemBoundaries { startIndex: number; endIndex: number; } export interface ExtractedItem { lines: string[]; boundaries: ItemBoundaries; } /** * Finds the boundaries of an item in a section by identifier */ export function findItemBoundaries(lines: string[], identifier: string): ItemBoundaries | null { for (let i = 0; i < lines.length; i++) { const line = lines[i].trim(); if (line.toLowerCase().includes(identifier.toLowerCase())) { const startIndex = i; let endIndex = i; // Find the end of this item by looking for the next heading or end of content for (let j = i + 1; j < lines.length; j++) { const nextLine = lines[j].trim(); // If we hit another heading (### ), this item ends at the previous line if (nextLine.startsWith('### ')) { endIndex = j - 1; break; } // If we hit an empty line followed by a heading, the item ends at the empty line if (nextLine === '' && lines[j + 1]?.trim().startsWith('### ')) { endIndex = j - 1; break; } // Otherwise, this line is part of the item endIndex = j; } return { startIndex, endIndex }; } } return null; } /** * Extracts an item from lines based on boundaries */ export function extractItemLines(lines: string[], boundaries: ItemBoundaries): string[] { return lines.slice(boundaries.startIndex, boundaries.endIndex + 1); } /** * Removes an item from lines based on boundaries */ export function removeItemFromLines(lines: string[], boundaries: ItemBoundaries): string[] { return [ ...lines.slice(0, boundaries.startIndex), ...lines.slice(boundaries.endIndex + 1) ]; } /** * Adds reason metadata to extracted item lines */ export function addReasonToItem(itemLines: string[], reason: string, fromSection: string): string[] { const reasonLine = ` <!-- Moved from ${fromSection}: ${reason} -->`; return [...itemLines, reasonLine]; } /** * Prepares content for destination section (new or existing) */ export function prepareDestinationContent( itemLines: string[], existingContent: string | null ): string { if (existingContent !== null) { // Append to existing section const existingLines = existingContent.split('\n'); const combinedLines = [...existingLines, '', ...itemLines]; return combinedLines.join('\n'); } else { // Create new section with the item return itemLines.join('\n'); } } /** * Validates that an item identifier exists in the given lines */ export function validateItemExists(lines: string[], identifier: string): boolean { return lines.some(line => line.trim().toLowerCase().includes(identifier.toLowerCase()) ); } /** * Counts remaining items in section after removal */ export function countRemainingItems(lines: string[]): number { return lines.filter(line => line.trim().startsWith('### ')).length; }
- src/index.ts:283-284 (registration)Dispatch handler in the switch statement for calling the moveListItemTool.case "move_list_item": return await moveListItemTool(storageManager, args);