Protobuf to Kotlin Ktor Client Generator
eu.metaengine:metaengine-protobuf-kotlin-ktor-maven-pluginConvert Protobuf 3 to Kotlin Ktor gRPC-Connect client services and message models, delivered as a Maven plugin. Each RPC becomes a suspend fun on a Ktor HttpClient with kotlinx.serialization models over Connect-over-HTTP — bearer/basic auth, custom headers, timeouts, KDoc and Bean Validation — generated straight into your build at generate-sources.
Pick your registry
The same generator, published to every ecosystem we support. Install however your project expects.
Drive it from Maven or programmatically
Maven Central ships a build-time plugin that runs inside your build. NuGet ships the same generator as a C# fluent API — same options, same output.
Add the plugin to your pom.xml. Its generate goal binds to the generate-sources phase, so the gRPC-Connect client and kotlinx.serialization models are produced — and added to your compile roots — on every mvn compile or package. Point <inputSpec> at a .proto file and set the target Kotlin <packageName>.
<build>
<plugins>
<plugin>
<groupId>eu.metaengine</groupId>
<artifactId>metaengine-protobuf-kotlin-ktor-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>generate-grpc-client</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/proto/service.proto</inputSpec>
<packageName>com.example.api</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>The generate goal binds to the generate-sources phase, so a normal mvn compile (or package) produces the client and registers it as a compile source root — no extra wiring. <inputSpec> accepts a local .proto path, an http(s) URL, or inline proto content. The gRPC transport is Connect-over-HTTP on the Ktor HttpClient.
<configuration>
<inputSpec>${project.basedir}/service.proto</inputSpec>
<packageName>com.example.api</packageName>
<bearerAuth>API_TOKEN</bearerAuth>
<timeout>30</timeout>
<customHeaders>
<customHeader>X-Tenant-ID:TENANT_ID</customHeader>
</customHeaders>
</configuration><configuration>
<inputSpec>${project.basedir}/service.proto</inputSpec>
<packageName>com.example.api</packageName>
<documentation>true</documentation>
<validationAnnotations>true</validationAnnotations>
</configuration><configuration>
<inputSpec>${project.basedir}/service.proto</inputSpec>
<packageName>com.example.api</packageName>
<basicAuth>API_USER,API_PASS</basicAuth>
<timeoutConnect>5</timeoutConnect>
<timeoutRead>30</timeoutRead>
</configuration>Every knob, documented
Every option is available on the C# fluent API as a method; the Maven plugin exposes most as <configuration> elements. Cross-cutting auth, headers, retries and timeouts apply across frameworks.
Ktor Options
2WithValidationAnnotations()Emit Jakarta Bean Validation annotations (@field:NotNull, @field:Size, @field:Pattern, @field:Min / @field:Max, @field:Email) on generated data classes from proto field rulesWithStrictEnums()Keep string enums strict (plain @Serializable — kotlinx throws on unknown values). By default a synthetic UNKNOWN member + companion KSerializer absorbs unrecognized wire values instead of crashing deserialization
Auth · Headers · Resilience
8WithBearerAuth()Bearer token from env var (default API_TOKEN) — adds Authorization headerWithBearerAuth(string)Bearer token from a specific env var nameWithBearerAuth(string, string)Bearer token with custom header name (e.g. X-Api-Key)WithBasicAuth()HTTP Basic auth from default env vars (API_USERNAME / API_PASSWORD)WithBasicAuth(string, string)HTTP Basic auth from username + password env varsWithCustomHeader(string, string)Static header from env var. Repeatable (e.g. X-Tenant-ID ← TENANT_ID)WithTimeout(double)Request timeout in seconds — sets Ktor connect, request and socket timeouts togetherWithTimeout(double?, double?, double?)Granular timeout: connect · read · write (Ktor HttpTimeout has no connection-pool timeout)
Kotlin Options
3WithDocumentation()Generate KDoc comments on methods and parameters from the specWithMethodNames(Func)Custom method naming ruleWithOptionsObjectThreshold(int)Parameter count for options object (default: 4)
Protobuf Options
5WithDocumentation()Generate KDoc comments from .proto field and service descriptionsWithTypeFilter(Func)Filter extracted proto types (messages + enums) before registration — only types returning true are generatedWithTypeMapping(string, Type)Override the Kotlin mapping for a protobuf well-known type by fully-qualified name (e.g. google.protobuf.Timestamp → String)WithMethodNames(Func)Custom method naming ruleWithOptionsObjectThreshold(int)Parameter count for options object (default: 4)
Naming Transformations
3Types(Func)Transform type namesPaths(Func)Transform output pathsFileNames(Func)Transform file names
File Management
5CleanDestination()Clean output directory before generationAlwaysOverwrite()Always overwrite existing filesOnlyWhenModelChanged()Update only when model changesOnlyWhenNew()Write only new files, preserve existingCleanDirectories(...)Clean specific subdirectories
Diagnostics
2Verbose()Enable verbose loggingWithLogger(Action<string>)Route generation log output to a custom sink