Skip to main content
OpenFilePicker is an action, not a component. It opens the browser’s native file picker when triggered — attach it to any clickable element and it handles the rest: reading selected files to base64 and passing them to onSuccess as $event. This is the counterpart to DropZone. Where DropZone gives you a dedicated upload area, OpenFilePicker turns any existing element into a file input. A button, a badge, an icon — anything with an on_click.
All file reading happens in the browser. Files are never sent to a server unless you explicitly wire up an on_success action (like CallTool) to do so.

Processing Files with a Tool

Files are read client-side, but they don’t go anywhere until you tell them to. The typical pattern is to nest a CallTool inside on_success — pick the file, then send its base64 data to your MCP server for processing.

Multiple Files

Set multiple=True to let users select several files at once. $event is always list[FileUpload] regardless of multiple, but the OS file picker restricts multi-select to when multiple=True.
Multiple file upload
from prefab_ui.components import Button
from prefab_ui.actions import OpenFilePicker
from prefab_ui.actions.mcp import CallTool

Button(
    "Upload Images",
    on_click=OpenFilePicker(
        accept="image/*",
        multiple=True,
        on_success=CallTool(
            "process_images",
            arguments={"images": "{{ $event }}"},
        ),
    ),
)

File Size Limits

The max_size parameter rejects files that exceed a byte limit before they ever reach onSuccess. Oversized files are silently dropped with a toast notification — the user sees the error, your tool never has to deal with it.
With size limit
from prefab_ui.components import Button
from prefab_ui.actions import OpenFilePicker
from prefab_ui.actions.mcp import CallTool

Button(
    "Upload (max 5MB)",
    on_click=OpenFilePicker(
        max_size=5_000_000,
        on_success=CallTool("upload", arguments={"file": "{{ $event }}"}),
    ),
)

Error Handling

The on_error callback on the nested CallTool fires if the server-side processing fails. The error message is available as $error.
With error handling
from prefab_ui.components import Button
from prefab_ui.actions import OpenFilePicker, ShowToast
from prefab_ui.actions.mcp import CallTool

Button(
    "Upload",
    on_click=OpenFilePicker(
        accept=".csv",
        on_success=CallTool(
            "process_csv",
            arguments={"file": "{{ $event }}"},
            on_success=ShowToast("File processed!", variant="success"),
            on_error=ShowToast(
                "Processing failed: {{ $error }}",
                variant="error",
            ),
        ),
    ),
)

The FileUpload Type

Both OpenFilePicker and DropZone produce the same $event shape. Prefab ships a FileUpload type you can use to annotate your tool parameters — see The FileUpload Type for details and usage.

User Activation

One constraint worth knowing: OpenFilePicker must execute before any async server actions in the same chain. Browsers require a recent user gesture to open the file picker — if a CallTool or SendMessage fires first, the activation window expires and the picker silently won’t open. This is the natural ordering anyway (pick the file, then send it), but it’s worth understanding why.

API Reference

OpenFilePicker Parameters

accept
str | None
default:"None"
File type filter. Accepts MIME types ("image/*"), extensions (".csv"), or a comma-separated mix.
multiple
bool
default:"False"
Allow selecting multiple files. $event is always list[FileUpload]; this controls whether the OS file picker allows multi-select.
max_size
int | None
default:"None"
Maximum file size in bytes. Oversized files are rejected with a toast notification.
on_success
Action | list[Action] | None
default:"None"
Action(s) to run after files are selected. $event is always list[FileUpload].
on_error
Action | list[Action] | None
default:"None"
Action(s) to run if file reading fails.

Protocol Reference

OpenFilePicker
{
  "action": "openFilePicker",
  "accept?": "string",
  "multiple?": false,
  "maxSize?": "number"
}
For the complete protocol schema, see OpenFilePicker.