Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support generating json schema for tools #32

Open
christophsturm opened this issue Dec 28, 2024 · 8 comments
Open

support generating json schema for tools #32

christophsturm opened this issue Dec 28, 2024 · 8 comments
Labels
enhancement New feature or request

Comments

@christophsturm
Copy link

the mcp docs for tools contain this:
Best practices

When implementing tools:
...
Use detailed JSON Schema definitions for parameters
..

and the typescript sdk examples just dynamically create json schema from the zod types that the typescript examples use. it would be great if the kotlin sdk has something like this too, or an example how to do it. (the current example is very bare bones)

@christophsturm christophsturm added the enhancement New feature or request label Dec 28, 2024
@morisil
Copy link
Contributor

morisil commented Jan 2, 2025

I'm the author of open source library providing this functionality:

https://github.com/xemantic/xemantic-ai-tool-schema

@christophsturm
Copy link
Author

@morisil how can i use that with the kotlin mcp sdk? the json schema field is of type Input:

    @Serializable
    public data class Input(
        val properties: JsonObject = EmptyJsonObject,
        val required: List<String>? = null,
    ) {
        val type: String = "object"
    }

or are you suggesting to fork the sdk? also your claudine library seems to have some overlap with mcp in general, are you planning to make it mcp compatible?

@morisil
Copy link
Contributor

morisil commented Jan 7, 2025

As a quick workaround - add a function translating JsonSchema instance, as produced by my library, to the Input instance of this SDK Tool. Or even instantiate the whole Tool with description from annotated class, as I am doing in my antrhopic-sdk-kotlin:

https://github.com/xemantic/anthropic-sdk-kotlin#using-tools

A long term solution I would like to propose for this project - move my xemantic-ai-tool-schema under the umbrella of the mcp project, and use the JsonSchema class in the API. The argument for this is that such a JsonSchema can be used in several other SDKs, for other LLMs, avoiding boilerplate and translation layers.

@morisil
Copy link
Contributor

morisil commented Jan 7, 2025

Regarding Claudine, I want to keep Claudine1 as an educational project showing the simplest Unix-omnipotent agent on top of the anthropic-sdk-kotlin, with multiplatform compilation targets. Claudine2 I am developing at the moment (might have a different name), will utilize MCP to a great extent.

@morisil
Copy link
Contributor

morisil commented Jan 7, 2025

@christophsturm As a quick workaround you can use something like:

import com.xemantic.ai.tool.schema.ObjectSchema
import com.xemantic.ai.tool.schema.generator.jsonSchemaOf
import io.modelcontextprotocol.kotlin.sdk.Tool.Input
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

public fun ObjectSchema.toMdcToolInput(): Input =
    Json.encodeToJsonElement(this).jsonObject.run {
        Input(
            properties = get("properties")!!.jsonObject,
            required = get("required")?.jsonArray?.map {
                it.jsonPrimitive.content
            }
        )
    }

public inline fun <reified T> Any.mdcToolInput(): Input =
    (jsonSchemaOf<T>() as ObjectSchema).toMdcToolInput()

Here is a test case:

import com.xemantic.kotlin.test.be
import com.xemantic.kotlin.test.have
import com.xemantic.kotlin.test.should
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlin.test.Test

class ObjectSchemaToMdcToolInputTest {

    @Serializable
    private data class Foo(
        val bar: String
    )

    @Test
    fun `Should convert class to MDC Tool Input`() {
        val input = mdcToolInput<Foo>()
        println(input)
        input should {
            have(properties.size == 1)
            properties["bar"] should {
                be<JsonObject>()
                have(size == 1)
                get("type") should {
                    be<JsonPrimitive>()
                    have(content == "string")
                }
            }
            have(required == listOf("bar"))
        }
    }

}

I will package it as a separate library for the time being. Should appear soon here:

https://github.com/xemantic/xemantic-ai-tool-schema-mdc

@morisil
Copy link
Contributor

morisil commented Jan 7, 2025

On a side note, I believe there is a major issue associated with how Tool.Input class is currently defined. It does not cover definitions property, therefore only single object level schemas can be expressed. It is not enough even for my basic use cases, where LLM is calling my tool with properties of type Vector2.

@morisil
Copy link
Contributor

morisil commented Jan 7, 2025

Ok, the project is there, and v0.1 released to maven central:

dependencies {
    implementation("com.xemantic.ai:xemantic-ai-tool-schema-mdc:0.1")
}

@christophsturm
Copy link
Author

On a side note, I believe there is a major issue associated with how Tool.Input class is currently defined. It does not cover definitions property, therefore only single object level schemas can be expressed. It is not enough even for my basic use cases, where LLM is calling my tool with properties of type Vector2.

maybe file a separate issue for that with an example?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants