list_directory
List directory entries with metadata, respecting path and depth constraints to prevent unauthorized access.
Instructions
List directory entries with metadata, honoring path and depth policy.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| ctx | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/tools/file_tools.py:287-344 (handler)Main handler function for the 'list_directory' tool. Resolves path relative to WORKSPACE_ROOT, checks path policy, validates directory existence, enforces max_directory_depth policy, then lists entries with metadata (name, type, size, modified time).
def list_directory(path: str, ctx: Context | None = None) -> str: """List directory entries with metadata, honoring path and depth policy.""" 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="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) finally: reset_runtime_context(context_tokens) - src/server.py:10-10 (registration)Import of list_directory from tools module.
list_directory, - src/server.py:29-31 (registration)Registration of list_directory as an MCP tool via mcp.tool()(list_directory).
list_directory, ]: mcp.tool()(tool) - src/tools/__init__.py:2-2 (helper)Re-export of list_directory from file_tools module.
from .file_tools import delete_file, edit_file, list_directory, read_file, write_file - src/mcp_config_manager.py:38-38 (helper)list_directory included in the list of tool names used for MCP configuration management.
"list_directory",