Skip to main content
Glama

Edit an image

edit_creative

Edit a finished image from written instructions: change or remove something in it, or add something to it. Headlines, text or a layout on a photo are a design, not an edit: use generate_design with the photo as photoCreativeId, which keeps the photo as it is and sets the type in the brand's fonts. For a design made in Rawa, prefer adapt_design, which keeps its editable layers. The source is a creative of the brand (creativeId) or an image on the web (imageUrl: a direct, public URL to a JPEG, PNG or WebP file). An image the user pasted or attached in the chat has no such URL and you cannot read it yourself: call request_image_upload right away (do not ask them to re-attach it), and once the image has landed use its creativeId here. An image you hold as a file on your own filesystem (a coding agent in a project) goes through upload_image_file instead. A linked image is added to the brand's library first and its creativeId is returned as sourceCreativeId; an image the library already holds is not added again, and sourceCreativeId is that creative, with alreadyInLibrary: true. Reuse sourceCreativeId for any further work on the same image instead of passing imageUrl again. Cost: 30 credits. Call with dryRun: true first and tell the user the cost. Once they agree, pass the quoted credits as expectedCredits; a call that would cost a different amount is refused. Give each new generation a new requestId, and repeat it unchanged only on a retry: a retry within 2 minutes returns the first result and is not charged again. Without a requestId, the same arguments within 2 minutes count as a retry. Needs generation allowed over MCP (see get_workspace); a dry run still quotes when it is not, and says why the call would be refused in wouldRefuse. Returns a jobId, creditsCharged and creditsRemaining; ready in 1 to 5 minutes. If a job panel shows, it tracks the work: do not poll, end your turn with one line saying it is under way, and later use show_creatives with the creativeIds you are told. Otherwise call wait_for_jobs with the jobIds until allFinal is true.

Input Schema

NameRequiredDescriptionDefault
dryRunNotrue: return the exact cost (credits, breakdown, balanceAfter) without charging or starting anything, and wouldRefuse when the organization's spending controls would refuse the real call.
brandIdNoA brand id from get_workspace or list_brands, or the brand's name. Omit it when the organization has a single brand.
imageUrlNoA direct, publicly reachable https URL of the image to work on, when it is not in the library yet.
requestIdNoYour own unique id for this request. Use a new one for every new request, even with the same arguments. Repeat it unchanged only to retry this exact call within 2 minutes; the retry returns the first result.
creativeIdNoA creative id from list_creatives, search_library, get_job or get_upload.
instructionsYesWhat to change in the image, in plain words.
expectedCreditsNoThe credits the dryRun quoted and the user agreed to. The call is refused if it would cost a different amount.

Output Schema

NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / brandId / description
      Previous value: -"A brand id from get_workspace or list_brands. Omit it when the organization has a single brand."New value: +"A brand id from get_workspace or list_brands, or the brand's name. Omit it when the organization has a single brand."
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "balanceAfter": {
      -        "type": "number"
      -      },
      -      "breakdown": {
      -        "type": "string"
      -      },
      -      "credits": {
      -        "type": "number"
      -      },
      -      "deduplicated": {
      -        "const": true,
      -        "description": "The same call was made in the last 2 minutes: this is its result, not charged again.",
      -        "type": "boolean"
      -      },
      -      "dryRun": {
      -        "const": true,
      -        "type": "boolean"
      -      },
      -      "wouldRefuse": {
      -        "description": "Set when the organization's MCP spending controls would refuse the real call: the refusal it would get.",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "dryRun",
      -      "credits",
      -      "breakdown",
      -      "balanceAfter"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "creditsCharged": {
      -        "type": "number"
      -      },
      -      "creditsRemaining": {
      -        "type": "number"
      -      },
      -      "deduplicated": {
      -        "const": true,
      -        "description": "The same call was made in the last 2 minutes: this is its result, not charged again.",
      -        "type": "boolean"
      -      },
      -      "jobId": {
      -        "type": "string"
      -      },
      -      "sourceCreativeId": {
      -        "type": "string"
      -      },
      -      "watchToken": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "jobId",
      -      "watchToken",
      -      "creditsCharged",
      -      "creditsRemaining",
      -      "sourceCreativeId"
      -    ],
      -    "type": "object"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "balanceAfter": {
      +        "type": "number"
      +      },
      +      "breakdown": {
      +        "type": "string"
      +      },
      +      "credits": {
      +        "type": "number"
      +      },
      +      "deduplicated": {
      +        "const": true,
      +        "description": "The same call was made in the last 2 minutes: this is its result, not charged again.",
      +        "type": "boolean"
      +      },
      +      "dryRun": {
      +        "const": true,
      +        "type": "boolean"
      +      },
      +      "wouldRefuse": {
      +        "description": "Set when the organization's MCP spending controls would refuse the real call: the refusal it would get.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "dryRun",
      +      "credits",
      +      "breakdown",
      +      "balanceAfter"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "alreadyInLibrary": {
      +        "const": true,
      +        "description": "The brand's library already held this image, so no new creative was added: the id names that one.",
      +        "type": "boolean"
      +      },
      +      "creditsCharged": {
      +        "type": "number"
      +      },
      +      "creditsRemaining": {
      +        "type": "number"
      +      },
      +      "deduplicated": {
      +        "const": true,
      +        "description": "The same call was made in the last 2 minutes: this is its result, not charged again.",
      +        "type": "boolean"
      +      },
      +      "jobId": {
      +        "type": "string"
      +      },
      +      "sourceCreativeId": {
      +        "type": "string"
      +      },
      +      "watchToken": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "jobId",
      +      "watchToken",
      +      "creditsCharged",
      +      "creditsRemaining",
      +      "sourceCreativeId"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations: states the 30-credit cost, mandates a dryRun-first confirmation flow, explains the expectedCredits guard, the requestId retry/dedup window (2 minutes, not re-charged), the MCP generation permission gate with wouldRefuse on dry run, the 1–5 minute latency, and the no-polling rule. These are operational facts an agent cannot infer from readOnlyHint/openWorldHint/idempotentHint.

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 purpose before routing and cost mechanics, and nearly every sentence carries actionable information. It is long (roughly 280 words), but the length is driven by a genuinely multi-path workflow rather than padding; a tighter split of job-tracking guidance would still help.

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 a costly, asynchronous, multi-source generation tool it covers sourcing, permissions, cost/confirmation, retry semantics, latency, and post-call tracking. Return fields are described even though an output schema exists, and nothing needed to invoke it correctly is missing.

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 schema already documents each field and the baseline would be 3. The description adds real meaning on top: the creativeId-vs-imageUrl source choice, the sourceCreativeId/alreadyInLibrary return semantics, and the instruction to reuse sourceCreativeId rather than re-passing imageUrl.

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 ('Edit a finished image from written instructions') and immediately bounds scope ('change or remove something in it, or add something to it'). It then explicitly separates itself from generate_design and adapt_design, so an agent can pick the right tool without opening any schema.

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?

Gives explicit alternatives keyed to conditions: text/layout on a photo → generate_design with photoCreativeId; a Rawa design → adapt_design; a pasted/attached image → request_image_upload; a local file → upload_image_file. Follow-up routing is also specified (show_creatives vs wait_for_jobs).

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