Headless and MCP
To use PubSub over MQTT without the GUI, run the headless simulator pdcomm-opcua-headless or the MCP server pdcomm-opcua-mcp.
Both are in bin/ of the simulator package and run the same simulator service as the GUI.
Running the headless simulator
Section titled “Running the headless simulator”| Command | Behavior |
|---|---|
bin/pdcomm-opcua-headless |
Reads one JSON command per line from standard input and writes one result line per command to standard output. Exits at the end of input or on shutdown. |
bin/pdcomm-opcua-headless --scenario <file> |
Runs the steps of a scenario file in order and prints one result line per step. |
Interactive replies look like {"ok":true,"result":…} or {"ok":false,"error":"…"}.
The exit code is 1 if any command failed or any line couldn’t be parsed, and 0 otherwise.
A command line can’t be longer than 1 MiB.
A scenario file is an array of steps in this format; the file can be up to 1 MiB with up to 10,000 steps:
| Key | Meaning |
|---|---|
command |
The command object to run, the same as an interactive command. |
expect |
Optional. Values that must be equal in the result object. |
expect_error |
When true, the step passes only if the command fails; its result line is {"error":"…"}. |
Output lines look like {"step":1,"result":…}. When a step doesn’t meet its expectation, the simulator writes a message such as Scenario step 2 failed: … to standard error and exits with code 1. Invalid arguments print the usage and exit with code 2.
PubSub commands
Section titled “PubSub commands”| Command | Arguments | Result |
|---|---|---|
configure |
config: the whole configuration object |
The current state (same as state) |
pubsub_start |
None | The PubSub status |
pubsub_publish |
fields: an array of 1 to 64 typed values. Without it: Boolean true, Int32 42, Double 3.5, String pdcomm |
sequence, bytes, fields |
pubsub_status |
None | The PubSub status, or {"running":false} when PubSub isn’t running |
pubsub_received |
None | messages: the received messages; they’re removed from the queue |
pubsub_stop |
None | {"running":false} |
state |
None | The configuration and the server, client and PubSub status |
capabilities |
None | Supported features, including "pubsub":{"encoding":"uadp","mqtt":true,"udp":true} |
trace |
None | The recent action log |
shutdown |
None | Closes every connection and ends the headless simulator (interactive mode only) |
Field type names are the same as for DataSet fields in The simulator PubSub tab.
The pubsub section of the configuration
Section titled “The pubsub section of the configuration”| Key | Meaning | Default |
|---|---|---|
transport |
mqtt or udp |
udp |
role |
both, publisher or subscriber |
both |
broker |
The broker’s IP address:port |
127.0.0.1:1883 |
topic |
The topic to publish to and subscribe to; no wildcards, 1 to 256 bytes | pdcomm/opcua/simulator |
publisher_id |
The PublisherId of NetworkMessages (1 to 65535) | 77 |
writer_group_id |
The WriterGroupId (1 to 65535) | 1 |
dataset_writer_id |
The DataSetWriterId (1 to 65535) | 17 |
listen, destination |
UDP only |
The broker connect timeout is client.timeout_ms (5000 by default).
PubSub status values
Section titled “PubSub status values”| Key | Meaning |
|---|---|
running |
Whether the worker thread runs; it turns false when the broker connection drops. |
transport, role |
The transport and role at start |
broker, topic |
With MQTT, the broker and topic in use; null with UDP |
listen, destination |
With UDP, the addresses in use; null with MQTT |
sent |
Messages published |
acknowledged |
Publications the broker confirmed with a successful PUBACK |
received |
Messages accepted by the subscriber |
rejected |
Messages received but rejected |
queued |
Messages not yet taken with pubsub_received (at most 256) |
dropped |
Messages dropped because the queue was full |
error |
The last error, or null |
The MCP server
Section titled “The MCP server”pdcomm-opcua-mcp is an MCP (Model Context Protocol) server that speaks JSON-RPC over standard input and output.
Register the executable in your MCP client’s configuration:
{ "mcpServers": { "pdcomm-opcua": { "command": "<simulator package directory>/bin/pdcomm-opcua-mcp" } }}- The server is named
pdcomm-opcuaand supports protocol versions2025-11-25,2025-06-18and2024-11-05. - Each tool is a headless command with an
opcua_prefix. The PubSub tools areopcua_pubsub_start,opcua_pubsub_publish,opcua_pubsub_status,opcua_pubsub_receivedandopcua_pubsub_stop. - Tool arguments are the headless command object without
action. - A result is a text content item that holds one JSON string. On failure,
isErroristrueand the text is the error message.
This is a PubSub over MQTT session through MCP; the table shows only the text content of each response:
| Tool call | Result text |
|---|---|
opcua_configure {"config":{"pubsub":{"transport":"mqtt","role":"both","broker":"127.0.0.1:1883","topic":"opcua/uadp/data/77/mcp"}}} |
The current state |
opcua_pubsub_start {} |
{"acknowledged":0,"broker":"127.0.0.1:1883",…,"running":true,…,"topic":"opcua/uadp/data/77/mcp","transport":"mqtt"} |
opcua_pubsub_publish {"fields":[{"type":"Int32","value":7}]} |
{"bytes":38,"fields":1,"sequence":1} |
opcua_pubsub_received {} |
{"messages":[{"bytes":38,"datasets":[{"fields":[{"type":"Int32","value":7}],…}],"publisher_id":77,"source":"mqtt",…}]} |
opcua_pubsub_stop {} |
{"running":false} |
opcua_pubsub_stop {} (again) |
isError: true, PubSub is not running |
To let AI tools search the PDComm docs as well, see Use the docs from AI tools.