MQTT Explorer Documentation

Installation

MacTools MQTT Explorer is a native macOS app built with Rust and Tauri. It bundles a full MQTT broker (no mosquitto, no Homebrew, no Docker) and a GUI client in one app. Runs natively on Apple Silicon and Intel Macs — no Rosetta, no Parallels, no Node.js. One-time purchase, no subscription.

Download

System Requirements

RequirementMinimum
macOS12 Monterey or newer (Apple Silicon & Intel)
Broker (local)Loopback or LAN — listens on TCP/1883 (plain), TCP/8883 (TLS), or TCP/9001 (WebSocket)
Connecting to remote brokersNetwork reachability to the broker host on its MQTT port

First Launch

If you downloaded the direct build outside the App Store, macOS Gatekeeper may block the unsigned binary on first run. Right-click the app, choose Open, then confirm. This is only required once.

The bundled broker binds to localhost by default. It does not expose your Mac to the network unless you change the bind address to 0.0.0.0. For LAN testing, set the bind address explicitly and ensure macOS Firewall allows incoming connections on the broker port.

Quick Start

1. Start the local broker and connect (2 minutes)

This is the most common path — you want a local broker on your Mac to test IoT devices, Node-RED flows, or an ESP32 firmware without spinning up mosquitto.

  1. Open the app. The Broker tab shows the local server status.
  2. Click Start Broker. It binds to 127.0.0.1:1883 and is ready immediately.
  3. Switch to the Client tab. A preconfigured connection to localhost:1883 is already listed — click Connect.
  4. The connection indicator turns green; the broker log shows a CONNECT and CONNACK.

If the client fails to connect, jump to Troubleshooting — the most frequent cause is the broker not running or a port conflict with a leftover mosquitto process.

2. Subscribe to a topic and publish a message

  1. In the Subscriptions panel, enter sensors/# and click Subscribe.
  2. In the Publish panel, enter topic sensors/temperature and payload 23.5.
  3. Set QoS to 1 and click Publish.
  4. The message appears instantly in the Messages log — you have a working pub/sub loop.

3. Test a retained message

  1. Publish a payload to device/status with the Retain flag on.
  2. Subscribe to device/status from a fresh client — you immediately receive the last retained message, even though it was published before you subscribed.
  3. To clear it, publish an empty (zero-length) payload to the same topic with Retain on.

4. Connect to a remote broker (Mosquitto, EMQX, HiveMQ, AWS IoT)

  1. Create a new connection: host, port (8883 for TLS, 1883 plain), Client ID.
  2. If the broker requires auth, set username/password. For AWS IoT / mTLS, attach the client certificate, private key, and CA.
  3. Enable TLS and (for managed brokers) set the SNI / ALPN if required.
  4. Click Connect.

Configuration

Broker Settings

ParameterOptions
Bind address127.0.0.1 (loopback, default), 0.0.0.0 (all interfaces / LAN)
Plain TCP port1883 (default)
TLS port8883 — requires a server certificate
WebSocket port9001 — for browser-based clients
Max connectionsDefault 1000 — lower for low-RAM Macs
Anonymous accessAllow / deny — deny requires username/password on every client

Client Connection Settings

ParameterOptions
Host / PortAny reachable broker
Client IDUnique per session — empty string lets the broker assign one (only MQTT v5)
Protocol versionMQTT v3.1.1 (default, widest compat) or MQTT v5
Clean sessiontrue (no persistence, default) or false (broker keeps subscriptions + queued QoS 1/2 messages)
Keep aliveDefault 60 s — the interval at which the broker pings if idle
AuthenticationNone, Username/Password, Certificate (mTLS)
Last WillA message published automatically if the client disconnects ungracefully

QoS Levels

QoSGuaranteeOverhead
0At most once — fire and forget, no ACK. Best for high-frequency telemetry you can afford to lose.1 round-trip
1At least once — PUBACK required. Duplicates possible on retry. The industrial default.2 round-trips
2Exactly once — four-step handshake (PUBREC/PUBREL/PUBCOMP). No duplicates.4 round-trips

QoS is set per-publish and per-subscribe independently. A QoS 1 message delivered to a QoS 0 subscription is delivered at most once. Match the subscription's QoS to the message's QoS to get the guarantee you want.

Topic Wildcards

PatternMatches
sensors/temperatureExactly that topic — no wildcards
sensors/+Any one level: sensors/temperature, sensors/humidity — but not sensors/room1/temperature
sensors/#All levels below: sensors/, sensors/a, sensors/a/b/c — multi-level. Must be the last character.
$SYS/#Broker system topics (stats, uptime) — note the leading $ excludes these from # subscriptions

Retained Messages & Last Will

Retained messages are stored by the broker and delivered to any future subscriber to that topic — the classic pattern for "last known state" (device status, current setpoint). Last Will and Testament (LWT) is a message the broker publishes on your behalf if your client drops ungracefully (network loss, crash) — used to flag a device as offline. Set both in the connection profile before connecting.

Key Features

Broker and client in one app

The bundled Rust broker handles thousands of concurrent connections and MQTT v3.1.1 + v5. You no longer need mosquitto in Homebrew, a Docker container, or a cloud broker just to test a firmware or a Node-RED flow. Start the broker, connect the client tab to localhost, done.

Topic tree with live subscriber count

As messages flow, the broker builds a live topic tree showing each topic, its subscriber count, and its message rate. Spot orphan publishers (topics with no subscribers) and congested topics (rate spikes) at a glance.

Payload inspector with JSON pretty-print

Every message is logged with timestamp, topic, QoS, retain flag, and payload. JSON payloads are pretty-printed and folded; binary payloads are shown as hex. Filter by topic pattern to follow one device's traffic in isolation.

MQTT v5 support

Beyond v3.1.1, the app supports MQTT v5 features: shared subscriptions ($share/group/topic for load-balanced consumers), user properties, content type, message expiry, and reason codes on every ACK.

TLS / mTLS and AWS IoT

For TLS brokers, supply a CA or use the system trust store. For mutual TLS (AWS IoT, Azure IoT Hub), attach the device certificate and private key — the app handles SNI and the TLS handshake. AWS IoT's device-shadow topics work like any other subscription.

Scripted publish (Sparkplug B ready)

Build a publish script that emits Sparkplug B-encoded payloads (birth/death certificates, data metrics) for IIoT testing. The script runs in the app, publishing on a schedule or triggered by a subscribe-side event.

Troubleshooting

CONNACK return codes (MQTT v3.1.1)

CodeNameLikely Cause
0Connection AcceptedSuccess
1Unacceptable protocol versionBroker wants v3.1.1 but you sent v5, or vice versa. Switch the client protocol version.
2Identifier rejectedEmpty or duplicate Client ID and the broker doesn't allow either
3Server unavailableBroker process not running or not ready
4Bad username or passwordWrong credentials, or the broker rejects the auth scheme
5Not authorizedAuth succeeded but the user has no connect permission

Broker won't start (port in use)

Symptom: "Address already in use" when clicking Start Broker.
Fix: Another process holds the port — usually a leftover mosquitto or a second instance. Find it:

sudo lsof -i :1883

Stop that process (or change the bundled broker's port in settings to 1884). On macOS, a previous app launch that crashed can also hold the socket — a reboot clears it.

Client connects but no messages arrive

Symptom: Connection is green, you published a message, but the subscriber sees nothing.
Fix: Check the subscription topic pattern against the publish topic. sensors/+ does not match sensors/room1/temp (two levels). Use sensors/# for multi-level. Also confirm you're not publishing with a leading slash mismatch (/sensors/temp vs sensors/temp are different topics — the leading slash adds an empty first level).

TLS handshake fails against a public broker

Symptom: Plain 1883 works, TLS 8883 fails with a handshake/cert error.
Fix: Either the broker's certificate isn't trusted by your system keychain (import the CA), or the broker requires SNI and you didn't enable it. For brokers like HiveMQ Public and EMQX, SNI is mandatory. AWS IoT additionally requires a client certificate (mTLS) — plain TLS without it returns an auth failure.

Duplicate messages on QoS 1

Symptom: The subscriber receives the same message twice.
Fix: This is by design — QoS 1 is at-least-once. If the PUBACK is delayed (slow network, busy subscriber), the publisher retransmits after its retry interval, and the broker may redeliver. Either accept duplicates and idempotently handle them, or move to QoS 2 (exactly-once) for state-changing commands.

Retained message persists after clear attempt

Symptom: You "cleared" a retained message but new subscribers still receive it.
Fix: A retained message is only cleared by publishing a zero-length payload with the Retain flag set — not by publishing a space or the word "null." Re-publish with an empty payload and Retain on, then re-subscribe to confirm.

Support

When reporting a broker or connection issue, attach the broker log (with client IDs redacted), the broker software/version you're connecting to, and the exact CONNACK code or TLS error message.