MCP File Uploads
How AI agents get files into FAL and attach them to records through the AI Foundation MCP server.
Ingest paths
Prefer these in order:
- URL upload —
file_for publicupload_ from_ url httplinks (and YouTube/Vimeo online media).(s) - Content upload —
file_withupload contentfor small text assets (SVG, CSV, VTT, plain text). - Pre-signed binary —
file_→ clientupload_ prepare PUT→ then attach (see below). - Tiny base64 —
file_withupload base64Contentonly for very small binaries undermcp(default 16 KiB). Larger payloads are rejected; use prepare instead.Max Base64Upload Bytes
URL upload
Call file_ with a direct file URL (not an HTML page). The response includes a sys_ uid, public, sha1, and a next hint.
YouTube and Vimeo page URLs are stored as online media assets instead of downloading video bytes.
Content upload
Use file_ with content (and a file name that includes an extension) when the agent authors the bytes inline. Dangerous extensions (.php, .html, .htaccess, …) are refused.
Pre-signed upload (chat / desktop binaries)
- Call
file_(optionalupload_ prepare file,Name directory,Path storage).Uid - Receive
upload,Url upload,Token valid, and curl-style instructions.Until PUT(orPOST) the raw file body touploadwith the token (Bearer or query).Url - Read the JSON
describeresponse (File uid,sha1,next, …).Step - Attach with
file_orreference_ add write_inline refs.table
Example attach after upload:
file_reference_add(table="tt_content", uid=45, fieldName="image", fileUids="88")
# or, on create/update:
write_table(action="create", tableName="tt_content", data='{"pid":1,"header":"Hero","image":[{"uid_local":88,"alternative":"Banner"}]}')
On write_ update, a present file-field array replaces existing references for that field; [] clears them.
Base64 policy
base64Content through the LLM channel silently truncates or corrupts mid-size binaries. Keep it for tiny fixtures only. Prefer prepare + PUT for anything larger than the configured base64 cap.
Integrity checks
Optional expected / expected apply to both content and base64Content. They validate the payload the client sends before FAL storage.
If TYPO3 rewrites the file while storing it (common for SVG sanitization), the upload still succeeds and the response includes rewritten: true, inbound / inbound, plus the stored sha1 / size. Prefer file_ for raster images (JPG/PNG) so bytes never pass through the model.
Create-only storage and destructive ops
Uploads are create-only: conflicts rename; identical SHA1 content is reused (dedupe). Deletes, renames, and moves of existing FAL objects are gated by mcp (default on for backward compatibility — turn off on stricter sites).
Related settings (extension / MCP Advanced): mcp, mcp, mcp, mcp.
mcp only caps Streamable HTTP MCP JSON bodies — large binaries go through the pre-signed PUT path.
Metadata and public URLs
Upload, list, search, and file_ responses include an absolute public when the storage can serve the file.
Edit title / alternative / description with write_ on sys_ (lookup the row by file = sys_ uid). Example:
write_table(action="update", tableName="sys_file_metadata", uid=<metadataUid>, data='{"title":"Hero","alternative":"Banner"}')
Discover fields first with table_ for sys_.
Relations, collections, and SEO file fields
table_ now surfaces:
- category / MM select (e.g.
categories,authors,tags) withwritable— writeAs: uid_ list "126"or"8,12"viawrite_. Reads (table pages_/get content_/ list / search) return the same UID-list string, not the parent counter.get - file fields (
og_,image image,assets, …) withwritable— useAs: file_ references file_orreference_ add [; do not set a bare integer.{"uid_ local": N}] file_syncs the parent counter used by SEO generators.reference_ add - Content Blocks collections (
type: collection) — do not write the parent field; create child rows inforeignwithTable foreign(oftenField foreign_). Order withtable_ parent_ uid pid=<page>thenpid=-<previous.Child Uid>
When write_ ignores a field, the response includes ignored with a concrete hint.
Verification checklist (TC)
- TC1 —
file_with a public image URL →upload_ from_ url uid+ absolutepublic.Url - TC2 — YouTube/Vimeo page URL → online media asset (no binary download).
- TC3 — Tiny
base64Contentundermcpsucceeds.Max Base64Upload Bytes - TC4 — Mid-size base64 ( 70 KiB) is rejected with a prepare hint.
- TC5 —
file_→ clientupload_ prepare PUT→201JSON withuid/sha1. - TC6 — Attach via
file_orreference_ add write_table [.{"uid_ local": N}] - TC7 — Private/reserved host URL is refused (SSRF); sandbox/clients still cannot hit private hosts.