😸 kt-schema
kt-schema generator turning Kotlin and Java code into JSON schemas

Generate JSON schemas and LLM function calling schemas from Java and Kotlin code — including classes you don't own.

Documentation

kt-schema generates JSON Schema and LLM function calling schemas from Kotlin and Java code. Choose the generation path that matches how your models are built and deployed, annotate (or don’t), and read the schema from a generated extension, a classpath resource or a runtime call.

Why kt-schema?

  1. 🤖 LLM function calling: generate tool definitions for OpenAI, Anthropic and MCP directly from Kotlin functions, with proper type definitions and descriptions.
  2. 📦 Third-party classes: create schemas for library classes without modifying their source (Spring entities, Ktor models, etc.).
  3. 🔄 Multi-framework compatibility: works with existing annotations from Jackson, LangChain4j, Koog and more, with no code changes.

Choosing Your Approach

🔧 KSP Processor☕ Java APT📦 Serialization-based🔍 Runtime Reflection
PlatformsJVM + MultiplatformJVM onlyJVM + MultiplatformJVM only
When generatedCompile-timeCompile-timeRuntimeRuntime
Requires annotation processorYes (KSP)Yes (APT)NoNo
Class must be @SerializableNoNoYesNo
Annotate class with @SchemaRequiredNot required¹Not requiredNot required
KDoc extracted to description✅❌❌❌
Extract default valuesPartial²Partial²❌✅
Third-party classes❌❌✅ (only @Serializable)✅ any JVM class

¹ with the rootPackage option — see Java Annotation Processor Guide .

² Jackson’s @JsonEnumDefaultValue becomes the enum’s default. Kotlin/Java default-value expressions can’t be evaluated at compile time, so no property default is emitted — see Multi-Framework Annotation Support .

Quick Start

Refer to the example projects .

Annotate Your Models

kotlin
/**
 * A postal address for deliveries and billing.
 */
@Schema
data class Address(
    @Description("Street address, including house number") @Size(max = 120) val street: String,
    @Description("City or town name") @Size(min = 1, max = 80) val city: String,
    @Description("Postal or ZIP code") @Pattern(regexp = "[0-9]{5}") val zipCode: String,
    @Description("Two-letter ISO country code; defaults to US") @Pattern(regexp = "[A-Z]{2}") val country: String = "US",
)
Generated JSON schema (KSP, default strict config)
json
{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "com.example.Address",
    "description": "A postal address for deliveries and billing.",
    "type": "object",
    "properties": {
        "street": {
            "type": "string",
            "description": "Street address, including house number",
            "maxLength": 120
        },
        "city": {
            "type": "string",
            "description": "City or town name",
            "minLength": 1,
            "maxLength": 80
        },
        "zipCode": {
            "type": "string",
            "description": "Postal or ZIP code",
            "pattern": "[0-9]{5}"
        },
        "country": {
            "type": "string",
            "description": "Two-letter ISO country code; defaults to US",
            "pattern": "[A-Z]{2}"
        }
    },
    "additionalProperties": false,
    "required": [
        "street",
        "city",
        "zipCode",
        "country"
    ]
}

Note: KDoc comments on classes can also be used as descriptions. Jakarta Bean Validation annotations such as @Size and @Pattern become maxLength, minLength and pattern — see Validation Constraints .

Quick Setup

Add the Google KSP plugin and the processor dependency:

kotlin
// Multiplatform (KMP)
plugins {
    kotlin("multiplatform")
    id("com.google.devtools.ksp") version "<ksp-version>"
}

dependencies {
    add("kspCommonMainMetadata", "me.kpavlov.kt.schema:kt-schema-ksp:<version>")
    implementation("me.kpavlov.kt.schema:kt-schema-annotations:<version>")
}

kotlin {
    sourceSets.commonMain.kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}

Then read the schema from the generated extension:

kotlin
val schema: String = Address::class.jsonSchemaString

For JVM-only projects and all processor options, see the KSP Configuration Guide . To see what the schema contains, see Generated Schemas .