Skip to main content
Glama

read_file

Retrieve the full text or specific lines from a file on the Serena MCP server using a relative path, with options to define start and end lines, and set a maximum character limit.

Instructions

Reads the given file or a chunk of it. Generally, symbolic operations like find_symbol or find_referencing_symbols should be preferred if you know which symbols you are looking for. Returns the full text of the file at the given relative path.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
end_lineNoThe 0-based index of the last line to be retrieved (inclusive). If None, read until the end of the file.
max_answer_charsNoIf the file (chunk) is longer than this number of characters, no content will be returned. Don't adjust unless there is really no other way to get the content required for the task.
relative_pathYesThe relative path to the file to read.
start_lineNoThe 0-based index of the first line to be retrieved.

Implementation Reference

  • ReadFileTool class: the main handler implementation for the 'read_file' MCP tool. Its apply method reads the file (or line range), handles validation, slicing, and length limiting.
    class ReadFileTool(Tool): """ Reads a file within the project directory. """ def apply(self, relative_path: str, start_line: int = 0, end_line: int | None = None, max_answer_chars: int = -1) -> str: """ Reads the given file or a chunk of it. Generally, symbolic operations like find_symbol or find_referencing_symbols should be preferred if you know which symbols you are looking for. :param relative_path: the relative path to the file to read :param start_line: the 0-based index of the first line to be retrieved. :param end_line: the 0-based index of the last line to be retrieved (inclusive). If None, read until the end of the file. :param max_answer_chars: if the file (chunk) is longer than this number of characters, no content will be returned. Don't adjust unless there is really no other way to get the content required for the task. :return: the full text of the file at the given relative path """ self.project.validate_relative_path(relative_path, require_not_ignored=True) result = self.project.read_file(relative_path) result_lines = result.splitlines() if end_line is None: result_lines = result_lines[start_line:] else: result_lines = result_lines[start_line : end_line + 1] result = "\n".join(result_lines) return self._limit_length(result, max_answer_chars)
  • Signature and docstring of ReadFileTool.apply defining the input schema (relative_path, start_line, end_line, max_answer_chars) and output for the MCP tool.
    def apply(self, relative_path: str, start_line: int = 0, end_line: int | None = None, max_answer_chars: int = -1) -> str: """ Reads the given file or a chunk of it. Generally, symbolic operations like find_symbol or find_referencing_symbols should be preferred if you know which symbols you are looking for. :param relative_path: the relative path to the file to read :param start_line: the 0-based index of the first line to be retrieved. :param end_line: the 0-based index of the last line to be retrieved (inclusive). If None, read until the end of the file. :param max_answer_chars: if the file (chunk) is longer than this number of characters, no content will be returned. Don't adjust unless there is really no other way to get the content required for the task. :return: the full text of the file at the given relative path """ self.project.validate_relative_path(relative_path, require_not_ignored=True) result = self.project.read_file(relative_path) result_lines = result.splitlines() if end_line is None: result_lines = result_lines[start_line:] else: result_lines = result_lines[start_line : end_line + 1] result = "\n".join(result_lines) return self._limit_length(result, max_answer_chars)
  • ToolRegistry.__init__: automatically discovers and registers all Tool subclasses from serena.tools.*, naming ReadFileTool as 'read_file'.
    def __init__(self) -> None: self._tool_dict: dict[str, RegisteredTool] = {} for cls in iter_subclasses(Tool): if not cls.__module__.startswith("serena.tools"): continue is_optional = issubclass(cls, ToolMarkerOptional) name = cls.get_name_from_cls() if name in self._tool_dict: raise ValueError(f"Duplicate tool name found: {name}. Tool classes must have unique names.") self._tool_dict[name] = RegisteredTool(tool_class=cls, is_optional=is_optional, tool_name=name)
  • Tool.get_name_from_cls: class method that converts ReadFileTool class name to the tool name 'read_file'.
    def get_name_from_cls(cls) -> str: name = cls.__name__ if name.endswith("Tool"): name = name[:-4] # convert to snake_case name = "".join(["_" + c.lower() if c.isupper() else c for c in name]).lstrip("_") return name
  • Project.read_file: supporting method called by ReadFileTool to actually read the file contents.
    def read_file(self, relative_path: str) -> str: """ Reads a file relative to the project root. :param relative_path: the path to the file relative to the project root :return: the content of the file """ abs_path = Path(self.project_root) / relative_path return FileUtils.read_file(str(abs_path), self.project_config.encoding)

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/oraios/serena'

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