read_file
Read file contents as text, with options to extract specific first or last lines for focused data retrieval.
Instructions
Read the complete contents of a file as text. DEPRECATED: Use read_text_file instead.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| tail | No | If provided, returns only the last N lines of the file | |
| head | No | If provided, returns only the first N lines of the file |
Implementation Reference
- src/filesystem/index.ts:172-192 (handler)Handler function that implements the core logic for the 'read_file' tool. Validates path, optionally tails/heads the file, otherwise reads full content using readFileContent, and returns as text content.const readTextFileHandler = async (args: z.infer<typeof ReadTextFileArgsSchema>) => { const validPath = await validatePath(args.path); if (args.head && args.tail) { throw new Error("Cannot specify both head and tail parameters simultaneously"); } let content: string; if (args.tail) { content = await tailFile(validPath, args.tail); } else if (args.head) { content = await headFile(validPath, args.head); } else { content = await readFileContent(validPath); } return { content: [{ type: "text" as const, text: content }], structuredContent: { content } }; };
- src/filesystem/index.ts:194-204 (registration)Registration of the 'read_file' tool, marking it as deprecated and pointing to read_text_file, using the shared readTextFileHandler.server.registerTool( "read_file", { title: "Read File (Deprecated)", description: "Read the complete contents of a file as text. DEPRECATED: Use read_text_file instead.", inputSchema: ReadTextFileArgsSchema.shape, outputSchema: { content: z.string() }, annotations: { readOnlyHint: true } }, readTextFileHandler );
- src/filesystem/index.ts:77-81 (schema)Zod input schema defining parameters for read_file (path, optional tail/head line limits).const ReadTextFileArgsSchema = z.object({ path: z.string(), tail: z.number().optional().describe('If provided, returns only the last N lines of the file'), head: z.number().optional().describe('If provided, returns only the first N lines of the file') });
- src/filesystem/lib.ts:134-136 (helper)Helper function that performs the actual fs.readFile operation for reading file contents as text, used by the read_file handler.export async function readFileContent(filePath: string, encoding: string = 'utf-8'): Promise<string> { return await fs.readFile(filePath, encoding as BufferEncoding); }
- src/filesystem/lib.ts:262-311 (helper)Helper for tailing last N lines, used when 'tail' parameter is provided in read_file.export async function tailFile(filePath: string, numLines: number): Promise<string> { const CHUNK_SIZE = 1024; // Read 1KB at a time const stats = await fs.stat(filePath); const fileSize = stats.size; if (fileSize === 0) return ''; // Open file for reading const fileHandle = await fs.open(filePath, 'r'); try { const lines: string[] = []; let position = fileSize; let chunk = Buffer.alloc(CHUNK_SIZE); let linesFound = 0; let remainingText = ''; // Read chunks from the end of the file until we have enough lines while (position > 0 && linesFound < numLines) { const size = Math.min(CHUNK_SIZE, position); position -= size; const { bytesRead } = await fileHandle.read(chunk, 0, size, position); if (!bytesRead) break; // Get the chunk as a string and prepend any remaining text from previous iteration const readData = chunk.slice(0, bytesRead).toString('utf-8'); const chunkText = readData + remainingText; // Split by newlines and count const chunkLines = normalizeLineEndings(chunkText).split('\n'); // If this isn't the end of the file, the first line is likely incomplete // Save it to prepend to the next chunk if (position > 0) { remainingText = chunkLines[0]; chunkLines.shift(); // Remove the first (incomplete) line } // Add lines to our result (up to the number we need) for (let i = chunkLines.length - 1; i >= 0 && linesFound < numLines; i--) { lines.unshift(chunkLines[i]); linesFound++; } } return lines.join('\n'); } finally { await fileHandle.close(); } }