Skip to main content
Glama

upload_asset

Destructive

UPLOAD A STATIC ASSET TO AN APP so app code stays small and the app reads it back same-origin. Use this when an app needs a large or static file — an image, PDF, audio clip, or a dataset bigger than a few KB — that would otherwise be inlined into module/ui and blow the 256 KiB source cap. Provide EXACTLY ONE of: sourceUrl (PREFERRED for any binary — the SERVER fetches the remote file, follows redirects, and the bytes never transit this tool call), text (UTF-8 dataset/JSON/CSV — no encoding needed), or dataBase64 (LAST RESORT, tiny binaries only: large base64 arguments can stall inside some MCP clients before ever reaching the server, so keep it under ~16 KB and use sourceUrl for anything bigger). The app reads the asset via window.charming.assets.getUrl(key) (for /) or env.assets.get(key) in its backend (the app must declare charming:storage/blob@1.0 in manifest.capabilities.imports to use env.assets). Caps: 10 MiB/asset, 50 assets/app, 100 MiB/app.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
keyYesAsset name, e.g. "dataset_v1.json". URL-safe [a-zA-Z0-9._-], <=128 chars, no leading dot.
textNoUTF-8 text payload (datasets, JSON, CSV). No base64.
appIdYesThe app id (app_modules.id) to attach the asset to. Must be an app you own.
sourceUrlNohttps URL the server fetches and stores. Bytes never pass through this tool call.
dataBase64NoBase64 of a SMALL binary. Last resort — prefer sourceUrl: large base64 tool arguments can stall in some MCP clients before reaching the server. Keep the encoded string under ~16 KB; the server-side hard cap is 64 KiB decoded.
contentTypeNoMIME type. Defaults: text/plain for text, sniffed for sourceUrl, application/octet-stream otherwise.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
okYesIndicates success. Errors arrive as content with isError:true.
keyYesThe asset key it was stored under. Same value passed in.
urlYesSame-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.charming.assets.getUrl(key).
appIdYesUUID of the asset-owning app.
bytesYesStored byte length of the asset payload after decode/fetch.
advisoriesNoStructured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.
contentTypeYesEffective MIME type stored with the asset (supplied, sniffed from sourceUrl, or defaulted).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedOutput schema / properties / advisories
      Added value: +{
      +  "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.",
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "data": {
      +        "additionalProperties": {},
      +        "description": "Kind-specific structured payload. Shape varies per advisory kind.",
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "doc_url": {
      +        "description": "Optional docs pointer for this advisory kind.",
      +        "type": "string"
      +      },
      +      "kind": {
      +        "description": "Stable advisory identifier (e.g. \"legacy-bridge\").",
      +        "type": "string"
      +      },
      +      "severity": {
      +        "description": "Severity; omitted advisories are treated as 'info'.",
      +        "enum": [
      +          "info",
      +          "warn"
      +        ],
      +        "type": "string"
      +      },
      +      "summary": {
      +        "description": "Agent-facing summary. Self-sufficient; no extra context required.",
      +        "type": "string"
      +      },
      +      "userSummary": {
      +        "description": "End-user-facing summary. Set when the advisory should render in-app.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "summary"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / url / description
      Previous value: -"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.buildy.assets.getUrl(key)."New value: +"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.charming.assets.getUrl(key)."
  2. First observed

TDQS

A4.5/5.0
Behavior4/5

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

Beyond the annotations, the description adds meaningful behavioral detail: the server fetches sourceUrl and follows redirects, bytes never transit through the tool call, base64 payloads can stall MCP clients around 16 KB, and caps are 10 MiB/asset, 50 assets/app, 100 MiB/app. It does not disclose what happens when uploading with an existing key, though the destructiveHint annotation is present but not elaborated.

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

Conciseness4/5

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

The description is dense and front-loaded with the core purpose, then immediately moves into how to invoke it, then into retrieval and caps. Every sentence earns its place, although it is still a long single paragraph that could be easier to scan as bullets or as separate paragraphs.

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?

Given the 6-parameter schema, annotations, output schema, and caps, the description covers the contract well: source selection, binary safety, retrieval APIs, and size constraints. The main gap is that it does not explain the overwrite/destructive behavior of reuploading an existing key, and it assumes the reader knows their app ownership requirement is enough.

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

Parameters4/5

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

Schema description coverage is 100%, so baseline is 3, but the description adds selection semantics above the schema: lasering xactly one way, source precedence, and size guidance for source vs base64. Some of this duplicates the parameter-level descriptions in the schema, so not a 5.

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

Purpose5/5

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

The opening phrase 'UPLOAD A STATIC ASSET TO AN APP' gives a specific verb, resource, and target. It also distinguishes itself from code inlining by mentioning the 256 KiB source cap and static files (images, PDFs, datasets), which an agent can use it aside from sibling app-mutation tools.

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?

The description explicitly says 'Use this when an app needs a large or static file... would otherwise be inlined into module/ui'. It also tells the agent to provide EXACTLY ONE of sourceUrl/text/dataBase64, and gives clear selection rules ('PREFERRED for any binary', 'LAST RESORT', 'use sourceUrl for anything bigger'). This gives the agent direct guidance on when and how to invoke.

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.