# Sgcwebsockets Mq

> sgcWebSockets Message Brokers

- Skill: `esegece-com/sgcwebsockets-mq` (Agent Skill, multi-file: 271 files)
- Install (CLI): `npx skillmds@latest add esegece-com/sgcwebsockets-mq`
- Raw SKILL.md: https://api.skillmd.com/api/skills/esegece-com/sgcwebsockets-mq/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: esegece-com (https://skillmd.com/u/esegece-com)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/esegece-com/sgcwebsockets-mq

---


# sgcWebSockets Message Brokers

These eight components speak the wire protocols of the common message brokers.
They are not standalone clients. Each one attaches to a `TsgcWebSocketClient`,
which owns the socket, the TLS, the reconnect and the heartbeat. Get that
relationship right and the rest follows.

## When to use this skill

- Publish to or subscribe from an MQTT broker (Mosquitto, HiveMQ, EMQX, AWS IoT)
- Talk STOMP to RabbitMQ, ActiveMQ or any STOMP broker
- Use AMQP 0.9.1 against RabbitMQ, or AMQP 1.0 against Azure Service Bus
- Produce to and consume from Kafka
- Use WAMP2 for publish/subscribe plus remote procedure calls

For the sgc built-in subprotocols (broker, dataset, files, presence, WAMP1,
E2EE) load `sgcwebsockets-protocols`. For the AWS IoT and Azure IoT wrappers,
which are MQTT with the cloud specifics already filled in, load
`sgcwebsockets-iot`.

## Install and uses clause

All eight live in one unit. You also need the transport client and the
connection class:

```pascal
uses
  sgcWebSocket,             // TsgcWebSocketClient, the transport
  sgcWebSocket_Protocols,   // the protocol components in this skill
  sgcWebSocket_Classes,     // TsgcWSConnection, handed to every event
  sgcWebSocket_Types;       // TmqttQoS and the other enumerations
```

## The binding rule, read this before writing any code

A protocol component does nothing until you assign a transport:

```pascal
MQTT.Client := WSClient;
```

Two consequences that cause most of the confusion:

**One protocol per client.** A `TsgcWebSocketClient` carries one protocol at a
time. If you have several protocol components on a form, set the ones you are
not using to `nil` before binding the one you want. Leaving two bound to the
same client produces a handshake that neither broker accepts.

```pascal
STOMP.Client := nil;
KAFKA.Client := nil;
MQTT.Client := WSClient;
```

**The transport is a switch on the client, not the protocol.** MQTT and STOMP
run either over a raw TCP socket or inside a WebSocket frame, and brokers
differ in which they expose, usually on different ports:

```pascal
WSClient.Specifications.RFC6455 := False;  // raw TCP, the usual broker port
WSClient.Specifications.RFC6455 := True;   // MQTT over WebSocket
```

Connecting a raw-TCP client to a WebSocket endpoint fails at the handshake with
an error that does not mention the transport, so check this first when a broker
refuses you.

## Before you start, ask the developer

Use a structured question tool if your host has one, for example Claude Code's
`AskUserQuestion`. Otherwise ask in chat. These change the code you write:

1. **Which broker and which protocol?** RabbitMQ speaks AMQP 0.9.1, STOMP and
   MQTT. Azure Service Bus speaks AMQP 1.0. They are different components, and
   AMQP 0.9.1 and AMQP 1.0 are unrelated protocols despite the name.
2. **Raw TCP or over WebSocket?** Sets `Specifications.RFC6455` and the port.
3. **TLS?** Broker TLS ports differ from plaintext ones, 8883 against 1883 for
   MQTT for instance.
4. **Which MQTT version?** `MQTTVersion` selects 3.1.1 or 5.0. Version 5 adds
   the properties parameters that appear throughout the API.
5. **What delivery guarantee?** QoS 0, 1 or 2 changes both the publish call and
   which acknowledgement events you need to handle.

## Components in this skill

| Component | Protocol | Shape of the API |
| --- | --- | --- |
| `TsgcWSPClient_MQTT` | MQTT 3.1.1 and 5.0 | `Publish`, `Subscribe`, event driven |
| `TsgcWSPClient_STOMP` | STOMP | `Send`, `Subscribe`, `ACK`, transactions |
| `TsgcWSPClient_STOMP_RabbitMQ` | STOMP | RabbitMQ specifics on top of STOMP |
| `TsgcWSPClient_STOMP_ActiveMQ` | STOMP | ActiveMQ specifics on top of STOMP |
| `TsgcWSPClient_AMQP` | AMQP 0.9.1 | channels: `OpenChannel`, exchanges, queues |
| `TsgcWSPClient_AMQP1` | AMQP 1.0 | sessions and links, Azure CBS token helpers |
| `TsgcWSPClient_Kafka` | Kafka | `Produce`, `Subscribe`, `Poll`, `CommitSync` |
| `TsgcWSPClient_WAMP2` | WAMP2 | `Publish`/`Subscribe` plus `Call`/`RegisterCall` |

Kafka is the odd one out. It is a poll loop, not an event stream: you call
`Poll` and it returns the messages it has. The others deliver through events.

## Quickstart, MQTT

```pascal
uses
  sgcWebSocket, sgcWebSocket_Protocols, sgcWebSocket_Classes, sgcWebSocket_Types;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FClient := TsgcWebSocketClient.Create(Self);
  FClient.Host := 'test.mosquitto.org';
  FClient.Port := 1883;
  FClient.Specifications.RFC6455 := False;   // raw TCP, not WebSocket

  FMQTT := TsgcWSPClient_MQTT.Create(Self);
  FMQTT.Client := FClient;                   // bind protocol to transport
  FMQTT.MQTTVersion := mqtt311;
  FMQTT.Authentication.Enabled := False;
  FMQTT.OnMQTTConnect := MQTTConnect;
  FMQTT.OnMQTTPublish := MQTTPublish;

  FClient.Active := True;
end;

// fires once the broker has accepted CONNECT. Subscribe here, not earlier.
procedure TForm1.MQTTConnect(Connection: TsgcWSConnection; const Session: Boolean;
  const ReasonCode: Integer; const ReasonName: string;
  const ConnectProperties: TsgcWSMQTTCONNACKProperties);
begin
  FMQTT.Subscribe('sensors/+/temperature', mtqsAtLeastOnce);
  FMQTT.Publish('sensors/hello', 'online', mtqsAtLeastOnce, True);
end;

// every message on every subscribed topic arrives here
procedure TForm1.MQTTPublish(Connection: TsgcWSConnection; aTopic, aText: string;
  PublishProperties: TsgcWSMQTTPUBLISHProperties);
begin
  Memo1.Lines.Add(aTopic + ' = ' + aText);
end;
```

`TmqttQoS` is `(mtqsAtMostOnce, mtqsAtLeastOnce, mtqsExactlyOnce, mtqsReserved)`.
The fourth value is the protocol's reserved slot, do not send it.

## Quickstart, STOMP

STOMP names a subscription with an id you choose, and you use that id to
unsubscribe and to acknowledge:

```pascal
FSTOMP.Client := FClient;
FSTOMP.Subscribe('sub-1', '/queue/orders', ackIndividual);
FSTOMP.Send('/queue/orders', '{"id":42}', 'application/json');
```

`TsgcSTOMPACK` is `(ackAuto, ackMultiple, ackIndividual)`. With `ackAuto` the
broker considers a message delivered the moment it sends it. With
`ackIndividual` it holds the message until you call `ACK` for that id, and
`ackMultiple` acknowledges everything up to that id at once. Transactions are
`BeginTransaction`, `CommitTransaction` and `AbortTransaction`, and every send
and acknowledgement takes the transaction name.

## Last will, for MQTT

A last will is published by the broker on your behalf when your connection
drops without a clean disconnect. Set it before connecting, never after:

```pascal
FMQTT.LastWillTestament.Enabled := True;
FMQTT.LastWillTestament.Topic := 'clients/me/status';
FMQTT.LastWillTestament.Text := 'offline';
FMQTT.LastWillTestament.QoS := mtqsAtLeastOnce;
FMQTT.LastWillTestament.Retain := True;
```

## Things that catch people out

- Subscribing before `OnMQTTConnect` silently does nothing. The socket being
  open is not the same as the broker having accepted CONNECT.
- Two protocol components bound to the same client is the most common cause of
  a broker rejecting the handshake. Set the unused ones to `nil`.
- `Specifications.RFC6455` lives on the client, not the protocol, and its
  default is the WebSocket one. Brokers on port 1883 need it set to `False`.
- QoS 2 involves a four-message exchange. If you are tracking delivery yourself
  you need `OnMQTTPubRec`, `OnMQTTPubRel` and `OnMQTTPubComp`, not just
  `OnMQTTPubAck`.
- The reconnect and heartbeat settings belong to the transport client. Set
  `FClient.WatchDog` and `FClient.HeartBeat`, and note MQTT also has its own
  protocol level `FMQTT.HeartBeat` for the MQTT keepalive, which is a different
  mechanism.

## Routing

- **Find a component**: `reference/components-index.md` lists every component, its `unit`, and its edition, grouped by Reg module.
- **Uses clause**: add the component's `unit:` value (shown on its API page) to your `uses` clause. Nothing compiles without it.
- **API detail**: `reference/api/<Component>.md` has the Properties, Events and Methods, each in both Delphi and C++Builder form.
- **Option / enum / event types**: property and event types link to `reference/types/<TypeName>.md`, which documents the sub-properties of option classes, the values of enums, and the parameter list of event handlers.
- **Examples**: `examples/index.md` is the full demo catalog; `examples/<Component>.md` is a focused, real usage snippet for the most-used components.
- **Concepts**: `concepts/overview.md` (getting started + uses-clause rule) and `concepts/editions-and-features.md` (which components your edition includes).
- **Bundled resources**: `concepts/resources.md` lists the browser-side assets (JavaScript, HTML, CSS) the server components serve or embed, so a browser client works without an external CDN.
- **Version history**: `reference/history.md` lists what changed in each sgcWebSockets release.

## Editions

Components are gated by edition (Professional, Enterprise, All-Access) or by a feature define. Check the edition column in the components index, or `concepts/editions-and-features.md`, before relying on a component.

Only public and published members are documented. Method bodies, private fields and protected members are intentionally not included.


