Skip to main content
Glama

Upload asset

upload_asset
Idempotent

Put an image into a form's storage: pass parent (the form id) and filename.

Two ways: • Small files (up to about 100 KB): pass the bytes base64-encoded as content_base64. Hard limit 2 MiB. • Anything larger: omit content_base64 and pass content_type and size_bytes. You get back a one-time upload_url; PUT the raw bytes to it with that content-type (no authorization header — the url is the permission, so keep it secret). It expires in 300 seconds, refuses more than size_bytes or a different content-type, and takes at most 26214400 bytes (25 MiB). • A file the person has but you cannot send (for example one attached in chat, when your sandbox cannot reach the upload host): pass content_type and for_person: true instead of size_bytes. You get { upload_url, expires_at, for_person: true, instructions }; give the person upload_url to open in their browser, where they choose the file (any file of that kind; for an image, a PNG, JPEG, GIF or WebP). It lasts up to 30 minutes and survives a wrong pick. When they say it is done, confirm the file exists before using it.

If the PUT to upload_url fails because the host cannot be reached (a network, proxy or allowlist error from your sandbox), either ask the person to add the upload_url's host to Settings > Capabilities > Additional allowed domains and try again, or call upload_asset again with for_person: true and hand them the link.

Confirm with the user before calling this.

Without bytes: { upload_url, method: "PUT", headers, expires_at, max_bytes, instructions }.

Forms: pass parent (the form id) and filename; images only (png, jpg/jpeg, gif, webp), the same two ways, except that a for_person link takes only the image type of filename (the form's storage signs it), so ask the person which kind of image they have and name the file to match; inline, content_type may be left out and is taken from the filename extension. Inline returns { url, name, type, size, width, height }; without bytes it returns the upload ticket above, and the PUT answers that object. Give a @media block the url, with width and height as srcWidth and srcHeight; paste the whole object into a product's images in @products.

Example: upload_asset({ parent: "12:form:5f1c…", filename: "hero.png", content_type: "image/png", size_bytes: 2489301 }) → { "upload_url": "https://…/uploads/…", … }; the PUT answers { "url": "https://…/hero.png", "width": 1600, … }

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "upload_asset"
  }
}

Input Schema

NameRequiredDescriptionDefault
parentNoA form id, to store an image for that form. Use with filename.
filenameNoWith parent: the image file name, e.g. "hero.png"; its extension must match content_type.
for_personNoWithout content_base64: return a link the person opens in a browser to choose and upload the file themselves, instead of a url for you to PUT to. size_bytes is not needed.
size_bytesNoThe exact file size in bytes. Required without content_base64, unless for_person.
content_typeNoThe MIME type, e.g. "image/png". Required without content_base64.
content_base64NoThe file, base64-encoded (small files only). Omit to get an upload url instead.

Output Schema

NameRequiredDescriptionDefault
hashNo
pathNo
sizeNo
methodNo
headersNo
max_bytesNo
expires_atNo
for_personNo
upload_urlNo
instructionsNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes far past the annotations: the upload_url is one-time, acts as its own credential ('the url is the permission, so keep it secret'), expires in 300 seconds, rejects wrong size or content-type, and caps at 25 MiB; the person-facing link lasts 30 minutes and survives a wrong pick. It also explains what to do after the PUT fails from a sandbox, which the annotations say nothing about.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The bulleted three-way split is well front-loaded, but the 'Forms:' paragraph largely repeats the opening sentence and re-derives the same rules, and the parenthetical asides (sandbox proxy errors, @media/srcWidth/srcHeight placement) pile detail onto an already dense block. Several sentences could be merged without losing information.

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?

With no required parameters but an implicitly expected parent/filename pair, the description does the work of explaining the valid combinations, return shapes in each mode, and the downstream @media / @products usage. The only gap is that it never resolves whether parent is mandatory, since the schema marks nothing required while the prose treats form storage as the default case.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, yet the description adds real meaning: the mutual-exclusion logic between content_base64, size_bytes and for_person, that content_type can be inferred from the filename extension inline, and that the form link only accepts the image type matching the filename. The example call ties parent, filename, content_type and size_bytes together concretely.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource ('Put an image into a form's storage'), and the three bullets enumerate the exact modes. It loses a point because the later 'Forms:' paragraph restates the same scope as if it were a separate variant, leaving the reader unsure whether form storage is the only target or one of two targets.

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?

Explicit branching rules: use content_base64 up to ~100 KB (2 MiB hard cap), switch to size_bytes + content_type for anything larger, and use for_person: true when the sandbox cannot reach the upload host. It also gives a recovery path (allowlist the host or re-call with for_person) and a standing instruction to confirm with the user before calling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources