Skip to main content
Glama

Upload Image to Post

upload_asset
DestructiveIdempotent

Uploads an image sent as base64, for an image with no public URL (for example one pasted, generated or edited in a conversation). The format is detected from the bytes (JPEG/PNG/GIF/WebP). Accepts up to 10MB; anything over 3MB is downscaled on the server (longest edge 2048px, EXIF orientation applied, EXIF/GPS metadata stripped). Stored as JPEG or PNG: a GIF or WebP is converted (first frame only). post_id is optional: with it, the image is stored and attached in one call; without it, the call returns a standalone asset { asset_id, url, bytes, width, height, format, resized } that can be attached to any number of posts later (unattached assets expire after 30 days). One call carries about 2.5MB of image. A larger image goes in sequential chunks of about 2MB: chunk 0 as { image_base64, chunk_index: 0, total_chunks: N } returns upload_session_id, chunks 1…N-1 carry it, and the final chunk returns the result (sessions expire after 24 hours; at most 3 open at once). dry_run=true validates without storing. A post holds one media format at a time (single image, carousel or video): replace=true swaps an existing carousel or video for this image. Published posts cannot be changed. Errors carry error.data = { code, recovery, ... } with codes IMAGE_TOO_LARGE (limit_bytes, received_bytes), UNSUPPORTED_FORMAT (detected_magic_bytes, supported_formats), INVALID_BASE64, POST_NOT_FOUND, POST_ALREADY_PUBLISHED, UPLOAD_SESSION_INVALID; recovery says how to fix the call. Attaching media to an approved (ready or scheduled) post returns it to draft, and it needs approval again before it can publish. When a post is attached (post_id), the response carries status_before, status_after and approval_required; a standalone upload has none.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

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

Input Schema

NameRequiredDescriptionDefault
dry_runNoWhen true, the call validates base64, format and size without storing (single call or final chunk).
post_idNoOptional. The post to attach the image to in the same call. Without it, the image is stored as a standalone asset that can be attached later.
replaceNoWhen true, the call discards any existing carousel or video on the post and attaches this image instead.
alt_textNoOptional accessibility text.
chunk_indexNoChunked uploads only: 0-based index of this chunk; chunks are accepted in order from 0.
image_base64YesThe image bytes (or this chunk's bytes), base64-encoded. A data-URI prefix (data:image/png;base64,) is accepted and stripped. Format is detected from the bytes (JPEG/PNG/GIF/WebP).
total_chunksNoChunked uploads only: total chunks (2–8), the same on every chunk.
upload_session_idNoChunked uploads only: the session id chunk 0 returned; required on later chunks.

Output Schema

NameRequiredDescriptionDefault
kindYes
assetNo
dry_runNo
post_idNo
resizedNo
asset_idNo
image_urlNo
mime_typeNo
size_bytesNo
chunk_indexNo
status_afterNo
total_chunksNo
dashboard_urlNo
status_beforeNo
approval_resetNo
approval_requiredNo
upload_session_idNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.6/5.0
Behavior5/5

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

With destructiveHint and idempotentHint already declared, the description still earns its place by disclosing the full consequences: server-side downscaling above 3MB, conversion of GIF/WebP to first-frame JPEG/PNG, EXIF/GPS stripping, 30-day expiry of unattached assets, 24-hour session expiry with 3 concurrent sessions, replace=true destroying an existing carousel or video, published posts being immutable, and media attachment resetting an approved post to draft. The error-code table with recovery guidance is a rare and useful addition beyond annotations.

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?

Front-loaded with what the tool does, then size/format rules, then the post_id fork, then chunking, then errors. It is a single dense block rather than sections or bullets, which makes the chunking protocol harder to scan, and a few clauses (post_id, dry_run) restate the schema. No sentence is pure filler, though.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with a rich output schema, the description covers everything an agent needs: format detection, size limits and transformations, chunked upload protocol, the attach-later asset lifecycle, replace semantics, approval side effects, and error recovery. Output shape explanation is redundant given the output schema but not harmful.

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 coverage is 100%, so the baseline is 3; however the description adds orchestration the schema cannot express — that chunk 0 returns upload_session_id, that chunks 1..N-1 carry it, and that the final chunk returns the result, plus the ~2MB chunk size and 2-8 chunk bounds. It also clarifies that a standalone asset can be attached to many posts later. Slight overlap with schema text (post_id, dry_run) keeps it below top marks.

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?

States a specific verb and resource ('Uploads an image sent as base64') and immediately scopes it to the case with no public URL, which separates it from the sibling set_post_image. The added note that it covers pasted, generated or edited images lets an agent match the source of the bytes to the right tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames the when: an image with no public URL. It also tells the agent when to supply post_id versus omit it, when to use dry_run, and when to switch to chunked upload (over ~2.5MB). It never names set_post_image or create_media_upload as the alternative for URL-based or platform-side uploads, so the routing is implied rather than stated.

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