Skip to main content
Glama
SDGLBL
by SDGLBL

write

Write files to the local filesystem with specified content, overwriting existing files when necessary for codebase modifications.

Instructions

Writes a file to the local filesystem.

Usage:

  • This tool will overwrite the existing file if there is one at the provided path.

  • If this is an existing file, you MUST use the Read tool first to read the file's contents. This tool will fail if you did not read the file first.

  • ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.

  • NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
file_pathYesThe absolute path to the file to write (must be absolute, not relative)
contentYesThe content to write to the file

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The core handler function that executes the 'write' tool logic: validates the file path, checks permissions, creates parent directories if needed, writes the content to the file, and returns success/error messages.
    async def call(
        self,
        ctx: MCPContext,
        **params: Unpack[WriteToolParams],
    ) -> str:
        """Execute the tool with the given parameters.
    
        Args:
            ctx: MCP context
            **params: Tool parameters
    
        Returns:
            Tool result
        """
        tool_ctx = self.create_tool_context(ctx)
        self.set_tool_context_info(tool_ctx)
    
        # Extract parameters
        file_path: FilePath = params["file_path"]
        content: Content = params["content"]
    
        # Validate parameters
        path_validation = self.validate_path(file_path)
        if path_validation.is_error:
            await tool_ctx.error(path_validation.error_message)
            return f"Error: {path_validation.error_message}"
    
        await tool_ctx.info(f"Writing file: {file_path}")
    
        # Check if file is allowed to be written
        allowed, error_msg = await self.check_path_allowed(file_path, tool_ctx)
        if not allowed:
            return error_msg
    
        # Additional check already verified by is_path_allowed above
        await tool_ctx.info(f"Writing file: {file_path}")
    
        try:
            path_obj = Path(file_path)
    
            # Check if parent directory is allowed
            parent_dir = str(path_obj.parent)
            if not self.is_path_allowed(parent_dir):
                await tool_ctx.error(f"Parent directory not allowed: {parent_dir}")
                return f"Error: Parent directory not allowed: {parent_dir}"
    
            # Create parent directories if they don't exist
            path_obj.parent.mkdir(parents=True, exist_ok=True)
    
            # Write the file
            with open(path_obj, "w", encoding="utf-8") as f:
                f.write(content)
    
            await tool_ctx.info(
                f"Successfully wrote file: {file_path} ({len(content)} bytes)"
            )
            return f"Successfully wrote file: {file_path} ({len(content)} bytes)"
        except Exception as e:
            await tool_ctx.error(f"Error writing file: {str(e)}")
            return f"Error writing file: {str(e)}"
  • Defines the input schema using Annotated types and TypedDict for the tool parameters: file_path (absolute path) and content (string to write).
    FilePath = Annotated[
        str,
        Field(
            description="The absolute path to the file to write (must be absolute, not relative)",
            min_length=1,
        ),
    ]
    
    Content = Annotated[
        str,
        Field(
            description="The content to write to the file",
            min_length=1,
        ),
    ]
    
    
    class WriteToolParams(TypedDict):
        """Parameters for the Write tool.
    
        Attributes:
            file_path: The absolute path to the file to write (must be absolute, not relative)
            content: The content to write to the file
        """
    
        file_path: FilePath
        content: Content
  • The register method of the Write class that defines the tool wrapper function decorated with @mcp_server.tool(name='write') and registers it, forwarding calls to the main handler.
    def register(self, mcp_server: FastMCP) -> None:
        """Register this tool with the MCP server.
    
        Creates a wrapper function with explicitly defined parameters that match
        the tool's parameter schema and registers it with the MCP server.
    
        Args:
            mcp_server: The FastMCP server instance
        """
        tool_self = self  # Create a reference to self for use in the closure
    
        @mcp_server.tool(name=self.name, description=self.description)
        async def write(
            ctx: MCPContext,
            file_path: FilePath,
            content: Content,
        ) -> str:
            ctx = get_context()
            return await tool_self.call(ctx, file_path=file_path, content=content)
  • Factory function that instantiates the Write tool (along with other filesystem tools) with the permission manager.
    def get_filesystem_tools(permission_manager: PermissionManager) -> list[BaseTool]:
        """Create instances of all filesystem tools.
    
        Args:
            permission_manager: Permission manager for access control
    
        Returns:
            List of filesystem tool instances
        """
        return [
            ReadTool(permission_manager),
            Write(permission_manager),
            Edit(permission_manager),
            MultiEdit(permission_manager),
            DirectoryTreeTool(permission_manager),
            Grep(permission_manager),
            ContentReplaceTool(permission_manager),
            GrepAstTool(permission_manager),
        ]
  • Registers all filesystem tools (including 'write') by instantiating them via get_filesystem_tools and calling ToolRegistry.register_tools, which invokes each tool's register method.
    def register_filesystem_tools(
        mcp_server: FastMCP,
        permission_manager: PermissionManager,
    ) -> list[BaseTool]:
        """Register all filesystem tools with the MCP server.
    
        Args:
            mcp_server: The FastMCP server instance
            permission_manager: Permission manager for access control
    
        Returns:
            List of registered tools
        """
        tools = get_filesystem_tools(permission_manager)
        ToolRegistry.register_tools(mcp_server, tools)
        return tools
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: the tool overwrites existing files, requires reading existing files first to avoid failure, and has specific constraints about creating new files and documentation. However, it doesn't mention permissions, rate limits, or error handling details that could be relevant for a filesystem write operation.

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?

The description is appropriately sized and front-loaded with the core purpose in the first sentence. The usage guidelines are organized as bullet points for clarity. While every sentence earns its place, the formatting with bullet points and multiple 'NEVER' statements could be slightly more concise while maintaining clarity.

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

Completeness5/5

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

Given this is a filesystem write tool with no annotations but 100% schema coverage and an output schema (implied by context signals), the description is complete enough. It covers the core purpose, critical behavioral constraints, and usage guidelines. The output schema would handle return values, so the description appropriately focuses on when and how to use the tool rather than output details.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters thoroughly. The description doesn't add any additional meaning about the parameters beyond what's in the schema descriptions. It implies file_path must be absolute through usage context but doesn't explicitly state this beyond the schema. Baseline 3 is appropriate when schema does the heavy lifting.

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 specific action ('writes a file') and resource ('to the local filesystem'), distinguishing it from sibling tools like 'read', 'edit', and 'content_replace' which have different purposes. The verb+resource combination is precise and unambiguous.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool vs alternatives: 'ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required.' It also specifies when NOT to use it ('NEVER proactively create documentation files') and references the 'Read' tool as a prerequisite for existing files, offering clear alternatives and exclusions.

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/SDGLBL/mcp-claude-code'

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