Skip to content

Support for MCP definations using kotlin annotation #80

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

alpeshvas
Copy link

@alpeshvas alpeshvas commented Apr 15, 2025

Motivation and Context

Add support for #76

How Has This Been Tested?

Unit tested and built jar was locally tested with MCP server built with annotations.

Breaking Changes

No

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@alpeshvas alpeshvas marked this pull request as ready for review April 15, 2025 14:55
@alpeshvas
Copy link
Author

@devcrocod @e5l it's ready for review.

@devcrocod
Copy link
Contributor

Sorry, I don’t fully understand the motivation.
There is already xemantic-ai-tool-schema, which was discussed in #32
There is also victools/jsonschema-generator.
Why is a separate implementation needed in kotlin-sdk?

@alpeshvas
Copy link
Author

alpeshvas commented Apr 16, 2025

Sorry, I don’t fully understand the motivation. There is already xemantic-ai-tool-schema, which was discussed in #32 There is also victools/jsonschema-generator. Why is a separate implementation needed in kotlin-sdk?

It basically provides better and more kotlin idiomatic way to define MCP tool.
Earlier, to define a MCP tool (https://modelcontextprotocol.io/docs/concepts/tools), there is a lot which you need to write, which can be derived from the kotlin method signature.

server.addTool(
    name = "get_forecast",
    description = """
        Get weather forecast for a specific latitude/longitude
    """.trimIndent(),
    inputSchema = Tool.Input(
        properties = buildJsonObject {
            putJsonObject("latitude") {
                put("type", "number")
            }
            putJsonObject("longitude") {
                put("type", "number")
            }
        },
        required = listOf("latitude", "longitude")
    )
)

Now, with the proposed changes, defining a MCP tool is simpler with annotation ( uses kotlin annotations https://kotlinlang.org/docs/annotations.html) similar to how it's there in python sdk which uses decorators (similar concept to kotlin annotations).

check out this for example which we built using jar from this changes:

@McpTool(
    name = "get_forecast",
    description = "Get weather forecast for a specific latitude/longitude",
)
fun getForecastTool(latitude: Float, longitude: Float) 

so in short, it's less of a schema generators and more around simplifying MCP tool definitions for kotlin-sdk users.

@devcrocod
Copy link
Contributor

That’s understandable, but it doesn’t explain why not support one of the libraries I sent earlier.

Besides, the solution using annotations seems excessive to me at this point.
It would be possible to support required without passing it as a parameter in the annotation, but instead by using the information about the default values of the parameters

Also, adding such a solution complicates support for multiplatform #70 , since reflection is platform-dependent

@alpeshvas
Copy link
Author

alpeshvas commented Apr 16, 2025

but it doesn’t explain why not support one of the libraries I sent earlier.

because they're MCP agnostic and have a generic purpose (schema generation)

It would be possible to support required without passing it as a parameter in the annotation, but instead by using the information about the default values of the parameters

required is only one of the usecase, larger purpose is to reduce verbosity defining MCP tool. i.e

server.addTool(
    name = "kljlkjlkj",
    description = """kljkljjlk""".trimIndent(),
    inputSchema = Tool.Input(
        properties = buildJsonObject {
            putJsonObject("latitude") {
                put("type", "number")
            }
            putJsonObject("longitude") {
                put("type", "number")
            }
        },
        required = listOf("latitude", "longitude")
    )
)

currently, it's too verbose to define a tool and can be simplified.

Also, adding such a solution complicates support for multiplatform #70 , since reflection is platform-dependent

fair point, hence this PR adds support for doing it with annotations as an another way instead of replacing current one.

@alpeshvas alpeshvas changed the title tool annotation support MCP definations using kotlin annotation support Apr 17, 2025
@alpeshvas alpeshvas changed the title MCP definations using kotlin annotation support Support for MCP definations using kotlin annotation Apr 17, 2025
@Stream29
Copy link

Stream29 commented Apr 27, 2025

I'm working on a solution based on KSP.

With that, we can do this:

@McpServerComponent
public class MyServerComponent {
    @McpTool
    public suspend fun response(message: String): String {
        return "Hello, $message"
    }
}

Generate code from below code (@McpServerCompnent @mcptool annotation) with KSP as follow:

public fun MyServerComponent.tools(adapter: ServerAdapter = ServerAdapter()): List<RegisteredTool>= ...(Implementation)

And we can use it like:

val server = Server(...)
val component = MyServerComponent()
server.addTools(component.tools())

I think this plan is friendly for dependency injection and Kotlin Multiplatform, with less runtime cost.

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

Successfully merging this pull request may close these issues.

3 participants