Skip to main content
Glama
runtimeguard

runtime-guard

Official

read_file

Read a text file securely from the workspace after applying path-policy enforcement to restrict access.

Instructions

Read a text file from the workspace after path-policy enforcement.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYes
ctxNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The read_file handler function. Resolves the path relative to WORKSPACE_ROOT, enforces path policy via check_path_policy, logs the result, reads and returns file content with error handling.
    def read_file(path: str, ctx: Context | None = None) -> str:
        """Read a text file from the workspace after path-policy enforcement."""
        context_tokens = activate_runtime_context(ctx)
        path = str(pathlib.Path(WORKSPACE_ROOT) / path) if not os.path.isabs(path) else path
    
        try:
            refresh_policy_if_changed()
            path_check = check_path_policy(path, tool="read_file")
            if path_check:
                result = PolicyResult(allowed=False, reason=path_check[0], decision_tier="blocked", matched_rule=path_check[1])
            else:
                result = PolicyResult(allowed=True, reason="allowed", decision_tier="allowed", matched_rule=None)
    
            append_log_entry(build_log_entry("read_file", result, path=path))
            if not result.allowed:
                return f"[POLICY BLOCK] {result.reason}"
    
            try:
                with open(path, "r", errors="replace") as f:
                    return f.read()
            except FileNotFoundError:
                return f"Error: file not found: {path}"
            except OSError as e:
                return f"Error reading file: {e}"
        finally:
            reset_runtime_context(context_tokens)
  • Imports used by read_file: check_path_policy, PolicyResult, activate_runtime_context, append_log_entry, build_log_entry, etc.
    import datetime
    import os
    import pathlib
    from typing import Any, TYPE_CHECKING
    
    if TYPE_CHECKING:
        from mcp.server.fastmcp import Context
    else:
        Context = Any
    
    from audit import append_log_entry, build_log_entry
    from backup import backup_paths
    from config import AGENT_ID, POLICY, WORKSPACE_ROOT, refresh_policy_if_changed
    from models import PolicyResult
    from policy_engine import check_path_policy, relative_depth
    from runtime_context import activate_runtime_context, reset_runtime_context
    import script_sentinel
  • src/server.py:19-31 (registration)
    The read_file function is registered as an MCP tool via mcp.tool()(read_file) in the FastMCP server setup.
    mcp = FastMCP("ai-runtime-guard")
    
    for tool in [
        server_info,
        restore_backup,
        execute_command,
        read_file,
        write_file,
        edit_file,
        delete_file,
        list_directory,
    ]:
        mcp.tool()(tool)
  • read_file is exported from the tools package in __all__ and imported from file_tools.
    from .command_tools import execute_command, server_info
    from .file_tools import delete_file, edit_file, list_directory, read_file, write_file
    from .restore_tools import restore_backup
    
    __all__ = [
        "server_info",
        "execute_command",
        "read_file",
        "write_file",
        "edit_file",
        "delete_file",
        "list_directory",
        "restore_backup",
    ]
  • The check_path_policy function used by read_file to enforce path policy (blocked paths, extensions, runtime paths, workspace boundary, backup access).
    def check_path_policy(path: str, tool: str | None = None) -> tuple[str, str] | None:
        blocked = POLICY.get("blocked", {})
        lower_path = str(path).lower()
        try:
            resolved = pathlib.Path(path).resolve()
        except Exception:
            resolved = pathlib.Path(path)
    
        for blocked_path in blocked.get("paths", []):
            if _blocked_path_matches(resolved, str(blocked_path)):
                return (
                    f"Sensitive path access not permitted: '{blocked_path}' may contain secrets or critical system configuration",
                    blocked_path,
                )
    
        for ext in blocked.get("extensions", []):
            if re.search(rf"{re.escape(ext)}\b", lower_path):
                return (
                    f"Sensitive file extension not permitted: '{ext}' files may contain private keys or certificates",
                    ext,
                )
    
        if is_protected_runtime_path(path):
            return (
                f"Path '{path}' is protected runtime state and is not accessible via {tool or 'this tool'}",
                "runtime_protected_path",
            )
    
        if not is_within_workspace(path):
            return (f"Path '{path}' is outside the allowed workspace", "workspace_boundary")
    
        backup_access = POLICY.get("backup_access", {})
        if backup_access.get("block_agent_tools", True) and is_backup_path(path):
            tool_name = (tool or "").lower()
            if tool_name != "restore_backup":
                return (
                    f"Path '{path}' is inside protected backup storage and is not accessible via {tool or 'this tool'}",
                    "backup_storage_protected",
                )
    
        return None
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided; description mentions 'path-policy enforcement' but does not disclose behavior like error handling (e.g., if file missing or binary), encoding assumptions, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, efficient and front-loaded. No wasted words, though could be slightly expanded for completeness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-file tool with an output schema, the description covers the core action and safety guard (path-policy). Could mention file existence requirement or default encoding, but overall adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage. Description does not explain 'path' format or the optional 'ctx' parameter. Agent must infer path meaning without support.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (read), the resource (text file), and the context (workspace after path-policy enforcement). It distinguishes from sibling tools like write_file, delete_file, and edit_file.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives such as list_directory or execute_command. Does not mention prerequisites or when not to use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/runtimeguard/runtime-guard'

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