append_memory_bank_entry
Appends a timestamped entry to a specified file in the memory bank, optionally under a specific markdown header, to maintain persistent project context for AI assistants.
Instructions
Appends a new, timestamped entry to a specified file, optionally under a specific markdown header.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| entry | Yes | The content of the entry to append. | |
| file_name | Yes | The name of the memory bank file to append to. | |
| section_header | No | (Optional) The exact markdown header (e.g., '## Decision') to append under. |
Implementation Reference
- src/index.ts:180-235 (handler)Main handler function that validates inputs, formats the entry with timestamp, ensures directory exists, and appends the entry to the specified file, optionally inserting under a markdown section header.async appendMemoryBankEntry(input: any): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> { const { file_name: fileName, entry, section_header: sectionHeader } = input; if (!fileName || typeof fileName !== 'string') { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "Missing or invalid 'file_name' parameter." }, null, 2) }], isError: true }; } if (!entry || typeof entry !== 'string') { return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: "Missing or invalid 'entry' parameter." }, null, 2) }], isError: true }; } const filePath = path.join(MEMORY_BANK_PATH, fileName); const timestamp = getCurrentTimestamp(); const formattedEntry = `\n[${timestamp}] - ${entry}\n`; try { await ensureMemoryBankDir(); // Ensure directory exists before appending if (sectionHeader && typeof sectionHeader === 'string') { let fileContent = ""; try { fileContent = await fs.readFile(filePath, 'utf-8'); } catch (readError: any) { if (readError.code === 'ENOENT') { // File doesn't exist, create it console.warn(chalk.yellow(`File ${fileName} not found, creating.`)); // Use initial template if available, otherwise just the header and entry const initialTemplate = INITIAL_FILES[fileName] ? INITIAL_FILES[fileName].replace('YYYY-MM-DD HH:MM:SS', timestamp) : ''; fileContent = initialTemplate; } else { throw readError; // Re-throw other read errors } } const headerIndex = fileContent.indexOf(sectionHeader); if (headerIndex !== -1) { // Find the end of the section (next header or end of file) const nextHeaderIndex = fileContent.indexOf('\n##', headerIndex + sectionHeader.length); const insertIndex = (nextHeaderIndex !== -1) ? nextHeaderIndex : fileContent.length; const updatedContent = fileContent.slice(0, insertIndex).trimEnd() + '\n' + formattedEntry.trimStart() + fileContent.slice(insertIndex); await fs.writeFile(filePath, updatedContent); } else { // Header not found, append to the end with the header console.warn(chalk.yellow(`Header "${sectionHeader}" not found in ${fileName}. Appending header and entry to the end.`)); await fs.appendFile(filePath, `\n${sectionHeader}\n${formattedEntry}`); } } else { // No section header, just append to the end await fs.appendFile(filePath, formattedEntry); } return { content: [{ type: "text", text: JSON.stringify({ status: "success", message: `Appended entry to ${fileName}` }, null, 2) }] }; } catch (error: any) { console.error(chalk.red(`Error appending to file ${fileName}:`), error); return { content: [{ type: "text", text: JSON.stringify({ status: "error", message: `Failed to append to file ${fileName}: ${error.message}` }, null, 2) }], isError: true }; } }
- src/index.ts:86-108 (schema)Tool definition with name, description, and input schema specifying parameters file_name (required), entry (required), and optional section_header.const APPEND_MEMORY_BANK_ENTRY_TOOL: Tool = { name: "append_memory_bank_entry", description: "Appends a new, timestamped entry to a specified file, optionally under a specific markdown header.", inputSchema: { type: "object", properties: { file_name: { type: "string", description: "The name of the memory bank file to append to." }, entry: { type: "string", description: "The content of the entry to append." }, section_header: { type: "string", description: "(Optional) The exact markdown header (e.g., '## Decision') to append under." } }, required: ["file_name", "entry"] } // Output: Confirmation message (handled in implementation) };
- src/index.ts:110-115 (registration)Includes the append_memory_bank_entry tool in the ALL_TOOLS array returned by the listTools handler.const ALL_TOOLS = [ INITIALIZE_MEMORY_BANK_TOOL, CHECK_MEMORY_BANK_STATUS_TOOL, READ_MEMORY_BANK_FILE_TOOL, APPEND_MEMORY_BANK_ENTRY_TOOL ];
- src/index.ts:272-273 (registration)Switch case in CallToolRequestHandler that routes tool calls to the appendMemoryBankEntry handler method.case "append_memory_bank_entry": return memoryBankServer.appendMemoryBankEntry(args);