@functionkit/functions-framework
v0.1.1
Published
fnkit Functions Framework for Node.js — invoke functions via MQTT topics instead of HTTP
Maintainers
Readme
fnkit — MQTT Functions Framework for Node.js
An open source FaaS (Function as a Service) framework for writing portable Node.js functions invoked via MQTT messages instead of HTTP requests.
Adapted from the Google Cloud Functions Framework for Node.js.
How It Works
Instead of standing up an HTTP server, fnkit connects to an MQTT broker and subscribes to a topic based on your function name. When a message arrives, your function is invoked with familiar (req, res) arguments.
MQTT Message → Broker → fnkit subscribes → Your Function(req, res) → Optional MQTT ResponseQuick Start
1. Create your function
// index.js
const fnkit = require('@functionkit/functions-framework')
fnkit.mqtt('hello', (req, res) => {
console.log('Received:', req.body)
res.send({ message: `Hello, ${req.body.name || 'World'}!` })
})2. Install the framework
npm install @functionkit/functions-framework3. Run it
npx fnkit --target=hello --broker=mqtt://localhost:1883Your function is now listening on topic fnkit/hello. Publish a message to that topic and your function will be invoked.
4. Test it
# In another terminal, publish a message
mosquitto_pub -h localhost -t fnkit/hello -m '{"name": "Max"}'Function Signature
fnkit uses the same (req, res) pattern as the HTTP Functions Framework:
fnkit.mqtt('myFunction', (req, res) => {
// req — MQTT request object
// res — MQTT response object
})Request Object (req)
| Property | Type | Description |
| ----------------- | ------------------------ | ---------------------------------------------------------------- |
| topic | string | The full MQTT topic the message was received on |
| payload | Buffer | The raw message payload |
| body | any | Parsed payload (JSON if possible, otherwise raw string) |
| params | Record<string, string> | Topic segments beyond the function name (wildcard subscriptions) |
| properties | object | MQTT v5 user properties (analogous to HTTP headers) |
| headers | object | Alias for properties |
| correlationData | Buffer | MQTT v5 correlation data |
| responseTopic | string | MQTT v5 response topic |
| contentType | string | MQTT v5 content type |
| messageId | number | MQTT packet identifier |
| qos | 0 \| 1 \| 2 | QoS level of the received message |
| retain | boolean | Whether the message was retained |
| executionId | string | Unique execution ID for this invocation |
Response Object (res)
| Method | Description |
| ----------------- | -------------------------------------------------------------------------------- |
| send(data) | Publish response. Accepts string, Buffer, or object (auto JSON-serialized) |
| json(obj) | Publish JSON response (sets content type) |
| status(code) | Set a status code in response user properties (chainable) |
| set(key, value) | Set an MQTT v5 user property on the response (chainable) |
| end() | Signal completion without sending a response |
Fire-and-Forget
Functions don't have to send a response. Just process the message and return:
fnkit.mqtt('logger', (req, res) => {
console.log('Event received:', req.body)
// No res.send() needed — fire and forget
})Async Functions
Async functions are fully supported:
fnkit.mqtt('process', async (req, res) => {
const result = await doSomethingAsync(req.body)
res.send(result)
})Response Topics
Responses are published to (in order of precedence):
- MQTT v5 Response Topic — If the incoming message has a
responseTopicproperty - Default —
fnkit/{functionName}/response
Correlation data from the incoming message is automatically forwarded.
Configuration
Configure via CLI flags or environment variables. CLI flags take precedence.
| CLI Flag | Environment Variable | Description | Default |
| ----------------------- | -------------------------- | ----------------------------------------- | ----------------------- |
| --broker | MQTT_BROKER | MQTT broker URL (mqtt:// or mqtts://) | mqtt://localhost:1883 |
| --target | FUNCTION_TARGET | Name of the function to invoke | function |
| --topic-prefix | MQTT_TOPIC_PREFIX | Topic prefix before function name | fnkit |
| --source | FUNCTION_SOURCE | Path to function source code | cwd |
| --qos | MQTT_QOS | Default QoS level (0, 1, 2) | 1 |
| --client-id | MQTT_CLIENT_ID | MQTT client identifier | auto-generated |
| --username | MQTT_USERNAME | Broker username | — |
| --password | MQTT_PASSWORD | Broker password | — |
| --ca | MQTT_CA | Path to CA certificate (TLS) | — |
| --cert | MQTT_CERT | Path to client certificate (mTLS) | — |
| --key | MQTT_KEY | Path to client private key (mTLS) | — |
| --reject-unauthorized | MQTT_REJECT_UNAUTHORIZED | Reject unauthorized TLS certs | true |
package.json Configuration
{
"scripts": {
"start": "fnkit --target=hello --broker=mqtt://localhost:1883"
}
}Security
TLS (Port 8883)
fnkit --target=hello --broker=mqtts://broker:8883 --ca=/path/to/ca.crtmTLS (Mutual TLS)
fnkit --target=hello \
--broker=mqtts://broker:8883 \
--ca=/path/to/ca.crt \
--cert=/path/to/client.crt \
--key=/path/to/client.keyUsername/Password
fnkit --target=hello --broker=mqtt://broker:1883 --username=user --password=passMQTT v5 Features
fnkit uses MQTT v5 by default, enabling:
- Response Topics — Request-reply pattern via
responseTopicproperty - Correlation Data — Match responses to requests
- User Properties — Key-value metadata on messages (like HTTP headers)
- Content Type — Indicate payload format
Comparison with HTTP Functions Framework
| Aspect | HTTP Framework | fnkit |
| ------------ | ------------------------------------- | ------------------------------------------ |
| Transport | HTTP server (Express) | MQTT client (subscribes to broker) |
| Routing | URL path → function | Topic fnkit/{name} → function |
| Request | Express req (URL, headers, body) | MqttRequest (topic, properties, payload) |
| Response | Express res (status, headers, body) | MqttResponse (publish to reply topic) |
| Invocation | Per HTTP request | Per MQTT message |
| Signature | (req, res) => {} | (req, res) => {} ✅ Same pattern! |
| Registration | functions.http('name', handler) | fnkit.mqtt('name', handler) |
| Config | --port, --target | --broker, --target, --topic-prefix |
Architecture
See the design docs for:
- Architecture — System overview and components
- Contract — The MQTT Functions Framework contract (language-agnostic)
- Decisions — Design decisions and rationale
Based On
This framework is adapted from the Google Cloud Functions Framework for Node.js (Apache-2.0 License). The function registry, loader, and options parsing patterns are reused. The HTTP transport layer has been replaced with MQTT.
License
Apache-2.0 — See LICENSE for details.
