Tools reference
The FLORA MCP server exposes execute, flora_discover_skills, and a set of flora_* endpoint tools. The endpoint tools map directly to the FLORA API, while execute runs TypeScript against the @flora-ai/flora SDK and flora_discover_skills provides reusable workflow instructions.
MCP tools
Section titled “MCP tools”execute
Section titled “execute”Runs TypeScript in a sandboxed environment with a pre-authenticated @flora-ai/flora client. The agent defines a function async function run(client) { ... } and the server invokes it, returning whatever the function returns plus any console.log output.
| Argument | Type | Description |
|---|---|---|
code | string | TypeScript code defining async function run(client) { ... } |
flora_discover_skills
Section titled “flora_discover_skills”Discovers reusable FLORA workflow skills. Omit name to list available skills; pass an exact skill name to retrieve its instructions.
| Argument | Type | Description |
|---|---|---|
name | string, optional | Exact skill name from a previous discovery result |
flora_* endpoint tools
Section titled “flora_* endpoint tools”These tools expose the current FLORA API surface directly. Their argument shapes are available in the API Reference and the SDK’s TypeScript types.
Read-only tools carry readOnlyHint. flora_update_project_sharing, flora_remove_from_canvas and flora_update_canvas_node_document carry destructiveHint because they revoke links people already hold, delete nodes for good, or replace a whole document, so a host can ask before running them.
Workspaces
Section titled “Workspaces”flora_list_workspaces— List the workspaces available to the account.
Projects
Section titled “Projects”flora_list_projects— List projects in a workspace, most recently active first.flora_get_project— Get one project’s metadata.flora_list_canvas_nodes— List a project’s media nodes and asset URLs.flora_open_project— Open a project canvas in a browser session with WebMCP tools.flora_create_project— Create an empty project canvas in a workspace.flora_share_project— Share a project by link and return the link.flora_get_project_sharing— Read a project’s link sharing mode, share link, owner, and members.flora_update_project_sharing— Change a project’s link sharing, including unsharing it.
Canvas
Section titled “Canvas”flora_get_canvas— Read a project’s canvas: every node with its position and size, every edge, and a revision marker.flora_add_to_canvas— Add nodes and edges to a project canvas.flora_update_canvas_nodes— Edit existing nodes in place (label, prompt, model, params, position, a note’s text) and remove edges.flora_remove_from_canvas— Delete nodes from a project canvas, with their edges and group members.flora_run_canvas_nodes— Run generation nodes already on a project canvas.flora_get_canvas_node_document— Read a document-bearing node’s full content: a timeline’s tracks, items and assets, a deck’s slides and layers, or a note’s whole text body.flora_update_canvas_node_document— Replace a timeline node’s document, guarded by base_revision.flora_arrange_canvas— Arrange nodes on a project canvas: Tidy (edge-following), or a row, column, or grid of named nodes with a chosen gap and origin.flora_add_action— Add a prebuilt action node to a project canvas.
Models and generations
Section titled “Models and generations”flora_list_models— List generation models available to the account.flora_view_model3d— Open a read-only 3D viewer for a run.flora_list_generations— List generation history or read a set of runs by run_ids.flora_create_generations— Start 1–20 generations; pass a one-itemgenerationsarray for a single request.
LoRA Styles
Section titled “LoRA Styles”flora_list_lora_trainers— Discover families, training defaults and limits, and compatible inference models with strength parameters.flora_train_lora— Train and save a Style through the same flow as the web Train dialog; this spends usage. Persistclient_tokenbefore submitting.flora_get_lora— Check saved Style readiness and compatible base-model family. Poll training withflora_list_generationsusingrun_ids: [run_id].
Use the ready style_id as params.lora_id in an item of flora_create_generations. See
LoRA training for captions, recovery and SDK examples. These are
remote MCP endpoint tools; the browser’s project WebMCP surface is separate.
Techniques
Section titled “Techniques”flora_list_techniques— List saved techniques with inputs, outputs, and run cost.flora_get_technique— Get a technique’s declared inputs and outputs.flora_list_technique_runs— List past technique runs with status, cost, and outputs.flora_run_technique— Run a saved technique; this spends credits.
Actions
Section titled “Actions”flora_search_actions— Search the credit-free prebuilt action registry.flora_run_action— Run a prebuilt action on inline inputs without touching the canvas.flora_run_canvas_action— Run an action node already on a canvas.
Assets
Section titled “Assets”flora_list_assets— List assets in a workspace or project.flora_get_asset— Get one asset’s metadata.flora_create_asset— Bring a file into a workspace from a URL or signed upload.flora_complete_asset— Finish a signed upload and return the asset’s final URL.flora_attach_asset— Put an existing asset onto a project canvas.
Brand OS
Section titled “Brand OS”Listed only for accounts with Brand OS.
flora_brand— Read a published brand:list(brands with their release and task profiles),context(the rules for one task profile),module,assets,package, andrender_textfor exact text and logos in the brand’s fonts.flora_brand_edit— Set up and edit a brand’s draft, then publish it:create,add_sourceandcomplete_source(public HTTPS URL or signed upload),extract,set_specs(palette, type styles, grids, logo lockups),import_templates(Figmaslots.jsonorspecs.json),set_asset_use(intent, imagery bank tags and usage notes, display names; up to 100 assets per call),save_ruleandpublish. It needs Brand OS edit access in the workspace. Agents read the changes throughflora_brandafter a publish.flora_brand_status— Read-only progress for that setup:extraction(a run’s status) andpublish_preview(what would ship, and the latest release).
execute constraints:
- Variables and imported state do not persist between
executecalls — each call is isolated. - Individual HTTP requests inside the sandbox time out at 30 seconds.
- Total code execution times out at approximately 5 minutes.
SDK surface reference
Section titled “SDK surface reference”The sections below describe every client.* namespace available inside execute, grouped by resource.
Techniques
Section titled “Techniques”The agent uses these methods to discover Techniques and create Technique runs.
// List all techniques (supports async iteration)const { techniques } = await client.techniques.list({ query: "thumbnail" })
// Inspect a specific technique's inputs, outputs, and costconst technique = await client.techniques.retrieve("tech_...")// → { technique_id, name, description, inputs[], outputs[], run_cost }
// Create a technique runconst run = await client.techniques.runs.create("tech_...", { mode: "async", inputs: [{ id: "image_in", type: "imageUrl", value: "https://..." }], callback_url: "https://yourserver.com/webhook", // optional})// → { run_id, status, progress, outputs? }
// List past technique runs (newest first, paginated; supports async iteration)const { runs } = await client.techniques.runs.list({ workspace_id: "ws_...", status: "completed", limit: 20,})
// Poll a technique runconst status = await client.techniques.runs.retrieve("run_...", { techniqueId: "tech_...",})// → { status: 'pending'|'running'|'completed'|'failed', progress,// outputs: [{ output_id, type, url }], error_code?, error_message? }Generations
Section titled “Generations”For one-off model generations that don’t require a saved Technique, the agent calls client.generations.create. This is the preferred path for plain image, video, audio, or text generation.
// Create a generationconst run = await client.generations.create({ type: "image", prompt: "a fox in the snow", workspace_id: "ws_...", project_id: "prj_...", model: "model_id_from_list", // optional params: { width: 1024, height: 768 }, // optional, model-specific})// → { run_id, type, charged_cost, estimated_seconds, model?, project_id? }
// List past generations (newest first, paginated; supports async iteration)for await (const gen of client.generations.list({ workspace_id: "ws_..." })) { console.log(gen.run_id, gen.status)}Assets
Section titled “Assets”For workflows that need user-supplied images or videos, the agent follows a 3-step signed-upload flow: create an asset slot → upload bytes via the signed URL → mark it complete. The resulting asset URL can then be passed as a Technique input.
// Step 1: create a signed upload slotconst asset = await client.assets.create(/* see the API Reference and SDK types for full args */)
// Step 2: upload bytes via the signed URL (the agent uses curl or fetch)
// Step 3: mark the upload completeawait client.assets.complete(asset.asset_id)
// Retry if the signed URL expiredawait client.assets.retry(asset.asset_id)
// List assetsconst { assets } = await client.assets.list({ workspace_id: "ws_..." })
// Retrieve a specific assetconst a = await client.assets.retrieve("asset_...")Projects, Canvas, and Actions
Section titled “Projects, Canvas, and Actions”Projects organize runs and assets inside a workspace. The canvas and actions methods let the agent read and modify a project’s node graph.
Video-generation nodes require the workspace video entitlement; a changeset that adds one without access is rejected. Static video uploads using content_url are exempt. If rejected, ask the user to enable video access or build the workflow with image nodes; do not retry the unchanged request.
// List and create projectsconst { projects } = await client.projects.list({ workspace_id: "ws_..." })const project = await client.projects.create({ name: "My Campaign", workspace_id: "ws_..." })
// Retrieve a project and its nodesconst p = await client.projects.retrieve("prj_...")for await (const node of client.projects.listNodes("prj_...")) { /* ... */}
// Attach an asset to a project canvasawait client.projects.assets.attach(/* see the API Reference and SDK types for exact args */)
// Read the full canvas graph: nodes, edges, and a revision markerconst graph = await client.projects.canvas.getGraph({ workspaceId: "ws_...", projectId: "prj_..." })
// Add and connect nodes in one changeset; created maps each ref to its assigned idsconst { created } = await client.projects.canvas.applyChangeset({ workspaceId: "ws_...", projectId: "prj_...", add: [{ ref: "outc", type: "image", prompt: "Editorial campaign image" }], connect: [{ from: "n1", to: "outc" }],})
// Run generation nodes the changeset created — spends credits, returns a run per nodeawait client.projects.canvas.runNodes({ workspaceId: "ws_...", projectId: "prj_...", node_ids: [created.outc.id],})
// Add a prebuilt action node from a raw action slugawait client.projects.actions.create("prj_...", { action_id: "rotate-image", params: { /* optional */ },})
// Run an existing canvas action nodeawait client.projects.actions.run("prj_...", "node_...")
// Share the project by link, the way the canvas Share tab does. Escalate-only:// sharing for "view" never downgrades a project already shared for "edit".// "edit" needs a plan with editable sharing (403 paid_plan_required otherwise).const { url } = await client.projects.sharing.share({ projectId: "prj_...", access: "view" })// → { url, role: "guest" | "editor", sharing_mode, created, canvas_url }
// Read the sharing state; the link appears only when the user may manage sharingconst state = await client.projects.sharing.get({ projectId: "prj_..." })// → { sharing_mode, is_private, can_manage_sharing, link | null, owner, members[] }
// Change it explicitly — "restricted" unshares; passphrase: null clears the passphraseawait client.projects.sharing.update({ projectId: "prj_...", sharing_mode: "restricted",})Agents that prefer the flora_* tools get the same three operations as
flora_share_project, flora_get_project_sharing (read-only), and
flora_update_project_sharing. A link returned by any of them grants access to
whoever holds it, so the agent should hand it to the user rather than post it elsewhere.
Workspaces
Section titled “Workspaces”const { workspaces } = await client.workspaces.list()// → [{ workspace_id, name, role, created_at }]The agent typically calls this first after OAuth, or when the user has access to multiple workspaces and needs to resolve the right workspace_id.
Models
Section titled “Models”For generation workflows that accept a model parameter, the agent lists models to discover available IDs and their parameter schemas.
const { models } = await client.models.list({ type: "image" }) // type optional// → [{ model_id, name, provider, type, estimated_credits, estimated_cost_usd, estimated_seconds,// params: [{ name, required, type, default, min, max, options }] }]Feedback
Section titled “Feedback”await client.feedback.record({ /* ... */})The agent calls this when the user wants to send feedback to the FLORA team — e.g. “tell FLORA the MCP keeps disconnecting”, “send feedback that I’d love a Technique for X”, “let FLORA know this worked great”.
How the agent picks tools
Section titled “How the agent picks tools”You don’t call tools directly. You describe what you want, and the agent handles the sequence. For example, “Run the Thumbnail Technique on this image” typically resolves to:
flora_list_techniques— find matching Techniques and their declared inputs.flora_get_technique— confirm the selected Technique’s input schema.flora_run_technique— start the run with an inputs map keyed by those input ids.flora_list_generations— passrun_ids: [run_id]andtechnique_idto poll the run until complete:
async function run(client) { // 1. Find the technique const { techniques } = await client.techniques.list({ query: "thumbnail" }) const tech = techniques[0] console.log("Using technique:", tech.technique_id, tech.name)
// 2. Create a run const run = await client.techniques.runs.create(tech.technique_id, { mode: "async", inputs: [{ id: "image_in", type: "imageUrl", value: "https://example.com/photo.jpg" }], }) console.log("Run created:", run.run_id)
// 3. Poll until complete let result do { await new Promise((r) => setTimeout(r, 3000)) result = await client.techniques.runs.retrieve(run.run_id, { techniqueId: tech.technique_id, }) console.log("Status:", result.status, result.progress) } while (result.status === "pending" || result.status === "running")
return result.outputs}Different prompts produce different sequences. The Recipes section walks through several end-to-end examples.
Tool naming in your client
Section titled “Tool naming in your client”Most clients namespace tools by server. You’ll see the current server tools under names like:
- Claude Code (
/mcplisting):flora:execute,flora:flora_discover_skills, andflora:flora_* - Cursor:
flora.execute,flora.flora_discover_skills, andflora.flora_* - Other MCP clients: similar namespacing depending on the client
You almost never need to type these directly — describe what you want and the agent picks the right tool.
Limits and billing
Section titled “Limits and billing”- Calls that create runs (
client.techniques.runs.create(...),client.generations.create(...)) are billed in USD against your workspace. The cost is shown inclient.techniques.retrieve(...)underrun_costand on the completed run ascharged_cost. - Rate limits apply at the workspace level and match the REST API. See the API Reference for current limits.
- A
402 insufficient_creditserror means the workspace balance is too low — see About FLORA credits.