Overview

MPE Flow is a multi-protocol workflow orchestration engine. It runs as either a desktop GUI or a CLI tool — from the same binary.

Two Modes, One Binary

  • No arguments → Opens the Tauri desktop GUI
  • With arguments → Runs in CLI mode

On Linux, only the CLI binary is available — no GUI dependencies required.

Installation

Windows

Download the Windows installer (.exe installer or portable build) from the Changelog page and run it to set up MPE.

macOS

Download the Universal DMG package from the Changelog page (a single image natively supporting both Apple Silicon M-series and Intel processors). Open the DMG and drag the MPE icon to your Applications folder.

macOS First Run: "Unverified Developer" or "App is damaged" Workaround

Notice: Current open-source release builds are not signed or notarized with a paid Apple Developer certificate. On macOS, Gatekeeper's security mechanism will prevent opening untrusted binaries on first launch, displaying a warning such as "MPE cannot be opened because Apple cannot check it for malicious software" or "MPE is damaged and can't be opened. You should move it to the Trash." This is standard macOS behavior for unsigned software; MPE is fully open source and completely safe to run.

To launch MPE, use either of the following solutions:

Method 1: Clear quarantine attribute via Terminal (Recommended)

After moving MPE to your /Applications directory, open Terminal and execute the following command to remove the quarantine flag:

xattr -cr /Applications/MPE.app

Once cleared, double-click MPE.app from Launchpad or Finder. Gatekeeper will not prompt again.

Method 2: Right-click Open in Finder

  1. Open Finder, navigate to your Applications directory, and find MPE.
  2. Hold down the Control key on your keyboard, right-click (or two-finger tap) the MPE icon, and click Open in the menu.
  3. In the dialog that appears, click the Open button to confirm. (This is only required once).

Linux (CLI)

Download the pre-built binary and add it to your PATH:

# Download and extract
curl -LO https://download.mpe.run/releases/latest/mpe-vX.Y.Z-linux-x86_64.tar.gz
tar xzf mpe-vX.Y.Z-linux-x86_64.tar.gz

# Make executable and move to PATH
chmod +x mpe
sudo mv mpe /usr/local/bin/

# Verify
mpe --help

Note

The Linux build is CLI-only — no GUI, no GTK/WebKit dependencies required.

Quick Example

Create a workflow file hello.mpf (defaults to clean YAML format):

_version: 1
flow:
  uuid: example-flow
  name: Hello World
  nodes:
    - uuid: entry-1
      type: entry
      name: Start
      data:
        type: entry
    - uuid: http-1
      type: http:request
      name: Fetch Data
      data:
        type: http:request
        url: https://httpbin.org/get
        method: get
    - uuid: end-1
      type: end
      name: End
      data:
        type: end
  connections:
    - id: conn-1
      source_node_uuid: entry-1
      target_node_uuid: http-1
      source_port_id: out
      target_port_id: in
    - id: conn-2
      source_node_uuid: http-1
      target_node_uuid: end-1
      source_port_id: "true"
      target_port_id: in

Run it:

mpe run -f hello.mpf

YAML by Default with Full JSON Compatibility

Starting in v0.3.0, MPE flow files (.mpf) use YAML by default for optimal readability and Git diff clarity. The engine, CLI, desktop app, and Web Playground automatically detect and support both YAML and JSON formats. Use mpe flow fmt to convert or format files anytime.

AI Copilot & Smart Orchestration

MPE Flow features a native, deep-integrated Agentic AI Copilot designed for natural language workflow generation, autonomous execution, canvas layout optimization, and one-click error self-healing.

Privacy & Data Sovereignty

The AI Copilot connects to any OpenAI-compatible provider (OpenAI, DeepSeek, Claude, or local Ollama/vLLM instances). All workflow files, tokens, and payloads stay on your machine. No mandatory accounts or cloud telemetry.

Configuring an AI Provider

Open Settings → AI Copilot to configure one or more model providers:

  • Preset Quick-Fill: 1-click configuration for popular providers like DeepSeek, OpenAI, Claude, Kimi, and Ollama.
  • Base URL & API Key: Connect to public cloud endpoints or private self-hosted models (e.g., http://localhost:11434/v1 for Ollama).
  • Model Selection: Fetch model lists automatically or specify custom model identifiers (e.g., deepseek-chat, deepseek-reasoner, gpt-4o, claude-3-5-sonnet).
  • Custom System Prompt: Inject domain rules, naming conventions, or company-specific API guidelines applied to every request.

Interaction Modes & Shortcuts

Access the AI Copilot across three integrated surfaces:

Surface Shortcut Description
Sidebar Copilot Ctrl+I / Cmd+I Collapsible right-side chat panel with conversation history, multi-session management, and model switcher.
Detachable Floating Window Drag header or Undock button Undock the Copilot panel into a free-floating, draggable modal across multi-monitor setups. Drag back to the right to re-dock.
Spotlight Quick Commands Ctrl+K / Cmd+K Center command palette to run natural language instructions, batch pipeline commands, or layout operations without opening the sidebar.
CLI AI Bridge mpe ai "<prompt>" Execute AI commands directly from your terminal, seamlessly bridging with the running GUI or executing in headless mode.

Canvas Tools & Natural Language Generation

The Copilot does not just generate static text — it operates the visual canvas directly through strict typed tool calls:

  • Natural Language to DAG: "Create an authentication flow that sends a POST to /api/login, extracts the bearer token, and pipes it to a WebSocket connection."
  • Batch Pipeline Creation: Constructs complete multi-node flows with typed schemas and default connections in a single atomic operation.
  • Automatic Layout & Adaptive Wrapping: Cleanly arranges complex branching DAGs. Supports standard horizontal/vertical layouts as well as the new Adaptive Wrap Auto-Layout for expansive multi-branch flows.
  • Script Generation: Automatically writes JavaScript or Rhai snippets for data transformations, crypto signing, or custom assertions.
  • Datasource Exploration: Searches connected API specifications and automatically imports target endpoints onto the canvas.

Autonomous Execution ("Run to Goal") & Midway Steering

When solving complex workflows, the AI Copilot can autonomously iterate through execution cycles:

  • Auto-Execute to Goal: Enable the Auto-Execute toggle to let the Copilot run the workflow, observe execution outputs, and self-correct until the desired assertion or business goal passes.
  • Midway Steering & Interruption: While the AI is actively running tools, you can type additional instructions in the input box (e.g., "Use port 8080 instead") without cancelling the task. The Copilot absorbs your correction in real-time.
  • Thinking Chain Visibility: Full support for reasoning models (e.g. DeepSeek-R1). The stream parser extracts <think> tags and provides an interactive collapsible thinking block.
  • High-Risk Safety Confirmations: Destructive operations like clearing the canvas, deleting multiple nodes, or installing third-party marketplace plugins require explicit user approval before execution.

One-Click Error Diagnosis & Self-Healing

When a protocol node fails (HTTP 500, WebSocket handshake timeout, assertion mismatch):

  • Click AI Diagnosis & Fix directly on the failed node's error banner or in the Execution History panel.
  • The Copilot analyzes upstream inputs, output payload schemas, and underlying error chains.
  • It identifies root causes (e.g., missing Authorization header, expired token, JSONPath extraction error) and suggests a 1-click automated fix on the canvas.

Local Project Workspace Awareness

Connect your local codebase repository (via Link Workspace) to empower the AI Copilot with repository context:

  • Project Structure Scanning: Detects frameworks, OpenAPI / Swagger specs, and config files.
  • Code Search & Snippet Reading: Discovers backend route signatures, payload DTOs, and environment contracts to accurately configure node URLs and request bodies.
  • Multimodal Screenshot Upload: Paste or drag-and-drop screenshots of API documentation, Swagger UIs, or terminal error traces directly into the chat for instant visual comprehension.

CLI Commands

Command Description Example
mpe run Execute a flow file (.mpf) with optional environment and variable overrides mpe run -f flow.mpf -e staging --var TIMEOUT=5000
mpe validate Validate flow structure without executing mpe validate -f flow.mpf
mpe debug Run with debug output (NDJSON protocol) and active environment mpe debug -f flow.mpf -e dev
mpe stress Run multi-protocol stress test with environment resolution mpe stress run -f flow.mpf -e staging -u 50 -r 10
mpe env Manage global environments and local overrides (list, show, set, delete) mpe env list --format table
mpe flow Manage and format flows (list, show, create, delete, fmt) mpe flow fmt -f flow.mpf --to yaml
mpe report Manage reports (list, show, delete) mpe report list
mpe run-node Execute a single protocol node for connectivity verification mpe run-node '{"type":"redis:connect","host":"127.0.0.1","port":6379}'
mpe plugin Manage plugins (dir, list, install) mpe plugin list
mpe ai Drive or query the AI Copilot from terminal (bridges with GUI or runs headless) mpe ai "Create a login flow that extracts JWT"
mpe open Open a workflow file in the running GUI desktop app mpe open flow.mpf
# View all commands
mpe --help

# Run flow with active environment and runtime variable overrides
mpe run -f flow.mpf -e staging --var TIMEOUT=5000 --var RETRIES=3

# Manage global environments
mpe env list --format table
mpe env show staging --source merged
mpe env set staging API_BASE=https://api.staging.com --local
mpe env delete staging --local

# Format flow file or convert between YAML and JSON
mpe flow fmt ./flows/hello.mpf --to yaml
mpe flow fmt --all --to yaml

# View command-specific help
mpe run --help
mpe env --help

CI/CD Integration (GitHub Actions)

mpe run can export execution results as standard JUnit XML, which is natively understood by Jenkins, GitHub Actions, and GitLab CI. Each node in the flow becomes a <testcase>; failed and skipped nodes map to <failure> and <skipped> elements.

# Export a JUnit XML report for CI consumers with staging environment
mpe run -f flow.mpf -e staging --report-format junit --report-file results.xml
# Or print the JUnit XML directly to stdout (no --report-file)
mpe run -f flow.mpf --report-format junit

Add a workflow step in your repository to run flows and publish the report on pull requests with dorny/test-reporter:

name: Flow Tests

on:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run MPE flows
        run: |
          mpe run -f tests/flows/api-smoke.mpf --report-format junit --report-file results.xml

      - name: Publish test report
        if: always()
        uses: dorny/test-reporter@v1
        with:
          name: MPE Flow Results
          path: results.xml
          reporter: java-junit
          fail-on-error: 'true'

Note

The JUnit report reflects node-level results: assertion, HTTP, WebSocket, and other protocol nodes map to individual test cases. A failed node produces a non-zero exit code, so plain mpe run --report-format junit --report-file results.xml also fails the job by default.

Output Format

All commands output JSON to stdout:

{
  "success": true,
  "data": null,
  "error": null,
  "execution_time": 156,
  "node_reports": [
    {
      "node_uuid": "entry-001",
      "node_type": "entry",
      "node_name": "Start",
      "status": "success",
      "duration_ms": 1,
      "used_port_id": "out"
    },
    {
      "node_uuid": "http-001",
      "node_type": "http:request",
      "node_name": "Fetch Data",
      "status": "success",
      "duration_ms": 233,
      "output_data": {
        "success": true,
        "status": 200,
        "body": { ... },
        "headers": { ... }
      }
    }
  ],
  "flow_report": {
    "flow_name": "Hello World",
    "total_nodes": 3,
    "executed_count": 3,
    "status": "success",
    "duration_ms": 234
  }
}

Exit Codes

Code Meaning
0 Success
1 Failure (error details in stderr and JSON output)
2 Invalid arguments

Flow File Structure

MPE flow files use the .mpf extension and follow the FlowFile wrapper format. Flow files default to YAML format (with seamless backwards compatibility for existing JSON files):

_version: 1
flow:
  uuid: my-flow
  name: My Flow
  initial_variables:
    api_base: https://api.example.com
    token: abc123
  nodes:
    # Array of protocol and logic nodes ...
  connections:
    # Array of directed connections ...

Top-level Fields

Field Type Required Description
_version number No File format version (default: 1)
flow object Yes Flow data container

Flow Fields

Field Type Required Description
uuid string Yes Unique flow identifier
name string Yes Human-readable flow name
initial_variables object No Flow fallback variables available via {{key}} syntax. Serves as base layer in the resolution cascade.
nodes array Yes List of nodes
connections array Yes Connections between nodes

Decoupled Environment Storage

Environment definitions are no longer embedded inside .mpf flow files. Environment files are managed independently as standalone YAML files under <flows_dir>/environments/ (e.g. dev.yaml, staging.yaml, prod.yaml). Any legacy embedded environment fields in older flow files are ignored upon loading.

Node Structure

uuid: node-uuid
type: http:request
name: My HTTP Request
data:
  type: http:request
  url: https://api.example.com
  method: get
Field Type Required Description
uuid string Yes Unique node identifier
type string Yes Node type (e.g. http, entry)
name string Yes Display name
data object Yes Node configuration. Must include "type" matching the node type
on_error string No Error strategy: "route_to_false" (default), "ignore", "abort_flow"

Important: data.type Field

Every data object must include "type": "<node_type>" for Rust deserialization. The value must match the node's top-level type field.

Connections

Connections define the execution flow between nodes.

id: conn-1
source_node_uuid: entry-1
target_node_uuid: http-1
source_port_id: out
target_port_id: in
Field Description
source_node_uuid UUID of the source node
target_node_uuid UUID of the target node
source_port_id Output port: out (single output), true/false (dual output)
target_port_id Must be "in" for all nodes

Critical Port Rules

  • target_port_id must always be "in" (not "input")
  • Nodes with dual output (true/false) should have both ports connected to prevent flow termination on failure
  • entry uses out, end has no output

Port Reference

Node Type Input Output
entrynoneout
endinnone
httpintrue / false
conditionalintrue / false
scriptintrue / false
assertionintrue / false
variable:extractorinout
ws_*, tcp_*, udp_*, sse:connect/sse:listen, graphql:connect/query/subscribe/introspectintrue / false
sse:disconnect, graphql:disconnect, proxyinout

Variables

Variable Pool vs Node Output

{{var}} syntax can only access the Variable Pool. Protocol node outputs are stored separately in last_node_output and do NOT automatically become variables.

To use node output data with {{var}}, you must first extract it using a variable:extractor or script node.

Syntax

Syntax Description
{{variable_name}} Reference a variable from the pool
{{obj.field}} Access nested field with dot notation

Adding Variables to the Pool

  1. Initial variables: Define in flow.initial_variables
  2. variable:extractor: Extract from last_node_output using JSONPath
  3. script: Use fn.variables.set(name, value)
// variable:extractor example
{
  "type": "variable:extractor",
  "data": {
    "type": "variable:extractor",
    "output_mappings": [
      { "source": "$.body.id", "target": "user_id" },
      { "source": "$.status", "target": "http_status" }
    ]
  }
}

// Later use: {{user_id}}, {{http_status}}

Built-in Dynamic Variables

MPE Flow includes dynamic template variables evaluated at runtime on each step execution:

Variable Description Example Output
{{$timestamp}} Current Unix timestamp in milliseconds 1772867200123
{{$isoTimestamp}} Current UTC timestamp in ISO 8601 format 2026-09-07T12:00:00.000Z
{{$guid}} / {{$uuid}} Random UUID v4 a3f89021-4b12-42fe-b58f-287517c2f829
{{$randomInt}} Random 6-digit integer (0-999999) 482103
{{$randomAlphaNumeric}} Random 8-character alphanumeric string k9X2mQ8L

Conditional / Assertion Paths

conditional and assertion nodes read directly from last_node_output:

Node Path Format Example
conditional.field_path Plain name, {{var}}, or $.path status, $.body.id
assertion.target JSONPath with $. prefix (required) $.status, $.body.data.id

Limitations

  • Only dot notation: {{obj.field.subfield}}
  • No array indexing: {{items[0]}} — not supported
  • No function calls: {{func()}} — not supported

Global Environments & Secret Layering

MPE Flow decouples environment variables from individual workflow files. Environments are stored as standalone YAML files under <flows_dir>/environments/ (default: ~/.app/flows/environments/, or configured via MPE_ENVIRONMENTS_DIR), allowing variable sets such as dev, staging, and prod to be shared across all workflows.

Two-File Secret Architecture

Every environment supports a two-file structure designed for version control safety:

  • Shared Base File (<name>.yaml): Contains team-wide non-sensitive configuration (base URLs, service ports, retry policies). Check this into Git along with workflows.
  • Machine-Local Override (<name>.local.yaml): Merged transparently on top of the shared file on the local machine. Ideal for developer-specific credentials, tokens, and private keys. Add *.local.yaml to your .gitignore to prevent accidental secret leakage.
# <flows_dir>/environments/staging.yaml (committed to Git)
name: staging
description: Staging Environment
variables:
  API_URL: https://staging-api.example.com
  TIMEOUT_MS: 5000
  MOCK_MODE: false

# <flows_dir>/environments/staging.local.yaml (git-ignored on local machine)
name: staging
variables:
  AUTH_TOKEN: dev_secret_bearer_token_xyz987
  CLIENT_SECRET: sk_staging_99214a8f

4-Tier Variable Resolution Cascade

When executing, debugging, or stress-testing a flow, variables are resolved through a strict 4-tier cascading priority:

Priority Layer Scope & Source Typical Usage
1 (Lowest) Flow Fallback flow.initial_variables in .mpf Default baseline values so the flow remains runnable when no environment is active.
2 Shared Environment <name>.yaml in environments directory Team-wide environment endpoints, common timeouts, and feature flags.
3 Local Override <name>.local.yaml in environments directory Machine-private secrets, personal API tokens, or local proxy overrides.
4 (Highest) Runtime Override CLI --var KEY=VALUE or explicit run input One-off dynamic overrides from CI/CD jobs or automation scripts.

Variable Reference Syntax

Variables resolved from all layers are accessible directly via bare keys: {{API_URL}} or nested fields {{USER.id}}. Do NOT prefix with env. (e.g. {{env.API_URL}} is invalid and will not be found).

GUI Environment Controls

  • Sidebar Environments Panel: A resizable section in the left sidebar displaying all discovered environments, active state indicators, and quick actions (activate, rename, duplicate, delete).
  • Canvas Toolbar Selector: Switch the active environment directly from the top canvas bar without leaving your workflow.
  • Environment Manager Dialog:
    • Global Mode: Edit environment YAML directly with inline syntax highlighting, toggle local override layers, and manage secrets safely.
    • Canvas Mode: Compare flow fallback variables side-by-side against the active environment in a Cascade Comparison Matrix, visually inspecting which layer wins for every key.
  • Unified Debug & Stress Execution: Interactive single runs, step debugging (F10/F11), and high-concurrency stress tests all automatically inherit and merge the active environment.
  • Flow Export with Environment Bake: When sharing a flow with external parties, export can optionally bake active environment variables into flow.initial_variables. An integrated Credential Scanner automatically detects sensitive keywords (key, secret, token, password, auth, cred, cert, private) and prompts you to redact them before export.

Storage Configuration

The environments directory defaults to <flows_dir>/environments and can be configured through multiple methods:

  • GUI: Settings → Storage → Environments Directory (environmentsDir).
  • Environment Variable: MPE_ENVIRONMENTS_DIR=/custom/path/environments
  • Configuration File: Set storage.environments_dir in config.toml (located at $MPE_CONFIG or user data directory).

CLI Environment Management (mpe env)

Manage environments in headless CI/CD environments without opening the desktop GUI:

# List all environments with variable counts and local override flags
mpe env list --format table

# Inspect variables in an environment (merged, base, or local layer)
mpe env show staging --source merged
mpe env show staging --source base
mpe env show staging --source local

# Set variables in the shared base file
mpe env set staging API_URL=https://staging.example.com TIMEOUT_MS=6000

# Set sensitive credentials in the local private override (.local.yaml)
mpe env set staging AUTH_TOKEN=secret_token_12345 --local

# Delete a local override layer or the entire environment
mpe env delete staging --local
mpe env delete staging

Running Workflows with Environments

Pass -e, --env <NAME> to mpe run, mpe debug, or mpe stress run:

# Run flow against staging environment
mpe run -f flows/checkout.mpf -e staging

# Run with environment plus one-off runtime overrides
mpe run -f flows/checkout.mpf -e staging --var TIMEOUT_MS=10000 --var NOTIFY=true

# Run stress test against staging environment
mpe stress run -f flows/checkout.mpf -e staging -u 100 -r 15

Entry & End Nodes

Entry Node

Starting point of every flow. Exactly one required.

{
  "uuid": "entry-1",
  "type": "entry",
  "name": "Start",
  "data": { "type": "entry" }
}

End Node

Terminal node. Flow ends when reaching end.

{
  "uuid": "end-1",
  "type": "end",
  "name": "End",
  "data": { "type": "end" }
}

Subflow Node

Subflow nodes enable modular workflow reuse by embedding another workflow into the current flow. Child flows can be referenced by workspace flow ID or relative file path.

Canvas Drag & Drop

You can drag any workflow file directly from the Sidebar Flow List onto the canvas to instantly create a Subflow node pre-configured to target that flow. Double-clicking a Subflow node opens the target workflow in a new tab within the FlowTabBar without losing your active drafting or debugging context.

{
  "uuid": "subflow-1",
  "type": "flow:sub",
  "name": "User Authentication Subflow",
  "data": {
    "type": "flow:sub",
    "target_flow_id": "7b6c3d9a-1234-5678-abcd-ef0123456789",
    "target_flow_path": "./subflows/auth.mpf",
    "inherit_all_variables": true,
    "variable_mappings": [
      { "source": "parent_username", "target": "login_user" },
      { "source": "parent_password", "target": "login_pass" }
    ],
    "export_all_variables": true,
    "output_mappings": [
      { "source": "access_token", "target": "auth_token" }
    ]
  }
}

Configuration Fields

Field Type Default Description
target_flow_idstring (optional)nullUUID of a saved workflow in the workspace (used in GUI mode).
target_flow_pathstring (optional)nullRelative or absolute file path to a .mpf, .yaml, or .json workflow file (portable & CLI mode).
inherit_all_variablesbooleantrueWhether the child subflow automatically inherits all parent scope variables.
variable_mappingsarray[]Explicit input parameter mappings (source expression/variable → target child variable). Overrides inherited variables.
export_all_variablesbooleantrueWhether child workflow output variables are exported back into parent workflow scope after execution completes.
output_mappingsarray[]Explicit return variable mappings (source child variable → target parent variable). Used when selective export is desired.

Cycle Detection & Safety

MPE Flow's DAG compiler validates subflow references before execution. Self-references and circular dependencies (A → B → A) are detected during pre-flight validation and rejected with descriptive error reports, preventing infinite recursion.

Nested Execution Reports

When a subflow executes, its child node execution metrics, step statuses, and duration are preserved in a hierarchical execution report tree viewable in the Execution History panel.

HTTP Node

Send HTTP requests. Supports GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.

{
  "uuid": "http-1",
  "type": "http:request",
  "name": "API Call",
  "data": {
    "type": "http:request",
    "url": "{{api_base}}/users",
    "method": "post",
    "headers": {
      "Authorization": "Bearer {{token}}"
    },
    "body_type": "body",
    "content_type": "json",
    "body": "{\"name\": \"test\"}",
    "timeout_ms": 30000
  }
}

Core Fields

Field Type Default Description
url string — Request URL (supports {{var}})
method string get HTTP method
headers object {} Request headers
body_type string none none / body / form-data / x-www-form-urlencoded / binary
content_type string json json / text / html / xml
timeout_ms number 30000 Timeout (1000–300000ms)

HTTP Output

{
  "success": true,
  "status": 200,
  "body": { "id": 1, "name": "test" },
  "headers": { "content-type": "application/json" },
  "timing": { "connect_ms": 45, "total_ms": 150 }
}

Conditional Node

Branch execution based on conditions. Routes to true or false port.

Simple Condition

{
  "uuid": "cond-1",
  "type": "conditional",
  "name": "Check Status",
  "data": {
    "type": "conditional",
    "condition_type": "simple",
    "field_path": "status",
    "operator": "equal",
    "expected_value": 200
  }
}

Advanced Expression

{
  "data": {
    "type": "conditional",
    "condition_type": "advanced",
    "advanced_expression": "status >= 200 && status < 300"
  }
}

Operators

Operator Description
equalEquals
not_equalNot equals
greaterGreater than
greater_or_equalGreater or equal
lessLess than
less_or_equalLess or equal
containsContains substring
starts_withStarts with
ends_withEnds with
existsField exists

Script Node

Execute JavaScript code in a QuickJS runtime (ES2020 subset).

{
  "uuid": "script-1",
  "type": "script",
  "name": "Process Data",
  "data": {
    "type": "script",
    "script": "const data = JSON.parse(fn.response.raw); fn.variables.set('user_id', data.body.id);",
    "timeout_ms": 5000
  }
}

Script API

API Description
fn.variables.get(name)Read variable from pool
fn.variables.set(name, value)Write variable to pool
fn.response.rawFull upstream node output (JSON string)
fn.response.codeHTTP status code (HTTP nodes only)
fn.console.log(msg)Log to execution output
fn.flow.stop(reason)Stop flow execution
fn.util.encodeBase64(str)Base64 encode
fn.util.md5(str)MD5 hash
fn.util.sha256(str)SHA-256 hash
fn.util.uuid()Generate UUID v4
fn.util.sleep(ms)Pause execution

Assertion Node

Validate conditions with detailed pass/fail reporting.

{
  "uuid": "assert-1",
  "type": "assertion",
  "name": "Validate Response",
  "data": {
    "type": "assertion",
    "mode": "all",
    "assertions": [
      { "id": "a1", "description": "Status is 200", "target": "$.status", "operator": "eq", "expected": 200 },
      { "id": "a2", "description": "Has data", "target": "$.body.data", "operator": "exists" }
    ]
  }
}

Assertion Operators

Category Operators
Comparisoneq, ne
Numericgt, gte, lt, lte
Stringcontains, not_contains, matches
Existenceexists, not_exists
Collectionin, not_in
Typetype_is
Rangebetween

Target Path Format

Assertion target must use JSONPath with $. prefix (e.g. $.status, $.body.id). Do not add body. prefix for non-HTTP nodes.

WebSocket Nodes

Three nodes for WebSocket communication: connect, send/collect, close.

// Connect
{ "type": "ws:connect", "data": { "type": "ws:connect", "url": "wss://echo.example.com/ws" } }

// Send and collect response
{ "type": "ws:send_collect", "data": {
    "type": "ws:send_collect",
    "connection_id": "ws-connect-uuid",
    "message": "{\"type\":\"ping\"}",
    "collect_timeout_ms": 10000
  }
}

// Close
{ "type": "ws:close", "data": { "type": "ws:close", "connection_id": "ws-connect-uuid" } }

Other Protocols

TCP

{ "type": "tcp:connect", "data": { "type": "tcp:connect", "host": "localhost", "port": 8080 } }
{ "type": "tcp:send", "data": { "type": "tcp:send", "connection_id": "uuid", "data": "Hello" } }
{ "type": "tcp:receive", "data": { "type": "tcp:receive", "connection_id": "uuid" } }
{ "type": "tcp:close", "data": { "type": "tcp:close", "connection_id": "uuid" } }

UDP

{ "type": "udp:bind", "data": { "type": "udp:bind", "local_addr": "0.0.0.0", "local_port": 8888 } }
{ "type": "udp:send_to", "data": { "type": "udp:send_to", "connection_id": "uuid", "data": "Hello", "target_addr": "192.168.1.100", "target_port": 9999 } }
{ "type": "udp:recv_from", "data": { "type": "udp:recv_from", "connection_id": "uuid" } }
{ "type": "udp:close", "data": { "type": "udp:close", "connection_id": "uuid" } }

SSE (Server-Sent Events)

{ "type": "sse:connect", "data": { "type": "sse:connect", "url": "https://api.example.com/events" } }
{ "type": "sse:listen", "data": { "type": "sse:listen", "connection_id": "uuid", "max_events": 100 } }
{ "type": "sse:disconnect", "data": { "type": "sse:disconnect", "connection_id": "uuid" } }

GraphQL

{ "type": "graphql:connect", "data": { "type": "graphql:connect", "endpoint": "https://api.example.com/graphql" } }
{ "type": "graphql:query", "data": { "type": "graphql:query", "connection_id": "uuid", "query": "query { users { id name } }" } }
{ "type": "graphql:subscribe", "data": { "type": "graphql:subscribe", "connection_id": "uuid", "query": "subscription { newUser { id } }" } }
{ "type": "graphql:introspect", "data": { "type": "graphql:introspect", "connection_id": "uuid" } }
{ "type": "graphql:disconnect", "data": { "type": "graphql:disconnect", "connection_id": "uuid" } }

Plugin Protocols

More protocols (Redis, MySQL/PostgreSQL, MongoDB, SMTP, gRPC, MCP) are available as installable plugins — see Plugin Development below.

Visual Debugging & Controls

MPE Flow provides an interactive visual step debugger built into both the desktop canvas and CLI. You can pause workflow execution, inspect node inputs/outputs, modify variable pools in flight, and bypass flaky endpoints.

Breakpoints

Click the red breakpoint dot on any canvas node to toggle a breakpoint. When debugging starts, execution proceeds until a breakpoint node is reached, pausing execution before the node runs.

Debug Actions & Global Shortcuts

Action Shortcut Description
ContinueF5 / ResumeResume execution until the next breakpoint or workflow completion.
Step OverF10Execute the current node and pause at the immediate next node. For Subflow nodes, runs the child flow completely.
Step IntoF11Step inside a flow:sub node to pause at its first internal node. On regular nodes, behaves as Step Over.
Step OutShift + F11Execute the remainder of the current subflow and pause at the successor node in the parent flow.
Skip Node—Bypass current node execution. Choose an active output branch (e.g. true / false) and supply mock output data.
Run to End—Ignore all remaining breakpoints and finish the workflow execution.
Stop Debugging—Terminate the debug session and generate a partial execution report.

Subflow Stepping & Call Stack Tracking

When orchestrating complex nested workflows, MPE Flow's debugger supports multi-level call frame tracking (DebugCallFrame) with hierarchical stepping.

Stepping into Subflows

When execution pauses at a Subflow node:

  • Press Step Into (F11): The canvas seamlessly switches context to the child workflow, highlighting its entry step with a paused indicator.
  • Press Step Over (F10): If you prefer treating the subflow as an atomic black box, Step Over runs the entire child flow and pauses at the parent flow's next node.
  • Press Step Out (Shift + F11): If you are deep inside a subflow and have inspected the critical logic, Step Out completes the remaining child nodes and returns control to the parent caller.

Hierarchical Call Stack Navigation

The Execution Stack panel displays a live call frame hierarchy during nested subflow debugging:

#0 Root Flow (Order Ingestion) → Subflow Node: Process Payment
  #1 Process Payment (Payment Pipeline) → Subflow Node: Auth Token
    #2 Auth Token (OAuth2 Refresh) → HTTP Request: /oauth/v2/token [PAUSED]

Clicking any parent frame in the stack navigates the canvas to that frame's workflow and displays its local variable pool snapshot, allowing you to inspect parent and child state simultaneously.

Plugin Overview

Plugins extend MPE Flow with new protocol node types. A plugin runs as a sidecar process that communicates with the host over stdio using JSON-RPC 2.0 — one JSON message per line (LF-delimited, CRLF tolerated). At startup the host spawns each plugin process and performs a describe handshake, registering the declared node types into the shared NodeRegistry. Plugin nodes behave identically to built-in nodes in flows, the executor, and execution reports.

Installation

Place a plugin directory containing a plugin.json manifest into the plugin directory (default get_data_dir()/plugins; %APPDATA%/multi-protocol-flow-executor/plugins on Windows; override with the MPE_PLUGIN_DIR environment variable). The host scans synchronously at startup: invalid manifests are skipped without crashing, and a plugin whose describe fails 3 consecutive times is quarantined for the host's lifetime.

plugin.json Fields

Field Description
namePlugin name (convention: directory name)
versionSemantic version
descriptionHuman-readable description
min_host_versionOptional version gate for host compatibility
entrycommand + args used to launch the plugin; interpreter plugins are first-class citizens (e.g. "python" + ["plugin.py"])
envEnvironment variables injected into the plugin process
permissionsReserved; ignored in P0
capabilities.streamingtrue = resident process; false = spawned on demand and recycled after 60s idle
capabilities.single_nodeNode-level capability; true = runnable standalone via mpe run-node for connectivity verification
locales / default_localeUI language declarations; the host injects the active locale via MPE_LOCALE

Protocol Plugins in This Repository

The plugins/ directory ships protocol plugins for: amqp, db (SQLite/MySQL/PostgreSQL), grpc, imap, kafka, mcp, mongo, mqtt, redis, smtp. Install by building a plugin and placing its directory into the plugin directory, or install from the Plugins page.

SDK & Development

The SDK and wire contract live in the standalone public repository multi-protocol-flow/mpe-plugin-sdk. The Rust SDK is first-class; lightweight Python and Node templates are also provided. Wire types are shared from mpe-plugin-sdk::protocol, so host and plugin never drift.

Development Flow

  1. Clone the SDK repository
  2. Implement the Plugin trait (describe + execute; optional flow_ended to release per-execution resources)
  3. Build the sidecar binary
  4. Place it into the plugin directory

Reference Docs

  • SDK repository: docs/plugin-guide.md (EN) / docs/plugin-guide.zh-CN.md (中文) and docs/plugin-protocol.md
  • Host repository: docs/plugin-architecture.md, docs/plugin-perf.md (visible under the multi-protocol-flow GitHub organization)

Marketplace

Plugins can be installed from the GUI settings panel's Plugin Market tab, or from the CLI:

mpe plugin dir
mpe plugin list
mpe plugin install <name> [--version <v>] [--registry <url>] [--dir <dir>] [--force]

Registry Contract

  • GET {base}/plugins returns the plugin list; each entry has a platform asset (zip) url and an optional sha256 — when provided the host enforces checksum validation and refuses mismatched installs.
  • Platform keys: windows-x64 | windows-arm64 | linux-x64 | linux-arm64 | macos-x64 | macos-arm64.
  • The zip root must contain a single top-level directory named after the plugin, holding plugin.json and the plugin files.

The registry base URL is configured via the MPE_PLUGIN_REGISTRY environment variable or the --registry flag. The public registry is served from GitHub Pages (multi-protocol-flow.github.io/mpe-plugin-registry) as a static JSON implementing this contract — browse and install plugins on the Plugins page.