Skip to main content
Glama

playwright_upload_file

Upload files to web forms using Playwright automation. Specify a CSS selector for the file input element and provide either a local file path or a resource URI to handle file uploads in browser automation workflows.

Instructions

Upload a file to an input[type='file'] element on the page. In HTTP mode (disabled), provide an uploadResourceUri from construct_upload_url (preferred) or a reachable filePath.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
selectorYesCSS selector for the file input element
filePathNoAbsolute path to the file to upload (stdio mode only; ignored in HTTP mode)
uploadResourceUriNoResource URI returned from the upload endpoint (HTTP mode)

Implementation Reference

  • Execution handler for the playwright_upload_file tool. Prepares the file path and uses Playwright's setInputFiles to upload to the specified selector.
    async execute(args: any, context: ToolContext): Promise<ToolResponse> {
      return this.safeExecute(context, async (page) => {
        if (!args.selector) {
          return createErrorResponse("Selector is required to upload a file");
        }
    
        const prepared = await this.prepareUploadFile(args, context.server, context);
        if ("error" in prepared) {
          return createErrorResponse(prepared.error);
        }
    
        const { path: uploadPath, cleanup, displayName } = prepared;
        try {
          await page.waitForSelector(args.selector);
          await page.setInputFiles(args.selector, uploadPath);
          return createSuccessResponse(`Uploaded file '${displayName}' to '${args.selector}'`);
        } finally {
          await cleanup().catch(() => {});
        }
      });
    }
  • Helper method to resolve file path from either local filePath (stdio mode) or uploadResourceUri (HTTP mode) using upload manager.
    private async prepareUploadFile(
      args: any,
      server: any,
      _context: ToolContext,
    ): Promise<{ path: string; cleanup: () => Promise<void>; displayName: string } | { error: string }> {
      const sessionId = getSessionIdForServer(server);
      const uploadResourceUri = args.uploadResourceUri ?? args.fileResourceUri;
      const inHttpMode = Boolean(sessionId);
    
      if (uploadResourceUri) {
        const parsed = parseUploadResourceUri(uploadResourceUri);
        const targetSession = parsed?.sessionId ?? sessionId;
        if (!parsed || !targetSession) {
          return { error: "Invalid upload resource URI" };
        }
        const meta = await resolveUploadResource({
          resourceUri: uploadResourceUri,
          sessionId: targetSession,
        });
        if (!meta) {
          return { error: "Uploaded file could not be resolved for this session" };
        }
        const cleanup = async () => {};
        return { path: meta.filePath, cleanup, displayName: meta.name };
      }
    
      if (args.filePath) {
        const resolvedPath = path.resolve(args.filePath);
        try {
          await fs.access(resolvedPath);
          return {
            path: resolvedPath,
            cleanup: async () => {},
            displayName: args.filePath,
          };
        } catch {
          if (inHttpMode) {
            return {
              error: `File not found at path: ${resolvedPath}. In HTTP mode, first call construct_upload_url, upload the file, then call playwright_upload_file with uploadResourceUri.`,
            };
          }
          return { error: `File not found at path: ${resolvedPath}` };
        }
      }
    
      if (inHttpMode) {
        const uploadUrl = getUploadEndpointUrl();
        const hint = uploadUrl
          ? ` Call construct_upload_url to obtain the upload endpoint for this session (e.g., ${uploadUrl}/<sessionId>).`
          : "";
        return {
          error: `No file provided. In HTTP mode, first upload a file and provide uploadResourceUri.${hint}`,
        };
      }
    
      return {
        error: "filePath is required in stdio mode.",
      };
    }
  • Input schema and description definition for the playwright_upload_file tool.
    {
      name: "playwright_upload_file",
      description: `Upload a file to an input[type='file'] element on the page. In HTTP mode (${httpMode ? "enabled" : "disabled"}), provide an uploadResourceUri from construct_upload_url (preferred) or a reachable filePath.`,
      inputSchema: {
        type: "object",
        properties: {
          selector: { type: "string", description: "CSS selector for the file input element" },
          filePath: {
            type: "string",
            description: "Absolute path to the file to upload (stdio mode only; ignored in HTTP mode)",
          },
          uploadResourceUri: {
            type: "string",
            description: "Resource URI returned from the upload endpoint (HTTP mode)",
          },
        },
        required: ["selector"],
      },
    },
  • Dispatch registration in handleToolCall switch statement routing to UploadFileTool.
    case "playwright_upload_file":
      return await uploadFileTool.execute(args, context);
  • Instantiation of UploadFileTool instance in initializeTools function.
    if (!uploadFileTool) uploadFileTool = new UploadFileTool(server);
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 explains key behavioral traits: the tool's dual-mode operation (HTTP vs. stdio), parameter dependencies (filePath ignored in HTTP mode, uploadResourceUri required for HTTP mode), and the need for a prior construct_upload_url call in preferred HTTP mode. However, it doesn't mention potential errors, permissions, or what happens after upload.

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 perfectly front-loaded with the core purpose in the first sentence, followed by essential mode-specific guidance. Both sentences earn their place by providing critical operational context without any redundant or verbose language. It's appropriately sized for a tool with three parameters and complex mode dependencies.

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

Completeness4/5

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

For a tool with no annotations, no output schema, and moderate complexity (dual modes, parameter dependencies), the description is quite complete. It covers the purpose, usage contexts, and behavioral constraints effectively. The main gap is lack of information about return values or error conditions, but given the tool's focus on file upload interaction rather than data retrieval, this is acceptable.

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 all three parameters thoroughly. The description adds some value by clarifying the relationship between parameters and modes (e.g., 'filePath' is for stdio mode only, 'uploadResourceUri' is for HTTP mode), but doesn't provide additional syntax, format, or constraint details beyond what the schema offers. Baseline 3 is appropriate given high schema coverage.

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 ('Upload a file') and target ('to an input[type='file'] element on the page'), distinguishing it from sibling tools like playwright_fill or playwright_click which handle different interactions. It precisely identifies both the verb and resource without being vague or tautological.

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 versus alternatives by specifying two modes (HTTP and stdio) and recommending a preferred approach ('provide an uploadResourceUri from construct_upload_url (preferred)'). It clearly distinguishes usage contexts, helping the agent choose between filePath and uploadResourceUri parameters based on mode.

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/aakashH242/mcp-playwright'

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