External harnesses
An external harness starts or observes a registered Workflow App and services its durable suspensions. It does not replace the Workflow App and it does not create a second workflow engine.
Construct the Workflow App MCP provider
There is no separate workflowAppMcp() wrapper. The existing public adapter is
createWorkflowControlPlaneMcpProvider():
Install the MCP SDK optional peer when using this integration surface:
bun add @dromio/workflow@^0.2.5 @modelcontextprotocol/sdk@^1.29.0
import { createWorkflowAppHost } from "@dromio/workflow";
import { createWorkflowControlPlaneMcpProvider } from
"@dromio/workflow/workflow-control-plane/mcp";
const host = await createWorkflowAppHost(app, {
storage: {kind: "sqlite", path: "./workflow-runs.sqlite"},
});
const mcp = createWorkflowControlPlaneMcpProvider({
controlPlane: host.controlPlane,
toolPrefix: "dromio",
});
Connect over stdio
await mcp.serveStdio();
Point Codex, Claude, OpenCode, or your own MCP client at the command that starts
that module. The harness discovers registered workflows and triggers with
dromio.list_workflows and dromio.list_triggers.
Connect over Streamable HTTP
The provider exposes a Web-standard fetch() handler:
Bun.serve({
port: 4319,
fetch: request => mcp.fetch(request),
});
Configure the harness endpoint as http://127.0.0.1:4319/mcp. Use bearer-token
environment references for remote or shared endpoints; never place a secret in
source control.
Service a delegated step
- Start the workflow through a trigger.
- Read the waiting run and its
handoff_requestedhook. - Perform the instructions using only the selected context and declared capabilities.
- Call
dromio.resume_hookwith the hook token and structured value. - If validation fails, correct the value and retry the same token.
Required capabilities are enforced before a hook token is consumed. Preferred capabilities permit an explicit fallback; the capabilities actually used are recorded with the resumed hook.
Questions use dromio.answer_question. Approval and other generic hooks resume
through dromio.resume_hook. A harness does not need a model router merely to
forward a human interaction.
Embedded MCP App UI
Run-producing tools advertise ui://dromio/workflow-run with the standard
text/html;profile=mcp-app media type. A compatible chat host renders the run
timeline, state, artifacts, questions, approvals, and delegated handoffs inline.
The UI calls the same MCP tools for refresh and resume. Hosts without MCP Apps
support continue to receive useful text plus structuredContent.
The embedded UI is a projection, not a runtime. It reads the registered graph
and the durable run snapshot from dromio.get_run. Approve, reject, answer,
and resume actions call the public MCP tools; the host's permission policy is
still authoritative.
Connect Shimex.app
Shimex.app is the interactive harness. shimex exec is only a one-shot model
prompt and does not service workflow suspensions.
Configure either a local command or Streamable HTTP endpoint in Shimex's Codex MCP profile. For a local HTTP server:
codex:
mcp_servers:
- id: dromio-workflow
enabled: true
required: false
url: http://127.0.0.1:4319/mcp
After Shimex regenerates its Codex profile, choose any configured model—such as DeepSeek or Kimi—and ask it to list Dromio workflows, fire a published trigger, inspect its job and run, and service every pending interaction. The model is the inference provider; Shimex/Codex is the harness; Dromio remains the workflow engine. Changing models must not require changing the workflow definition.
Complete harness lifecycle
Retry the same delegation token after validation errors. Transport retries may
repeat a consumed token safely, but an unknown token remains an error. After a
process restart, get_run returns the persisted graph state and pending token;
completed steps are not replayed.
Build a custom harness
A custom harness needs only an MCP client and this loop:
Keep inference, browser state, subagents, and approval policy inside the harness. Keep checkpoints, token consumption, validation, and routing inside Dromio.