Updated ServerPromptsTest, move AbstractTransport to it's own file (#376)

# Refactor and enhance prompt handling logic and tests, update Kotest
version and modularize `AbstractTransport`

- Added more post-conditions/scenarios to ServerPromptsTest
- Extracted `AbstractTransport` to a dedicated file for modularity.
- Improved Protocol connection state validation: When disconnected, the
Protocol will throw `IllegalStateException` instead of `Error`.
- Minor Kotlin fixes and suppressions to improve code quality.

## Motivation and Context

Improve test scenarios in ServerPromptsTest 

## How Has This Been Tested?
Integration tests updated

## Breaking Changes
When disconnected, the Protocol will throw `IllegalStateException`
instead of `Error`.

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Test update
- [x] Refactoring

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [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
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
This commit is contained in:
Konstantin Pavlov 2025-11-12 14:40:33 +02:00 • committed by GitHub
commit 5636faf60c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 282 additions and 67 deletions

View file

@ -558,6 +558,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/AudioContent : io/mo
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getMimeType ()Ljava/lang/String;
public fun getType ()Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -587,6 +588,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/BaseNotificationPara
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/BaseNotificationParams;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/BaseNotificationParams;
public fun equals (Ljava/lang/Object;)Z
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -649,6 +651,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/BlobResourceContents
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getMimeType ()Ljava/lang/String;
public fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -746,6 +749,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CallToolResult : io/
public final fun getContent ()Ljava/util/List;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getStructuredContent ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public final fun isError ()Ljava/lang/Boolean;
public fun toString ()Ljava/lang/String;
@ -811,6 +815,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CancelledNotificatio
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getReason ()Ljava/lang/String;
public final fun getRequestId ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestId;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -920,6 +925,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ClientResult$Compani
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ClientResult$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/ClientResult;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/CommonKt {
public static final field LATEST_PROTOCOL_VERSION Ljava/lang/String;
public static final fun ProgressToken (J)Lio/modelcontextprotocol/kotlin/sdk/types/RequestId;
@ -1063,6 +1072,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CompleteResult : io/
public fun equals (Ljava/lang/Object;)Z
public final fun getCompletion ()Lio/modelcontextprotocol/kotlin/sdk/types/CompleteResult$Completion;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1123,6 +1133,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ContentBlock$Compani
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ContentBlock$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/ContentBlock;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ContentTypes : java/lang/Enum {
public static final field AUDIO Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes$Companion;
@ -1239,6 +1253,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/CreateMessageResult
public final fun getModel ()Ljava/lang/String;
public final fun getRole ()Lio/modelcontextprotocol/kotlin/sdk/types/Role;
public final fun getStopReason-6olV-UY ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1423,6 +1438,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ElicitResult : io/mo
public final fun getAction ()Lio/modelcontextprotocol/kotlin/sdk/types/ElicitResult$Action;
public final fun getContent ()Lkotlinx/serialization/json/JsonObject;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1470,6 +1486,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/EmbeddedResource : i
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getResource ()Lio/modelcontextprotocol/kotlin/sdk/types/ResourceContents;
public fun getType ()Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1499,6 +1516,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/EmptyResult : io/mod
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/EmptyResult;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/EmptyResult;
public fun equals (Ljava/lang/Object;)Z
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1521,6 +1539,8 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/EmptyResult$Companio
public final class io/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest$Companion;
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequestParams;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Map;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Map;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequestParams;
public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequestParams;)Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest;
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest;Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequestParams;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/types/GetPromptRequest;
@ -1595,6 +1615,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/GetPromptResult : io
public final fun getDescription ()Ljava/lang/String;
public final fun getMessages ()Ljava/util/List;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1677,6 +1698,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ImageContent : io/mo
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getMimeType ()Ljava/lang/String;
public fun getType ()Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -1830,6 +1852,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/InitializeResult : i
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getProtocolVersion ()Ljava/lang/String;
public final fun getServerInfo ()Lio/modelcontextprotocol/kotlin/sdk/types/Implementation;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2075,6 +2098,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListPromptsResult :
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getNextCursor ()Ljava/lang/String;
public final fun getPrompts ()Ljava/util/List;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2140,6 +2164,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourceTemplate
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getNextCursor ()Ljava/lang/String;
public final fun getResourceTemplates ()Ljava/util/List;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2205,6 +2230,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListResourcesResult
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getNextCursor ()Ljava/lang/String;
public final fun getResources ()Ljava/util/List;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2267,6 +2293,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListRootsResult : io
public fun equals (Ljava/lang/Object;)Z
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getRoots ()Ljava/util/List;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2332,6 +2359,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ListToolsResult : io
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getNextCursor ()Ljava/lang/String;
public final fun getTools ()Ljava/util/List;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2414,6 +2442,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/LoggingMessageNotifi
public final fun getLevel ()Lio/modelcontextprotocol/kotlin/sdk/types/LoggingLevel;
public final fun getLogger ()Ljava/lang/String;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2449,6 +2478,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/MediaContent$Compani
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/MediaContent$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/MediaContent;)Lkotlinx/serialization/json/JsonObject;
}
public abstract interface class io/modelcontextprotocol/kotlin/sdk/types/Method {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/Method$Companion;
public abstract fun getValue ()Ljava/lang/String;
@ -2602,6 +2635,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/NotificationParams$C
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/NotificationParams$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/NotificationParams;)Lkotlinx/serialization/json/JsonObject;
}
public abstract interface class io/modelcontextprotocol/kotlin/sdk/types/PaginatedRequest : io/modelcontextprotocol/kotlin/sdk/types/Request {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/PaginatedRequest$Companion;
public abstract fun getParams ()Lio/modelcontextprotocol/kotlin/sdk/types/PaginatedRequestParams;
@ -2650,6 +2687,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult$Comp
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/PaginatedResult$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/PaginatedResult;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/PingRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest, io/modelcontextprotocol/kotlin/sdk/types/ServerRequest {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/PingRequest$Companion;
public fun <init> ()V
@ -2752,6 +2793,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ProgressNotification
public final fun getProgress ()D
public final fun getProgressToken ()Lio/modelcontextprotocol/kotlin/sdk/types/RequestId;
public final fun getTotal ()Ljava/lang/Double;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -2790,6 +2832,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Prompt : io/modelcon
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getName ()Ljava/lang/String;
public final fun getTitle ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3049,6 +3092,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ReadResourceResult :
public fun equals (Ljava/lang/Object;)Z
public final fun getContents ()Ljava/util/List;
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3218,6 +3262,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/RequestResult$Compan
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/RequestResult$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/RequestResult;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/Resource : io/modelcontextprotocol/kotlin/sdk/types/ResourceLike {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/Resource$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/Annotations;Ljava/util/List;Lkotlinx/serialization/json/JsonObject;)V
@ -3243,6 +3291,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Resource : io/modelc
public final fun getSize ()Ljava/lang/Long;
public final fun getTitle ()Ljava/lang/String;
public final fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3272,6 +3321,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceContents$Com
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceContents$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/ResourceContents;)Lkotlinx/serialization/json/JsonObject;
}
public abstract interface class io/modelcontextprotocol/kotlin/sdk/types/ResourceLike : io/modelcontextprotocol/kotlin/sdk/types/WithMeta {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ResourceLike$Companion;
}
@ -3280,6 +3333,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceLike$Compani
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceLike$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/ResourceLike;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceLink : io/modelcontextprotocol/kotlin/sdk/types/ContentBlock, io/modelcontextprotocol/kotlin/sdk/types/ResourceLike {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/ResourceLink$Companion;
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/util/List;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/types/Annotations;Lkotlinx/serialization/json/JsonObject;)V
@ -3306,6 +3363,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceLink : io/mo
public final fun getTitle ()Ljava/lang/String;
public fun getType ()Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public final fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3379,6 +3437,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceTemplate : i
public final fun getName ()Ljava/lang/String;
public final fun getTitle ()Ljava/lang/String;
public final fun getUriTemplate ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3466,6 +3525,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ResourceUpdatedNotif
public fun equals (Ljava/lang/Object;)Z
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3511,6 +3571,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Root : io/modelconte
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getName ()Ljava/lang/String;
public final fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3744,6 +3805,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/ServerResult$Compani
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/ServerResult$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/ServerResult;)Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/SetLevelRequest : io/modelcontextprotocol/kotlin/sdk/types/ClientRequest {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/SetLevelRequest$Companion;
public fun <init> (Lio/modelcontextprotocol/kotlin/sdk/types/SetLevelRequestParams;)V
@ -3913,6 +3978,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/TextContent : io/mod
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public final fun getText ()Ljava/lang/String;
public fun getType ()Lio/modelcontextprotocol/kotlin/sdk/types/ContentTypes;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3947,6 +4013,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/TextResourceContents
public fun getMimeType ()Ljava/lang/String;
public final fun getText ()Ljava/lang/String;
public fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -3989,6 +4056,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/Tool : io/modelconte
public final fun getName ()Ljava/lang/String;
public final fun getOutputSchema ()Lio/modelcontextprotocol/kotlin/sdk/types/ToolSchema;
public final fun getTitle ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -4128,6 +4196,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UnknownResourceConte
public fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun getMimeType ()Ljava/lang/String;
public fun getUri ()Ljava/lang/String;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
@ -4211,9 +4280,14 @@ public final class io/modelcontextprotocol/kotlin/sdk/types/UnsubscribeRequestPa
public abstract interface class io/modelcontextprotocol/kotlin/sdk/types/WithMeta {
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/types/WithMeta$Companion;
public abstract fun getMeta ()Lkotlinx/serialization/json/JsonObject;
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/WithMeta$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class io/modelcontextprotocol/kotlin/sdk/types/WithMeta$DefaultImpls {
public static fun get_meta (Lio/modelcontextprotocol/kotlin/sdk/types/WithMeta;)Lkotlinx/serialization/json/JsonObject;
}

View file

@ -0,0 +1,54 @@
package io.modelcontextprotocol.kotlin.sdk.shared
import io.modelcontextprotocol.kotlin.sdk.JSONRPCMessage
import kotlinx.coroutines.CompletableDeferred
/**
* Implements [onClose], [onError] and [onMessage] functions of [Transport] providing
* corresponding [_onClose], [_onError] and [_onMessage] properties to use for an implementation.
*/
@Suppress("PropertyName")
public abstract class AbstractTransport : Transport {
protected var _onClose: (() -> Unit) = {}
private set
protected var _onError: ((Throwable) -> Unit) = {}
private set
// to not skip messages
private val _onMessageInitialized = CompletableDeferred<Unit>()
protected var _onMessage: (suspend ((JSONRPCMessage) -> Unit)) = {
_onMessageInitialized.await()
_onMessage.invoke(it)
}
private set
override fun onClose(block: () -> Unit) {
val old = _onClose
_onClose = {
old()
block()
}
}
override fun onError(block: (Throwable) -> Unit) {
val old = _onError
_onError = { e ->
old(e)
block(e)
}
}
override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) {
val old: suspend (JSONRPCMessage) -> Unit = when (_onMessageInitialized.isCompleted) {
true -> _onMessage
false -> { _ -> }
}
_onMessage = { message ->
old(message)
block(message)
}
_onMessageInitialized.complete(Unit)
}
}

View file

@ -1,7 +1,6 @@
package io.modelcontextprotocol.kotlin.sdk.shared
import io.modelcontextprotocol.kotlin.sdk.types.JSONRPCMessage
import kotlinx.coroutines.CompletableDeferred
/**
* Describes the minimal contract for MCP transport that a client or server can communicate over.
@ -47,53 +46,3 @@ public interface Transport {
*/
public fun onMessage(block: suspend (JSONRPCMessage) -> Unit)
}
/**
* Implements [onClose], [onError] and [onMessage] functions of [Transport] providing
* corresponding [_onClose], [_onError] and [_onMessage] properties to use for an implementation.
*/
@Suppress("PropertyName")
public abstract class AbstractTransport : Transport {
protected var _onClose: (() -> Unit) = {}
private set
protected var _onError: ((Throwable) -> Unit) = {}
private set
// to not skip messages
private val _onMessageInitialized = CompletableDeferred<Unit>()
protected var _onMessage: (suspend ((JSONRPCMessage) -> Unit)) = {
_onMessageInitialized.await()
_onMessage.invoke(it)
}
private set
override fun onClose(block: () -> Unit) {
val old = _onClose
_onClose = {
old()
block()
}
}
override fun onError(block: (Throwable) -> Unit) {
val old = _onError
_onError = { e ->
old(e)
block(e)
}
}
override fun onMessage(block: suspend (JSONRPCMessage) -> Unit) {
val old: suspend (JSONRPCMessage) -> Unit = when (_onMessageInitialized.isCompleted) {
true -> _onMessage
false -> { _ -> }
}
_onMessage = { message ->
old(message)
block(message)
}
_onMessageInitialized.complete(Unit)
}
}

View file

@ -1,5 +1,7 @@
package io.modelcontextprotocol.kotlin.sdk.types
import io.modelcontextprotocol.kotlin.sdk.types.Icon.Theme.Dark
import io.modelcontextprotocol.kotlin.sdk.types.Icon.Theme.Light
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject
@ -27,6 +29,14 @@ public val SUPPORTED_PROTOCOL_VERSIONS: List<String> = listOf(
public sealed interface WithMeta {
@SerialName("_meta")
public val meta: JsonObject?
@Deprecated(
message = "Use 'meta' instead.",
replaceWith = ReplaceWith("meta"),
)
@Suppress("PropertyName", "VariableNaming")
public val _meta: JsonObject
get() = meta ?: EmptyJsonObject
}
// ============================================================================

View file

@ -113,6 +113,22 @@ public data class GetPromptRequest(override val params: GetPromptRequestParams)
@EncodeDefault
override val method: Method = Method.Defined.PromptsGet
@Deprecated(
message = "Use constructor with GetPromptRequestParams instead",
replaceWith = ReplaceWith("GetPromptRequest(GetPromptRequestParams(name, arguments, meta))"),
)
public constructor(
name: String,
arguments: Map<String, String>? = null,
meta: RequestMeta? = null,
) : this(
GetPromptRequestParams(
name = name,
arguments = arguments,
meta = meta,
),
)
/**
* The name of the prompt or prompt template to retrieve.
*/

View file

@ -14,6 +14,7 @@ kotlin {
implementation(dependencies.platform(libs.ktor.bom))
implementation(project(":kotlin-sdk"))
implementation(kotlin("test"))
implementation(libs.kotest.assertions.core)
implementation(libs.kotest.assertions.json)
implementation(libs.kotlin.logging)
implementation(libs.kotlinx.coroutines.test)

View file

@ -1,12 +1,24 @@
package io.modelcontextprotocol.kotlin.sdk.server
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe
import io.kotest.matchers.throwable.shouldHaveMessage
import io.modelcontextprotocol.kotlin.sdk.EmptyJsonObject
import io.modelcontextprotocol.kotlin.sdk.GetPromptRequest
import io.modelcontextprotocol.kotlin.sdk.GetPromptResult
import io.modelcontextprotocol.kotlin.sdk.Implementation
import io.modelcontextprotocol.kotlin.sdk.Method
import io.modelcontextprotocol.kotlin.sdk.Prompt
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities
import io.modelcontextprotocol.kotlin.sdk.types.McpException
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
@ -21,9 +33,51 @@ class OldSchemaServerPromptsTest : OldSchemaAbstractServerFeaturesTest() {
)
@Test
fun `removePrompt should remove a prompt`() = runTest {
fun `Should list no prompts by default`() = runTest {
client.listPrompts() shouldNotBeNull {
prompts.shouldBeEmpty()
}
}
@Test
fun `Should add a prompt`() = runTest {
// Add a prompt
val testPrompt = Prompt("test-prompt", "Test Prompt", null)
val testPrompt = Prompt(
name = "test-prompt-with-custom-handler",
description = "Test Prompt",
arguments = null,
)
val expectedPromptResult = GetPromptResult(
description = "Test prompt description",
messages = listOf(),
)
server.addPrompt(testPrompt) {
expectedPromptResult
}
client.getPrompt(
GetPromptRequest(
name = "test-prompt-with-custom-handler",
arguments = null,
),
) shouldBe expectedPromptResult
client.listPrompts() shouldNotBeNull {
prompts shouldContainExactly listOf(testPrompt)
nextCursor shouldBe null
_meta shouldBe EmptyJsonObject
}
}
@Test
fun `Should remove a prompt`() = runTest {
// given
val testPrompt = Prompt(
name = "test-prompt-to-remove",
description = "Test Prompt",
arguments = null,
)
server.addPrompt(testPrompt) {
GetPromptResult(
description = "Test prompt description",
@ -31,15 +85,32 @@ class OldSchemaServerPromptsTest : OldSchemaAbstractServerFeaturesTest() {
)
}
// Remove the prompt
client.listPrompts() shouldNotBeNull {
prompts shouldContain testPrompt
}
// when
val result = server.removePrompt(testPrompt.name)
// Verify the prompt was removed
// then
assertTrue(result, "Prompt should be removed successfully")
val mcpException = shouldThrow<McpException> {
client.getPrompt(
GetPromptRequest(
name = testPrompt.name,
arguments = null,
),
)
}
mcpException shouldHaveMessage "MCP error -32603: Prompt not found: ${testPrompt.name}"
client.listPrompts() shouldNotBeNull {
prompts.firstOrNull { it.name == testPrompt.name } shouldBe null
}
}
@Test
fun `removePrompts should remove multiple prompts and send notification`() = runTest {
fun `Should remove multiple prompts and send notification`() = runTest {
// Add prompts
val testPrompt1 = Prompt("test-prompt-1", "Test Prompt 1", null)
val testPrompt2 = Prompt("test-prompt-2", "Test Prompt 2", null)
@ -56,11 +127,17 @@ class OldSchemaServerPromptsTest : OldSchemaAbstractServerFeaturesTest() {
)
}
client.listPrompts() shouldNotBeNull {
prompts shouldHaveSize 2
}
// Remove the prompts
val result = server.removePrompts(listOf(testPrompt1.name, testPrompt2.name))
// Verify the prompts were removed
assertEquals(2, result, "Both prompts should be removed")
client.listPrompts() shouldNotBeNull {
prompts.shouldBeEmpty()
}
}
@Test
@ -82,21 +159,55 @@ class OldSchemaServerPromptsTest : OldSchemaAbstractServerFeaturesTest() {
assertFalse(promptListChangedNotificationReceived, "No notification should be sent when prompt doesn't exist")
}
@Test
fun `removePrompt should throw when prompts capability is not supported`() = runTest {
@Nested
inner class NoPromptsCapabilitiesTests {
// Create server without prompts capability
val serverOptions = ServerOptions(
capabilities = ServerCapabilities(),
)
val server = Server(
val serverWithoutPrompts = Server(
Implementation(name = "test server", version = "1.0"),
serverOptions,
ServerOptions(
capabilities = ServerCapabilities(),
),
)
// Verify that removing a prompt throws an exception
val exception = assertThrows<IllegalStateException> {
server.removePrompt("test-prompt")
@Test
fun `RemovePrompt should throw when prompts capability is not supported`() = runTest {
// Verify that removing a prompt throws an exception
val exception = assertThrows<IllegalStateException> {
serverWithoutPrompts.removePrompt("test-prompt")
}
assertEquals("Server does not support prompts capability.", exception.message)
}
@Test
fun `Remove Prompts should throw when prompts capability is not supported`() = runTest {
// Verify that removing a prompt throws an exception
val exception = assertThrows<IllegalStateException> {
serverWithoutPrompts.removePrompts(emptyList())
}
assertEquals("Server does not support prompts capability.", exception.message)
}
@Test
fun `Add Prompt should throw when prompts capability is not supported`() = runTest {
// Verify that removing a prompt throws an exception
val exception = assertThrows<IllegalStateException> {
serverWithoutPrompts.addPrompt(name = "test-prompt") {
GetPromptResult(
description = "Test prompt description",
messages = listOf(),
)
}
}
assertEquals("Server does not support prompts capability.", exception.message)
}
@Test
fun `Add Prompts should throw when prompts capability is not supported`() = runTest {
// Verify that removing a prompt throws an exception
val exception = assertThrows<IllegalStateException> {
serverWithoutPrompts.addPrompts(emptyList())
}
assertEquals("Server does not support prompts capability.", exception.message)
}
assertEquals("Server does not support prompts capability.", exception.message)
}
}