Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ 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
import io.modelcontextprotocol.kotlin.sdk.client.StdioClientTransport
import io.modelcontextprotocol.kotlin.sdk.types.EmptyJsonObject
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.yield
import kotlinx.io.asSink
import kotlinx.io.asSource
import kotlinx.io.buffered
Expand Down Expand Up @@ -137,8 +138,8 @@ class MCPClient : AutoCloseable {
"type": "tool_result",
"tool_name": $toolName,
"result": ${
result?.content?.joinToString("\n") {
(it as TextContent).text ?: ""
result.content.joinToString("\n") {
(it as TextContent).text
}
}
""".trimIndent(),
Expand Down Expand Up @@ -173,6 +174,7 @@ class MCPClient : AutoCloseable {
if (message.lowercase() == "quit") break
val response = processQuery(message)
println("\n$response")
yield()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@ import io.ktor.server.routing.routing
import io.ktor.server.sse.SSE
import io.ktor.server.sse.sse
import io.ktor.util.collections.ConcurrentMap
import io.modelcontextprotocol.kotlin.sdk.CallToolResult
import io.modelcontextprotocol.kotlin.sdk.GetPromptResult
import io.modelcontextprotocol.kotlin.sdk.Implementation
import io.modelcontextprotocol.kotlin.sdk.PromptArgument
import io.modelcontextprotocol.kotlin.sdk.PromptMessage
import io.modelcontextprotocol.kotlin.sdk.ReadResourceResult
import io.modelcontextprotocol.kotlin.sdk.Role
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities
import io.modelcontextprotocol.kotlin.sdk.TextContent
import io.modelcontextprotocol.kotlin.sdk.TextResourceContents
import io.modelcontextprotocol.kotlin.sdk.Tool
import io.modelcontextprotocol.kotlin.sdk.server.Server
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
import io.modelcontextprotocol.kotlin.sdk.server.ServerSession
import io.modelcontextprotocol.kotlin.sdk.server.SseServerTransport
import io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransport
import io.modelcontextprotocol.kotlin.sdk.server.mcp
import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
import io.modelcontextprotocol.kotlin.sdk.types.GetPromptResult
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
import io.modelcontextprotocol.kotlin.sdk.types.PromptArgument
import io.modelcontextprotocol.kotlin.sdk.types.PromptMessage
import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceResult
import io.modelcontextprotocol.kotlin.sdk.types.Role
import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import io.modelcontextprotocol.kotlin.sdk.types.TextResourceContents
import kotlinx.coroutines.Job
import kotlinx.coroutines.runBlocking
import kotlinx.io.asSink
Expand Down Expand Up @@ -66,7 +65,7 @@ fun configureServer(): Server {
GetPromptResult(
messages = listOf(
PromptMessage(
role = Role.user,
role = Role.User,
content = TextContent(
"Develop a kotlin project named <name>${request.arguments?.get("Project Name")}</name>",
),
Expand All @@ -80,7 +79,6 @@ fun configureServer(): Server {
server.addTool(
name = "kotlin-sdk-tool",
description = "A test tool",
inputSchema = Tool.Input(),
) { _ ->
CallToolResult(
content = listOf(TextContent("Hello, world!")),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import io.modelcontextprotocol.kotlin.sdk.EmptyJsonObject
import io.modelcontextprotocol.kotlin.sdk.ReadResourceRequest
import io.modelcontextprotocol.kotlin.sdk.TextContent
import io.modelcontextprotocol.kotlin.sdk.TextResourceContents
import io.modelcontextprotocol.kotlin.sdk.client.Client
import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequest
import io.modelcontextprotocol.kotlin.sdk.types.ReadResourceRequestParams
import io.modelcontextprotocol.kotlin.sdk.types.TextContent
import io.modelcontextprotocol.kotlin.sdk.types.TextResourceContents
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue

class SseServerIntegrationTest {
Expand All @@ -20,7 +21,7 @@ class SseServerIntegrationTest {
val listToolsResult = client.listTools()

// then
assertEquals(expected = EmptyJsonObject, actual = listToolsResult._meta)
assertNull(listToolsResult.meta)

val tools = listToolsResult.tools
assertEquals(actual = tools.size, expected = 1)
Expand All @@ -33,7 +34,7 @@ class SseServerIntegrationTest {
val listPromptsResult = client.listPrompts()

// then
assertEquals(expected = EmptyJsonObject, actual = listPromptsResult._meta)
assertNull(listPromptsResult.meta)

val prompts = listPromptsResult.prompts

Expand All @@ -45,7 +46,7 @@ class SseServerIntegrationTest {
val listResourcesResult = client.listResources()

// then
assertEquals(expected = EmptyJsonObject, actual = listResourcesResult._meta)
assertNull(listResourcesResult.meta)
val resources = listResourcesResult.resources

assertEquals(expected = listOf("Web Search"), actual = resources.map { it.name })
Expand All @@ -55,11 +56,11 @@ class SseServerIntegrationTest {
fun `should get resource`(): Unit = runBlocking {
val testResourceUri = "https://search.com/"
val getResourcesResult = client.readResource(
ReadResourceRequest(uri = testResourceUri),
ReadResourceRequest(ReadResourceRequestParams(uri = testResourceUri)),
)

// then
assertEquals(expected = EmptyJsonObject, actual = getResourcesResult._meta)
assertEquals(expected = null, actual = getResourcesResult.meta)
val contents = getResourcesResult.contents
assertEquals(expected = 1, actual = contents.size)
assertTrue {
Expand All @@ -72,11 +73,14 @@ class SseServerIntegrationTest {
@Test
fun `should call tool`(): Unit = runBlocking {
// when
val toolResult = client.callTool("kotlin-sdk-tool", EmptyJsonObject)
val toolResult = client.callTool(
name = "kotlin-sdk-tool",
arguments = emptyMap(),
)

// then
assertNotNull(toolResult)
assertEquals(expected = EmptyJsonObject, actual = toolResult._meta)
assertNull(toolResult.meta)
val content = toolResult.content.single()
assertIs<TextContent>(content, "Tool result should be a text content")

Expand Down
Loading