- name
- run-workflow
- description
- Use the run-workflow MCP to discover, compose, execute, publish, and save Adobe Firefly workflows. TRIGGER when: user asks what the MCP can do; wants to process images/video/3D via workflow; wants to build/run/save/publish a workflow; wants to list/view saved or recent workflows, presets/interfaces, or golden demos (e.g. 'run banners at scale'); pastes any workflow/batch/execution ID; names a featured workflow (retargeting, product banners, localization, packaging, banner advertising) — call get_featured_workflow first. NOTE: 'banners at scale' = GOLDEN DEMO (list_golden_workflows), NOT the featured workflow 'Product Banners At Scale'. BARE ID = INSPECT ONLY — call inspect_run, never run_workflow_submit. ALWAYS call list_actions first for action/node discovery; a "what tools" question is answered directly from your visible tool list, no call. DO NOT TRIGGER for direct Firefly API calls without MCP (use firefly-api-specs).
- compatibility
- Requires an enterprise Adobe account with a Firefly Services or Firefly Creative Production entitlement, assigned via the Adobe Admin Console. Not available to individual/personal Adobe accounts.
- license
- Apache-2.0
- metadata
- {"version":"1.0.0","visibility":"public"}
# run-workflow MCP
<!-- SYNC: This skill is maintained in three locations that must be kept identical:
`.claude/skills/run-workflow/` (source), `.cursor/skills/run-workflow/` (Cursor),
and `packages/mcp-server/references/` (reference files only, bundled with the MCP server).
Change one, change all three. See docs/CODE_PATTERNS.md → "run-workflow skill twins". -->
Discover, compose, run, publish, and save Adobe Firefly workflows through the run-workflow MCP
server. Never answer capability questions from training knowledge — always ground answers in live
tool calls. `list_actions` is ALWAYS the first call for any **action/node catalog** discovery
question (e.g. "what actions are available"). A **tools** question (e.g. "show me the tools",
"what MCP tools do you have") is a different vocabulary — answer directly from your own visible
tool definitions (name + one-line description each); do not call `list_actions` for it.
This file is the always-loaded core. Deeper procedures live in `references/` and should be read
**only when the current turn needs them**:
| Read this reference when… | File |
| --- | --- |
| User uploads/pastes a document that reads like a creative/marketing brief (not a bare ID, not a named workflow) | [`references/intake.md`](references/intake.md) |
| User names a featured workflow, or supplies a custom `.indd`/`.psd` template to rewire | [`references/featured-and-templates.md`](references/featured-and-templates.md) |
| Composing a non-trivial graph, wants multi-variant outputs, or a required input is missing | [`references/compose.md`](references/compose.md) |
| Inspecting a run, listing history, or a workflow failed (error tables, `inspect_run` routing) | [`references/diagnostics.md`](references/diagnostics.md) |
| Uploading files, resolving inline pastes, macOS permission error, saving outputs | [`references/asset-input.md`](references/asset-input.md) |
| User asks for alert triage / RCA (dev-only: `login --dev`, Splunk + Slack) | [`references/alert-rca.md`](references/alert-rca.md) |
## BARE ID RULE — read this before anything else
**When the skill argument is just an ID (UUID, workflowId, batchId, executionId) with no other
context, the intent is ALWAYS to inspect — NEVER to execute.**
1. Call `inspect_run(id)` immediately.
2. Present the results (executions, outputs, diagnostics).
3. **STOP.** Do not call `run_workflow_submit` as a follow-up.
**"run-workflow" is the product name, NOT an instruction to execute anything.** Required keywords to
justify `run_workflow_submit`: **"run", "execute", "process", "generate", "rerun", "redo"**. If NONE
appear in the user's message, call `inspect_run`.
**FORBIDDEN:** calling `run_workflow_submit` on a bare pasted ID; trying `run_workflow_submit` first
and falling back to `inspect_run` after a 404. For rerun-after-inspect handling (route on the `rerun`
object, never `canRerun`), see [`references/diagnostics.md`](references/diagnostics.md).
**"What assets/inputs does this golden workflow or interface need (and are they still available)?"**
is also an `inspect_run(workflowId)` question — it resolves the interface's authoritative baked
definition and reports each asset's `rerunAssets[].resolvedVia` (warm-url / durable-storage /
unavailable). NEVER answer it with `get_featured_workflow` (a different catalog). See
[`references/diagnostics.md`](references/diagnostics.md) → "What assets does this golden/interface need".
## Workflow types (user-facing vocabulary)
Every workflow the user sees falls into one of these types. Use these plain labels when talking to
the user; **never** show the raw internal field values.
- **Published** — a workflow the user published as a reusable API endpoint (stable `workflowId` + curl).
- **Preset** — a published workflow run from a Firefly UI. **"Preset" and "interface" are the SAME
thing** — if the user asks about "interfaces" or "presets", they mean this. (Not a separate saved
definition; it's a *published workflow that was launched from an interface.*)
- **Inline** — a workflow composed and run ad-hoc through the MCP with no saved/published definition.
- **Draft** — saved to Workflow Builder but not yet published. A draft **stays a draft after it is
run** (source `draft` whether or not it has ever executed), matching the builder UI. Use
`firstExecutionAt` to tell run from un-run: set = a **run draft**, null/absent = an **un-run draft**.
- **Preview** — a one-off preview execution; ephemeral.
- **Shared** — a workflow shared into this org from a different org (author-initiated); read-only.
A **workflows-listing** request ("give me my workflows", "what have I built") surfaces the caller's
own **Draft** and **Published** rows, plus other org members' **Published** rows and any **Shared**
rows (Preset is a labeled subset of Published) — Inline and Preview are execution artifacts with no
saved definition and are excluded from that intent entirely. Never claim to have run or edited a
workflow authored by someone else, and never offer to edit/republish a Shared row.
For that intent, **by default hide un-run drafts** (`workflowSource === "draft" && !firstExecutionAt`)
and show run drafts alongside published — the un-run drafts are unfinished scratch work the user
rarely means. Include un-run drafts only when the user explicitly asks for un-run / unfinished / all
drafts.
Translate to these labels when listing — full field mapping in [`references/diagnostics.md`](references/diagnostics.md).
## Tool routing
| User intent | Tool |
| --- | --- |
| "Show me the tools" / "show me the MCP tools" / "what tools do you have" / "what tools are available" | Answer directly from your own visible tool list (name + one-line description each) — do NOT call `list_actions` or any other tool |
| "What actions are available?" / "show me the nodes/actions I can use" / "what can I use to build workflows" / "show me the catalog" / "what can you do" (as a workflow-capability question) | `list_actions` |
| "What parameters does action X accept?" | `get_action_schema` |
| "Build / compose / create a workflow for…" | `compose_workflow` |
| Upload a local file to get a URL | `upload_asset` |
| Execute a workflow — only with explicit run/execute keywords. Returns a `batchId` immediately (async); safe for any size | `run_workflow_submit` |
| Check whether a running execution is done — **always pass `includeOutputs: true`** on every poll | `run_workflow_get_status` |
| Abort a running batch by batchId | `cancel_workflow` |
| "Give me my workflows" / "Show me **all** my workflows" / "my recent workflows" / "What have I **built / defined / saved**?" (ANY plain workflows-listing intent, with or without the word "all" — no date filter, no mention of "runs"/"executions") | `list_all_workflows` — ONE call; its `renderedTable` already contains, in order, the 8 golden-demo rows, the `typeSummary` type-count block, then the caller's own workflows table, as a single combined string — never a separate `list_golden_workflows` call, and never separately paste the standalone `typeSummary` field too (it's already embedded). Never `list_workflow_history`/`list_batches`/`inspect_run` for this intent — exact columns and pre-computed fields in [`references/diagnostics.md`](references/diagnostics.md) |
| A **filtered/date-ranged** own-workflow query (e.g. "workflows I published last week") — not the broad listing intent above | `list_workflow_history` (own drafts/published only, with date filters) |
| "List my **interfaces**" / "my **presets**" / "what presets/interfaces do I have published" (DEFINITIONS — a genuinely different entity from a regular published workflow, not runs) | `list_interfaces` — one call, already formatted; render `renderedTable` verbatim |
| "List my **jobs**" / "my interface runs" / "preset runs" / "interface executions" (RUNS only — never bulk-workflow-service traffic, no preview/headless runs) | `list_interface_runs` — one call, already filtered + formatted; render `renderedTable` verbatim; for outputs/errors on one run, `inspect_run` with its `batchId` |
| "List my **workflow runs**" / "runs of my saved workflow" / "what have I run" (when NOT asking about interfaces/presets/jobs specifically) — plain, non-interface runs, no UI precedent so columns/formats are this tool's own design | `list_workflow_runs` — one call, already filtered (excludes interface/preset runs entirely, regardless of channel) + formatted; render `renderedTable` verbatim; for outputs/errors on one run, `inspect_run` with its `batchId` |
| "Show my recent **runs**" / "everything I've **run**" / "The interface I just ran" / "Runs from a specific UI" (any-`batchSource`/`invocationSource`/`hostId` filtered run query — not the intents above) | `list_batches` (filter `batchSource:"preset"` for interface runs, `hostId` for a specific UI) |
| "Last workflow I ran" / "Most recent run" (**single**, by recency) | `list_workflow_history` (limit=1) → `inspect_run` — single-item only, never for a broad list |
| Per-action outputs/logs/errors for a run; "why did it fail?"; any pasted ID | `inspect_run` |
| Look up known-good examples to debug a failed compose | `get_workflow_examples` |
| Reload examples after editing JSON files on disk | `reload_examples` |
| Publish workflow as a reusable API endpoint with curl | `publish_workflow` |
| Save workflow as an editable DRAFT in Workflow Builder (dual-writes ACP + the unified store the backend reads) | `save_workflow` |
| Generate a curl command for a published workflowId | `generate_curl` |
| Display output images inline in chat (not in Claude Desktop — 1MB cap; only after presenting URLs per the Presenting outputs sequence) | `display_asset` |
| See newly registered actions (catalog stale) | `refresh_catalog` |
| Run a named/featured workflow (retargeting, **product** banners at scale, localization, packaging…) — a per-use-case TEMPLATE, distinct from a golden demo (see note below) | `get_featured_workflow` → see [`references/featured-and-templates.md`](references/featured-and-templates.md) |
| "List golden workflows" / "what are the golden demos" (FFCPE's homepage showcase cards — Banners at Scale, Product Assets, Social Video Adaptation — different from featured workflows, which are per-use-case templates, not showcase demos) | `list_golden_workflows` — one call, already formatted; render `renderedTable` verbatim |
| "Run/execute **`<golden demo name>`**" (e.g. "run banners at scale", "run the social video adaptation demo") — an EXECUTE intent naming a golden demo, not a plain listing request | `list_golden_workflows` first to resolve the name to its `workflowId` — a use-case name like "Banners at Scale" matches more than one row; list them and ask which before proceeding, never guess — then submit `run_workflow_submit({ workflowId, inputs: [] })` directly (baked defaults, no confirmation needed — see the **ASK-FIRST (assets)** rule under **Key rules**), unless their prompt already asked for their own assets, in which case collect and pass `inputs`. Never route a bare "run `<use case>`" to `get_featured_workflow` — that's the agent-facing template path, not the user run path. |
**Single vs. multiple:** one ID / "the last one" / "that workflow" → `inspect_run` (full details).
A broad "list my workflows" request with no named target and no "run"/"ran"/"execution" wording →
`list_all_workflows`. If the request mentions runs/executions instead of (or alongside) workflows
— including "my workflow runs" specifically → `list_workflow_runs` (never `list_all_workflows`
or `list_workflow_history`); a broader/filtered run query (any source, a specific `hostId`, etc.)
→ `list_batches` instead.
### Workflows-listing intent — ONE call, THREE sections baked into `renderedTable`
A plain "give me my workflows" intent (see the table row above) is answered with exactly ONE
`list_all_workflows` call. Its `renderedTable` already contains three sections, IN THIS ORDER,
inside one combined string, each separated by a blank line. Paste that string as your reply,
unchanged — do not reconstruct the table from the `workflows` array, do not drop the golden-demo
rows or the Workflow ID column, and do not replace any section with a prose summary. A short
follow-up offer to filter/narrow after the pasted block is fine; it is not a substitute for
pasting the block first.
The three sections:
1. A **"Golden demos:"** label, then FFCPE's 8 homepage golden-demo rows (byte-identical to
`list_golden_workflows`' own table).
2. The `typeSummary` type-count block (also returned as its own standalone field, for callers
that want just the counts — but when rendering `renderedTable`, it's already positioned here;
do not ALSO separately paste the standalone `typeSummary` field before `renderedTable`, or the
block appears twice).
3. A **"Your workflows:"** label, then the caller's own workflows table (5 columns — see
[`references/diagnostics.md`](references/diagnostics.md)).
On a paginated call (`offset > 0`), section 1 is skipped entirely — golden demos are the same
static 8 rows every time, so they're only fetched/rendered on the first page.
Present the WHOLE string verbatim, top to bottom, in one piece. Do not call
`list_golden_workflows` separately for this intent, do not split `renderedTable` back into
multiple tables/fields, and do not summarize or trim any section just because it isn't the
"main" content.
Three designs for the golden-demos section specifically were tried, in order — the first two
abandoned: (1) two separate sequential tool calls (`list_golden_workflows` then
`list_all_workflows`) — reliably summarized away in practice even with explicit instructions,
because skipping an entire extra tool call turned out to be just as easy for a model to do as
dropping one field; (2) a `goldenRenderedTable` SIBLING field on `list_all_workflows`'s own
response — also reliably dropped, for the same underlying reason a second field is as skippable
as a second call; (3, current) folding the golden rows directly into the ONE string that has
reliably survived every other similar test this feature went through (`renderedTable` itself) —
there is nothing left to selectively omit. The same reasoning was then applied to `typeSummary`'s
position once golden-demo ordering surfaced a second problem (a separate `typeSummary` field
rendered in the wrong order relative to `renderedTable`) — folding it into the same string at the
correct position removes that ordering ambiguity too. `goldenUnavailable: true` means the golden
section specifically failed and was omitted entirely (not left as a blank placeholder) — mention
this to the user rather than presenting the table as if golden demos simply don't exist.
**Interfaces/presets vs. their runs:** "interfaces"/"presets" (same thing — "preset" is the
older, backend-internal name) name a DEFINITION (published through a genuinely separate
endpoint/namespace from a regular published workflow) → `list_interfaces`. "jobs" names their
RUNS (executions) → `list_interface_runs`, never bulk-workflow-service traffic (a separate
product with no representation in run-workflow's batch data at all). Don't conflate these two
intents with each other or with `list_all_workflows`/`list_batches`.
**Plain workflow runs vs. interface runs:** `list_workflow_runs` excludes interface/preset runs
entirely (regardless of who/what launched them) — it's the complement of `list_interface_runs`,
not a superset. There is no existing UI for this (unlike interfaces, which mirror bulk-creation's
UI exactly) — its columns/formats are this tool's own design; don't claim they match a screen.
**Golden demos vs. featured workflows on "banners":** both catalogs happen to use the word
"banners," but they are unrelated. "Banners at Scale" (bare) is a golden-demo USE CASE — a homepage
showcase card with 2 sub-demos, resolved via `list_golden_workflows`. "Product Banners At Scale" is
a featured-workflow TEMPLATE (agent-facing, resolved via `get_featured_workflow`). A bare user
"run banners at scale" (or any bare "run `<use case>`") is a GOLDEN request — resolve it via
`list_golden_workflows`, never `get_featured_workflow`. Reach for `get_featured_workflow` only when
the user EXPLICITLY asks for a featured/predefined template, or as a `compose_workflow` precursor.
For the Type/channel taxonomy (`batchSource` vs `invocationSource`) and run-centric routing
details, see [`references/diagnostics.md`](references/diagnostics.md).
## Workflow pattern
```
1. upload_asset — upload local files; get back URLs for use as inputs
1b. get_action_schema — SKIP when: you already have a session_id, OR the workflow is a clear
single-action keyword (remove-background, upscale, crop, expand, generate,
etc.). CALL when: composing a multi-step custom workflow where at least one
action's parameters are uncertain. See references/compose.md.
2. compose_workflow — describe the desired processing in natural language; the AI graph agent
designs the graph. DO NOT manually specify actions or connections.
3. run_workflow_submit — execute with inputs; pass session_id from step 2. Pass ALL images in ONE
call. Returns a batchId immediately (async); does NOT block on completion.
→ For featured workflow runs (session_id from get_featured_workflow OR from
a compose_workflow rewire): inputs[] = one entry per asset type using node
IDs from prepared.inputNodes — preserved through rewires. See table in
references/featured-and-templates.md. No deliberation needed.
4. run_workflow_get_status — poll the batchId; ALWAYS pass includeOutputs: true. On completion,
present ALL output URLs verbatim and STOP (see post-completion sequence).
5. download_output — ONLY after the user asks; saveTo a folder they choose.
6. publish_workflow — publish for API reuse OR save_workflow — save for UI editing.
```
## Async polling
After `run_workflow_submit`, poll `run_workflow_get_status` with `includeOutputs: true` using a
tiered interval — read `elapsedSeconds` from each response to pick the next wait:
| `elapsedSeconds` so far | Wait before next poll |
|---|---|
| < 60 | 15s — may finish quickly |
| 60 – 180 | 30s |
| > 180 | 60s — large batch; halve tool calls |
Report progress using `elapsedSeconds` and `percentage` from the response directly — do not estimate
elapsed time yourself:
> **Running** — 3/10 assets complete (30%) · 45s elapsed
GitHubで見る