Tools reference
The two MCP tools the FLORA server exposes, plus the full SDK method surface available inside execute.
The FLORA MCP server exposes exactly two tools: search_docs and execute. Rather than wrapping each API endpoint as a separate tool, the agent writes TypeScript against the @flora-ai/flora SDK inside a single execute call — keeping the interface simple and the agent in full control of sequencing and error handling.
The two tools
Section titled “The two tools”search_docs
Section titled “search_docs”Searches the @flora-ai/flora SDK documentation to find the right method, its parameter shapes, and usage examples. The agent calls this before writing code whenever it is unsure of a method name, argument structure, or return type.
| Argument | Type | Description |
| --- | --- | --- |
| query | string | Natural-language question or method name to look up |
| language | string | Target language, e.g. "typescript" |
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.
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 search_docs 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.
// 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.attachAsset(/* see search_docs for exact args */);
// Retrieve the canvas topology as a Mermaid flowchartconst canvas = await client.projects.canvas.retrieve("prj_...");
// Apply a Mermaid patch to add or connect nodesawait client.projects.canvas.update("prj_...", { diagram: "...", // Mermaid diff node_params: { /* optional per-node param overrides */ },});
// 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_...");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_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:
search_docs— look upclient.techniques.listandclient.techniques.runs.createparameter shapes.execute— a single function that lists Techniques (filtering by name), retrieves the matching one to confirm its inputs, creates a run, and polls 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. With the new two-tool model you’ll see:
- Claude Code (
/mcplisting):flora:execute,flora:search_docs - Cursor:
flora.execute,flora.search_docs - 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 — top up in FLORA → Settings → Billing.