Getting started with Flowbrew
Flowbrew turns plain-language workflow descriptions into versioned Cloudflare Workflows and lets those workflows call plugin-provided actions. This page is a short map for someone operating Flowbrew through MCP and then moving on to plugin development.
For exact tool names and inputs, see the MCP reference.
Concept map
Section titled “Concept map”Workspace
Section titled “Workspace”A workspace is the top-level authorization and isolation boundary. An API key or OAuth identity resolves to one workspace, and MCP operations derive that workspace from the credential rather than accepting a caller-supplied workspace ID.
Project (optional)
Section titled “Project (optional)”A project is an organizational scope inside a workspace. A workflow may belong to one project or remain workspace-global; deleting a project is blocked while workflows still reference it. Project-scoped connections and triggers can only be used with workflows in the same project, while workspace-scoped resources can be used across the workspace where the operation permits it.
Workflow
Section titled “Workflow”A workflow is created first as a metadata-only shell with a workspace-unique name and an optional project. Each successful description-driven update compiles and publishes a new version, and new instances start from the current version while existing instances retain the version on which they began.
Plugin
Section titled “Plugin”A plugin is a versioned manifest containing bricks, connection types, and trigger definitions. Public plugins are visible to every workspace; private plugins are owned by and installed into the workspace that uploads them.
A brick is a plugin-provided action with an HTTPS endpoint plus input and output
schemas. A brick can declare named connection slots, and generated workflow
code invokes it by the stable <plugin-slug>.<brick-slug> ID.
Connection type and connection
Section titled “Connection type and connection”A connection type belongs to a plugin version and defines a credential schema, optional fixed plugin configuration, and a same-plugin validation brick. A connection is a user’s encrypted credential instance of that type, scoped to the workspace or to one project; credential creation and rotation happen in the web console.
Trigger
Section titled “Trigger”A plugin manifest declares trigger definitions with lifecycle endpoints, configuration and event schemas, and optionally one required connection type. An MCP-created trigger instance is workspace- or project-scoped, and a trigger subscription connects that instance to a workflow; each instance accepts at most five subscriptions.
Set up access
Section titled “Set up access”- Sign in to the web console at
https://console.flowbrew.app(or your deployment’s console URL) and create or select a workspace. - Create a workspace API key in API Keys. The raw key is shown only once.
- Point an MCP client at
https://mcp.flowbrew.app/mcp(or your deployment’s own/mcpendpoint) and authenticate with that key as a bearer token. A deployment with the OAuth bridge enabled can authenticate an MCP client through OAuth instead.
For local or scripted calls from a repository checkout, the repository helper reads the local SST output
by default and accepts TASKFLOW_MCP_URL and TASKFLOW_API_KEY overrides:
TASKFLOW_API_KEY='...' bun run mcp:call list_projects '{}'The current product boundary is:
- The web console creates and manages workspaces/organizations, membership and invitations, and raw API keys. It also creates, rotates, revokes, and purges credential-bearing connections.
- MCP owns workflow and trigger-instance/subscription lifecycle. It also owns project lifecycle and can list or revoke existing API keys.
- MCP can list connection metadata and create a credential-less pending connection with
create_connection, but cannot create or rotate credentials. The console does not currently expose workflow or trigger lifecycle routes.
That boundary is slightly less absolute than “all API-key management is in the
console”: list_api_keys and revoke_api_key are live MCP tools, but creating a
key (and receiving its one-time raw value) remains a console operation.
Build and run a workflow through MCP
Section titled “Build and run a workflow through MCP”The normal order is shell, deployment, start, then status polling.
1. Inspect the available scope
Section titled “1. Inspect the available scope”Use list_projects if the workflow should be project-scoped. list_plugins
shows visible plugins and their connection types, brick contracts, and trigger
definitions. list_connections returns metadata for connections usable at
workspace scope or in a selected project.
list_connections requires an explicit projectId: pass null for only
workspace-scoped connections, or a project ID for workspace connections plus
connections belonging to that project.
2. Create an empty workflow shell
Section titled “2. Create an empty workflow shell”Call create_workflow with a name and, optionally, projectId. The result has
currentVersionName: null and currentVersionNumber: null; it cannot be
started until code is deployed.
3. Generate and deploy workflow code
Section titled “3. Generate and deploy workflow code”Call update_workflow with the shell’s id and a plain-language
description. Flowbrew supplies the code generator with the visible brick
catalog and the configured connections allowed for the workflow’s scope.
Generation produces a complete TypeScript file, not a patch. The candidate is compiled but not executed; a generation or compilation failure leaves the currently deployed version unchanged.
Name and project changes use the same tool in a separate metadata-only call.
Do not combine description with name or projectId.
4. Start one workflow instance
Section titled “4. Start one workflow instance”Call start_workflow with either workflowId or name, a non-empty
idempotencyKey, and an optional JSON payload. Caller payload becomes
event.payload.input inside the workflow.
The idempotency key is workspace-scoped. Retrying with the same key returns the same instance rather than intentionally starting another one, so use a new key for each new logical run.
start_workflow returns an instanceId immediately; it does not wait for the
workflow to finish.
5. Poll for the result
Section titled “5. Poll for the result”Pass the instanceId to read_instance. One call can long-poll for about 50
seconds and returns the current status, plus output or error when available.
Use list_instances to rediscover recent instances or filter them by workflow.
6. Add a brick with a connection binding
Section titled “6. Add a brick with a connection binding”There is no separate “add brick” MCP mutation. Create and validate the
connection in the web console, use list_connections to obtain its ID, then
describe the desired plugin action in a description-driven update_workflow.
Flowbrew generates the brick call and binds required named slots to literal
connection IDs; compilation rejects missing, unknown, wrongly typed, or
out-of-scope bindings.
Only configured workspace connections and configured connections belonging
to the workflow’s project are offered to workflow generation. A
workspace-global workflow cannot use a project-owned connection.
7. Register and subscribe a trigger
Section titled “7. Register and subscribe a trigger”Choose a trigger definition from list_plugins, then call
create_trigger_instance with its id as triggerDefinitionId and:
scope: "workspace"andprojectId: null, orscope: "project"and the matching project ID;- configuration that matches the definition’s schema; and
- either the required compatible
connectionIdornullfor a connectionless definition.
Creation calls the plugin’s registration endpoint and becomes active only
after the plugin acknowledges it. Then call create_trigger_subscription with
the returned trigger-instance ID and the workflow ID. A project-scoped trigger
can subscribe only workflows in that project; a workspace-scoped trigger can
subscribe workflows anywhere in its workspace.
The MCP catalog does not list subscriptions, so retain the subscription ID returned at creation if it may need to be deleted later.
Build a plugin
Section titled “Build a plugin”Start with these code-backed references:
packages/plugin-sdk/README.mdis the SDK quickstart for manifests, brick handlers, typed connections, trigger lifecycle handlers, and event delivery.packages/e2e-fixture-plugin/src/index.tscontains copyable brick manifests, handlers, and request routing. The smallertrigger-fixture.tsandtrigger-fixture-worker.tsshow a minimal trigger manifest, lifecycle handler, state, and event delivery path. The adjacentbasic-bearer-fixture.ts/basic-bearer-worker.tsandoauth-fixture.ts/oauth-worker.tspairs exercise connection providers.packages/core-plugin/src/manifest.ts,bricks.ts, andworker.tsare the production-grade reference, with supporting storage and deduplication modules in the same directory. The core plugin declares no connection types; use the SDK README’sissue-tools/ Jira example for that shape instead.
Deploy every brick and trigger lifecycle handler at the exact endpoint in the
manifest, then upload only the JSON manifest to the authenticated
POST /plugins/upload endpoint. This upload route is HTTP, not an MCP tool.
Known gotchas
Section titled “Known gotchas”create_workflowcreates no executable version. Always complete at least one successful description-drivenupdate_workflowbeforestart_workflow.- Workflow deployment validation is compile-only. A candidate that compiles can still fail or behave incorrectly at runtime, so start and inspect a real instance after an update.
- Plugin endpoints must be public HTTPS URLs with no embedded credentials or custom port, and their DNS must resolve to publicly routable addresses. Localhost and private-address endpoints are rejected during upload.
- A published plugin version is immutable. Re-uploading the same version works only for byte-identical manifest content; changed content needs a greater semantic version. Existing connection-type security semantics cannot be changed across versions.
- Every connection type needs a same-plugin validation brick with exactly one
required slot of that type.
configSchemaand fixedconfigmust either both be present or both be absent. - Trigger registration must persist the ingestion secret and credential generation atomically before acknowledging. The SDK explicitly warns that a bare eventually-consistent KV read/write pair is not a sufficient production state store.