read_file
Read a file from the workspace, optionally specifying start and end lines to extract only the needed text without loading the entire document.
Instructions
Read a file from the workspace with optional line slicing.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| start_line | No | ||
| end_line | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The main handler function for the 'read_file' tool. Reads a file from the workspace with optional line slicing (start_line to end_line). Resolves the path via _resolve_path, validates it's a file, reads the file, slices lines, numbers them, and returns as a string.
def read_file(path: str, start_line: int = 1, end_line: int = 200) -> str: """Read a file from the workspace with optional line slicing.""" target = _resolve_path(path) if not target.is_file(): raise ValueError(f"'{path}' is not a file.") if start_line < 1 or end_line < start_line: raise ValueError("Line range is invalid.") lines = target.read_text(encoding="utf-8", errors="replace").splitlines() selected = lines[start_line - 1 : end_line] numbered = [ f"{line_number}. {line}" for line_number, line in enumerate(selected, start=start_line) ] return "\n".join(numbered) - Helper function _resolve_path that resolves a given path relative to the workspace root, with security checks to prevent accessing files outside the allowed workspace (unless allow_external_paths is enabled).
def _resolve_path(path: str) -> Path: raw_path = Path(path).expanduser() resolved = ( raw_path.resolve() if raw_path.is_absolute() else (config.workspace_root / raw_path).resolve() ) if config.allow_external_paths: return resolved if resolved != config.workspace_root and config.workspace_root not in resolved.parents: raise ValueError( f"Path '{path}' is outside the workspace root {config.workspace_root}." ) return resolved - src/friday_mcp_server/tools/__init__.py:6-11 (registration)Registration entry point: register_all_tools calls workspace.register(mcp, config=config) which sets up the @mcp.tool() decorator for read_file.
def register_all_tools(mcp, *, config, skill_store) -> None: system.register(mcp, config=config) utils.register(mcp) web.register(mcp, config=config) workspace.register(mcp, config=config) skills.register(mcp, skill_store=skill_store) - src/friday_mcp_server/tools/workspace.py:9-11 (registration)The register function in workspace.py that takes 'mcp' and 'config' parameters. Inside this function, the @mcp.tool() decorator on line 43 registers read_file as an MCP tool.
def register(mcp, *, config) -> None: def _resolve_path(path: str) -> Path: raw_path = Path(path).expanduser()