Skip to main content
Glama

write_resource

Edit files on the Backlog MCP Server by replacing, inserting, or appending content to manage task backlog updates.

Instructions

Edit existing files on the MCP server. All file creation goes through backlog_create.

  • The append command will add content to the end of an existing file, automatically adding a newline if the file doesn't end with one. Notes for using the str_replace command:

  • The old_str parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!

  • If the old_str parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in old_str to make it unique

  • The new_str parameter should contain the edited lines that should replace the old_str

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
uriYesMCP resource URI, e.g. mcp://backlog/path/to/file.md
operationYesOperation to apply

Implementation Reference

  • The write_resource tool handler callback that executes the write operation via resourceManager.write() and returns the result as JSON
      async ({ uri, operation }) => {
        const result = this.write(uri, operation);
        return {
          content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
        };
      }
    );
  • Core write method that resolves URIs to file paths, applies operations, updates task timestamps, and handles file operations
    write(uri: string, operation: Operation): WriteResourceResult {
      try {
        const filePath = this.resolve(uri);
        const isTask = this.isTaskUri(uri);
        
        if (!existsSync(filePath)) {
          return {
            success: false,
            message: 'File not found',
            error: `Resource not found: ${uri} (${operation.type} requires existing file). Use backlog_create to create new entities.`,
          };
        }
    
        const fileContent = readFileSync(filePath, 'utf-8');
    
        let newContent = applyOperation(fileContent, operation);
        
        // Update timestamp for task files
        if (isTask) {
          newContent = this.updateTaskTimestamp(newContent);
        }
        
        writeFileSync(filePath, newContent, 'utf-8');
    
        return {
          success: true,
          message: `Successfully applied ${operation.type} to ${uri}`,
        };
      } catch (error) {
        return {
          success: false,
          message: 'Operation failed',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    }
  • Zod schema definition for write_resource tool input parameters, validating URI and operation types (str_replace, insert, append)
    inputSchema: z.object({
      uri: z.string().describe('MCP resource URI, e.g. mcp://backlog/path/to/file.md'),
      operation: z.preprocess(
        // Workaround: MCP clients stringify object params with $ref/oneOf schemas
        // https://github.com/anthropics/claude-code/issues/18260
        (val) => typeof val === 'string' ? JSON.parse(val) : val,
        z.discriminatedUnion('type', [
        z.object({
          type: z.literal('str_replace'),
          old_str: z.string().describe('String in file to replace (must match exactly)'),
          new_str: z.string().describe('New string to replace old_str with'),
        }),
        z.object({
          type: z.literal('insert'),
          insert_line: z.number().describe('Line number after which new_str will be inserted'),
          new_str: z.string().describe('String to insert'),
        }),
        z.object({
          type: z.literal('append'),
          new_str: z.string().describe('Content to append to the file'),
        }),
      ])).describe('Operation to apply'),
    }),
  • Method that registers the write_resource tool with the MCP server, including description, input schema, and handler callback
     registerWriteTool(server: McpServer) {
       server.registerTool(
         'write_resource',
         {
           description: `Edit existing files on the MCP server. All file creation goes through backlog_create.
    * The \`append\` command will add content to the end of an existing file, automatically adding a newline if the file doesn't end with one.
    Notes for using the \`str_replace\` command:
    * The \`old_str\` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespaces!
    * If the \`old_str\` parameter is not unique in the file, the replacement will not be performed. Make sure to include enough context in \`old_str\` to make it unique
    * The \`new_str\` parameter should contain the edited lines that should replace the \`old_str\``,
           inputSchema: z.object({
             uri: z.string().describe('MCP resource URI, e.g. mcp://backlog/path/to/file.md'),
             operation: z.preprocess(
               // Workaround: MCP clients stringify object params with $ref/oneOf schemas
               // https://github.com/anthropics/claude-code/issues/18260
               (val) => typeof val === 'string' ? JSON.parse(val) : val,
               z.discriminatedUnion('type', [
               z.object({
                 type: z.literal('str_replace'),
                 old_str: z.string().describe('String in file to replace (must match exactly)'),
                 new_str: z.string().describe('New string to replace old_str with'),
               }),
               z.object({
                 type: z.literal('insert'),
                 insert_line: z.number().describe('Line number after which new_str will be inserted'),
                 new_str: z.string().describe('String to insert'),
               }),
               z.object({
                 type: z.literal('append'),
                 new_str: z.string().describe('Content to append to the file'),
               }),
             ])).describe('Operation to apply'),
           }),
         },
         async ({ uri, operation }) => {
           const result = this.write(uri, operation);
           return {
             content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
           };
         }
       );
     }
  • Helper function that applies the actual text operations (str_replace, insert, append) to file content
    export function applyOperation(content: string, operation: Operation): string {
      switch (operation.type) {
        case 'str_replace': {
          const { old_str, new_str } = operation;
          if (!content.includes(old_str)) {
            throw new Error(`str_replace failed: old_str not found in content`);
          }
          // Check uniqueness - fail if old_str appears more than once
          const firstIndex = content.indexOf(old_str);
          const secondIndex = content.indexOf(old_str, firstIndex + 1);
          if (secondIndex !== -1) {
            throw new Error(`str_replace failed: old_str is not unique in file. Include more context to make it unique.`);
          }
          return content.replace(old_str, new_str);
        }
    
        case 'insert': {
          // insert_line: insert AFTER this line (1-based, like fs_write)
          const lines = content.split('\n');
          const lineNum = operation.insert_line;
          if (lineNum < 0 || lineNum > lines.length) {
            throw new Error(`insert failed: line ${lineNum} out of range (0-${lines.length})`);
          }
          lines.splice(lineNum, 0, operation.new_str);
          return lines.join('\n');
        }
    
        case 'append': {
          // Add newline if file doesn't end with one (like fs_write)
          const needsNewline = content.length > 0 && !content.endsWith('\n');
          return content + (needsNewline ? '\n' : '') + operation.new_str;
        }
    
        default:
          throw new Error(`Unknown operation type: ${(operation as any).type}`);
      }
    }

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/gkoreli/backlog-mcp'

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