Skip to content
Charming Docs
Esc
navigateopen⌘Jpreview
On this page

Upload Asset

UPLOAD A STATIC ASSET TO AN APP so app code stays small and the app reads it back same-origin.

MCP name: upload_asset

Tool contract

{
  "annotations": {
    "destructiveHint": true,
    "openWorldHint": true,
    "readOnlyHint": false,
    "title": "Upload Asset"
  },
  "description": "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 <img>/<a>) 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.",
  "execution": {
    "taskSupport": "forbidden"
  },
  "inputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "properties": {
      "appId": {
        "description": "The app id (app_modules.id) to attach the asset to. Must be an app you own.",
        "type": "string"
      },
      "contentType": {
        "description": "MIME type. Defaults: text/plain for text, sniffed for sourceUrl, application/octet-stream otherwise.",
        "type": "string"
      },
      "dataBase64": {
        "description": "Base64 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.",
        "type": "string"
      },
      "key": {
        "description": "Asset name, e.g. \"dataset_v1.json\". URL-safe [a-zA-Z0-9._-], <=128 chars, no leading dot.",
        "type": "string"
      },
      "sourceUrl": {
        "description": "https URL the server fetches and stores. Bytes never pass through this tool call.",
        "format": "uri",
        "type": "string"
      },
      "text": {
        "description": "UTF-8 text payload (datasets, JSON, CSV). No base64.",
        "type": "string"
      }
    },
    "required": [
      "appId",
      "key"
    ],
    "type": "object"
  },
  "name": "upload_asset",
  "outputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "additionalProperties": false,
    "properties": {
      "appId": {
        "description": "UUID of the asset-owning app.",
        "type": "string"
      },
      "bytes": {
        "description": "Stored byte length of the asset payload after decode/fetch.",
        "maximum": 9007199254740991,
        "minimum": -9007199254740991,
        "type": "integer"
      },
      "contentType": {
        "description": "Effective MIME type stored with the asset (supplied, sniffed from sourceUrl, or defaulted).",
        "type": "string"
      },
      "key": {
        "description": "The asset key it was stored under. Same value passed in.",
        "type": "string"
      },
      "ok": {
        "const": true,
        "description": "Indicates success. Errors arrive as content with isError:true.",
        "type": "boolean"
      },
      "url": {
        "description": "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).",
        "type": "string"
      }
    },
    "required": [
      "ok",
      "appId",
      "key",
      "bytes",
      "contentType",
      "url"
    ],
    "type": "object"
  }
}

Was this page helpful?