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 <devcrocod@gmail.com>
This commit is contained in:
Jeff Clyne 2025-11-04 11:39:22 -06:00 • committed by GitHub
commit e4bd866fdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 10 deletions

View file

@ -1242,7 +1242,12 @@ public data class Tool(
* Optional additional tool information.
*/
val annotations: ToolAnnotations?,
) {
/**
* Optional metadata for the tool.
*/
override val _meta: JsonObject = EmptyJsonObject,
) : WithMeta {
@Serializable
public data class Input(val properties: JsonObject = EmptyJsonObject, val required: List<String>? = null) {
@OptIn(ExperimentalSerializationApi::class)

View file

@ -75,7 +75,8 @@ class RequestSerializerTest {
"inputSchema": {
"type": "object",
"properties": {}
}
},
"_meta": {}
}
]
}"""

View file

@ -3,6 +3,7 @@ package io.modelcontextprotocol.kotlin.sdk
import io.kotest.assertions.json.shouldEqualJson
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject
import kotlin.test.Test
@ -44,6 +45,9 @@ class ToolSerializationTest {
}
},
"required": ["temperature", "conditions", "humidity"]
},
"_meta": {
"_for_test_only": true
}
}
""".trimIndent()
@ -91,6 +95,9 @@ class ToolSerializationTest {
},
required = listOf("temperature", "conditions", "humidity"),
),
_meta = buildJsonObject {
put("_for_test_only", JsonPrimitive(true))
},
)
//region Serialize
@ -411,6 +418,7 @@ class ToolSerializationTest {
name: String = "get_weather",
title: String? = null,
outputSchema: String? = null,
@Suppress("LocalVariableName") _meta: String? = null,
): String {
val stringBuilder = StringBuilder()
@ -453,6 +461,14 @@ class ToolSerializationTest {
)
}
stringBuilder
.appendLine(",")
.append(
"""
"_meta": ${_meta ?: "{}"}
""".trimIndent(),
)
stringBuilder
.appendLine()
.appendLine("}")
@ -464,6 +480,7 @@ class ToolSerializationTest {
name: String = "get_weather",
title: String? = null,
outputSchema: Tool.Output? = null,
@Suppress("LocalVariableName") _meta: JsonObject? = null,
): Tool = Tool(
name = name,
title = title,
@ -482,6 +499,7 @@ class ToolSerializationTest {
required = listOf("location"),
),
outputSchema = outputSchema,
_meta = _meta ?: EmptyJsonObject,
)
//endregion Private Methods