read_file
Read files from the filesystem with configurable encoding and size limits. Supports text and binary files while blocking path traversal for secure file access.
Instructions
Read a file from the filesystem. Paths are relative to the configured root directory (/app/workspace). Path traversal (../) is blocked. Use encoding=base64 for binary files.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the file, relative to the configured root directory | |
| encoding | No | File encoding — use base64 for binary files | utf8 |
| max_bytes | No | Maximum bytes to read (default: 1MB, max: 10MB) |
Implementation Reference
- src/tools/file-reader.ts:46-120 (handler)The readFile function handles reading files from the filesystem while enforcing safety checks (path traversal) and file limits.
export async function readFile( input: ReadFileInput ): Promise<ToolResult<ReadFileResult>> { const result = safePath(input.path); if ("error" in result) { return { ok: false, error: result.error, code: "PATH_TRAVERSAL" }; } const { resolved } = result; const maxBytes = input.max_bytes ?? DEFAULT_MAX_BYTES; const encoding = input.encoding ?? "utf8"; logger.debug("Reading file", { path: resolved, maxBytes, encoding }); let stat: Awaited<ReturnType<typeof fs.stat>>; try { stat = await fs.stat(resolved); } catch (err) { const code = (err as NodeJS.ErrnoException).code; if (code === "ENOENT") { return { ok: false, error: `File not found: ${input.path}`, code: "NOT_FOUND" }; } return { ok: false, error: `Cannot stat file: ${(err as Error).message}`, code: "STAT_ERROR", }; } if (!stat.isFile()) { return { ok: false, error: `Path is not a file: ${input.path}`, code: "NOT_A_FILE", }; } const truncated = stat.size > maxBytes; const bytesToRead = Math.min(stat.size, maxBytes); let content: string; try { const handle = await fs.open(resolved, "r"); try { const buffer = Buffer.alloc(bytesToRead); await handle.read(buffer, 0, bytesToRead, 0); content = encoding === "base64" ? buffer.toString("base64") : buffer.toString("utf8"); } finally { await handle.close(); } } catch (err) { return { ok: false, error: `Failed to read file: ${(err as Error).message}`, code: "READ_ERROR", }; } logger.info("File read", { path: input.path, bytes: bytesToRead, truncated }); return { ok: true, data: { path: input.path, size_bytes: stat.size, encoding, content, truncated, read_at: new Date().toISOString(), }, }; } - src/types.ts:60-79 (schema)Schema definition for the inputs to the read_file tool.
export const ReadFileSchema = z.object({ path: z .string() .min(1) .describe("Path to the file, relative to the configured root directory"), encoding: z .enum(["utf8", "base64"]) .optional() .default("utf8") .describe("File encoding — use base64 for binary files"), max_bytes: z .number() .int() .min(1) .max(10_485_760) .optional() .describe("Maximum bytes to read (default: 1MB, max: 10MB)"), }); export type ReadFileInput = z.infer<typeof ReadFileSchema>; - src/index.ts:63-71 (registration)Registration and tool handler invocation in the main server logic. Note: The snippet is reconstructed from the flow in index.ts based on the provided search context.
"read_file", `Read a file from the filesystem. Paths are relative to the configured root directory (${config.fileReaderRoot}). ` + "Path traversal (../) is blocked. " + "Use encoding=base64 for binary files.", ReadFileSchema.shape, async (args) => { const result = await readFile(args); if (!result.ok) {