Skip to main content
Glama
modelcontextprotocol

Filesystem MCP Server

Official

Write File

write_file
DestructiveIdempotent

Create or overwrite files with specified content in allowed directories. Handles text encoding and requires caution as existing files are replaced without warning.

Instructions

Create a new file or completely overwrite an existing file with new content. Use with caution as it will overwrite existing files without warning. Handles text content with proper encoding. Only works within allowed directories.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYes
contentYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
contentYes

Implementation Reference

  • The handler function for the 'write_file' tool. It validates the input path and delegates the actual writing to the writeFileContent helper function.
    async (args: z.infer<typeof WriteFileArgsSchema>) => {
      const validPath = await validatePath(args.path);
      await writeFileContent(validPath, args.content);
      const text = `Successfully wrote to ${args.path}`;
      return {
        content: [{ type: "text" as const, text }],
        structuredContent: { content: text }
      };
    }
  • Zod schema defining the input arguments for the write_file tool: path (string) and content (string).
    const WriteFileArgsSchema = z.object({
      path: z.string(),
      content: z.string(),
    });
  • Registration of the 'write_file' tool using server.registerTool, specifying title, description, schemas, annotations, and handler.
    server.registerTool(
      "write_file",
      {
        title: "Write File",
        description:
          "Create a new file or completely overwrite an existing file with new content. " +
          "Use with caution as it will overwrite existing files without warning. " +
          "Handles text content with proper encoding. Only works within allowed directories.",
        inputSchema: {
          path: z.string(),
          content: z.string()
        },
        outputSchema: { content: z.string() },
        annotations: { readOnlyHint: false, idempotentHint: true, destructiveHint: true }
      },
      async (args: z.infer<typeof WriteFileArgsSchema>) => {
        const validPath = await validatePath(args.path);
        await writeFileContent(validPath, args.content);
        const text = `Successfully wrote to ${args.path}`;
        return {
          content: [{ type: "text" as const, text }],
          structuredContent: { content: text }
        };
      }
    );
  • Helper function that implements secure file writing with checks for symlinks and atomic operations to prevent race conditions.
    export async function writeFileContent(filePath: string, content: string): Promise<void> {
      try {
        // Security: 'wx' flag ensures exclusive creation - fails if file/symlink exists,
        // preventing writes through pre-existing symlinks
        await fs.writeFile(filePath, content, { encoding: "utf-8", flag: 'wx' });
      } catch (error) {
        if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
          // Security: Use atomic rename to prevent race conditions where symlinks
          // could be created between validation and write. Rename operations
          // replace the target file atomically and don't follow symlinks.
          const tempPath = `${filePath}.${randomBytes(16).toString('hex')}.tmp`;
          try {
            await fs.writeFile(tempPath, content, 'utf-8');
            await fs.rename(tempPath, filePath);
          } catch (renameError) {
            try {
              await fs.unlink(tempPath);
            } catch {}
            throw renameError;
          }
        } else {
          throw error;
        }
      }
    }
Behavior4/5

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

The description adds valuable behavioral context beyond annotations: it warns about overwriting without warning (reinforcing destructiveHint), specifies it handles text content with encoding (not in annotations), and mentions directory restrictions. Annotations cover readOnlyHint=false, idempotentHint=true, and destructiveHint=true, but the description elaborates on the destructive nature and operational limits.

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

Conciseness5/5

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

The description is front-loaded with the core purpose in the first sentence, followed by warnings and constraints in subsequent sentences. Each sentence adds critical information (overwrite risk, content handling, directory limits) without redundancy, making it efficient and well-structured.

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 the tool's complexity (destructive write operation), the description is complete: it covers purpose, usage guidelines, behavioral traits, and constraints. Annotations provide safety hints, and the existence of an output schema means return values need not be explained, making this description sufficiently comprehensive for agent use.

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?

With 0% schema description coverage, the description does not explain the 'path' or 'content' parameters beyond implying 'path' relates to file location and 'content' is text. It adds minimal semantic value (e.g., 'text content' hints at content type), but does not fully compensate for the lack of schema descriptions, keeping it at the baseline for high schema coverage scenarios.

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 tool's purpose with specific verbs ('create' and 'overwrite') and resource ('file'), distinguishing it from siblings like 'edit_file' (partial modification) and 'read_file' (no writing). It explicitly mentions handling text content with encoding, which further clarifies its scope.

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 ('create a new file or completely overwrite an existing file') and when not to use it ('use with caution as it will overwrite existing files without warning'), with clear alternatives implied (e.g., 'edit_file' for partial updates). It also specifies constraints ('only works within allowed directories'), helping differentiate from tools like 'list_allowed_directories'.

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/modelcontextprotocol/filesystem'

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