upload_file
Upload a file to the workspace CDN — ONLY for callers that can run shell commands / send HTTP requests themselves .
If you are not capable of sending HTTP requests to an endpoint,
call ``upload_file_widget`` instead and ask the user to drop the file into the panel.
Two modes, keyed on ``base64_content``:
- ``base64_content`` OMITTED → **presigned** (preferred, any size): returns
``{"upload_url", "cdn_url", "storage_path", "content_type", "expires_in"}``.
PUT the bytes to ``upload_url`` (sending ``Content-Type: <content_type>``
when provided), then reference ``cdn_url`` from other tools. Bytes stream
client → S3; nothing goes through the model. NOTE: ``cdn_url`` is dead
until your PUT completes — never pass it to other tools before then.
This is the path the upload widget drives. If you cannot send HTTP
requests or the endpoint is blocked, call ``upload_file_widget`` instead.
- ``base64_content`` GIVEN → **inline** (tiny blobs only, <= ~1.5 MB):
decode + upload in one call. ONLY pass bytes you actually hold —
read from a real file or returned by an API. NEVER construct
base64 from an image you can merely see in the chat: you do not
have access to attachment bytes, and fabricated base64 fails
validation or uploads corrupt data. For a file on the user's
machine, call ``upload_file_widget`` instead. Returns
``{"cdn_url", "storage_path", "content_type", "bytes_uploaded"}``. Larger
bodies are rejected and can exceed the transport's request-size limit, so
omit it and use the presigned mode.
Mirrors ``api.views.uploads.ApiUploadView``'s two modes over MCP.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | Yes | File name, e.g. 'face.png'. Only the leaf name is used; directory parts are stripped. | |
| content_type | No | MIME type, e.g. 'image/png'. Recommended. In the presigned path it is signed into the URL, so the PUT must send a matching Content-Type header. | |
| base64_content | No | OPTIONAL — only for tiny in-memory blobs (<= ~1.5 MB): the file body, base64-encoded, uploaded in one call. OMIT for anything larger or on-disk; you then get back a presigned `upload_url` to PUT the bytes straight to S3 (no size cap, nothing base64-encoded through the model). |