Call a gRPC Service from MQTT
A gRPC connector opens a channel from the broker to an external gRPC service and maps MQTT topics onto that service’s calls. Publish bytes on a source topic and the connector sends them; replies are published back onto a destination topic.gRPC connectors are beta. Coreflux HUB lists the gRPC template with the other streaming connectors when the broker exposes it. The fields on that template are the same
GRPC_CONFIG parameters as the LoT on this page.When to use it
- A service you already run speaks gRPC, and MQTT messages should invoke it without a separate gateway.
- Each device needs its own long-lived stream. With the default session scope, one IMEI (or any other id in the source topic) gets its own bidirectional call.
- The exchange is one request and one reply, a server stream, a client stream, or a bidirectional stream.
.proto file.
Define the channel once, then map the MQTT topics that feed it.
Quick Start
- Unary call
- Server stream
- One call per device
One MQTT message opens one call and publishes the single reply:A payload on
grpc/echo/in is the request. The response bytes are published to grpc/echo/out.USE_TLS "false" is for a service that speaks plaintext HTTP/2. The default is TLS on port 443. Use 127.0.0.1 only when that service listens on the broker host. Set ADDRESS with GET ENV and credentials with GET SECRET.How a Call Is Chosen
One connector is one channel and one RPC method (SERVICE + METHOD). HTTP/2 carries many calls on that channel. Add another connector when you need a second method.
There is no session-key setting. Put application ids inside the payload. The connector correlates calls with the MQTT topic match.
ADD ROUTE_CONFIG still controls wait-or-drop when this connector falls behind incoming MQTT. See Store and Forward Configuration.
GRPC_CONFIG
The parser also accepts
SERVERSTREAM, CLIENTSTREAM, BIDIRECTIONAL, and DUPLEX for RPC_TYPE, and SOURCE, SOURCE_TOPIC, SHARED, and ROUTE for SESSION_SCOPE. Use the spellings in the table.
Event parameters
Several
ADD EVENT blocks share the same channel and the same method. Each event keeps its own calls.
Response publishes use QoS 0 and are not retained.
RPC Types
An empty MQTT payload is a real empty request for
UNARY and SERVER_STREAM. For CLIENT_STREAM and BIDI it is the half-close (no more client messages). The connector then waits up to 30 seconds for the remaining server bytes so the last response can still be published.
PAYLOAD AS BYTES in an Action does not publish an empty payload. Send the zero-length message from an MQTT client (MQTT Explorer or any MQTT client) on that source topic.
Raise DEADLINE above the longest call you expect. The default of 30 seconds ends a bidirectional session that runs longer than that, even when messages are still flowing. Raise IDLE_TIMEOUT when silence between messages is normal, or set it to 0 so only an empty payload half-closes the call.
Client stream
Publish request bytes togrpc/upload/in. Publish an empty payload, or wait for IDLE_TIMEOUT, to half-close. The single response is published to grpc/upload/out.
One shared call (SESSION_SCOPE EVENT)
SESSION_SCOPE "EVENT" keeps a single bidirectional call for every topic that matches the event. A new IMEI does not open its own call. Replies are published with {topic.N} taken from the latest source topic, not from the topic that opened the call.
TOPIC when each device must stay isolated. Use EVENT only when the service expects one shared stream.
Authentication
CLIENT_AUTH attaches credentials as initial metadata on each call. Access tokens are not published on MQTT topics. If the service returns unauthenticated, the connector invalidates the cached token, drops the streaming call, and retries that payload once so the new token is on the new call.
TOKEN_AUTH chooses how the client authenticates to the token endpoint: CLIENT_SECRET_BASIC (default), CLIENT_SECRET_POST, or PRIVATE_KEY_JWT (CLIENT_ID plus CLIENT_ASSERTION_KEY as PEM or JWK). ISSUER is the OIDC issuer; the connector discovers the token endpoint when TOKEN_URL is omitted. BEARER_TOKEN and API_KEY also accept the setting name AUTH_SECRET.
For OAUTH2_JWT_BEARER, set TOKEN_URL when the service-account JSON has no token_uri. For GOOGLE_METADATA, the default metadata address is http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token. Set METADATA_URL to point elsewhere. When SCOPE is set and that URL has no query string, the connector adds the scope as a scopes query parameter.
- API key
- OAuth client
- Service account
Send a static key in initial metadata:
Payloads
The connector sends and publishes the MQTT payload as raw bytes. It does not encode JSON and it does not compile protobuf. A binary publish stays binary. If the topic cache has no raw bytes, the connector sends the payload text as UTF-8, which corrupts protobuf and audio. Publish protobuf withPUBLISH MODEL, or forward an existing blob with PAYLOAD AS BYTES. Decode replies with GET PROTO on the destination topic.
The model describes the request. The Action writes binary protobuf to the topic the connector is listening on:
EchoGrpc from the Quick Start then forwards those bytes and publishes the service’s reply on grpc/echo/out. Read fields from that reply with GET PROTO and a response model. See Protobuf models.
Check the Round Trip
1
Deploy the connector
Deploy the LoT, then confirm the connector reaches the service. Health is retained on
$SYS/Coreflux/Routes/EchoGrpc/status. See Connector status.2
Subscribe to the reply
In MQTT Explorer, subscribe to the destination topic (
grpc/echo/out, or devices/+/downlink for the per-device example).3
Publish a request
Publish a payload to the source topic. For a unary echo, the reply is one message. For a bidirectional device topic, further publishes on that same topic reuse the call until an empty payload or the idle timeout.
4
Half-close a stream
For
CLIENT_STREAM or BIDI, publish a zero-length payload on that source topic. The last server bytes are published, and the next non-empty payload opens a new call.Best Practices
- Keep
SESSION_SCOPE "TOPIC"(the default) so each device topic, such as one IMEI, has its own call. - Set
DEADLINEto the full length of a streaming call, not the gap between messages. - Store keys with
GET SECRET. Do not publish tokens on MQTT topics. - Put correlation ids in the payload. The connector will not add a session id for you.
- Tell operators that an empty payload half-closes
CLIENT_STREAMandBIDI. - Do not send metadata keys that start with
grpc-.
Limitations
Troubleshooting
The connector will not start
The connector will not start
GRPC_CONFIGneedsADDRESS,SERVICE, andMETHOD. Each event needsSOURCE_TOPICandDESTINATION_TOPIC.- The channel must connect within 10 seconds. Use a host and port the broker host can reach, and match
USE_TLSto the service (plaintext often uses port50051; TLS often uses443). - If the route fails to start, the broker retries in the background, from 2 seconds up to 60 seconds, until the route starts or you remove it.
- OAuth modes fetch a token at startup. Check
TOKEN_URLorISSUER, and the secret names.
Unauthenticated replies
Unauthenticated replies
The connector retries once after refreshing the token and opening a new streaming call. If that retry fails, check
CLIENT_AUTH, the token endpoint, and that the secret resolves. Tokens are not written to MQTT topics.Binary payloads look corrupted
Binary payloads look corrupted
Publish raw bytes (
PUBLISH MODEL or PAYLOAD AS BYTES). A text payload is sent as UTF-8.Metadata is rejected
Metadata is rejected
Remove any key that starts with
grpc-. Use a JSON object for METADATA when a value contains a comma.The stream never finishes
The stream never finishes
Nothing published an empty payload, and
IDLE_TIMEOUT is high or 0. Publish a zero-length payload on the source topic, or lower IDLE_TIMEOUT.MQTT publishes continue but replies stop
MQTT publishes continue but replies stop
The previous bidirectional call already ended. Payloads on that topic are dropped until an empty payload. Publish the empty payload, then send the next request. Check connector logs for the dropped-byte warning.
Replies land on the wrong device topic
Replies land on the wrong device topic
SESSION_SCOPE "EVENT" expands {topic.N} from the latest source topic. Use TOPIC when each IMEI needs its own call and its own reply topic.Next Steps
Protobuf Models
Encode request bytes with
PUBLISH MODEL and read replies with GET PROTO.Kafka Connector
Stream MQTT to an event log when the other side is Kafka, not a gRPC method.

