The connector serves a Model Context Protocol endpoint at
/mcp. An AI agent (Claude Code, Claude Desktop, Cursor, omp, …) connects to it and can do
what you do in the dashboard: look at the connector’s health, build and edit the flow, dry-run
every source, deploy, watch live data, and check printers, push delivery and the license. It is
meant for commissioning: build and verify a configuration with an agent, then ship it to the
client.
It is part of the default build (the mcp feature) and uses the same HTTP listener as the API
(bind_addr:health_check_port, default 127.0.0.1:3000).
Enable, disable, restrict
connector:
mcp:
enabled: true # default; false removes /mcp entirely
read_only: false # true hides every tool that changes anythingenabled: falsemakes/mcpanswer 404. A build without themcpfeature has no endpoint.read_only: trueremoves the mutating tools from the tool list (and refuses calls to them). The agent can still inspect, validate scripts and flows, and dry-runtest_flowwith a flow it passes in. Use it on a client’s production connector.
Connecting
/mcp is behind the same credentials and Host/Origin checks as /api/*
(see Security); the legacy api_token (admin) or a named API token opens both. Find the legacy
token in connector.api_token, the OPEX_API_TOKEN environment variable, or <data_dir>/api_token when it was
generated. The transport is MCP streamable HTTP: send Authorization: Bearer <token> on every request.
Claude Code
claude mcp add --transport http opex-flow http://127.0.0.1:3000/mcp \
--header "Authorization: Bearer $OPEX_API_TOKEN"Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"opex-flow": {
"url": "http://127.0.0.1:3000/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}omp (~/.omp/agent/mcp.json, or .omp/mcp.json in a project)
{
"mcpServers": {
"opex-flow": {
"type": "http",
"url": "http://127.0.0.1:3000/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}Claude Desktop (claude_desktop_config.json; it reaches remote servers through the
mcp-remote bridge)
{
"mcpServers": {
"opex-flow": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://127.0.0.1:3000/mcp",
"--header", "Authorization:${OPEX_AUTH}"],
"env": { "OPEX_AUTH": "Bearer <token>" }
}
}
}A connector on another machine: use its address in the URL. With the default loopback bind, open an
SSH tunnel (ssh -L 3000:127.0.0.1:3000 user@host) rather than exposing the port; see
Deployment.
How an agent works with it
get_status: is the connector healthy, adapters connected, flow warnings,unroutedcount?get_flow {summary: true},get_help,read_docs: learn what exists and what fields a node needs.- Stage changes with
upsert_nodes,connect,remove_nodes,create_flow_tab. These edit a private draft that belongs to the MCP session; nothing is live until you deploy it. Each reply shows the draft’s diff against the live flow and a validation summary. validate_flow(the draft, else the live flow), thentest_flowonce per source: a dry run that really executes the scripts but records sink deliveries, HTTP calls and printer jobs instead of performing them.deploy_draft: validates and compiles every source, savesflow.jsonand swaps all pipelines in one step. It is refused with a version conflict if the live flow changed since the draft was started (discard_draftand redo).- Verify with
get_node_stats(counters per node),watch_debug(what nodes saw, for up to 30 s) orsend_ingest ... capture_debug: true(one real record with its per-node events).
Node positions (x, y) can be omitted: they are laid out when the flow is deployed.
The server sends the agent this workflow as its instructions, and offers a prompt,
commission_checklist, that walks a pre-client-deploy verification: sources connected, every source
routed, no warnings, a dry run per source, printers reachable and a confirmed test print, push
delivering, license valid, data directory backed up.
Tools
Every tool has a description written for the model, a JSON-schema input, and MCP annotations
(readOnlyHint, destructiveHint, idempotentHint, openWorldHint). Failures come back as tool
errors with the reason (a rejected deploy includes the validation findings). Results over about
48 KB are shortened and carry truncated: true.
| Group | Tools | Changes things? |
|---|---|---|
| Overview | get_status, get_config (secrets redacted), list_secrets (names only, admin), get_help, read_docs |
no |
| Sources | list_sources, last_record |
no |
add_source, remove_source |
yes (persisted) | |
inject_source |
real run | |
| Flow | get_flow, validate_flow, test_flow (dry run), get_node_stats, watch_debug |
no |
deploy_flow (full document + if_version) |
replaces the live flow | |
| Draft | get_draft |
no |
upsert_nodes, remove_nodes, connect, disconnect, create_flow_tab, discard_draft |
draft only | |
deploy_draft |
replaces the live flow | |
| Ingest | send_ingest |
real run, may print |
| Printers | list_printers, get_printer, list_printer_lines, printer_jobs, printer_status |
no (printer_status asks the device) |
upsert_printer, remove_printer, import_printers (dry_run defaults to true) |
yes (persisted) | |
run_printer_job |
physically prints | |
| Monitoring | get_sla_health (per flow / per external system, SLA state), get_monthly_report (json, html or csv), siem_status, get_published_openapi (OpenAPI 3.1 of every exposed interface; filter with path_prefix / tag) |
no |
| Diagnostics | list_traces, get_trace, pipeline_dead_letters, get_dead_letter, dead_letter_audit, push_dead_letters |
no |
edit_dead_letter |
yes (stores a correction beside the original; audited) | |
replay_dead_letter, replay_dead_letters |
re-runs records through the flow (real posts / prints; audited) | |
discard_dead_letter, discard_dead_letters |
yes (the record is not processed; audited) | |
replay_push_dead |
re-sends to the cloud | |
| Reconciliation | list_reconcile_reports, get_reconcile_report (csv: true for the CSV text), ledger_tally |
no |
| Exception cases | list_cases, get_case, case_summary |
no |
assign_case, comment_case, set_case_status, link_case, bulk_update_cases |
yes (case history and audit log; see Finance controls) | |
| Approvals | list_approvals, get_approval, posting_status |
no |
approve_approval, reject_approval, resume_approval |
releases or stops a parked record (needs the approve node’s role; audited) | |
request_go_live, approve_go_live, reject_go_live |
approve_go_live switches a posting node to live (second approver only; audited) |
|
| Events | list_event_types, get_event_type, validate_event_record, export_asyncapi, event_log |
no |
upsert_event_type |
yes (writes events/<name>.json) |
|
| Lookups | list_lookup_tables, get_lookup_entries, resolve_lookup |
no |
upsert_lookup_table, upsert_lookup_entries, delete_lookup_entries, import_lookup_csv (dry_run defaults to true) |
yes (persisted, applies to running flows at once) | |
| Apps | list_apps, get_app |
no |
upsert_app (validated; 422 with errors:[{path,message}]), publish_app |
yes (changes the draft / the app users run; audited; see Apps) | |
| Versions | list_versions, get_version, diff_versions |
no |
rollback (redeploys version N as a new version; allowed in a protected environment; audited flow.rollback) |
yes | |
| License | license_status |
no |
| Scripts | validate_script (JS or DSL) |
no |
Tools are the same code as the matching REST endpoints (REST API): get_flow is
GET /api/flow, deploy_flow is PUT /api/flow, send_ingest is POST /api/ingest/{source}/{id}
and so on, so behaviour, validation and limits cannot differ.
Resources and prompts
| URI / name | Content |
|---|---|
opexflow://flow |
The deployed flow document (JSON). |
opexflow://docs/<page> |
Any page of this documentation as markdown (opexflow://docs/printers, …). |
prompt commission_checklist |
The pre-client-deploy checklist. |
get_help serves the same text as the dashboard’s help cards: one registry,
apps/ui/src/help/registry.json, embedded in the binary.
Safety
- Give each agent its own named token with the least role it needs. The legacy
api_tokenis an admin: as powerful as the dashboard’s administrator. Createopx_...tokens in Admin → Access (see Security): aviewertoken can read everything and stage drafts; anoperatortoken can also replay dead letters, inject and print; aneditortoken can deploy and edit printers, sources, the catalogue and lookups;adminis only forget_configandlist_secrets. Keep the default loopback bind, or put the connector behind a firewall or reverse proxy; do not expose/mcpto the internet. - Roles are enforced per tool from the same table as the REST routes:
tools/listonly offers the tools the token’s role may call, a call above the role is refused (required_rolein the error), and every state-changing call (deploys, sources, printers, dead letters, catalogue, lookups) is written to the audit log under the token’s name withvia: mcp. Dead-letter audit trails name the token too; the oldactortool argument no longer exists. - Destructive tools act for real:
deploy_flow,deploy_draft,send_ingest,inject_source,run_printer_job,upsert_printer,remove_printer,import_printers(withdry_run: false),remove_source,replay_push_dead,replay_dead_letter,replay_dead_letters,discard_dead_letter,discard_dead_letters. Their annotations say so; let your client ask for approval rather than auto-approving them, and prefertest_flowoversend_ingest. - A client’s production connector: set
connector.mcp.read_only: true, orenabled: false. - Drafts live in memory per MCP session and expire after 8 hours idle; a restart forgets them. The
deployed flow is always the saved
flow.json. A client that uses the sessionless protocol revision has no session id and shares one draft with every other such client;deploy_draftstill refuses a stale draft, so two agents cannot silently overwrite each other. - Nothing secret is returned:
get_configredacts,license_statusshows only the last four characters of the key. - Calls are logged at info level (
mcp tool call, tool name, outcome, duration; not arguments).