@@ -51,11 +51,11 @@ import kotlinx.collections.immutable.minus
5151import kotlinx.collections.immutable.persistentMapOf
5252import kotlinx.collections.immutable.toPersistentSet
5353import kotlinx.serialization.ExperimentalSerializationApi
54- import kotlinx.serialization.json.JsonArray
5554import kotlinx.serialization.json.JsonElement
5655import kotlinx.serialization.json.JsonNull
5756import kotlinx.serialization.json.JsonObject
5857import kotlinx.serialization.json.JsonPrimitive
58+ import kotlinx.serialization.json.add
5959import kotlinx.serialization.json.buildJsonArray
6060import kotlinx.serialization.json.buildJsonObject
6161import kotlin.coroutines.cancellation.CancellationException
@@ -189,20 +189,14 @@ public open class Client(private val clientInfo: Implementation, options: Client
189189 }
190190 }
191191
192- Method .Defined .PromptsGet ,
193- Method .Defined .PromptsList ,
194- Method .Defined .CompletionComplete ,
195- -> {
192+ Method .Defined .PromptsGet , Method .Defined .PromptsList , Method .Defined .CompletionComplete -> {
196193 if (serverCapabilities?.prompts == null ) {
197194 throw IllegalStateException (" Server does not support prompts (required for $method )" )
198195 }
199196 }
200197
201- Method .Defined .ResourcesList ,
202- Method .Defined .ResourcesTemplatesList ,
203- Method .Defined .ResourcesRead ,
204- Method .Defined .ResourcesSubscribe ,
205- Method .Defined .ResourcesUnsubscribe ,
198+ Method .Defined .ResourcesList , Method .Defined .ResourcesTemplatesList ,
199+ Method .Defined .ResourcesRead , Method .Defined .ResourcesSubscribe , Method .Defined .ResourcesUnsubscribe ,
206200 -> {
207201 val resCaps = serverCapabilities?.resources
208202 ? : error(" Server does not support resources (required for $method )" )
@@ -214,17 +208,13 @@ public open class Client(private val clientInfo: Implementation, options: Client
214208 }
215209 }
216210
217- Method .Defined .ToolsCall ,
218- Method .Defined .ToolsList ,
219- -> {
211+ Method .Defined .ToolsCall , Method .Defined .ToolsList -> {
220212 if (serverCapabilities?.tools == null ) {
221213 throw IllegalStateException (" Server does not support tools (required for $method )" )
222214 }
223215 }
224216
225- Method .Defined .Initialize ,
226- Method .Defined .Ping ,
227- -> {
217+ Method .Defined .Initialize , Method .Defined .Ping -> {
228218 // No specific capability required
229219 }
230220
@@ -604,31 +594,37 @@ public open class Client(private val clientInfo: Implementation, options: Client
604594 private fun validateMetaKeys (keys : Set <String >) {
605595 val labelPattern = Regex (" [a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?" )
606596 val namePattern = Regex (" [a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?" )
607-
597+
608598 keys.forEach { key ->
609599 require(key.isNotEmpty()) { " Meta key cannot be empty" }
610-
600+
611601 val (prefix, name) = key.split(' /' , limit = 2 ).let { parts ->
612602 when (parts.size) {
613603 1 -> null to parts[0 ]
614- else -> parts[0 ] to parts[1 ]
604+ 2 -> parts[0 ] to parts[1 ]
605+ else -> throw IllegalArgumentException (" Unexpected split result for key: $key " )
615606 }
616607 }
617-
608+
618609 // Validate prefix if present
619610 prefix?.let {
620611 require(it.isNotEmpty()) { " Invalid _meta key '$key ': prefix cannot be empty" }
621-
612+
622613 val labels = it.split(' .' )
623614 require(labels.all { label -> label.matches(labelPattern) }) {
624615 " Invalid _meta key '$key ': prefix labels must start with a letter, end with letter/digit, and contain only letters, digits, or hyphens"
625616 }
626-
627- require(labels.none { label -> label.equals(" modelcontextprotocol" , ignoreCase = true ) || label.equals(" mcp" , ignoreCase = true ) }) {
617+
618+ require(
619+ labels.none { label ->
620+ label.equals(" modelcontextprotocol" , ignoreCase = true ) ||
621+ label.equals(" mcp" , ignoreCase = true )
622+ },
623+ ) {
628624 " Invalid _meta key '$key ': prefix cannot contain reserved labels 'modelcontextprotocol' or 'mcp'"
629625 }
630626 }
631-
627+
632628 // Validate name (empty allowed)
633629 require(name.isEmpty() || name.matches(namePattern)) {
634630 " Invalid _meta key '$key ': name must start and end with alphanumeric characters, and contain only alphanumerics, hyphens, underscores, or dots"
@@ -648,45 +644,53 @@ public open class Client(private val clientInfo: Implementation, options: Client
648644 @OptIn(ExperimentalUnsignedTypes ::class , ExperimentalSerializationApi ::class )
649645 private fun convertToJsonElement (value : Any? ): JsonElement = when (value) {
650646 null -> JsonNull
647+
651648 is JsonElement -> value
649+
652650 is String -> JsonPrimitive (value)
651+
653652 is Number -> JsonPrimitive (value)
653+
654654 is Boolean -> JsonPrimitive (value)
655+
655656 is Char -> JsonPrimitive (value.toString())
657+
656658 is Enum <* > -> JsonPrimitive (value.name)
657659
658- is Map <* , * > -> buildJsonObject {
659- value.forEach { (k, v) ->
660- put(k.toString(), convertToJsonElement(v))
661- }
662- }
660+ is Map <* , * > -> buildJsonObject { value.forEach { (k, v) -> put(k.toString(), convertToJsonElement(v)) } }
663661
664- is Collection <* > -> buildJsonArray {
665- value.forEach { add(convertToJsonElement(it)) }
666- }
662+ is Collection <* > -> buildJsonArray { value.forEach { add(convertToJsonElement(it)) } }
667663
668- is Array <* > -> buildJsonArray {
669- value.forEach { add(convertToJsonElement(it)) }
670- }
664+ is Array <* > -> buildJsonArray { value.forEach { add(convertToJsonElement(it)) } }
671665
672- // Primitive arrays - use iterator for unified handling
666+ // Primitive arrays
673667 is IntArray -> buildJsonArray { value.forEach { add(it) } }
668+
674669 is LongArray -> buildJsonArray { value.forEach { add(it) } }
670+
675671 is FloatArray -> buildJsonArray { value.forEach { add(it) } }
672+
676673 is DoubleArray -> buildJsonArray { value.forEach { add(it) } }
674+
677675 is BooleanArray -> buildJsonArray { value.forEach { add(it) } }
676+
678677 is ShortArray -> buildJsonArray { value.forEach { add(it) } }
678+
679679 is ByteArray -> buildJsonArray { value.forEach { add(it) } }
680+
680681 is CharArray -> buildJsonArray { value.forEach { add(it.toString()) } }
681682
682- // ExperimentalUnsignedTypes
683- is UIntArray -> buildJsonArray { value.forEach { add(it) } }
684- is ULongArray -> buildJsonArray { value.forEach { add(it) } }
685- is UShortArray -> buildJsonArray { value.forEach { add(it) } }
686- is UByteArray -> buildJsonArray { value.forEach { add(it) } }
683+ // Unsigned arrays
684+ is UIntArray -> buildJsonArray { value.forEach { add(JsonPrimitive (it)) } }
685+
686+ is ULongArray -> buildJsonArray { value.forEach { add(JsonPrimitive (it)) } }
687+
688+ is UShortArray -> buildJsonArray { value.forEach { add(JsonPrimitive (it)) } }
689+
690+ is UByteArray -> buildJsonArray { value.forEach { add(JsonPrimitive (it)) } }
687691
688692 else -> {
689- logger.debug { " Converting unknown type ${value::class .simpleName } to string: $value " }
693+ logger.debug { " Converting unknown type ${value::class } to string: $value " }
690694 JsonPrimitive (value.toString())
691695 }
692696 }
0 commit comments