Kepware MQTT publishing is one of the quickest ways to move data from a plant full of mixed PLCs into the cloud, because Kepware already speaks the drivers and its IoT Gateway feature adds an MQTT client on top. In this tutorial you will configure the Kepware MQTT Client agent to publish tags to a cloud broker over TLS, choose and shape the JSON payload, add a Last Will, verify the data, and optionally split the agent's batched messages into a clean per-tag topic tree.
How the Kepware MQTT Agent Works
Kepware (KEPServerEX and its successor Kepware Server) is an industrial connectivity server with drivers for hundreds of PLC and device protocols. Its IoT Gateway plug-in adds agents that push tag data to external systems. The MQTT Client agent is one of them: it connects to a broker as an ordinary MQTT client and publishes tag values as JSON.
The model is simple:
- Channels and devices poll your PLCs through Kepware drivers, as they already do for SCADA.
- An MQTT Client agent holds the broker connection, publish settings and payload format.
- IoT items are the tags you add to that agent, each with its own scan rate and change behaviour.
- On each publish cycle the agent sends a JSON message to its topic containing the values that are due.
Because the agent makes an outbound connection, you do not open inbound ports to the Kepware machine. That is a big part of why this pattern is popular for getting OT data to a cloud MQTT broker. Exact labels and defaults vary slightly between Kepware versions, so treat the field names below as a guide and check your version's help file if something looks different.
Before You Start
- Kepware with the IoT Gateway feature licensed and installed.
- At least one channel and device already returning good-quality tags. Check this in the Quick Client first.
- Broker connection details. For a first test, use the public MQTT test broker with non-sensitive tags only. For production, create a private broker and note its username, password and client ID.
- Outbound access from the Kepware host to TCP 8883 (TLS) on the broker.
Step 1: Create the MQTT Client Agent
In the Kepware configuration tool, expand IoT Gateway, right-click and add a new agent, and select MQTT Client as the type. The wizard asks for the core settings:
| Setting | Value for ConnectMQ | Notes |
|---|---|---|
| Name | ConnectMQ_Cloud |
Any descriptive name |
| URL | ssl://broker.connectmq.com:8883 |
Use ssl:// for TLS; tcp://...:1883 only for quick public tests |
| Topic | connectmq/demo/k7q2/plant1/kepware |
For production, use your own hierarchy, such as acme/plant1/kepware |
| QoS | 1 | The free Serverless plan supports QoS 0 and 1; QoS 2 needs a paid plan |
| Rate | 1000 ms | How often the agent publishes pending updates |
| Format | Standard (JSON) | Switch to Advanced later to customise the payload |
| Max events per publish | Default | Caps how many tag updates go into one message |
Then open the agent's security or client settings and fill in:
- Client ID: for the public broker, any unique, non-empty value such as
kepware-k7q2. For a private broker, the exact client ID issued with your credentials; client IDs are bound to those credentials. - Username and password: blank for the public broker;
YOUR_USERNAMEandYOUR_PASSWORDfor a private one. - TLS version: TLS 1.2 or later.
The broker presents a publicly trusted Let's Encrypt certificate, so you normally do not need to import a CA certificate. If your organisation inspects TLS traffic with a proxy, the Kepware host must trust that proxy's certificate instead.
Step 2: Add a Last Will
Configure the agent's Last Will so consumers can tell when Kepware disappears:
- Topic:
connectmq/demo/k7q2/plant1/kepware/status - Message:
offline
When the agent drops unexpectedly, the broker publishes this on its behalf. Pair it with a dashboard rule that greys out values whenever the status reads offline.
Step 3: Add IoT Items
Right-click the agent and add IoT items, browsing to the tags you want. For each item, set:
- Scan rate: how often Kepware samples the tag for this agent. Match it to how fast the value really changes; one to five seconds suits most process values.
- Publish every scan vs on data change: prefer data change for states and slow analog values. This is Kepware's built-in report by exception, explained in our report by exception guide.
- Deadband: for noisy analog values, a deadband suppresses changes smaller than a threshold.
Start with a handful of tags, confirm the end-to-end flow, then add the rest.
Step 4: Verify the Data
Subscribe from any machine with the Mosquitto client:
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-i kepware-viewer-k7q2 -t "connectmq/demo/k7q2/#" -v
With the Standard format, each message on the agent topic looks like this:
{
"timestamp": 1792137600000,
"values": [
{ "id": "Line1.Filler.Speed", "v": 118.4, "q": true, "t": 1792137599950 },
{ "id": "Line1.Filler.Running", "v": true, "q": true, "t": 1792137599950 },
{ "id": "Line1.Filler.GoodCount", "v": 48211, "q": true, "t": 1792137599950 }
]
}
id is the full Kepware tag path, v the value, q whether quality is good, and t the tag timestamp in milliseconds since the epoch. On a private ConnectMQ broker, the portal's in-browser MQTT client and live topic explorer show the same messages without installing anything.
Step 5: Shape the Payload with an Advanced Template
The Advanced format lets you write a template with placeholders that Kepware fills in. A template that renames fields to something friendlier for downstream code looks like this:
{
"source": "kepware-plant1",
"sent": |SERVERTIMESTAMP|,
"tags": [
|#each VALUES|
{ "name": "|TAGNAME|", "value": |VALUE|, "good": |QUALITY|, "ts": |TIMESTAMP| }|#unless @last|,|/unless|
|/each|
]
}
Keep the template valid JSON for every combination of values, including when only one tag changed. Test it by watching messages while you toggle tags in the PLC simulator or Quick Client.
Step 6: Fan Out to a Per-Tag Topic Tree
The agent publishes batches to one topic. That is efficient, but many consumers prefer one topic per value in an ISA-95 hierarchy, which is also what makes a Unified Namespace navigable. A small republisher can do the split. It runs anywhere, connects to the broker as a normal client and maps Kepware tag paths to topics:
# kepware_fanout.py - split Kepware Standard-format batches into per-tag topics
import json, uuid
import paho.mqtt.client as mqtt
ROOT = "connectmq/demo/k7q2/plant1"
SOURCE = f"{ROOT}/kepware"
def to_topic(tag_id: str) -> str:
# "Line1.Filler.Speed" -> "connectmq/demo/k7q2/plant1/line1/filler/speed"
return f"{ROOT}/" + "/".join(part.lower() for part in tag_id.split("."))
def on_connect(client, userdata, flags, reason_code, properties):
client.subscribe(SOURCE, qos=1)
def on_message(client, userdata, message):
batch = json.loads(message.payload)
for item in batch.get("values", []):
payload = {"value": item["v"], "quality": "good" if item["q"] else "bad", "ts": item["t"]}
client.publish(to_topic(item["id"]), json.dumps(payload), qos=1, retain=True)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"kep-fanout-{uuid.uuid4().hex[:8]}")
client.on_connect = on_connect
client.on_message = on_message
client.tls_set()
# client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD") # private broker
client.connect("broker.connectmq.com", 8883, keepalive=30)
client.loop_forever()
Each Kepware batch becomes several retained per-tag messages, so the public broker's ten messages per second per client limit applies to the fan-out client; keep the test tag list small. On a private broker the limits follow your plan. Our ISA-95 MQTT topics article helps you design the target hierarchy, and ConnectMQ detects ISA-95 structured topics automatically in the devices view.
Troubleshooting the Kepware MQTT Agent
| Symptom in Kepware event log or behaviour | Likely cause | Fix |
|---|---|---|
| Agent cannot connect, connection refused | Wrong URL scheme or port | ssl:// with 8883, tcp:// with 1883 |
| TLS handshake errors | TLS inspection proxy, old TLS version | Trust the proxy CA, select TLS 1.2+ |
| Not authorized | Wrong username, password or client ID | Copy all three from the broker portal |
| Connects then disconnects repeatedly | Two clients using the same client ID | Give every agent and test client a unique ID |
Messages arrive but q is false |
Device communication problem in Kepware | Fix the channel or device, check Quick Client |
| Messages rejected as too large | Too many tags per publish | Lower max events per publish, or split into several agents |
| Topic rejected on the public broker | More than eight topic levels | Shorten the topic |
Production Checklist
- Private broker with TLS on 8883 and credentials from the portal.
- Unique client ID per agent, never shared with test tools.
- Last Will configured and monitored.
- On data change publishing and deadbands on analog tags.
- Message size within your plan's limit: 256 KB on the free Serverless plan, 1 MB on paid Serverless.
- Kepware host firewall: outbound 8883 only.
- A runbook for certificate or credential rotation.
For the bigger picture of where Kepware sits among PLCs, gateways and consumers, see the industrial IoT MQTT guide. If you are comparing Kepware with a custom gateway, our OPC UA to MQTT gateway tutorial shows the open-source alternative.
Get Started with ConnectMQ
Give your Kepware server a cloud destination in minutes. Sign up at app.connectmq.com, choose the free Serverless plan with no credit card, create a broker and copy the generated username, password and client ID into the MQTT Client agent. ConnectMQ is a managed MQTT broker, so there is no server to patch, and threshold alert rules in the portal can watch your tags as soon as they arrive.
Frequently Asked Questions
Does Kepware support MQTT over TLS?
Yes. Use an ssl:// URL with port 8883 in the MQTT Client agent and select a current TLS version. Brokers with publicly trusted certificates normally need no extra certificate import.
Can Kepware publish each tag to its own MQTT topic?
The MQTT Client agent publishes batches to the agent's topic, and options for per-tag topics depend on the Kepware version. A small fan-out client that splits batches into per-tag topics works with any version.
Which QoS should the Kepware MQTT agent use?
QoS 1 is a good default for tag data: delivery is guaranteed at least once with little overhead. QoS 2 is rarely needed for telemetry.
Can a cloud application write tags back through Kepware MQTT?
The agent can be configured to accept write requests on a subscribed topic, but enable this only with strict access control and a clear need. Most deployments keep the cloud path read-only.



