Skip to main content
Glama
read-files.ts2.88 kB
// mcp-bridge/src/tools/read-files.ts import * as fs from "fs/promises"; import * as path from "path"; import { z } from "zod"; const readFilesSchema = z.object({ paths: z.array(z.string()).min(1).max(50).describe("File paths to read"), max_size_bytes: z .number() .default(1048576) .describe("Max size per file (1MB default)"), fail_on_error: z.boolean().default(false).describe("Fail if any file fails"), }); type ReadFileSuccess = { path: string; status: "success"; content: string; size_bytes: number; line_count: number; last_modified: string; }; type ReadFileError = { path: string; status: "error"; error: string; }; type ReadFileResult = ReadFileSuccess | ReadFileError; export async function readFiles(input: z.infer<typeof readFilesSchema>) { const workspaceRoot = process.cwd(); const settledResults = await Promise.allSettled( input.paths.map(async (filepath): Promise<ReadFileSuccess> => { const fullPath = path.resolve(workspaceRoot, filepath); // Security check if (!fullPath.startsWith(workspaceRoot)) { throw new Error("Access denied: outside workspace"); } const stat = await fs.stat(fullPath); if (stat.size > input.max_size_bytes) { throw new Error( `File too large: ${stat.size} bytes > ${input.max_size_bytes} bytes` ); } const content = await fs.readFile(fullPath, "utf-8"); return { path: filepath, status: "success", content, size_bytes: stat.size, line_count: content.split("\n").length, last_modified: stat.mtime.toISOString(), }; }) ); // Convert to single result array preserving order const results: ReadFileResult[] = settledResults.map((result, index) => { if (result.status === "fulfilled") { return result.value; } else { return { path: input.paths[index], status: "error", error: result.reason.message, }; } }); const successful = results.filter((r) => r.status === "success").length; const failed = results.filter((r) => r.status === "error").length; if (input.fail_on_error && failed > 0) { const errorPaths = results .filter((r) => r.status === "error") .map((r) => r.path) .join(", "); throw new Error(`Failed to read ${failed} file(s): ${errorPaths}`); } const totalBytes = results.reduce((sum, r) => { return r.status === "success" ? sum + r.size_bytes : sum; }, 0); return { results, summary: { total_requested: input.paths.length, successful, failed, total_bytes: totalBytes, }, }; } export const readFilesTool = { name: "read_files", description: "Read multiple files in batch with optional partial failure handling", inputSchema: readFilesSchema, handler: readFiles, };

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/plasticbeachllc/dolphin-mcp'

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