write_file
Write file content under policy enforcement, with audit logging and automatic backup for data safety.
Instructions
Write full file content with policy checks, logging, and backup support.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| ctx | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/tools/file_tools.py:48-109 (handler)Core handler that writes file content with policy enforcement, backup creation, and Script Sentinel scanning.
def write_file(path: str, content: str, ctx: Context | None = None) -> str: """Write full file content with policy checks, logging, and backup support.""" 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="write_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) log_entry = build_log_entry("write_file", result, path=path) append_log_entry(log_entry) if not result.allowed: return f"[POLICY BLOCK] {result.reason}" backup_location = None backup_enabled = bool(POLICY.get("audit", {}).get("backup_enabled", True)) if backup_enabled and os.path.exists(path): backup_location = backup_paths([path]) if backup_location: append_log_entry( { **log_entry, "source": "mcp-server", "backup_location": backup_location, "event": "backup_created", } ) try: with open(path, "w") as f: f.write(content) except OSError as e: return f"Error writing file: {e}" sentinel_scan = script_sentinel.scan_and_record_write(path, content, writer_agent_id=AGENT_ID) if sentinel_scan.get("flagged"): append_log_entry( { **log_entry, "source": "mcp-server", "event": "script_sentinel_flagged", "content_hash": sentinel_scan.get("content_hash", ""), "matched_signatures": sentinel_scan.get("matched_signatures", []), "script_sentinel_mode": POLICY.get("script_sentinel", {}).get("mode", "match_original"), "script_sentinel_scan_mode": sentinel_scan.get("scan_mode", POLICY.get("script_sentinel", {}).get("scan_mode", "exec_context")), } ) msg = f"Successfully wrote {len(content)} characters to {path}" if backup_location: msg += f" (previous version backed up to {backup_location})" else: msg += " (no content-change backup needed)" if sentinel_scan.get("flagged"): msg += " (Script Sentinel flagged content)" return msg finally: reset_runtime_context(context_tokens) - src/tools/file_tools.py:48-48 (schema)The function signature defines the schema: accepts path (str), content (str), and optional ctx; returns str.
def write_file(path: str, content: str, ctx: Context | None = None) -> str: - src/server.py:21-31 (registration)write_file is registered as an MCP tool via mcp.tool()(write_file) in the main server entrypoint.
for tool in [ server_info, restore_backup, execute_command, read_file, write_file, edit_file, delete_file, list_directory, ]: mcp.tool()(tool) - src/tools/__init__.py:2-14 (registration)write_file is re-exported from the tools package init.
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", ] - src/mcp_config_manager.py:30-35 (registration)write_file is listed in the AIRG_MCP_TOOLS configuration array used for MCP config generation.
AIRG_MCP_TOOLS = [ "server_info", "restore_backup", "execute_command", "read_file", "write_file",