New MCP Schema types (#386)
Implement the last version of the mcp schema and complete restructuring of the mcp schema implementation from a monolithic `types.kt` file into separate files. - #158 - #185 - #353 - #298 - #248 ## Motivation and Context The previous implementation of the mcp schema was outdated and contained several issues. In addition, it stored all mcp types in a single large file, which made maintenance and further development more difficult ## How Has This Been Tested? All tests passed ## Breaking Changes Yes. The new types are now located in a separate package. Additionally, many types have new parameters and modified constructors ## Types of changes - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context to adopt the new structure: **Before:** ```kotlin import io.modelcontextprotocol.kotlin.sdk.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.Resource ``` **After:** ```kotlin import io.modelcontextprotocol.kotlin.sdk.types.InitializeRequest import io.modelcontextprotocol.kotlin.sdk.types.Resource ```
This commit is contained in:
parent
91d45b0f8d
commit
21393e7ce3
5 changed files with 13048 additions and 4230 deletions
|
|
@ -9,6 +9,7 @@ import com.anthropic.models.messages.Tool
|
|||
import com.anthropic.models.messages.ToolUnion
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import io.modelcontextprotocol.kotlin.sdk.EmptyJsonObject
|
||||
import io.modelcontextprotocol.kotlin.sdk.Implementation
|
||||
import io.modelcontextprotocol.kotlin.sdk.TextContent
|
||||
import io.modelcontextprotocol.kotlin.sdk.client.Client
|
||||
|
|
@ -76,7 +77,7 @@ class MCPClient : AutoCloseable {
|
|||
.inputSchema(
|
||||
Tool.InputSchema.builder()
|
||||
.type(JsonValue.from(tool.inputSchema.type))
|
||||
.properties(tool.inputSchema.properties.toJsonValue())
|
||||
.properties(tool.inputSchema.properties?.toJsonValue() ?: EmptyJsonObject.toJsonValue())
|
||||
.putAdditionalProperty("required", JsonValue.from(tool.inputSchema.required))
|
||||
.build(),
|
||||
)
|
||||
|
|
@ -135,9 +136,11 @@ class MCPClient : AutoCloseable {
|
|||
"""
|
||||
"type": "tool_result",
|
||||
"tool_name": $toolName,
|
||||
"result": ${result?.content?.joinToString("\n") {
|
||||
(it as TextContent).text ?: ""
|
||||
}}
|
||||
"result": ${
|
||||
result?.content?.joinToString("\n") {
|
||||
(it as TextContent).text ?: ""
|
||||
}
|
||||
}
|
||||
""".trimIndent(),
|
||||
)
|
||||
.build(),
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ fun configureServer(): Server {
|
|||
),
|
||||
) { request ->
|
||||
GetPromptResult(
|
||||
"Description for ${request.name}",
|
||||
messages = listOf(
|
||||
PromptMessage(
|
||||
role = Role.user,
|
||||
|
|
@ -73,6 +72,7 @@ fun configureServer(): Server {
|
|||
),
|
||||
),
|
||||
),
|
||||
description = "Description for ${request.name}",
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import io.modelcontextprotocol.kotlin.sdk.EmptyJsonObject
|
|||
import io.modelcontextprotocol.kotlin.sdk.TextContent
|
||||
import io.modelcontextprotocol.kotlin.sdk.client.Client
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertIs
|
||||
|
|
@ -39,6 +38,6 @@ class SseServerIntegrationTest {
|
|||
assertIs<TextContent>(content, "Tool result should be a text content")
|
||||
|
||||
assertEquals(expected = "Hello, world!", actual = content.text)
|
||||
assertEquals(expected = "text", actual = content.type)
|
||||
assertEquals(expected = "text", actual = "${content.type}".lowercase())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ fun runMcpServer() {
|
|||
required = listOf("state"),
|
||||
),
|
||||
) { request ->
|
||||
val state = request.arguments["state"]?.jsonPrimitive?.content ?: return@addTool CallToolResult(
|
||||
val state = request.arguments?.get("state")?.jsonPrimitive?.content ?: return@addTool CallToolResult(
|
||||
content = listOf(TextContent("The 'state' parameter is required.")),
|
||||
)
|
||||
|
||||
|
|
@ -109,8 +109,8 @@ fun runMcpServer() {
|
|||
required = listOf("latitude", "longitude"),
|
||||
),
|
||||
) { request ->
|
||||
val latitude = request.arguments["latitude"]?.jsonPrimitive?.doubleOrNull
|
||||
val longitude = request.arguments["longitude"]?.jsonPrimitive?.doubleOrNull
|
||||
val latitude = request.arguments?.get("latitude")?.jsonPrimitive?.doubleOrNull
|
||||
val longitude = request.arguments?.get("longitude")?.jsonPrimitive?.doubleOrNull
|
||||
if (latitude == null || longitude == null) {
|
||||
return@addTool CallToolResult(
|
||||
content = listOf(TextContent("The 'latitude' and 'longitude' parameters are required.")),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package io.modelcontextprotocol.sample.client
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.CallToolRequest
|
||||
import io.modelcontextprotocol.kotlin.sdk.Implementation
|
||||
import io.modelcontextprotocol.kotlin.sdk.TextContent
|
||||
import io.modelcontextprotocol.kotlin.sdk.client.Client
|
||||
|
|
@ -9,9 +8,6 @@ import kotlinx.coroutines.runBlocking
|
|||
import kotlinx.io.asSink
|
||||
import kotlinx.io.asSource
|
||||
import kotlinx.io.buffered
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
|
||||
fun main(): Unit = runBlocking {
|
||||
val process = ProcessBuilder("java", "-jar", "./build/libs/weather-stdio-server-0.1.0-all.jar")
|
||||
|
|
@ -33,12 +29,10 @@ fun main(): Unit = runBlocking {
|
|||
println("Available Tools = $toolsList")
|
||||
|
||||
val weatherForecastResult = client.callTool(
|
||||
CallToolRequest(
|
||||
name = "get_forecast",
|
||||
arguments = buildJsonObject {
|
||||
put("latitude", JsonPrimitive(38.5816))
|
||||
put("longitude", JsonPrimitive(-121.4944))
|
||||
},
|
||||
name = "get_forecast",
|
||||
arguments = mapOf(
|
||||
"latitude" to 38.5816,
|
||||
"longitude" to -121.4944,
|
||||
),
|
||||
)?.content?.map { if (it is TextContent) it.text else it.toString() }
|
||||
|
||||
|
|
@ -46,10 +40,8 @@ fun main(): Unit = runBlocking {
|
|||
|
||||
val alertResult =
|
||||
client.callTool(
|
||||
CallToolRequest(
|
||||
name = "get_alerts",
|
||||
arguments = JsonObject(mapOf("state" to JsonPrimitive("TX"))),
|
||||
),
|
||||
name = "get_alert",
|
||||
arguments = mapOf("state" to "TX"),
|
||||
)?.content?.map { if (it is TextContent) it.text else it.toString() }
|
||||
|
||||
println("Alert Response = $alertResult")
|
||||
|
|
|
|||
Loading…
Reference in a new issue