FnKit.Functions.Framework
0.1.0
dotnet add package FnKit.Functions.Framework --version 0.1.0
NuGet\Install-Package FnKit.Functions.Framework -Version 0.1.0
<PackageReference Include="FnKit.Functions.Framework" Version="0.1.0" />
<PackageVersion Include="FnKit.Functions.Framework" Version="0.1.0" />
<PackageReference Include="FnKit.Functions.Framework" />
paket add FnKit.Functions.Framework --version 0.1.0
#r "nuget: FnKit.Functions.Framework, 0.1.0"
#:package FnKit.Functions.Framework@0.1.0
#addin nuget:?package=FnKit.Functions.Framework&version=0.1.0
#tool nuget:?package=FnKit.Functions.Framework&version=0.1.0
fnkit — MQTT Functions Framework for .NET
An open source FaaS (Function as a Service) framework for writing portable .NET functions invoked via MQTT messages instead of HTTP requests.
Adapted from the Google Cloud Functions Framework for .NET.
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 (request, response) arguments.
MQTT Message → Broker → fnkit subscribes → Your Function(req, res) → Optional MQTT Response
Prerequisites
The fnkit Functions Framework for .NET requires .NET 8.0 or later.
Quick Start
1. Create a .NET project
mkdir MyFunction && cd MyFunction
dotnet new console
dotnet add package FnKit.Functions.Framework
dotnet add package FnKit.Functions.Hosting
2. Create your function
// HelloFunction.cs
using FnKit.Functions.Framework;
public class HelloFunction : IMqttFunction
{
public Task HandleAsync(MqttRequest request, MqttResponse response, CancellationToken cancellationToken)
{
string name = "World";
if (request.Body.HasValue &&
request.Body.Value.TryGetProperty("name", out var nameProp))
{
name = nameProp.GetString() ?? "World";
}
response.Send(new { message = $"Hello, {name}!" });
return Task.CompletedTask;
}
}
3. Create the entry point
// Program.cs
using FnKit.Functions.Hosting;
return await EntryPoint.StartAsync(typeof(HelloFunction).Assembly, args);
4. Run it
FUNCTION_TARGET=HelloFunction dotnet run
# Output: [fnkit] Listening on topic: fnkit/HelloFunction
5. Test it
# In another terminal, publish a message
mosquitto_pub -h localhost -t fnkit/HelloFunction -m '{"name": "Max"}'
Function Signature
fnkit uses an interface-based pattern consistent with the .NET Functions Framework:
public class MyFunction : IMqttFunction
{
public Task HandleAsync(MqttRequest request, MqttResponse response, CancellationToken cancellationToken)
{
// request — MQTT request object
// response — MQTT response object
// cancellationToken — cancellation token
return Task.CompletedTask;
}
}
Request Object (MqttRequest)
| Property | Type | Description |
|---|---|---|
Topic |
string |
The full MQTT topic the message was received on |
Payload |
byte[] |
The raw message payload |
Body |
JsonElement? |
Parsed payload (JSON if possible, otherwise null) |
BodyText |
string |
The raw payload as a string |
Params |
Dictionary<string, string> |
Topic segments beyond the function name (wildcard subscriptions) |
Properties |
Dictionary<string, string> |
MQTT v5 user properties (analogous to HTTP headers) |
Headers |
Dictionary<string, string> |
Alias for Properties |
CorrelationData |
byte[]? |
MQTT v5 correlation data |
ResponseTopic |
string? |
MQTT v5 response topic |
ContentType |
string? |
MQTT v5 content type |
MessageId |
ushort |
MQTT packet identifier |
QoS |
byte |
QoS level of the received message |
Retain |
bool |
Whether the message was retained |
ExecutionId |
string |
Unique execution ID for this invocation |
Use request.GetBody<T>() for typed deserialization of the JSON body.
Response Object (MqttResponse)
| Method | Description |
|---|---|
Send(data) |
Publish response. Accepts string, byte[], or any 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:
public class LoggerFunction : IMqttFunction
{
public Task HandleAsync(MqttRequest request, MqttResponse response, CancellationToken cancellationToken)
{
Console.WriteLine($"Event received: {request.BodyText}");
// No response.Send() needed — fire and forget
return Task.CompletedTask;
}
}
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 | auto-detected |
--topic-prefix |
MQTT_TOPIC_PREFIX |
Topic prefix before function name | fnkit |
--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 |
If FUNCTION_TARGET is not specified and the assembly contains exactly one IMqttFunction implementation, it is used automatically (same pattern as the Google Cloud Functions Framework).
Security
TLS (Port 8883)
FUNCTION_TARGET=HelloFunction dotnet run -- --broker=mqtts://broker:8883 --ca=/path/to/ca.crt
mTLS (Mutual TLS)
FUNCTION_TARGET=HelloFunction dotnet run -- \
--broker=mqtts://broker:8883 \
--ca=/path/to/ca.crt \
--cert=/path/to/client.crt \
--key=/path/to/client.key
Username/Password
FUNCTION_TARGET=HelloFunction dotnet run -- --broker=mqtt://broker:1883 --username=user --password=pass
MQTT 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 (.NET) | fnkit (.NET) |
|---|---|---|
| Transport | HTTP server (Kestrel) | MQTT client (subscribes to broker) |
| Routing | URL path → function | Topic fnkit/{name} → function |
| Request | HttpContext (URL, headers, body) |
MqttRequest (topic, properties, payload) |
| Response | HttpContext.Response |
MqttResponse (publish to reply topic) |
| Invocation | Per HTTP request | Per MQTT message |
| Interface | IHttpFunction |
IMqttFunction |
| Config | PORT, FUNCTION_TARGET |
MQTT_BROKER, FUNCTION_TARGET |
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 .NET (Apache-2.0 License). The function resolution, assembly scanning, and framework patterns are reused. The HTTP transport layer has been replaced with MQTT using MQTTnet.
License
Apache-2.0 — See LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on FnKit.Functions.Framework:
| Package | Downloads |
|---|---|
|
FnKit.Functions.Hosting
fnkit Functions Framework for .NET — MQTT hosting, connection management, and function invocation. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 141 | 2/15/2026 |