Skip to content

Commit 89c2037

Browse files
SeanChinJunKaidevcrocode5l
authored
feat: add tool annotations according to 2025-03-26 spec (#71)
* feat: add tool annotations * chore: commit api dump * fix import and api --------- Co-authored-by: devcrocod <[email protected]> Co-authored-by: Leonid Stashevsky <[email protected]>
1 parent ed842e5 commit 89c2037

File tree

5 files changed

+105
-7
lines changed

5 files changed

+105
-7
lines changed

api/kotlin-sdk.api

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,13 +2439,15 @@ public final class io/modelcontextprotocol/kotlin/sdk/TextResourceContents$Compa
24392439

24402440
public final class io/modelcontextprotocol/kotlin/sdk/Tool {
24412441
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/Tool$Companion;
2442-
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;)V
2442+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;)V
24432443
public final fun component1 ()Ljava/lang/String;
24442444
public final fun component2 ()Ljava/lang/String;
24452445
public final fun component3 ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;
2446-
public final fun copy (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2447-
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/Tool;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2446+
public final fun component4 ()Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
2447+
public final fun copy (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2448+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/Tool;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
24482449
public fun equals (Ljava/lang/Object;)Z
2450+
public final fun getAnnotations ()Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
24492451
public final fun getDescription ()Ljava/lang/String;
24502452
public final fun getInputSchema ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;
24512453
public final fun getName ()Ljava/lang/String;
@@ -2500,6 +2502,42 @@ public final class io/modelcontextprotocol/kotlin/sdk/Tool$Input$Companion {
25002502
public final fun serializer ()Lkotlinx/serialization/KSerializer;
25012503
}
25022504

2505+
public final class io/modelcontextprotocol/kotlin/sdk/ToolAnnotations {
2506+
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations$Companion;
2507+
public fun <init> (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;)V
2508+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
2509+
public final fun component1 ()Ljava/lang/String;
2510+
public final fun component2 ()Ljava/lang/Boolean;
2511+
public final fun component3 ()Ljava/lang/Boolean;
2512+
public final fun component4 ()Ljava/lang/Boolean;
2513+
public final fun component5 ()Ljava/lang/Boolean;
2514+
public final fun copy (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;)Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
2515+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;Ljava/lang/Boolean;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
2516+
public fun equals (Ljava/lang/Object;)Z
2517+
public final fun getDestructiveHint ()Ljava/lang/Boolean;
2518+
public final fun getIdempotentHint ()Ljava/lang/Boolean;
2519+
public final fun getOpenWorldHint ()Ljava/lang/Boolean;
2520+
public final fun getReadOnlyHint ()Ljava/lang/Boolean;
2521+
public final fun getTitle ()Ljava/lang/String;
2522+
public fun hashCode ()I
2523+
public fun toString ()Ljava/lang/String;
2524+
}
2525+
2526+
public final synthetic class io/modelcontextprotocol/kotlin/sdk/ToolAnnotations$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
2527+
public static final field INSTANCE Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations$$serializer;
2528+
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
2529+
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
2530+
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
2531+
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
2532+
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;)V
2533+
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
2534+
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
2535+
}
2536+
2537+
public final class io/modelcontextprotocol/kotlin/sdk/ToolAnnotations$Companion {
2538+
public final fun serializer ()Lkotlinx/serialization/KSerializer;
2539+
}
2540+
25032541
public final class io/modelcontextprotocol/kotlin/sdk/ToolListChangedNotification : io/modelcontextprotocol/kotlin/sdk/ServerNotification {
25042542
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/ToolListChangedNotification$Companion;
25052543
public fun <init> ()V
@@ -2824,8 +2862,8 @@ public class io/modelcontextprotocol/kotlin/sdk/server/Server : io/modelcontextp
28242862
public final fun addResource (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V
28252863
public static synthetic fun addResource$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
28262864
public final fun addResources (Ljava/util/List;)V
2827-
public final fun addTool (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lkotlin/jvm/functions/Function2;)V
2828-
public static synthetic fun addTool$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
2865+
public final fun addTool (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlin/jvm/functions/Function2;)V
2866+
public static synthetic fun addTool$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
28292867
public final fun addTools (Ljava/util/List;)V
28302868
protected fun assertCapabilityForMethod (Lio/modelcontextprotocol/kotlin/sdk/Method;)V
28312869
protected fun assertNotificationCapability (Lio/modelcontextprotocol/kotlin/sdk/Method;)V

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import io.modelcontextprotocol.kotlin.sdk.ResourceUpdatedNotification
3939
import io.modelcontextprotocol.kotlin.sdk.SUPPORTED_PROTOCOL_VERSIONS
4040
import io.modelcontextprotocol.kotlin.sdk.ServerCapabilities
4141
import io.modelcontextprotocol.kotlin.sdk.Tool
42+
import io.modelcontextprotocol.kotlin.sdk.ToolAnnotations
4243
import io.modelcontextprotocol.kotlin.sdk.ToolListChangedNotification
4344
import io.modelcontextprotocol.kotlin.sdk.shared.Protocol
4445
import io.modelcontextprotocol.kotlin.sdk.shared.ProtocolOptions
@@ -183,14 +184,15 @@ public open class Server(
183184
name: String,
184185
description: String,
185186
inputSchema: Tool.Input = Tool.Input(),
187+
toolAnnotations: ToolAnnotations? = null,
186188
handler: suspend (CallToolRequest) -> CallToolResult
187189
) {
188190
if (capabilities.tools == null) {
189191
logger.error { "Failed to add tool '$name': Server does not support tools capability" }
190192
throw IllegalStateException("Server does not support tools capability. Enable it in ServerOptions.")
191193
}
192194
logger.info { "Registering tool: $name" }
193-
tools[name] = RegisteredTool(Tool(name, description, inputSchema), handler)
195+
tools[name] = RegisteredTool(Tool(name, description, inputSchema, toolAnnotations), handler)
194196
}
195197

196198
/**

src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types.kt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,58 @@ public class PromptListChangedNotification : ServerNotification {
10311031
}
10321032

10331033
/* Tools */
1034+
/**
1035+
* Additional properties describing a Tool to clients.
1036+
*
1037+
* NOTE: all properties in ToolAnnotations are **hints**.
1038+
* They are not guaranteed to provide a faithful description of
1039+
* tool behavior (including descriptive properties like `title`).
1040+
*
1041+
* Clients should never make tool use decisions based on ToolAnnotations
1042+
* received from untrusted servers.
1043+
*/
1044+
@Serializable
1045+
public data class ToolAnnotations(
1046+
/**
1047+
* A human-readable title for the tool.
1048+
*/
1049+
val title: String?,
1050+
/**
1051+
* If true, the tool does not modify its environment.
1052+
*
1053+
* Default: false
1054+
*/
1055+
val readOnlyHint: Boolean? = false,
1056+
/**
1057+
* If true, the tool may perform destructive updates to its environment.
1058+
* If false, the tool performs only additive updates.
1059+
*
1060+
* (This property is meaningful only when `readOnlyHint == false`)
1061+
*
1062+
* Default: true
1063+
*/
1064+
val destructiveHint: Boolean? = true,
1065+
/**
1066+
* If true, calling the tool repeatedly with the same arguments
1067+
* will have no additional effect on the its environment.
1068+
*
1069+
* (This property is meaningful only when `readOnlyHint == false`)
1070+
*
1071+
* Default: false
1072+
*/
1073+
val idempotentHint: Boolean? = false,
1074+
/**
1075+
* If true, this tool may interact with an "open world" of external
1076+
* entities. If false, the tool's domain of interaction is closed.
1077+
* For example, the world of a web search tool is open, whereas that
1078+
* of a memory tool is not.
1079+
*
1080+
* Default: true
1081+
*/
1082+
val openWorldHint: Boolean? = true,
1083+
)
1084+
1085+
10341086
/**
10351087
* Definition for a tool the client can call.
10361088
*/
@@ -1048,6 +1100,11 @@ public data class Tool(
10481100
* A JSON object defining the expected parameters for the tool.
10491101
*/
10501102
val inputSchema: Input,
1103+
1104+
/**
1105+
* Optional additional tool information.
1106+
*/
1107+
val annotations: ToolAnnotations?,
10511108
) {
10521109
@Serializable
10531110
public data class Input(

src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/ToolSerializationTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package io.modelcontextprotocol.kotlin.sdk
22

33
import io.kotest.assertions.json.shouldEqualJson
44
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
5-
import kotlinx.serialization.encodeToString
65
import kotlinx.serialization.json.Json
76
import kotlinx.serialization.json.JsonPrimitive
87
import kotlinx.serialization.json.buildJsonObject
@@ -33,6 +32,7 @@ class ToolSerializationTest {
3332
val getWeatherTool = Tool(
3433
name = "get_weather",
3534
description = "Get the current weather in a given location",
35+
annotations = null,
3636
inputSchema = Tool.Input(
3737
properties = buildJsonObject {
3838
put("location", buildJsonObject {

src/jvmTest/kotlin/client/ClientTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ class ClientTest {
583583
Tool(
584584
name = "testTool",
585585
description = "testTool description",
586+
annotations = null,
586587
inputSchema = Tool.Input()
587588
)
588589
), nextCursor = null

0 commit comments

Comments
 (0)