Upload, display (view), and download (attachment)·View as Markdown

Upload flow

A PUT to the bucket is not enough. file.rocks lists files from its index (shadow file), not from a live S3 listing. After PUT, you must register the object.

MCP (use this in agents)

Do not call REST POST .../files/upload-complete from an agent HTTP client. Cloudflare Bot Fight Mode may return error 1010. MCP complete_upload runs on the file.rocks server and does not hit that path.

  1. presign_upload — scope files:upload. Returns a short-lived PUT URL.
  2. PUT the bytes to that URL (the storage bucket, not file.rocks).
  3. complete_upload — same scope files:upload, same key. Registers the object. After this, list_files returns it.

The Upload + read API key preset already includes files:upload. Do not request files:write to register a file.

If the object is already in the bucket but missing from list_files, skip steps 1–2 and call complete_upload with the object key.

presign_upload returns a next object that names complete_upload. Follow it.

Display and download

After complete_upload (and on list_files / get_file), each file includes:

  • url — public CDN URL when the bucket has publicDomain. This does not expire. Use it to display images, embed in markdown, or pass to another tool. The browser treats it as a view (inline), not a file download.
  • thumbnailUrl — public URL of the thumbnail when one exists.

Do not invent a URL from the key. Read url from the file object.

View vs download

These are different:

GoalTool / fieldBrowser behavior
Display / embed (image, markdown, iframe)file.url if set, else presign_viewInline — shows the file
Save as a file (attachment)presign_downloadAttachment — downloads the file

presign_view and presign_download both require files:download.

Public CDN URLs cannot force a download. Even when file.url exists, call presign_download for an attachment. That signed URL expires.

Lifetime when there is no public domain (or for attachments)

S3-compatible presigns cannot be non-expiring (SigV4 max is 7 days).

IntentpurposeLifetime
Show a person nowpreview (default)1 hour
Place in another tool / pageembed7 days (max)

Returns url, as, disposition, expiresAt, durable.

Optional expiresIn (seconds, 60–604800) overrides the purpose default.

A true non-expiring view URL requires publicDomain on the bucket (file.url). There is no non-expiring attachment URL. Do not tell the user that a 7-day presign is permanent.

Tags and description (optional)

update_file sets tags/description. It requires files:write and only works on files that are already in the index. It does not register an upload.

Upload + read keys cannot tag. Leave tags off, or use a key that includes files:write.

REST (scripts only)

Prefer MCP in agents. For curl/scripts:

  1. POST .../files/presign-upload · files:upload
  2. PUT to the returned URL
  3. POST .../files/upload-complete · files:upload with { key, size, etag?, contentType?, contentHash? }

Details: Files.

Common mistakes

MistakeWhat to do
PUT succeeded, list_files is emptyCall complete_upload. The index is not a live bucket listing.
Ask the user for files:write to registerUse complete_upload (files:upload). Upload + read is enough.
Call REST upload-complete from an agentUse MCP complete_upload. REST may be blocked (Cloudflare 1010).
Call update_file to create the rowupdate_file only patches an indexed file. Register first.
Expect tags on Upload + readTags need files:write. Registration does not.
Invent a URL from the keyUse file.url to display. If it is null, call presign_view. For a save-as-file link, call presign_download.
Use presign_download to show an imageThat is an attachment. Use file.url or presign_view to display.
Treat an embed presign as permanentIt lasts at most 7 days. Non-expiring view URLs need publicDomain.

Scopes

ActionScopeTool / route
Presign + registerfiles:uploadpresign_upload, complete_upload
List after registerfiles:readlist_files (includes url when public)
Show / embed without public CDNfiles:downloadpresign_view (preview or embed)
Save as attachmentfiles:downloadpresign_download (preview or embed)
Tags / descriptionfiles:writeupdate_file
Upload flow · file.rocks docs