Skip to main content
Glama

read_file

Retrieve file contents efficiently, either in full or by specific line ranges, using a file path. Option to display line numbers for enhanced readability and precise file navigation.

Instructions

Read the contents of a file. You can read the entire file or specific line ranges.

Input Schema

NameRequiredDescriptionDefault
end_lineNoEnding line number (1-based). Cannot be used with full=true
file_pathYesAbsolute path to the file to read
fullNoRead the entire file. Cannot be used with start_line or end_line
show_line_numbersNoWhether to prefix each line with its line number
start_lineNoStarting line number (1-based). Cannot be used with full=true

Input Schema (JSON Schema)

{ "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "end_line": { "description": "Ending line number (1-based). Cannot be used with full=true", "exclusiveMinimum": 0, "type": "integer" }, "file_path": { "description": "Absolute path to the file to read", "type": "string" }, "full": { "description": "Read the entire file. Cannot be used with start_line or end_line", "type": "boolean" }, "show_line_numbers": { "default": false, "description": "Whether to prefix each line with its line number", "type": "boolean" }, "start_line": { "description": "Starting line number (1-based). Cannot be used with full=true", "exclusiveMinimum": 0, "type": "integer" } }, "required": [ "file_path" ], "type": "object" }

Implementation Reference

  • src/index.ts:24-80 (registration)
    Registers the read_file tool using server.addTool, including name, description, parameters schema, and execute handler.
    server.addTool({ name: 'read_file', description: 'Read the contents of a file. You can read the entire file or specific line ranges.', parameters: z.object({ file_path: z.string().describe('Absolute path to the file to read'), show_line_numbers: z.boolean().optional().default(false).describe('Whether to prefix each line with its line number'), start_line: z.number().int().positive().optional().describe('Starting line number (1-based). Cannot be used with full=true'), end_line: z.number().int().positive().optional().describe('Ending line number (1-based). Cannot be used with full=true'), full: z.boolean().optional().describe('Read the entire file. Cannot be used with start_line or end_line') }), execute: async ({ file_path, show_line_numbers, start_line, end_line, full }) => { // Validate parameters if (full && (start_line || end_line)) { throw new UserError('Cannot use "full" parameter together with "start_line" or "end_line". Choose either full=true or specify line ranges.'); } if ((start_line && !end_line) || (!start_line && end_line)) { throw new UserError('Both "start_line" and "end_line" must be provided together.'); } if (start_line && end_line && start_line > end_line) { throw new UserError('"start_line" must be less than or equal to "end_line".'); } const absolutePath = validateAbsolutePath(file_path, 'file_path'); validateFileExists(absolutePath); try { const content = fs.readFileSync(absolutePath, 'utf-8'); const lines = content.split('\n'); let resultLines: string[]; if (full) { resultLines = lines; } else if (start_line && end_line) { if (start_line > lines.length) { throw new UserError(`Start line ${start_line} is beyond the file length (${lines.length} lines).`); } if (end_line > lines.length) { throw new UserError(`End line ${end_line} is beyond the file length (${lines.length} lines).`); } resultLines = lines.slice(start_line - 1, end_line); // Convert to 0-based } else { resultLines = lines; } if (show_line_numbers) { const startLineNum = start_line || 1; return resultLines.map((line, index) => `${startLineNum + index} | ${line}`).join('\n'); } else { return resultLines.join('\n'); } } catch (error: any) { if (error instanceof UserError) throw error; throw new UserError(`Error reading file "${absolutePath}": ${error.message}`); } } });
  • The core handler function for the read_file tool. It validates input parameters, reads the file using fs.readFileSync, processes line ranges if specified, optionally adds line numbers, and returns the content.
    execute: async ({ file_path, show_line_numbers, start_line, end_line, full }) => { // Validate parameters if (full && (start_line || end_line)) { throw new UserError('Cannot use "full" parameter together with "start_line" or "end_line". Choose either full=true or specify line ranges.'); } if ((start_line && !end_line) || (!start_line && end_line)) { throw new UserError('Both "start_line" and "end_line" must be provided together.'); } if (start_line && end_line && start_line > end_line) { throw new UserError('"start_line" must be less than or equal to "end_line".'); } const absolutePath = validateAbsolutePath(file_path, 'file_path'); validateFileExists(absolutePath); try { const content = fs.readFileSync(absolutePath, 'utf-8'); const lines = content.split('\n'); let resultLines: string[]; if (full) { resultLines = lines; } else if (start_line && end_line) { if (start_line > lines.length) { throw new UserError(`Start line ${start_line} is beyond the file length (${lines.length} lines).`); } if (end_line > lines.length) { throw new UserError(`End line ${end_line} is beyond the file length (${lines.length} lines).`); } resultLines = lines.slice(start_line - 1, end_line); // Convert to 0-based } else { resultLines = lines; } if (show_line_numbers) { const startLineNum = start_line || 1; return resultLines.map((line, index) => `${startLineNum + index} | ${line}`).join('\n'); } else { return resultLines.join('\n'); } } catch (error: any) { if (error instanceof UserError) throw error; throw new UserError(`Error reading file "${absolutePath}": ${error.message}`); } }
  • Zod schema defining the input parameters for the read_file tool, including file_path, optional line ranges, full read flag, and line number display option.
    parameters: z.object({ file_path: z.string().describe('Absolute path to the file to read'), show_line_numbers: z.boolean().optional().default(false).describe('Whether to prefix each line with its line number'), start_line: z.number().int().positive().optional().describe('Starting line number (1-based). Cannot be used with full=true'), end_line: z.number().int().positive().optional().describe('Ending line number (1-based). Cannot be used with full=true'), full: z.boolean().optional().describe('Read the entire file. Cannot be used with start_line or end_line')
  • Helper function validateAbsolutePath used in read_file handler to ensure the file_path is absolute (called at line 46).
    export function validateAbsolutePath(filePath: string, parameterName: string = 'path'): string { if (!path.isAbsolute(filePath)) { throw new UserError( `The ${parameterName} must be an absolute path. You provided a relative path: "${filePath}". ` + `Please provide the full absolute path (e.g., "/home/user/file.txt" on Linux/Mac or "C:\\Users\\user\\file.txt" on Windows).` ); } return filePath; }
  • Helper function validateFileExists used in read_file handler to check if the file exists and is readable (called at line 47).
    export function validateFileExists(filePath: string): void { try { const stats = fs.statSync(filePath); if (!stats.isFile()) { throw new UserError( `The path "${filePath}" exists but is not a file. Please ensure you're providing the path to a file, not a directory.` ); } } catch (error: any) { if (error.code === 'ENOENT') { throw new UserError( `File not found: "${filePath}". Please verify that the file exists and the path is correct.` ); } else if (error.code === 'EACCES') { throw new UserError( `Permission denied: Cannot access "${filePath}". Please check file permissions.` ); } else { throw new UserError( `Error accessing file "${filePath}": ${error.message}` ); } } }

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/pwilkin/mcp-file-edit'

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