list_directory
Browse and view directory contents within AI agent operations, enabling controlled file system exploration while maintaining security boundaries.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| ctx | No |
Implementation Reference
- src/tools/file_tools.py:196-249 (handler)The handler for the `list_directory` tool, which lists the contents of a directory, enforces directory depth policy, and returns formatted file/directory info.
def list_directory(path: str, ctx: Context | None = None) -> str: context_tokens = activate_runtime_context(ctx) path = str(pathlib.Path(WORKSPACE_ROOT) / path) if not os.path.isabs(path) else path try: path_check = check_path_policy(path, tool="list_directory") 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) if result.allowed: if not os.path.exists(path): append_log_entry(build_log_entry("list_directory", result, path=path, error="path not found")) return f"Error: path not found: {path}" if not os.path.isdir(path): append_log_entry(build_log_entry("list_directory", result, path=path, error="not a directory")) return f"Error: '{path}' is a file, not a directory" depth = relative_depth(path) max_depth = POLICY.get("allowed", {}).get("max_directory_depth", 5) if depth > max_depth: result = PolicyResult( allowed=False, reason=f"Directory depth {depth} exceeds the policy limit of {max_depth} (allowed.max_directory_depth): '{path}'", decision_tier="blocked", matched_rule="allowed.max_directory_depth", ) append_log_entry(build_log_entry("list_directory", result, path=path)) if not result.allowed: return f"[POLICY BLOCK] {result.reason}" lines = [f"Contents of {path}:"] try: entries = sorted(os.scandir(path), key=lambda e: (e.is_file(), e.name)) except OSError as e: return f"Error reading directory: {e}" for entry in entries: try: stat = entry.stat(follow_symlinks=False) mtime = datetime.datetime.fromtimestamp(stat.st_mtime, datetime.UTC).isoformat().replace("+00:00", "Z") kind = "file" if entry.is_file(follow_symlinks=False) else "directory" size = f"{stat.st_size} bytes" if kind == "file" else "-" lines.append(f" {entry.name} [{kind}] size={size} modified={mtime}") except OSError: lines.append(f" {entry.name} [unreadable]") if len(lines) == 1: lines.append(" (empty)") return "\n".join(lines) - src/server.py:20-29 (registration)Registration of `list_directory` tool with the MCP server.
for tool in [ server_info, restore_backup, execute_command, read_file, write_file, delete_file, list_directory, ]: mcp.tool()(tool)