.NET SDK for developing mcpd
middleware plugins.
This SDK provides .NET types and gRPC interfaces for building middleware plugins that integrate with mcpd
.
Plugins can process HTTP requests and responses, implementing capabilities like authentication, rate limiting,
content transformation, and observability.
Add the package reference to your project:
dotnet add package MozillaAI.Mcpd.Plugins.Sdk
Or add it directly to your .csproj
file:
<ItemGroup>
<PackageReference Include="MozillaAI.Mcpd.Plugins.Sdk" Version="0.0.3" />
</ItemGroup>
The SDK provides the PluginServer
helper and BasePlugin
class to minimize boilerplate.
using Google.Protobuf.WellKnownTypes;
using MozillaAI.Mcpd.Plugins.V1;
public class MyPlugin : BasePlugin
{
public override Task<Metadata> GetMetadata(Empty request, Grpc.Core.ServerCallContext context)
{
return Task.FromResult(new Metadata
{
Name = "my-plugin",
Version = "1.0.0",
Description = "Example plugin that does something useful"
});
}
public override Task<Capabilities> GetCapabilities(Empty request, Grpc.Core.ServerCallContext context)
{
return Task.FromResult(new Capabilities
{
Flows = { FlowConstants.FlowRequest }
});
}
public override Task<HTTPResponse> HandleRequest(HTTPRequest request, Grpc.Core.ServerCallContext context)
{
var response = new HTTPResponse
{
Continue = true,
StatusCode = 0,
Body = request.Body
};
foreach (var header in request.Headers)
{
response.Headers.Add(header.Key, header.Value);
}
return Task.FromResult(response);
}
}
public class Program
{
public static async Task<int> Main(string[] args)
{
return await PluginServer.Serve<MyPlugin>(args);
}
}
The BasePlugin
class provides default implementations for all plugin methods. Override only the methods you need:
Method/Property | Default Behavior |
---|---|
CheckHealth() |
Returns OK |
CheckReady() |
Returns OK |
Configure() |
No-op |
Stop() |
No-op |
HandleRequest() |
Pass through unchanged |
HandleResponse() |
Pass through unchanged |
GetMetadata() |
Returns empty (should be overridden) |
GetCapabilities() |
Returns empty (should be overridden) |
Logger |
Automatically provided ILogger instance for structured logging |
Plugins can modify incoming HTTP requests by setting the ModifiedRequest
field in the returned HTTPResponse
. This allows plugins to transform requests before they reach downstream handlers:
public override Task<HTTPResponse> HandleRequest(HTTPRequest request, Grpc.Core.ServerCallContext context)
{
// Create a modified version of the request.
var modifiedRequest = new HTTPRequest
{
Method = request.Method,
Url = request.Url,
Path = request.Path,
Body = request.Body,
RemoteAddr = request.RemoteAddr,
RequestUri = request.RequestUri
};
// Copy and modify headers.
foreach (var header in request.Headers)
{
modifiedRequest.Headers.Add(header.Key, header.Value);
}
modifiedRequest.Headers["X-Custom-Header"] = "added-by-plugin";
// Return response with modified request.
return Task.FromResult(new HTTPResponse
{
Continue = true,
StatusCode = 0,
ModifiedRequest = modifiedRequest
});
}
Plugins that extend BasePlugin
have access to an ILogger
instance via the Logger
property. This allows plugins to emit structured logs that appear in the host application's output.
using Microsoft.Extensions.Logging;
using MozillaAI.Mcpd.Plugins.V1;
public class MyPlugin : BasePlugin
{
public override Task<Empty> Configure(PluginConfig request, Grpc.Core.ServerCallContext context)
{
Logger?.LogInformation("Plugin configured with {Count} settings", request.Settings.Count);
return Task.FromResult(new Empty());
}
public override Task<HTTPResponse> HandleRequest(HTTPRequest request, Grpc.Core.ServerCallContext context)
{
Logger?.LogInformation("Processing request: {Method} {Path}", request.Method, request.Path);
// Your plugin logic here.
return Task.FromResult(new HTTPResponse { Continue = true });
}
}
The SDK automatically suppresses ASP.NET Core framework logs at the Info level to reduce noise. Plugin logs at Info level and above will appear normally in the host application's output.
Build and run your plugin:
dotnet build
dotnet run -- --address /tmp/my-plugin.sock --network unix
Or for TCP:
dotnet run -- --address localhost:50051 --network tcp
The SDK automatically downloads proto definitions from mcpd-proto at build time.
Current proto version: v0.0.3
Version Type | Description |
---|---|
API Version | plugins/v1/ (in proto repo) maps to MozillaAI.Mcpd.Plugins.V1 namespace (in SDK) |
Release Version | Proto repo tags like v0.0.1 , v0.0.2 , etc. |
SDK Version | This repo's tags track SDK releases and may differ from proto versions |
To update the proto version, modify the <ProtoVersion>
property in the SDK .csproj
file.
mcpd-plugins-sdk-dotnet/
├── README.md # This file.
├── LICENSE # Apache 2.0 license.
├── mcpd-plugins-sdk-dotnet.sln # Solution file.
├── .gitignore # Ignores proto/ and bin/obj directories.
├── src/
│ └── MozillaAI.Mcpd.Plugins.Sdk/
│ ├── MozillaAI.Mcpd.Plugins.Sdk.csproj # SDK project file.
│ ├── BasePlugin.cs # BasePlugin helper class.
│ ├── PluginServer.cs # PluginServer helper class.
│ ├── FlowConstants.cs # Flow enum constants.
│ └── proto/ # Downloaded protos (auto-generated, gitignored).
└── examples/
└── MyPlugin/
├── MyPlugin.csproj # Example plugin project.
├── MyPlugin.cs # Plugin implementation.
└── Program.cs # Entry point.
- .NET 9.0 SDK or later
- Protocol Buffer Compiler (protoc) - automatically installed via
Grpc.Tools
NuGet package
dotnet build
The proto files are automatically downloaded during the build process via the FetchProto
target defined in the .csproj
file.
cd examples/MyPlugin
dotnet run -- --address /tmp/my-plugin.sock --network unix
- Edit the
<ProtoVersion>
property insrc/MozillaAI.Mcpd.Plugins.Sdk/MozillaAI.Mcpd.Plugins.Sdk.csproj
- Run
dotnet clean
anddotnet build
- Commit the updated project file
The SDK follows gRPC Health Checking Protocol conventions:
rpc CheckHealth(google.protobuf.Empty) returns (google.protobuf.Empty);
rpc CheckReady(google.protobuf.Empty) returns (google.protobuf.Empty);
Apache 2.0 - See LICENSE file for details.
This is an early PoC. Contribution guidelines coming soon.