A low-level MQTT 5 client library that prioritizes correctness — upholding the protocol's ordering, delivery, and state rules — and control — giving the application, rather than the library, the final say over connection lifecycle, task structure, and message handling.
It is built to facilitate demanding, long-lived applications such as edge and IoT services, message relays, and higher-level SDKs — systems that need many concurrent components to share a single reliable connection and to reason precisely about the fate of every operation.
The client is designed for use with any standards-compliant MQTT 5 servers, such as Mosquitto.
QoS 0 and QoS 1 are supported. The QoS 2 types and methods reserve the intended public API, but end-to-end QoS 2 publishing and receiving are not yet implemented.
See MQTT 5 feature support for the detailed protocol and client feature matrix.
- Three independent components.
new_client()returns aClient(outgoing operations), aConnectHandle/Connection(connection lifecycle and I/O), and aReceiver(incoming publishes). Each can be owned by a different task, so concerns stay cleanly separated. - Cloneable connection actor. The
Clientis a cheap, cloneable handle to a single connection "actor". Because the internal channels are multi-producer, many tasks or threads can multiplex their operations over one shared connection, and the connection task serializes them to preserve protocol ordering and flow control. - Lifecycle enforced by the type system. Connect, run, and reconnect are expressed through ownership (
ConnectHandle→Connection→ConnectHandle), so illegal states such as connecting twice or running a disconnected connection are compile errors rather than runtime faults. - Tiered result reporting. The API separately reports the stages applicable to each operation: acceptance by the client, operation-specific completion, and, when provided by the protocol, the server's verdict through an MQTT reason code.
- Explicit QoS and acknowledgement. Publishing uses QoS-specific methods, and incoming PUBLISHes expose the acknowledgement control appropriate to their QoS. Applications can handle acknowledgement flows explicitly, while dropping an unused control attempts the default successful response where one is required.
- QoS 2 is not yet implemented
- You drive the connection. The library does not drive the MQTT connection in the background; the application chooses its own task topology, reconnect policy, and message dispatch.
- A Tokio runtime
- OpenSSL development libraries discoverable by
pkg-config
Install the OpenSSL build dependencies for your platform:
# Debian or Ubuntu
sudo apt-get update
sudo apt-get install pkg-config libssl-dev
# Fedora or RHEL
sudo dnf install pkgconf-pkg-config openssl-devel
# macOS with Homebrew
brew install pkg-config openssl@3TCP and TLS transports are available by default. WebSocket transports are available through the websockets feature.
use std::error::Error;
use ms_mqtt_client::client::{
ClientOptions, ConnectResult, KeepAliveConfig, new_client,
};
use ms_mqtt_client::packet::{
ConnectProperties, DisconnectProperties, PublishProperties,
};
use ms_mqtt_client::topic::TopicName;
use ms_mqtt_client::transport::{
ConnectionTransportConfig, ConnectionTransportType,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let (client, connect_handle, _receiver) = new_client(ClientOptions::default());
let result = connect_handle
.connect(
ConnectionTransportConfig {
transport_type: ConnectionTransportType::Tcp {
hostname: "localhost".into(),
port: 1883,
},
timeout: None,
proxy: None,
tcp_nodelay: false,
},
true,
KeepAliveConfig::Infinite,
None,
None,
None,
ConnectProperties::default(),
None,
)
.await;
let (connection, disconnect_handle) = match result {
ConnectResult::Success(connection, _, disconnect_handle) => {
(connection, disconnect_handle)
}
ConnectResult::Failure(_, error) => return Err(error.into()),
};
let connection_task = tokio::spawn(connection.run_until_disconnect());
let publish_result: Result<(), Box<dyn Error>> = async {
let puback = client
.publish_qos1(
TopicName::new("example/topic")?,
"hello".into(),
false,
PublishProperties::default(),
)
.await?
.await?;
puback.as_result()?;
Ok(())
}
.await;
let _ = disconnect_handle.disconnect(&DisconnectProperties::default());
let _ = connection_task.await?;
publish_result
}The crate documentation and runnable examples are the canonical references for application code and coding assistants. Start from the pattern that matches the intended task:
| Canonical pattern | Reference |
|---|---|
| Single-client lifecycle: connect, subscribe, publish, receive, acknowledge, and shut down | Simple-client example |
| Reconnect supervisor: retry, resubscribe, and rebuild connection-scoped state | Document-update example |
| Multiple-client supervision: independently reconnect clients and coordinate shutdown | Message-relay example |
The examples guide explains how to configure and run these references against an MQTT server.
Code built from these patterns must preserve four invariants:
- Continuously poll
Connection::run_until_disconnect()while using the client or receiver; no background task drives MQTT I/O. - Distinguish three phases: successful completion of a
Clientoperation future means submission, awaiting its completion token reports operation-specific completion, andas_result()on an acknowledgement reports the MQTT server's verdict. - For an orderly shutdown, call
DisconnectHandle::disconnect()and keep driving the connection until it returns. - Use QoS 0 or QoS 1 only. QoS 2 types and methods reserve a future API and are not implemented end to end.
See CONTRIBUTING.md for contribution guidelines and the project's code of conduct. For help, see SUPPORT.md. Report security vulnerabilities according to SECURITY.md.
See LICENSE for details.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.