Skip to content

Commit a9ff1fc

Browse files
authored
Merge branch 'main' into jclyne.10-23-adds_optional__meta_field_to_tool
2 parents 7e361ad + ee341df commit a9ff1fc

File tree

19 files changed

+317
-264
lines changed

19 files changed

+317
-264
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
**/build/reports/
6767
6868
- name: Publish Test Report
69-
uses: mikepenz/action-junit-report@v5
69+
uses: mikepenz/action-junit-report@v6
7070
if: ${{ !cancelled() }} # always run even if the previous step fails
7171
with:
7272
report_paths: '**/test-results/**/TEST-*.xml'

kotlin-sdk-server/api/kotlin-sdk-server.api

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/server/RegisteredTool {
4545
}
4646

4747
public class io/modelcontextprotocol/kotlin/sdk/server/Server {
48-
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Ljava/lang/String;)V
49-
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Lkotlin/jvm/functions/Function0;)V
50-
public synthetic fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
48+
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
49+
public synthetic fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
50+
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)V
51+
public synthetic fun <init> (Lio/modelcontextprotocol/kotlin/sdk/Implementation;Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
5152
public final fun addPrompt (Lio/modelcontextprotocol/kotlin/sdk/Prompt;Lkotlin/jvm/functions/Function2;)V
5253
public final fun addPrompt (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function2;)V
5354
public static synthetic fun addPrompt$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
@@ -61,6 +62,7 @@ public class io/modelcontextprotocol/kotlin/sdk/server/Server {
6162
public final fun addTools (Ljava/util/List;)V
6263
public final fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
6364
public final fun connect (Lio/modelcontextprotocol/kotlin/sdk/shared/Transport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
65+
public final fun createSession (Lio/modelcontextprotocol/kotlin/sdk/shared/Transport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
6466
protected final fun getInstructionsProvider ()Lkotlin/jvm/functions/Function0;
6567
protected final fun getOptions ()Lio/modelcontextprotocol/kotlin/sdk/server/ServerOptions;
6668
public final fun getPrompts ()Ljava/util/Map;

kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/KtorServer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ internal suspend fun ServerSSESession.mcpSseEndpoint(
8888
sseTransportManager.removeTransport(transport.sessionId)
8989
}
9090

91-
server.connect(transport)
91+
server.createSession(transport)
9292

9393
logger.debug { "Server connected to transport for sessionId: ${transport.sessionId}" }
9494
}

kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/Server.kt

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,29 @@ public class ServerOptions(public val capabilities: ServerCapabilities, enforceS
5959
* @param options Configuration options for the server.
6060
* @param instructionsProvider Optional provider for instructions from the server to the client about how to use
6161
* this server. The provider is called each time a new session is started to support dynamic instructions.
62+
* @param block A block to configure the mcp server.
6263
*/
6364

6465
public open class Server(
6566
protected val serverInfo: Implementation,
6667
protected val options: ServerOptions,
6768
protected val instructionsProvider: (() -> String)? = null,
69+
block: Server.() -> Unit = {},
6870
) {
6971
/**
7072
* Alternative constructor that provides the instructions directly as a string.
7173
*
7274
* @param serverInfo Information about this server implementation (name, version).
7375
* @param options Configuration options for the server.
7476
* @param instructions Instructions from the server to the client about how to use this server.
77+
* @param block A block to configure the mcp server.
7578
*/
7679
public constructor(
7780
serverInfo: Implementation,
7881
options: ServerOptions,
7982
instructions: String,
80-
) : this(serverInfo, options, { instructions })
83+
block: Server.() -> Unit = {},
84+
) : this(serverInfo, options, { instructions }, block)
8185

8286
private val sessions = atomic(persistentListOf<ServerSession>())
8387

@@ -100,6 +104,10 @@ public open class Server(
100104
public val resources: Map<String, RegisteredResource>
101105
get() = _resources.value
102106

107+
init {
108+
block(this)
109+
}
110+
103111
public suspend fun close() {
104112
logger.debug { "Closing MCP server" }
105113
sessions.value.forEach { it.close() }
@@ -113,7 +121,21 @@ public open class Server(
113121
* @param transport The transport layer to connect the session with.
114122
* @return The initialized and connected server session.
115123
*/
116-
public suspend fun connect(transport: Transport): ServerSession {
124+
@Deprecated(
125+
"Use createSession(transport) instead.",
126+
ReplaceWith("createSession(transport)"),
127+
DeprecationLevel.WARNING,
128+
)
129+
public suspend fun connect(transport: Transport): ServerSession = createSession(transport)
130+
131+
/**
132+
* Starts a new server session with the given transport and initializes
133+
* internal request handlers based on the server's capabilities.
134+
*
135+
* @param transport The transport layer to connect the session with.
136+
* @return The initialized and connected server session.
137+
*/
138+
public suspend fun createSession(transport: Transport): ServerSession {
117139
val session = ServerSession(serverInfo, options, instructionsProvider?.invoke())
118140

119141
// Internal handlers for tools
@@ -149,6 +171,11 @@ public open class Server(
149171
}
150172
}
151173

174+
// Register cleanup handler to remove session from list when it closes
175+
session.onClose {
176+
logger.debug { "Removing closed session from active sessions list" }
177+
sessions.update { list -> list - session }
178+
}
152179
logger.debug { "Server session connecting to transport" }
153180
session.connect(transport)
154181
logger.debug { "Server session successfully connected to transport" }

kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ServerSession.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public open class ServerSession(
107107
* @return The result of the ping request.
108108
* @throws IllegalStateException If for some reason the method is not supported or the connection is closed.
109109
*/
110-
public suspend fun ping(): EmptyRequestResult = request<EmptyRequestResult>(PingRequest())
110+
public suspend fun ping(): EmptyRequestResult = request(PingRequest())
111111

112112
/**
113113
* Creates a message using the server's sampling capability.
@@ -121,8 +121,12 @@ public open class ServerSession(
121121
params: CreateMessageRequest,
122122
options: RequestOptions? = null,
123123
): CreateMessageResult {
124-
logger.debug { "Creating message with params: $params" }
125-
return request<CreateMessageResult>(params, options)
124+
logger.debug {
125+
"Creating message with ${params.messages.size} messages, maxTokens=${params.maxTokens}, " +
126+
"temperature=${params.temperature}, systemPrompt=${if (params.systemPrompt != null) "present" else "absent"}"
127+
}
128+
logger.trace { "Full createMessage params: $params" }
129+
return request(params, options)
126130
}
127131

128132
/**
@@ -138,15 +142,19 @@ public open class ServerSession(
138142
options: RequestOptions? = null,
139143
): ListRootsResult {
140144
logger.debug { "Listing roots with params: $params" }
141-
return request<ListRootsResult>(ListRootsRequest(params), options)
145+
return request(ListRootsRequest(params), options)
142146
}
143147

144148
public suspend fun createElicitation(
145149
message: String,
146150
requestedSchema: RequestedSchema,
147151
options: RequestOptions? = null,
148152
): CreateElicitationResult {
149-
logger.debug { "Creating elicitation with message: $message" }
153+
logger.debug {
154+
"Creating elicitation with message length=${message.length}, " +
155+
"schema properties count=${requestedSchema.properties.size}"
156+
}
157+
logger.trace { "Full elicitation message: $message, requestedSchema: $requestedSchema" }
150158
return request(CreateElicitationRequest(message, requestedSchema), options)
151159
}
152160

kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/WebSocketMcpKtorServerExtensions.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ internal suspend fun WebSocketServerSession.mcpWebSocketEndpoint(block: () -> Se
6969
val server = block()
7070
var session: ServerSession? = null
7171
try {
72-
session = server.connect(transport)
72+
session = server.createSession(transport)
7373
awaitCancellation()
7474
} catch (e: CancellationException) {
7575
session?.close()
@@ -103,7 +103,7 @@ public fun Route.mcpWebSocket(options: ServerOptions? = null, handler: suspend S
103103
)
104104
public fun Route.mcpWebSocket(block: () -> Server) {
105105
webSocket {
106-
block().connect(createMcpTransport(this))
106+
block().createSession(createMcpTransport(this))
107107
}
108108
}
109109

@@ -190,7 +190,7 @@ private suspend fun Route.createMcpServer(
190190
),
191191
)
192192

193-
server.connect(transport)
193+
server.createSession(transport)
194194
handler(server)
195195
server.close()
196196
}

kotlin-sdk-test/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ kotlin {
2424
}
2525
jvmTest {
2626
dependencies {
27-
implementation(kotlin("test-junit5"))
2827
implementation(libs.awaitility)
2928
runtimeOnly(libs.slf4j.simple)
3029
}

kotlin-sdk-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/ClientTest.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ class ClientTest {
258258
client.connect(clientTransport)
259259
},
260260
launch {
261-
serverSessionResult.complete(server.connect(serverTransport))
261+
serverSessionResult.complete(server.createSession(serverTransport))
262262
},
263263
).joinAll()
264264

@@ -322,7 +322,7 @@ class ClientTest {
322322
println("Client connected")
323323
},
324324
launch {
325-
server.connect(serverTransport)
325+
server.createSession(serverTransport)
326326
println("Server connected")
327327
},
328328
).joinAll()
@@ -379,7 +379,7 @@ class ClientTest {
379379
println("Client connected")
380380
},
381381
launch {
382-
serverSessionResult.complete(server.connect(serverTransport))
382+
serverSessionResult.complete(server.createSession(serverTransport))
383383
println("Server connected")
384384
},
385385
).joinAll()
@@ -439,7 +439,7 @@ class ClientTest {
439439
println("Client connected")
440440
},
441441
launch {
442-
serverSessionResult.complete(server.connect(serverTransport))
442+
serverSessionResult.complete(server.createSession(serverTransport))
443443
println("Server connected")
444444
},
445445
).joinAll()
@@ -502,7 +502,7 @@ class ClientTest {
502502
println("Client connected")
503503
},
504504
launch {
505-
serverSessionResult.complete(server.connect(serverTransport))
505+
serverSessionResult.complete(server.createSession(serverTransport))
506506
println("Server connected")
507507
},
508508
).joinAll()
@@ -594,7 +594,7 @@ class ClientTest {
594594
println("Client connected")
595595
},
596596
launch {
597-
serverSessionResult.complete(server.connect(serverTransport))
597+
serverSessionResult.complete(server.createSession(serverTransport))
598598
println("Server connected")
599599
},
600600
).joinAll()
@@ -680,7 +680,7 @@ class ClientTest {
680680
println("Client connected")
681681
},
682682
launch {
683-
serverSessionResult.complete(server.connect(serverTransport))
683+
serverSessionResult.complete(server.createSession(serverTransport))
684684
println("Server connected")
685685
},
686686
).joinAll()
@@ -812,7 +812,7 @@ class ClientTest {
812812
println("Client connected")
813813
},
814814
launch {
815-
serverSessionResult.complete(server.connect(serverTransport))
815+
serverSessionResult.complete(server.createSession(serverTransport))
816816
println("Server connected")
817817
},
818818
).joinAll()
@@ -859,7 +859,7 @@ class ClientTest {
859859
println("Client connected")
860860
},
861861
launch {
862-
serverSessionResult.complete(server.connect(serverTransport))
862+
serverSessionResult.complete(server.createSession(serverTransport))
863863
println("Server connected")
864864
},
865865
).joinAll()
@@ -939,7 +939,7 @@ class ClientTest {
939939
println("Client connected")
940940
},
941941
launch {
942-
serverSessionResult.complete(server.connect(serverTransport))
942+
serverSessionResult.complete(server.createSession(serverTransport))
943943
println("Server connected")
944944
},
945945
).joinAll()

kotlin-sdk-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/SseTransportTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class SseTransportTest : BaseTransportTest() {
4848

4949
val actualPort = server.actualPort()
5050

51-
val client = HttpClient {
51+
val transport = HttpClient {
5252
install(ClientSSE)
5353
}.mcpSseTransport {
5454
url {
@@ -58,7 +58,7 @@ class SseTransportTest : BaseTransportTest() {
5858
}
5959

6060
try {
61-
testClientOpenClose(client)
61+
testTransportRead(transport)
6262
} finally {
6363
server.stopSuspend()
6464
}
@@ -76,7 +76,7 @@ class SseTransportTest : BaseTransportTest() {
7676

7777
val actualPort = server.actualPort()
7878

79-
val client = HttpClient {
79+
val transport = HttpClient {
8080
install(ClientSSE)
8181
}.mcpSseTransport {
8282
url {
@@ -86,7 +86,7 @@ class SseTransportTest : BaseTransportTest() {
8686
}
8787

8888
try {
89-
testClientRead(client)
89+
testTransportRead(transport)
9090
} finally {
9191
server.stopSuspend()
9292
}
@@ -104,7 +104,7 @@ class SseTransportTest : BaseTransportTest() {
104104

105105
val actualPort = server.actualPort()
106106

107-
val client = HttpClient {
107+
val transport = HttpClient {
108108
install(ClientSSE)
109109
}.mcpSseTransport {
110110
url {
@@ -115,7 +115,7 @@ class SseTransportTest : BaseTransportTest() {
115115
}
116116

117117
try {
118-
testClientRead(client)
118+
testTransportRead(transport)
119119
} finally {
120120
server.stopSuspend()
121121
}

kotlin-sdk-test/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/WebSocketTransportTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class WebSocketTransportTest : BaseTransportTest() {
2222
install(io.ktor.client.plugins.websocket.WebSockets)
2323
}.mcpWebSocketTransport()
2424

25-
testClientOpenClose(client)
25+
testTransportOpenClose(client)
2626
}
2727

2828
@Test
@@ -41,11 +41,11 @@ class WebSocketTransportTest : BaseTransportTest() {
4141
}
4242
}
4343

44-
val client = createClient {
44+
val transport = createClient {
4545
install(io.ktor.client.plugins.websocket.WebSockets)
4646
}.mcpWebSocketTransport()
4747

48-
testClientRead(client)
48+
testTransportRead(transport)
4949

5050
clientFinished.complete(Unit)
5151
}

0 commit comments

Comments
 (0)