read_file_section
Extracts specific line ranges from a file in local repositories, enabling targeted code analysis without manual uploads. Supports file path, start and end lines, and optional line number display.
Instructions
读取文件的指定行范围
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| endLine | Yes | 结束行号(包含) | |
| filePath | Yes | 带前缀的完整文件路径, e.g., '[backend/src]/main.ts' | |
| showLineNumbers | No | 是否显示行号 | |
| startLine | Yes | 起始行号(从1开始) |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"endLine": {
"description": "结束行号(包含)",
"type": "number"
},
"filePath": {
"description": "带前缀的完整文件路径, e.g., '[backend/src]/main.ts'",
"type": "string"
},
"showLineNumbers": {
"default": true,
"description": "是否显示行号",
"type": "boolean"
},
"startLine": {
"description": "起始行号(从1开始)",
"type": "number"
}
},
"required": [
"filePath",
"startLine",
"endLine"
],
"type": "object"
}
Implementation Reference
- src/index.ts:534-579 (handler)The handler function reads a file section by line range. It parses the prefixed file path, resolves the full path safely, reads the file, extracts the specified lines, optionally adds line numbers, and returns the content wrapped in MCP response format. Handles errors like invalid paths, missing files, etc.async ({ filePath, startLine, endLine, showLineNumbers = true }) => { const match = filePath.match(/^(\[.*?\])\/(.*)$/s); if (!match) return { content: [{ type: "text", text: "错误:文件路径格式不正确,必须包含如 '[backend/src]/' 的前缀。" }] }; const prefix = match[1]; const relativePath = match[2]; const rootPath = pathRegistry.get(prefix); if (!rootPath) return { content: [{ type: "text", text: `错误:未知的路径前缀 '${prefix}'。` }] }; const resolvedPath = path.resolve(rootPath, relativePath); if (!resolvedPath.startsWith(path.resolve(rootPath))) return { content: [{ type: "text", text: "错误:禁止访问项目目录之外的文件。" }] }; try { const fileContent = await fs.readFile(resolvedPath, "utf-8"); const lines = fileContent.split('\n'); // 验证行号范围 if (startLine < 1) startLine = 1; if (endLine > lines.length) endLine = lines.length; if (startLine > endLine) { return { content: [{ type: "text", text: `错误:起始行号 ${startLine} 大于结束行号 ${endLine}` }] }; } // 提取指定行范围(转换为0-based索引) const selectedLines = lines.slice(startLine - 1, endLine); let resultContent: string; if (showLineNumbers) { resultContent = selectedLines .map((line, index) => `${startLine + index}: ${line}`) .join('\n'); } else { resultContent = selectedLines.join('\n'); } const resultText = `文件 '${filePath}' 第 ${startLine}-${endLine} 行内容:\n---\n${resultContent}`; return { content: [{ type: "text", text: resultText }] }; } catch (error: any) { let errorMessage = `读取文件 '${filePath}' 时发生错误。`; if (error.code === 'ENOENT') errorMessage = `错误:文件 '${filePath}' 未找到。`; console.error(errorMessage, error); return { content: [{ type: "text", text: errorMessage }] }; } }
- src/index.ts:529-533 (schema)Zod schema defining input parameters: filePath (prefixed path), startLine, endLine, and optional showLineNumbers.filePath: z.string().describe("带前缀的完整文件路径, e.g., '[backend/src]/main.ts'"), startLine: z.number().describe("起始行号(从1开始)"), endLine: z.number().describe("结束行号(包含)"), showLineNumbers: z.boolean().optional().default(true).describe("是否显示行号"), },
- src/index.ts:525-580 (registration)Registration of the 'read_file_section' tool using server.tool(), including name, Chinese description, input schema, and inline handler function.server.tool( "read_file_section", "读取文件的指定行范围", { filePath: z.string().describe("带前缀的完整文件路径, e.g., '[backend/src]/main.ts'"), startLine: z.number().describe("起始行号(从1开始)"), endLine: z.number().describe("结束行号(包含)"), showLineNumbers: z.boolean().optional().default(true).describe("是否显示行号"), }, async ({ filePath, startLine, endLine, showLineNumbers = true }) => { const match = filePath.match(/^(\[.*?\])\/(.*)$/s); if (!match) return { content: [{ type: "text", text: "错误:文件路径格式不正确,必须包含如 '[backend/src]/' 的前缀。" }] }; const prefix = match[1]; const relativePath = match[2]; const rootPath = pathRegistry.get(prefix); if (!rootPath) return { content: [{ type: "text", text: `错误:未知的路径前缀 '${prefix}'。` }] }; const resolvedPath = path.resolve(rootPath, relativePath); if (!resolvedPath.startsWith(path.resolve(rootPath))) return { content: [{ type: "text", text: "错误:禁止访问项目目录之外的文件。" }] }; try { const fileContent = await fs.readFile(resolvedPath, "utf-8"); const lines = fileContent.split('\n'); // 验证行号范围 if (startLine < 1) startLine = 1; if (endLine > lines.length) endLine = lines.length; if (startLine > endLine) { return { content: [{ type: "text", text: `错误:起始行号 ${startLine} 大于结束行号 ${endLine}` }] }; } // 提取指定行范围(转换为0-based索引) const selectedLines = lines.slice(startLine - 1, endLine); let resultContent: string; if (showLineNumbers) { resultContent = selectedLines .map((line, index) => `${startLine + index}: ${line}`) .join('\n'); } else { resultContent = selectedLines.join('\n'); } const resultText = `文件 '${filePath}' 第 ${startLine}-${endLine} 行内容:\n---\n${resultContent}`; return { content: [{ type: "text", text: resultText }] }; } catch (error: any) { let errorMessage = `读取文件 '${filePath}' 时发生错误。`; if (error.code === 'ENOENT') errorMessage = `错误:文件 '${filePath}' 未找到。`; console.error(errorMessage, error); return { content: [{ type: "text", text: errorMessage }] }; } } );