write_file
Write or append content to files in chunks of 25-30 lines to manage text documents, code files, and Excel spreadsheets within allowed directories.
Instructions
Write or append to file contents.
IMPORTANT: DO NOT use this tool to create PDF files. Use 'write_pdf' for all PDF creation tasks.
CHUNKING IS STANDARD PRACTICE: Always write files in chunks of 25-30 lines maximum.
This is the normal, recommended way to write files - not an emergency measure.
STANDARD PROCESS FOR ANY FILE:
1. FIRST → write_file(filePath, firstChunk, {mode: 'rewrite'}) [≤30 lines]
2. THEN → write_file(filePath, secondChunk, {mode: 'append'}) [≤30 lines]
3. CONTINUE → write_file(filePath, nextChunk, {mode: 'append'}) [≤30 lines]
ALWAYS CHUNK PROACTIVELY - don't wait for performance warnings!
WHEN TO CHUNK (always be proactive):
1. Any file expected to be longer than 25-30 lines
2. When writing multiple files in sequence
3. When creating documentation, code files, or configuration files
HANDLING CONTINUATION ("Continue" prompts):
If user asks to "Continue" after an incomplete operation:
1. Read the file to see what was successfully written
2. Continue writing ONLY the remaining content using {mode: 'append'}
3. Keep chunks to 25-30 lines each
FORMAT HANDLING (by extension):
- Text files: String content
- Excel (.xlsx, .xls, .xlsm): JSON 2D array or {"SheetName": [[...]]}
Example: '[["Name","Age"],["Alice",30]]'
Files over 50 lines will generate performance notes but are still written successfully.
Only works within allowed directories.
IMPORTANT: Always use absolute paths for reliability. Paths are automatically normalized regardless of slash direction. Relative paths may fail as they depend on the current working directory. Tilde paths (~/...) might not work in all contexts. Unless the user explicitly asks for relative paths, use absolute paths.
This command can be referenced as "DC: ..." or "use Desktop Commander to ..." in your instructions.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| mode | No | rewrite |
Implementation Reference
- MCP handler function for the 'write_file' tool. Validates input using WriteFileArgsSchema, enforces line limits, calls the core writeFile function, and returns success message.export async function handleWriteFile(args: unknown): Promise<ServerResult> { try { const parsed = WriteFileArgsSchema.parse(args); // Get the line limit from configuration const config = await configManager.getConfig(); const MAX_LINES = config.fileWriteLineLimit ?? 50; // Default to 50 if not set // Strictly enforce line count limit const lines = parsed.content.split('\n'); const lineCount = lines.length; let errorMessage = ""; if (lineCount > MAX_LINES) { errorMessage = `✅ File written successfully! (${lineCount} lines) 💡 Performance tip: For optimal speed, consider chunking files into ≤30 line pieces in future operations.`; } // Pass the mode parameter to writeFile await writeFile(parsed.path, parsed.content, parsed.mode); // Provide more informative message based on mode const modeMessage = parsed.mode === 'append' ? 'appended to' : 'wrote to'; return { content: [{ type: "text", text: `Successfully ${modeMessage} ${parsed.path} (${lineCount} lines) ${errorMessage}` }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return createErrorResponse(errorMessage); } }
- src/tools/schemas.ts:61-65 (schema)Zod schema defining input parameters for the write_file tool: path, content, and optional mode (rewrite or append).export const WriteFileArgsSchema = z.object({ path: z.string(), content: z.string(), mode: z.enum(['rewrite', 'append']).default('rewrite'), });
- src/server.ts:312-357 (registration)Tool registration/spec for 'write_file' in the list_tools response, including name, detailed description, input schema reference, and annotations.{ name: "write_file", description: ` Write or append to file contents. IMPORTANT: DO NOT use this tool to create PDF files. Use 'write_pdf' for all PDF creation tasks. CHUNKING IS STANDARD PRACTICE: Always write files in chunks of 25-30 lines maximum. This is the normal, recommended way to write files - not an emergency measure. STANDARD PROCESS FOR ANY FILE: 1. FIRST → write_file(filePath, firstChunk, {mode: 'rewrite'}) [≤30 lines] 2. THEN → write_file(filePath, secondChunk, {mode: 'append'}) [≤30 lines] 3. CONTINUE → write_file(filePath, nextChunk, {mode: 'append'}) [≤30 lines] ALWAYS CHUNK PROACTIVELY - don't wait for performance warnings! WHEN TO CHUNK (always be proactive): 1. Any file expected to be longer than 25-30 lines 2. When writing multiple files in sequence 3. When creating documentation, code files, or configuration files HANDLING CONTINUATION ("Continue" prompts): If user asks to "Continue" after an incomplete operation: 1. Read the file to see what was successfully written 2. Continue writing ONLY the remaining content using {mode: 'append'} 3. Keep chunks to 25-30 lines each FORMAT HANDLING (by extension): - Text files: String content - Excel (.xlsx, .xls, .xlsm): JSON 2D array or {"SheetName": [[...]]} Example: '[["Name","Age"],["Alice",30]]' Files over 50 lines will generate performance notes but are still written successfully. Only works within allowed directories. ${PATH_GUIDANCE} ${CMD_PREFIX_DESCRIPTION}`, inputSchema: zodToJsonSchema(WriteFileArgsSchema), annotations: { title: "Write File", readOnlyHint: false, destructiveHint: true, openWorldHint: false, }, },
- src/server.ts:1282-1284 (registration)Dispatcher case in call_tool handler that routes 'write_file' calls to the specific handleWriteFile function.case "write_file": result = await handlers.handleWriteFile(args); break;
- src/tools/filesystem.ts:477-500 (helper)Core implementation of file writing logic. Validates path access, captures telemetry, selects appropriate file handler (text/binary/Excel/etc.), and performs the write operation in specified mode.export async function writeFile(filePath: string, content: string, mode: 'rewrite' | 'append' = 'rewrite'): Promise<void> { const validPath = await validatePath(filePath); // Get file extension for telemetry const fileExtension = getFileExtension(validPath); // Calculate content metrics const contentBytes = Buffer.from(content).length; const lineCount = TextFileHandler.countLines(content); // Capture file extension and operation details in telemetry without capturing the file path capture('server_write_file', { fileExtension: fileExtension, mode: mode, contentBytes: contentBytes, lineCount: lineCount }); // Get appropriate handler for this file type (async - includes binary detection) const handler = await getFileHandler(validPath); // Use handler to write the file await handler.write(validPath, content, mode); }