Skip to main content
Glama
IncomeStreamSurfer

Roo Code Memory Bank MCP Server

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
NameRequiredDescriptionDefault
entryYesThe content of the entry to append.
file_nameYesThe name of the memory bank file to append to.
section_headerNo(Optional) The exact markdown header (e.g., '## Decision') to append under.

Implementation Reference

  • 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 };
       }
     }
  • 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);
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden but offers minimal behavioral insight. It states the tool appends with timestamping and optional header placement, but lacks details on permissions, file format constraints, error handling (e.g., if file doesn't exist), or mutation effects (e.g., overwriting). This is inadequate for a write operation with zero annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action and key optional feature. Every word earns its place, with no redundancy or fluff, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (a write operation with 3 parameters), lack of annotations, and no output schema, the description is incomplete. It doesn't cover behavioral aspects like error cases, return values, or interaction with siblings, leaving significant gaps for an agent to use it correctly in context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all parameters. The description adds marginal value by clarifying that 'section_header' is for markdown headers and 'entry' is content, but doesn't provide syntax examples or constraints beyond the schema. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Appends'), resource ('to a specified file'), and key details ('new, timestamped entry', 'optionally under a specific markdown header'), making the purpose unambiguous. However, it doesn't explicitly differentiate from sibling tools like 'initialize_memory_bank' (which likely creates files) or 'read_memory_bank_file' (which reads content), missing full sibling distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., file must exist), exclusions (e.g., not for creating new files), or comparisons to siblings like 'initialize_memory_bank' for setup or 'read_memory_bank_file' for retrieval, leaving usage context implied at best.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/IncomeStreamSurfer/roo-code-memory-bank-mcp-server'

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