Skip to content

Commit e4bd866

Browse files
jclynedevcrocod
andauthored
Adds optional _meta field to Tool (#339)
<!-- Provide a brief summary of your changes --> ## Motivation and Context The recently released openAI [Apps SDK ](https://developers.openai.com/apps-sdk/reference/#_meta-fields-the-client-provides)adds a '__meta_' field on the Tool Descriptor. This would be in addition to it being available on Messages. It remains optional and defaults to an empty json object, following existing conventions. ## How Has This Been Tested? Unit tests for serialization added ## Breaking Changes N/A ## 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) - [X] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## 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 - [X] I have added appropriate error handling - [X] I have added or updated documentation as needed ## Additional context https://developers.openai.com/apps-sdk https://developers.openai.com/apps-sdk/reference/#_meta-fields-the-client-provides --------- Co-authored-by: Pavel Gorgulov <[email protected]>
1 parent f462019 commit e4bd866

File tree

7 files changed

+50
-10
lines changed

7 files changed

+50
-10
lines changed

kotlin-sdk-client/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/client/StreamableHttpClientTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ internal class StreamableHttpClientTest : AbstractStreamableHttpClientTest() {
113113
}
114114
},
115115
"required": ["temperature"]
116-
}
116+
},
117+
"_meta": {}
117118
}
118119
]
119120
}

kotlin-sdk-core/api/kotlin-sdk-core.api

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2889,24 +2889,27 @@ public final class io/modelcontextprotocol/kotlin/sdk/TextResourceContents$Compa
28892889
public final fun serializer ()Lkotlinx/serialization/KSerializer;
28902890
}
28912891

2892-
public final class io/modelcontextprotocol/kotlin/sdk/Tool {
2892+
public final class io/modelcontextprotocol/kotlin/sdk/Tool : io/modelcontextprotocol/kotlin/sdk/WithMeta {
28932893
public static final field Companion Lio/modelcontextprotocol/kotlin/sdk/Tool$Companion;
2894-
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;)V
2894+
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;)V
2895+
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
28952896
public final fun component1 ()Ljava/lang/String;
28962897
public final fun component2 ()Ljava/lang/String;
28972898
public final fun component3 ()Ljava/lang/String;
28982899
public final fun component4 ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;
28992900
public final fun component5 ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;
29002901
public final fun component6 ()Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
2901-
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2902-
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/Tool;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2902+
public final fun component7 ()Lkotlinx/serialization/json/JsonObject;
2903+
public final fun copy (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
2904+
public static synthetic fun copy$default (Lio/modelcontextprotocol/kotlin/sdk/Tool;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;ILjava/lang/Object;)Lio/modelcontextprotocol/kotlin/sdk/Tool;
29032905
public fun equals (Ljava/lang/Object;)Z
29042906
public final fun getAnnotations ()Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;
29052907
public final fun getDescription ()Ljava/lang/String;
29062908
public final fun getInputSchema ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;
29072909
public final fun getName ()Ljava/lang/String;
29082910
public final fun getOutputSchema ()Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;
29092911
public final fun getTitle ()Ljava/lang/String;
2912+
public fun get_meta ()Lkotlinx/serialization/json/JsonObject;
29102913
public fun hashCode ()I
29112914
public fun toString ()Ljava/lang/String;
29122915
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,12 @@ public data class Tool(
12421242
* Optional additional tool information.
12431243
*/
12441244
val annotations: ToolAnnotations?,
1245-
) {
1245+
1246+
/**
1247+
* Optional metadata for the tool.
1248+
*/
1249+
override val _meta: JsonObject = EmptyJsonObject,
1250+
) : WithMeta {
12461251
@Serializable
12471252
public data class Input(val properties: JsonObject = EmptyJsonObject, val required: List<String>? = null) {
12481253
@OptIn(ExperimentalSerializationApi::class)

kotlin-sdk-core/src/commonTest/kotlin/io/modelcontextprotocol/kotlin/sdk/RequestSerializerTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ class RequestSerializerTest {
7575
"inputSchema": {
7676
"type": "object",
7777
"properties": {}
78-
}
78+
},
79+
"_meta": {}
7980
}
8081
]
8182
}"""

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk
33
import io.kotest.assertions.json.shouldEqualJson
44
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
55
import kotlinx.serialization.json.Json
6+
import kotlinx.serialization.json.JsonObject
67
import kotlinx.serialization.json.JsonPrimitive
78
import kotlinx.serialization.json.buildJsonObject
89
import kotlin.test.Test
@@ -44,6 +45,9 @@ class ToolSerializationTest {
4445
}
4546
},
4647
"required": ["temperature", "conditions", "humidity"]
48+
},
49+
"_meta": {
50+
"_for_test_only": true
4751
}
4852
}
4953
""".trimIndent()
@@ -91,6 +95,9 @@ class ToolSerializationTest {
9195
},
9296
required = listOf("temperature", "conditions", "humidity"),
9397
),
98+
_meta = buildJsonObject {
99+
put("_for_test_only", JsonPrimitive(true))
100+
},
94101
)
95102

96103
//region Serialize
@@ -411,6 +418,7 @@ class ToolSerializationTest {
411418
name: String = "get_weather",
412419
title: String? = null,
413420
outputSchema: String? = null,
421+
@Suppress("LocalVariableName") _meta: String? = null,
414422
): String {
415423
val stringBuilder = StringBuilder()
416424

@@ -453,6 +461,14 @@ class ToolSerializationTest {
453461
)
454462
}
455463

464+
stringBuilder
465+
.appendLine(",")
466+
.append(
467+
"""
468+
"_meta": ${_meta ?: "{}"}
469+
""".trimIndent(),
470+
)
471+
456472
stringBuilder
457473
.appendLine()
458474
.appendLine("}")
@@ -464,6 +480,7 @@ class ToolSerializationTest {
464480
name: String = "get_weather",
465481
title: String? = null,
466482
outputSchema: Tool.Output? = null,
483+
@Suppress("LocalVariableName") _meta: JsonObject? = null,
467484
): Tool = Tool(
468485
name = name,
469486
title = title,
@@ -482,6 +499,7 @@ class ToolSerializationTest {
482499
required = listOf("location"),
483500
),
484501
outputSchema = outputSchema,
502+
_meta = _meta ?: EmptyJsonObject,
485503
)
486504

487505
//endregion Private Methods

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ public class io/modelcontextprotocol/kotlin/sdk/server/Server {
6060
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
6161
public final fun addResources (Ljava/util/List;)V
6262
public final fun addTool (Lio/modelcontextprotocol/kotlin/sdk/Tool;Lkotlin/jvm/functions/Function2;)V
63-
public final fun addTool (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlin/jvm/functions/Function2;)V
64-
public static synthetic fun addTool$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
63+
public final fun addTool (Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/functions/Function2;)V
64+
public static synthetic fun addTool$default (Lio/modelcontextprotocol/kotlin/sdk/server/Server;Ljava/lang/String;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Input;Ljava/lang/String;Lio/modelcontextprotocol/kotlin/sdk/Tool$Output;Lio/modelcontextprotocol/kotlin/sdk/ToolAnnotations;Lkotlinx/serialization/json/JsonObject;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
6565
public final fun addTools (Ljava/util/List;)V
6666
public final fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
6767
public final fun connect (Lio/modelcontextprotocol/kotlin/sdk/shared/Transport;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk.server
33
import io.github.oshai.kotlinlogging.KotlinLogging
44
import io.modelcontextprotocol.kotlin.sdk.CallToolRequest
55
import io.modelcontextprotocol.kotlin.sdk.CallToolResult
6+
import io.modelcontextprotocol.kotlin.sdk.EmptyJsonObject
67
import io.modelcontextprotocol.kotlin.sdk.GetPromptRequest
78
import io.modelcontextprotocol.kotlin.sdk.GetPromptResult
89
import io.modelcontextprotocol.kotlin.sdk.Implementation
@@ -30,6 +31,7 @@ import kotlinx.atomicfu.atomic
3031
import kotlinx.atomicfu.update
3132
import kotlinx.collections.immutable.persistentListOf
3233
import kotlinx.coroutines.CancellationException
34+
import kotlinx.serialization.json.JsonObject
3335

3436
private val logger = KotlinLogging.logger {}
3537

@@ -243,6 +245,7 @@ public open class Server(
243245
* @param inputSchema The expected input schema for the tool.
244246
* @param outputSchema The optional expected output schema for the tool.
245247
* @param toolAnnotations Optional additional tool information.
248+
* @param _meta Optional metadata as a [JsonObject].
246249
* @param handler A suspend function that handles executing the tool when called by the client.
247250
* @throws IllegalStateException If the server does not support tools.
248251
*/
@@ -254,9 +257,18 @@ public open class Server(
254257
title: String? = null,
255258
outputSchema: Tool.Output? = null,
256259
toolAnnotations: ToolAnnotations? = null,
260+
@Suppress("LocalVariableName") _meta: JsonObject? = null,
257261
handler: suspend (CallToolRequest) -> CallToolResult,
258262
) {
259-
val tool = Tool(name, title, description, inputSchema, outputSchema, toolAnnotations)
263+
val tool = Tool(
264+
name = name,
265+
title = title,
266+
description = description,
267+
inputSchema = inputSchema,
268+
outputSchema = outputSchema,
269+
annotations = toolAnnotations,
270+
_meta = _meta ?: EmptyJsonObject,
271+
)
260272
addTool(tool, handler)
261273
}
262274

0 commit comments

Comments
 (0)