diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b1e985ea..3cd40e99 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -80,6 +80,9 @@ See [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/ * Run `./gradlew assemble` to build the project and produce the corresponding artifacts. * Run `./gradlew test` to test the module and speed up development. * Run `./gradlew build` to build the project, which also runs all the tests. +* Run `./gradlew allTests` to run all tests. + +*note*: when you change the data model, you might need to regenerate the .api files by running `./gradlew apiDump`. ## Contacting maintainers diff --git a/kotlin-sdk-core/api/kotlin-sdk-core.api b/kotlin-sdk-core/api/kotlin-sdk-core.api index ed9a268c..d2299dc2 100644 --- a/kotlin-sdk-core/api/kotlin-sdk-core.api +++ b/kotlin-sdk-core/api/kotlin-sdk-core.api @@ -29,7 +29,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/Annotations$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class io/modelcontextprotocol/kotlin/sdk/AudioContent : io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal { +public final class io/modelcontextprotocol/kotlin/sdk/AudioContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock, io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent, io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/AudioContent$Companion; public static final field TYPE Ljava/lang/String; public fun (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;)V @@ -450,6 +450,14 @@ public final class io/modelcontextprotocol/kotlin/sdk/CompleteResult$Completion$ public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public abstract interface class io/modelcontextprotocol/kotlin/sdk/ContentBlock : io/modelcontextprotocol/kotlin/sdk/PromptMessageContent { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ContentBlock$Companion; +} + +public final class io/modelcontextprotocol/kotlin/sdk/ContentBlock$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/CreateElicitationRequest : io/modelcontextprotocol/kotlin/sdk/ServerRequest, io/modelcontextprotocol/kotlin/sdk/WithMeta { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/CreateElicitationRequest$Companion; public fun (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/CreateElicitationRequest$RequestedSchema;Lkotlinx/serialization/json/JsonObject;)V @@ -622,17 +630,17 @@ public final class io/modelcontextprotocol/kotlin/sdk/CreateMessageRequest$Inclu public final class io/modelcontextprotocol/kotlin/sdk/CreateMessageResult : io/modelcontextprotocol/kotlin/sdk/ClientResult { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult$Companion; - public fun (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;Lkotlinx/serialization/json/JsonObject;)V - public synthetic fun (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent;Lkotlinx/serialization/json/JsonObject;)V + public synthetic fun (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/lang/String; public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/StopReason; public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/Role; - public final fun component4 ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal; + public final fun component4 ()Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent; public final fun component5 ()Lkotlinx/serialization/json/JsonObject; - public final fun copy (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult; - public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult; + public final fun copy (Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/StopReason;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResult; public fun equals (Ljava/lang/Object;)Z - public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal; + public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent; public final fun getModel ()Ljava/lang/String; public final fun getRole ()Lio/modelcontextprotocol/kotlin/sdk/Role; public final fun getStopReason ()Lio/modelcontextprotocol/kotlin/sdk/StopReason; @@ -656,6 +664,14 @@ public final class io/modelcontextprotocol/kotlin/sdk/CreateMessageResult$Compan public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public abstract interface class io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent$Companion; +} + +public final class io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/CustomMeta : io/modelcontextprotocol/kotlin/sdk/WithMeta { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/CustomMeta$Companion; public fun ()V @@ -702,7 +718,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/CustomRequest$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class io/modelcontextprotocol/kotlin/sdk/EmbeddedResource : io/modelcontextprotocol/kotlin/sdk/PromptMessageContent { +public final class io/modelcontextprotocol/kotlin/sdk/EmbeddedResource : io/modelcontextprotocol/kotlin/sdk/ContentBlock { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/EmbeddedResource$Companion; public static final field TYPE Ljava/lang/String; public fun (Lio/modelcontextprotocol/kotlin/sdk/ResourceContents;Lio/modelcontextprotocol/kotlin/sdk/Annotations;)V @@ -875,7 +891,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/GetPromptResult$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class io/modelcontextprotocol/kotlin/sdk/ImageContent : io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal { +public final class io/modelcontextprotocol/kotlin/sdk/ImageContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock, io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent, io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ImageContent$Companion; public static final field TYPE Ljava/lang/String; public fun (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;)V @@ -1994,13 +2010,13 @@ public final class io/modelcontextprotocol/kotlin/sdk/PromptListChangedNotificat public final class io/modelcontextprotocol/kotlin/sdk/PromptMessage { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/PromptMessage$Companion; - public fun (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/ContentBlock;)V public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/Role; - public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent; - public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent;)Lio/modelcontextprotocol/kotlin/sdk/PromptMessage; - public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/PromptMessage;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/PromptMessage; + public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/ContentBlock; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/ContentBlock;)Lio/modelcontextprotocol/kotlin/sdk/PromptMessage; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/PromptMessage;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/ContentBlock;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/PromptMessage; public fun equals (Ljava/lang/Object;)Z - public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent; + public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/ContentBlock; public final fun getRole ()Lio/modelcontextprotocol/kotlin/sdk/Role; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -2022,20 +2038,10 @@ public final class io/modelcontextprotocol/kotlin/sdk/PromptMessage$Companion { } public abstract interface class io/modelcontextprotocol/kotlin/sdk/PromptMessageContent { - public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContent$Companion; public abstract fun getType ()Ljava/lang/String; } -public final class io/modelcontextprotocol/kotlin/sdk/PromptMessageContent$Companion { - public final fun serializer ()Lkotlinx/serialization/KSerializer; -} - public abstract interface class io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal : io/modelcontextprotocol/kotlin/sdk/PromptMessageContent { - public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal$Companion; -} - -public final class io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal$Companion { - public final fun serializer ()Lkotlinx/serialization/KSerializer; } public final class io/modelcontextprotocol/kotlin/sdk/PromptReference : io/modelcontextprotocol/kotlin/sdk/Reference { @@ -2268,6 +2274,48 @@ public final class io/modelcontextprotocol/kotlin/sdk/ResourceContents$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class io/modelcontextprotocol/kotlin/sdk/ResourceLink : io/modelcontextprotocol/kotlin/sdk/ContentBlock { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ResourceLink$Companion; + public static final field TYPE Ljava/lang/String; + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/lang/String; + public final fun component3 ()Ljava/lang/Long; + public final fun component4 ()Ljava/lang/String; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ljava/lang/String; + public final fun component7 ()Lio/modelcontextprotocol/kotlin/sdk/Annotations; + public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;)Lio/modelcontextprotocol/kotlin/sdk/ResourceLink; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/ResourceLink;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Annotations;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/ResourceLink; + public fun equals (Ljava/lang/Object;)Z + public final fun getAnnotations ()Lio/modelcontextprotocol/kotlin/sdk/Annotations; + public final fun getDescription ()Ljava/lang/String; + public final fun getMimeType ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getSize ()Ljava/lang/Long; + public final fun getTitle ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public final fun getUri ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final synthetic class io/modelcontextprotocol/kotlin/sdk/ResourceLink$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/ResourceLink$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/ResourceLink; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/ResourceLink;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class io/modelcontextprotocol/kotlin/sdk/ResourceLink$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/ResourceListChangedNotification : io/modelcontextprotocol/kotlin/sdk/ServerNotification { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ResourceListChangedNotification$Companion; public fun ()V @@ -2558,13 +2606,13 @@ public final class io/modelcontextprotocol/kotlin/sdk/RootsListChangedNotificati public final class io/modelcontextprotocol/kotlin/sdk/SamplingMessage { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage$Companion; - public fun (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;)V + public fun (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent;)V public final fun component1 ()Lio/modelcontextprotocol/kotlin/sdk/Role; - public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal; - public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;)Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage; - public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage; + public final fun component2 ()Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent; + public final fun copy (Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent;)Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage; + public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage;Lio/modelcontextprotocol/kotlin/sdk/Role;Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/SamplingMessage; public fun equals (Ljava/lang/Object;)Z - public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal; + public final fun getContent ()Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent; public final fun getRole ()Lio/modelcontextprotocol/kotlin/sdk/Role; public fun hashCode ()I public fun toString ()Ljava/lang/String; @@ -2585,6 +2633,14 @@ public final class io/modelcontextprotocol/kotlin/sdk/SamplingMessage$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public abstract interface class io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock { + public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/SamplingMessageContent$Companion; +} + +public final class io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class io/modelcontextprotocol/kotlin/sdk/ServerCapabilities { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ServerCapabilities$Companion; public fun ()V @@ -2823,7 +2879,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/SubscribeRequest$Companion public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class io/modelcontextprotocol/kotlin/sdk/TextContent : io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal { +public final class io/modelcontextprotocol/kotlin/sdk/TextContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock, io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent, io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/TextContent$Companion; public static final field TYPE Ljava/lang/String; public fun ()V @@ -3100,7 +3156,7 @@ public final class io/modelcontextprotocol/kotlin/sdk/Types_utilKt { public static synthetic fun ok$default (Lio/modelcontextprotocol/kotlin/sdk/CallToolResult$Companion;Ljava/lang/String;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/CallToolResult; } -public final class io/modelcontextprotocol/kotlin/sdk/UnknownContent : io/modelcontextprotocol/kotlin/sdk/PromptMessageContentMultimodal { +public final class io/modelcontextprotocol/kotlin/sdk/UnknownContent : io/modelcontextprotocol/kotlin/sdk/ContentBlock, io/modelcontextprotocol/kotlin/sdk/CreateMessageResultContent, io/modelcontextprotocol/kotlin/sdk/SamplingMessageContent { public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/UnknownContent$Companion; public fun (Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt index b6879241..4f14930b 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt @@ -970,19 +970,34 @@ public data class GetPromptRequest( override val method: Method = Method.Defined.PromptsGet } -/** - * Represents the content of a prompt message. - */ -@Serializable(with = PromptMessageContentPolymorphicSerializer::class) +@Deprecated("For backwards compatibility; use ContentBlock instead", ReplaceWith("ContentBlock")) public sealed interface PromptMessageContent { public val type: String } +@Deprecated( + "For backwards compatibility; use CreateMessageResultContent or SamplingMessageContent instead", + ReplaceWith("CreateMessageResultContent"), +) +public sealed interface PromptMessageContentMultimodal : PromptMessageContent + /** - * Represents prompt message content that is either text, image or audio. + * Represents the types of a ContentBlock */ -@Serializable(with = PromptMessageContentMultimodalPolymorphicSerializer::class) -public sealed interface PromptMessageContentMultimodal : PromptMessageContent +@Serializable(with = ContentBlockPolymorphicSerializer::class) +public sealed interface ContentBlock : PromptMessageContent + +/** + * Represents content for the CreateMessageResult + */ +@Serializable(with = CreateMessageResultContentMultimodalPolymorphicSerializer::class) +public sealed interface CreateMessageResultContent : ContentBlock + +/** + * Represents content for the SamplingMessage + */ +@Serializable(with = SamplingMessageContentMultimodalPolymorphicSerializer::class) +public sealed interface SamplingMessageContent : ContentBlock /** * Text provided to or from an LLM. @@ -998,7 +1013,9 @@ public data class TextContent( * Optional annotations for the client. */ val annotations: Annotations? = null, -) : PromptMessageContentMultimodal { +) : ContentBlock, + CreateMessageResultContent, + SamplingMessageContent { override val type: String = TYPE public companion object { @@ -1025,7 +1042,9 @@ public data class ImageContent( * Optional annotations for the client. */ val annotations: Annotations? = null, -) : PromptMessageContentMultimodal { +) : ContentBlock, + CreateMessageResultContent, + SamplingMessageContent { override val type: String = TYPE public companion object { @@ -1052,7 +1071,9 @@ public data class AudioContent( * Optional annotations for the client. */ val annotations: Annotations? = null, -) : PromptMessageContentMultimodal { +) : ContentBlock, + CreateMessageResultContent, + SamplingMessageContent { override val type: String = TYPE public companion object { @@ -1060,11 +1081,70 @@ public data class AudioContent( } } +/** + * A Resource Link provided to or from an LLM. + */ +@Serializable +public data class ResourceLink( + /** + * A description of what this resource represents. + * + * This can be used by clients to improve the LLM’s understanding of available resources. It can be thought of like a “hint” to the model. + * + */ + val description: String? = null, + + /** + * Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn’t present). + */ + val name: String, + + /** + * The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known. + * + * This can be used by Hosts to display file sizes and estimate context window usage. + * + */ + val size: Long? = null, + + /** + * Intended for UI and end-user contexts — optimized to be human-readable and easily understood, even by those unfamiliar with domain-specific terminology. + * + * If not provided, the name should be used for display (except for Tool, where annotations.title should be given precedence over using name, if present). + * + */ + val title: String? = null, + + /** + * The URI of this resource. + */ + val uri: String, + + /** + * The MIME type of this resource, if known. + */ + val mimeType: String, + + /** + * Optional annotations for the client. + */ + val annotations: Annotations? = null, +) : ContentBlock { + override val type: String = TYPE + + public companion object { + public const val TYPE: String = "resource_link" + } +} + /** * Unknown content provided to or from an LLM. */ @Serializable -public data class UnknownContent(override val type: String) : PromptMessageContentMultimodal +public data class UnknownContent(override val type: String) : + ContentBlock, + CreateMessageResultContent, + SamplingMessageContent /** * The contents of a resource, embedded into a prompt or tool call result. @@ -1080,7 +1160,7 @@ public data class EmbeddedResource( * Optional annotations for the client. */ val annotations: Annotations? = null, -) : PromptMessageContent { +) : ContentBlock { override val type: String = TYPE public companion object { @@ -1130,7 +1210,7 @@ public data class Annotations( * Describes a message returned as part of a prompt. */ @Serializable -public data class PromptMessage(val role: Role, val content: PromptMessageContent) +public data class PromptMessage(val role: Role, val content: ContentBlock) /** * The server's response to a prompts/get request from the client. @@ -1282,7 +1362,7 @@ public class ListToolsResult( */ @Serializable public sealed interface CallToolResultBase : ServerResult { - public val content: List + public val content: List public val structuredContent: JsonObject? public val isError: Boolean? get() = false } @@ -1292,7 +1372,7 @@ public sealed interface CallToolResultBase : ServerResult { */ @Serializable public class CallToolResult( - override val content: List, + override val content: List, override val structuredContent: JsonObject? = null, override val isError: Boolean? = false, override val _meta: JsonObject = EmptyJsonObject, @@ -1303,7 +1383,7 @@ public class CallToolResult( */ @Serializable public class CompatibilityCallToolResult( - override val content: List, + override val content: List, override val structuredContent: JsonObject? = null, override val isError: Boolean? = false, override val _meta: JsonObject = EmptyJsonObject, @@ -1448,7 +1528,7 @@ public class ModelPreferences( * Describes a message issued to or received from an LLM API. */ @Serializable -public data class SamplingMessage(val role: Role, val content: PromptMessageContentMultimodal) +public data class SamplingMessage(val role: Role, val content: SamplingMessageContent) /** * A request from the server to sample an LLM via the client. @@ -1530,7 +1610,7 @@ public data class CreateMessageResult( */ val stopReason: StopReason? = null, val role: Role, - val content: PromptMessageContentMultimodal, + val content: CreateMessageResultContent, override val _meta: JsonObject = EmptyJsonObject, ) : ClientResult diff --git a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.util.kt b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.util.kt index 07a0bf4c..3cad0891 100644 --- a/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.util.kt +++ b/kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.util.kt @@ -81,21 +81,32 @@ internal object ReferencePolymorphicSerializer : JsonContentPolymorphicSerialize } } -internal object PromptMessageContentPolymorphicSerializer : - JsonContentPolymorphicSerializer(PromptMessageContent::class) { - override fun selectDeserializer(element: JsonElement): DeserializationStrategy = +internal object ContentBlockPolymorphicSerializer : + JsonContentPolymorphicSerializer(ContentBlock::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy = when (element.jsonObject.getValue("type").jsonPrimitive.content) { ImageContent.TYPE -> ImageContent.serializer() TextContent.TYPE -> TextContent.serializer() EmbeddedResource.TYPE -> EmbeddedResource.serializer() AudioContent.TYPE -> AudioContent.serializer() + ResourceLink.TYPE -> ResourceLink.serializer() else -> UnknownContent.serializer() } } -internal object PromptMessageContentMultimodalPolymorphicSerializer : - JsonContentPolymorphicSerializer(PromptMessageContentMultimodal::class) { - override fun selectDeserializer(element: JsonElement): DeserializationStrategy = +internal object CreateMessageResultContentMultimodalPolymorphicSerializer : + JsonContentPolymorphicSerializer(CreateMessageResultContent::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy = + when (element.jsonObject.getValue("type").jsonPrimitive.content) { + ImageContent.TYPE -> ImageContent.serializer() + TextContent.TYPE -> TextContent.serializer() + AudioContent.TYPE -> AudioContent.serializer() + else -> UnknownContent.serializer() + } +} +internal object SamplingMessageContentMultimodalPolymorphicSerializer : + JsonContentPolymorphicSerializer(SamplingMessageContent::class) { + override fun selectDeserializer(element: JsonElement): DeserializationStrategy = when (element.jsonObject.getValue("type").jsonPrimitive.content) { ImageContent.TYPE -> ImageContent.serializer() TextContent.TYPE -> TextContent.serializer() diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesTest.kt index 23e2ffb7..ffadc846 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesTest.kt @@ -81,7 +81,7 @@ class TypesTest { assertEquals("invalid_type", decoded.type) } - // PromptMessageContent Tests + // ContentBlock Tests @Test fun `should validate text content`() { val textContent = TextContent(text = "Hello, world!") @@ -94,8 +94,8 @@ class TypesTest { fun `should serialize and deserialize text content correctly`() { val textContent = TextContent(text = "Test message") - val json = McpJson.encodeToString(textContent) - val decoded = McpJson.decodeFromString(json) + val json = McpJson.encodeToString(textContent) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("text", decoded.type) @@ -121,8 +121,8 @@ class TypesTest { mimeType = "image/jpeg", ) - val json = McpJson.encodeToString(imageContent) - val decoded = McpJson.decodeFromString(json) + val json = McpJson.encodeToString(imageContent) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("image", decoded.type) @@ -149,8 +149,8 @@ class TypesTest { mimeType = "audio/wav", ) - val json = McpJson.encodeToString(audioContent) - val decoded = McpJson.decodeFromString(json) + val json = McpJson.encodeToString(audioContent) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("audio", decoded.type) @@ -158,6 +158,52 @@ class TypesTest { assertEquals("audio/wav", decoded.mimeType) } + @Test + fun `should validate resource link content`() { + val resourceLink = ResourceLink( + mimeType = "application/pdf", + description = "This pdf is meant to be a resource link test", + name = "file01", + size = 76859L, + title = "This is a pdf", + uri = "file:///path/to/my_file.pdf", + ) + + with(resourceLink) { + assertEquals("application/pdf", mimeType) + assertEquals("This pdf is meant to be a resource link test", description) + assertEquals("file01", name) + assertEquals(76859L, size) + assertEquals("This is a pdf", title) + assertEquals("file:///path/to/my_file.pdf", uri) + } + } + + @Test + fun `should serialize and deserialize resource link correctly`() { + val resourceLink = ResourceLink( + mimeType = "application/pdf", + description = "This pdf is meant to be a resource link test", + name = "file01", + size = 76859L, + title = "This is a pdf", + uri = "file:///path/to/my_file.pdf", + ) + + val json = McpJson.encodeToString(resourceLink) + val decoded = McpJson.decodeFromString(json) + + assertIs(decoded) + with(decoded) { + assertEquals("application/pdf", mimeType) + assertEquals("This pdf is meant to be a resource link test", description) + assertEquals("file01", name) + assertEquals(76859L, size) + assertEquals("This is a pdf", title) + assertEquals("file:///path/to/my_file.pdf", uri) + } + } + @Test fun `should validate embedded resource content`() { val resource = TextResourceContents( @@ -180,8 +226,8 @@ class TypesTest { ) val embeddedResource = EmbeddedResource(resource = resource) - val json = McpJson.encodeToString(embeddedResource) - val decoded = McpJson.decodeFromString(json) + val json = McpJson.encodeToString(embeddedResource) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("resource", decoded.type) @@ -196,7 +242,7 @@ class TypesTest { fun `should handle unknown content type`() { val unknownJson = """{"type": "unknown_type"}""" - val decoded = McpJson.decodeFromString(unknownJson) + val decoded = McpJson.decodeFromString(unknownJson) assertIs(decoded) assertEquals("unknown_type", decoded.type) diff --git a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesUtilTest.kt b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesUtilTest.kt index 5207af35..d0a1f184 100644 --- a/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesUtilTest.kt +++ b/kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/TypesUtilTest.kt @@ -111,12 +111,12 @@ class TypesUtilTest { assertEquals("unknown_ref", decoded.type) } - // PromptMessageContent Polymorphic Serializer Tests + // ContentBlock Polymorphic Serializer Tests @Test fun `should deserialize TextContent polymorphically`() { val json = """{"type": "text", "text": "Hello world"}""" - val decoded = McpJson.decodeFromString(json) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("text", decoded.type) @@ -127,7 +127,7 @@ class TypesUtilTest { fun `should deserialize ImageContent polymorphically`() { val json = """{"type": "image", "data": "aW1hZ2U=", "mimeType": "image/png"}""" - val decoded = McpJson.decodeFromString(json) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("image", decoded.type) @@ -139,7 +139,7 @@ class TypesUtilTest { fun `should deserialize AudioContent polymorphically`() { val json = """{"type": "audio", "data": "YXVkaW8=", "mimeType": "audio/mp3"}""" - val decoded = McpJson.decodeFromString(json) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("audio", decoded.type) @@ -147,12 +147,34 @@ class TypesUtilTest { assertEquals("audio/mp3", decoded.mimeType) } + @Test + fun `should deserialize ResourceLink polymorphically`() { + val json = """ + { + "type": "resource_link", + "uri": "file:///project/src/main.rs", + "name": "main.rs", + "description": "Primary application entry point", + "mimeType": "text/x-rust" + } + """.trimIndent() + + val decoded = McpJson.decodeFromString(json) + + assertIs(decoded) + assertEquals("resource_link", decoded.type) + assertEquals("file:///project/src/main.rs", decoded.uri) + assertEquals("main.rs", decoded.name) + assertEquals("Primary application entry point", decoded.description) + assertEquals("text/x-rust", decoded.mimeType) + } + @Test fun `should deserialize EmbeddedResource polymorphically`() { val json = """{"type": "resource", "resource": {"uri": "file:///test.txt", "mimeType": "text/plain", "text": "content"}}""" - val decoded = McpJson.decodeFromString(json) + val decoded = McpJson.decodeFromString(json) assertIs(decoded) assertEquals("resource", decoded.type) diff --git a/kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractToolIntegrationTest.kt b/kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractToolIntegrationTest.kt index 3b0de299..021da486 100644 --- a/kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractToolIntegrationTest.kt +++ b/kotlin-sdk-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/integration/kotlin/AbstractToolIntegrationTest.kt @@ -4,8 +4,8 @@ import io.kotest.assertions.json.shouldEqualJson import io.modelcontextprotocol.kotlin.sdk.CallToolRequest import io.modelcontextprotocol.kotlin.sdk.CallToolResult import io.modelcontextprotocol.kotlin.sdk.CallToolResultBase +import io.modelcontextprotocol.kotlin.sdk.ContentBlock import io.modelcontextprotocol.kotlin.sdk.ImageContent -import io.modelcontextprotocol.kotlin.sdk.PromptMessageContent import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities import io.modelcontextprotocol.kotlin.sdk.TextContent import io.modelcontextprotocol.kotlin.sdk.Tool @@ -402,7 +402,7 @@ abstract class AbstractToolIntegrationTest : KotlinTestBase() { val text = (request.arguments["text"] as? JsonPrimitive)?.content ?: "Default text" val includeImage = (request.arguments["includeImage"] as? JsonPrimitive)?.content?.toBoolean() ?: true - val content = mutableListOf( + val content = mutableListOf( TextContent(text = "Text content: $text"), )