Skip to main content
Glama

edit_document

Modify line sequences in markdown documents by replacing specified text. Generates a git-style diff to track changes and supports dry-run for testing edits. Ideal for precise document updates.

Instructions

Make line-based edits to a markdown document. Each edit replaces exact line sequences with new content. Returns a git-style diff showing the changes made.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dryRunNo
editsYes
pathYes

Implementation Reference

  • The core handler function that implements the edit_document tool logic. Reads the document, applies sequential text replacements with line-matching fallback, generates a unified diff, optionally writes changes (unless dryRun), and returns the diff.
    async editDocument( docPath: string, edits: Array<{ oldText: string; newText: string }>, dryRun = false ): Promise<ToolResponse> { try { const validPath = await this.validatePath(docPath); // Read file content and normalize line endings const content = normalizeLineEndings( await fs.readFile(validPath, "utf-8") ); // Apply edits sequentially let modifiedContent = content; for (const edit of edits) { const normalizedOld = normalizeLineEndings(edit.oldText); const normalizedNew = normalizeLineEndings(edit.newText); // If exact match exists, use it if (modifiedContent.includes(normalizedOld)) { modifiedContent = modifiedContent.replace( normalizedOld, normalizedNew ); continue; } // Otherwise, try line-by-line matching with flexibility for whitespace const oldLines = normalizedOld.split("\n"); const contentLines = modifiedContent.split("\n"); let matchFound = false; for (let i = 0; i <= contentLines.length - oldLines.length; i++) { const potentialMatch = contentLines.slice(i, i + oldLines.length); // Compare lines with normalized whitespace const isMatch = oldLines.every((oldLine, j) => { const contentLine = potentialMatch[j]; return oldLine.trim() === contentLine.trim(); }); if (isMatch) { // Preserve original indentation of first line const originalIndent = contentLines[i].match(/^\s*/)?.[0] || ""; const newLines = normalizedNew.split("\n").map((line, j) => { if (j === 0) return originalIndent + line.trimStart(); // For subsequent lines, try to preserve relative indentation const oldIndent = oldLines[j]?.match(/^\s*/)?.[0] || ""; const newIndent = line.match(/^\s*/)?.[0] || ""; if (oldIndent && newIndent) { const relativeIndent = newIndent.length - oldIndent.length; return ( originalIndent + " ".repeat(Math.max(0, relativeIndent)) + line.trimStart() ); } return line; }); contentLines.splice(i, oldLines.length, ...newLines); modifiedContent = contentLines.join("\n"); matchFound = true; break; } } if (!matchFound) { throw new Error( `Could not find exact match for edit:\n${edit.oldText}` ); } } // Create unified diff const diff = createUnifiedDiff(content, modifiedContent, docPath); // Format diff with appropriate number of backticks let numBackticks = 3; while (diff.includes("`".repeat(numBackticks))) { numBackticks++; } const formattedDiff = `${"`".repeat( numBackticks )}diff\n${diff}${"`".repeat(numBackticks)}\n\n`; if (!dryRun) { await fs.writeFile(validPath, modifiedContent, "utf-8"); } return { content: [{ type: "text", text: formattedDiff }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error editing document: ${errorMessage}` }, ], isError: true, }; } }
  • Zod schema for validating input to edit_document: requires path, array of edits (each with oldText and newText), optional dryRun boolean.
    export const EditDocumentSchema = ToolInputSchema.extend({ path: z.string(), edits: z.array( z.object({ oldText: z.string(), newText: z.string(), }) ), dryRun: z.boolean().default(false), });
  • src/index.ts:214-220 (registration)
    Tool registration in the listTools handler, defining name, description, and input schema for edit_document.
    { name: "edit_document", description: "Make line-based edits to a markdown document. Each edit replaces exact line sequences " + "with new content. Returns a git-style diff showing the changes made.", inputSchema: zodToJsonSchema(EditDocumentSchema) as any, },
  • src/index.ts:335-347 (registration)
    Dispatch logic in the callToolRequestSchema handler that parses arguments and invokes the documentHandler.editDocument method.
    case "edit_document": { const parsed = EditDocumentSchema.safeParse(args); if (!parsed.success) { throw new Error( `Invalid arguments for edit_document: ${parsed.error}` ); } return await documentHandler.editDocument( parsed.data.path, parsed.data.edits, parsed.data.dryRun ); }

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/alekspetrov/mcp-docs-service'

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