Create multi-step MCP workflows with assertions.
Learn how to design workflow checks that call multiple MCP tools, reference results from earlier steps, and validate responses with JSON Schema assertions.
What is a workflow check?
A workflow check is a sequence of MCP tool calls that validates your server behaves correctly end-to-end. Each step calls one tool, and later steps can reference data from earlier responses.
Example scenario: Search for a customer by email, then fetch that customer's orders using the id the first call returned.
Create your first workflow
Register your server and press Discover tools on its card first. Then open MCP tools in your dashboard, find the Workflow checks panel, and fill in the form:
-
Name
A label shown on the workflow card and in alerts (for example
Customer order flow). -
Steps (JSON)
A JSON array with one object per step, in the order they run. Press Save workflow when it is ready.
Describe a step
Each step needs a serverId and a toolName:
-
serverId: the id of the registered server the tool lives on, shown as Server id on its card. One workflow can use more than one server. -
toolName: the tool, exactly as the server advertises it. -
parameters: the input object passed to the tool. It can use{{'{{'}}name.field{{'}}'}}to refer to an earlier result. -
extractOutputAs(optional): the name this step's result is stored under, for later steps to use. -
assertOutput(optional): a JSON Schema the result must match. The step fails if it does not. -
stopOnFailure(optional): set tofalseto keep going after this step fails. The default is to stop.
[
{
"serverId": "mcp_1",
"toolName": "search_customers",
"parameters": { "email": "alice@example.com" },
"extractOutputAs": "customer",
"assertOutput": {
"type": "object",
"required": ["id"],
"properties": { "id": { "type": "string" } }
}
},
{
"serverId": "mcp_1",
"toolName": "list_orders",
"parameters": { "customer_id": "{{customer.id}}" }
}
]
Reference earlier results
Use {{'{{'}}stepName.path{{'}}'}} to inject values from a
previous step's result into a later step's arguments.
Example workflow
Step 1: Create a customer
Tool: create_customer
Arguments:
{
"name": "Alice",
"email": "alice@example.com"
}
Expected result (schema):
{
"type": "object",
"required": ["id"],
"properties": {
"id": { "type": "string" }
}
}
Step 2: Retrieve the customer by ID
Tool: get_customer
Arguments:
{
"id": "{{create_customer.id}}"
}
Expected result (schema):
{
"type": "object",
"required": ["name", "email"],
"properties": {
"name": { "const": "Alice" },
"email": { "type": "string", "format": "email" }
}
}
The {{'{{'}}create_customer.id{{'}}'}} reference pulls the
id field from Step 1's result and injects it into Step 2's
arguments.
Write assertions with JSON Schema
The Expected result field uses JSON Schema Draft 2020-12. This lets you validate structure, types, required fields, and value constraints.
Common patterns
Require specific fields
{
"type": "object",
"required": ["id", "status"],
"properties": {
"id": { "type": "string" },
"status": { "enum": ["active", "pending"] }
}
}
Validate array length
{
"type": "array",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "object",
"required": ["name"]
}
}
Check a field matches a pattern
{
"type": "object",
"properties": {
"email": {
"type": "string",
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
}
}
}
Require an exact value
{
"type": "object",
"properties": {
"version": { "const": "2.0" }
}
}
When a workflow runs
Run once
Press Run once on a workflow card to run it now. The card then shows the time, how it ran, and each step with its duration and the reason if it failed. Only the latest result is kept.
On a schedule
A saved workflow also runs on its own, with the MCP monitor. It uses the same schedule as tool-change checking: weekly on Free, daily on Pro, every 6 hours on Business.
- Turn the monitor on. In Settings, tick Monitor MCP tool drift. Without it nothing runs on its own, and the workflow card says so. Run once always works.
- Switch one workflow off. Press Switch off on its card to stop it running on schedule without deleting it.
Stop on first failure
By default a workflow stops at the first step that fails (a tool error,
a schema mismatch, or a tool that cannot be called). Later steps are
skipped, which prevents cascading failures when a step needs an earlier
result. Set stopOnFailure to false on a step
to keep going.
Read-only tools only
A workflow calls only tools that the server marks read-only right now. A step is refused if its tool is not read-only, so a workflow never changes your data. To call a tool that changes data, use the one-time tool console, where you approve each call yourself.
When a tool changes
If a tool a workflow calls has changed since you last pressed Discover tools (a new schema, or even a new description), the workflow is not run. Its card shows needs review and says why. Press Discover tools on that server's card to record the tool as it is now, then press Run once.
When a workflow fails
Once a workflow has run more than once, its card also says how many of its last 20 runs passed, and whether each run was scheduled or started by hand.
A scheduled workflow that fails, or is not run because a tool changed, sends one A saved MCP workflow fails alert. It does not repeat while the workflow stays broken, and it alerts again after the workflow has passed and then fails. You can turn this alert off in Settings. A failed workflow does not open a Finding.
Troubleshooting
Step fails: the tool reported an error
The tool answered with an error. The usual causes are a missing required
field, a value of the wrong type, or a
{{'{{'}}reference{{'}}'}}
that points to a field the earlier step did not return. Check the tool's
input schema on its card.
Step fails: the output does not match the assertion
The tool returned a result, but it did not match your
assertOutput schema. The card names the field or constraint
that failed. Either update the schema to match what the tool really
returns, or fix the tool if the result is wrong.
A reference is not resolved
A {{'{{'}}name.field{{'}}'}} reference was not replaced.
Check that the name matches an extractOutputAs on an
earlier step, that the field exists in that step's result, and that the
earlier step passed, because a failed step stores nothing.
Best practices
- Start simple: Test one tool at a time before chaining several steps.
-
Name results clearly: Use
extractOutputAsnames such ascustomerororder, notresult1. -
Validate structure, not exact values: Assertions
should focus on
"type","required", and"enum"rather than brittle"const"checks on dynamic data. - Keep workflows focused: One workflow per feature or user journey.
- Run once before you rely on the schedule. Catch a bad parameter or assertion early.