Proposal: DSL Builders for request types (#399)
This PR introduces type-safe DSL builders for all MCP request types,
making it easier to construct requests
### Current Solution
All request types now have DSL builders:
```kotlin
// Initialize request
val request = initializeRequest {
protocolVersion = "2024-11-05"
capabilities {
sampling(ClientCapabilities.sampling)
roots(listChanged = true)
}
info("MyClient", "1.0.0")
}
// Create message request with conversation
val messageRequest = createMessageRequest {
maxTokens = 1000
systemPrompt = "You are a helpful assistant"
messages {
user { "What is the capital of France?" }
assistant { "The capital of France is Paris." }
user { "What about Germany?" }
}
}
// Call tool request
val toolRequest = callToolRequest {
name = "searchDatabase"
arguments {
put("query", "users")
put("limit", 10)
}
}
// Elicit request with schema
val elicitRequest = elicitationRequest {
message = "Please provide your contact information"
requestedSchema {
properties {
put("email", JsonObject(mapOf(
"type" to JsonPrimitive("string"),
"description" to JsonPrimitive("Your email address")
)))
}
required = listOf("email")
}
}
```
Each DSL builder includes:
- Clear separation of required (but runtime) vs optional fields
- Multiple usage examples
- Concise error messages with examples when required fields are missing
- Cross-references to related types
### Design Considerations
1. Function Naming Convention
The current naming convention (e.g., initializeRequest, callToolRequest) might be confusing since these functions don't send requests, they just build request objects.
Alternative approach: Add a build prefix to clarify intent:
- `initializeRequest` → `buildInitializeRequest`
- `callToolRequest` → `buildCallToolRequest`
- `createMessageRequest` → `buildCreateMessageRequest`
This would make it clearer that these are builder functions.
2. Runtime vs Compile-Time Validation
Currently, required fields are validated at runtime in the `build()` method:
```kotlin
val request = initializeRequest {
protocolVersion = "2024-11-05"
// Missing required fields: capabilities, info
// Error thrown at runtime ❌
}
```
Alternative approach: Use Compose UI style where required parameters are in the function signature:
```kotlin
fun initializeRequest(
protocolVersion: String,
capabilities: ClientCapabilities,
info: Implementation,
block: InitializeRequestBuilder.() -> Unit = {}
): InitializeRequest
```
```kotlin
// Usage
val request = initializeRequest(
protocolVersion = "2024-11-05",
capabilities = ClientCapabilities(sampling =
ClientCapabilities.sampling),
info = Implementation("MyClient", "1.0.0")
) {
// Optional fields only
meta { put("key", "value") }
}
```
Pros:
- Compile-time safety for required fields ✅
- Clear which fields are required ✅
- Better IDE autocomplete ✅
Cons:
- Multiple trailing lambdas can be confusing:
```kotlin
// When required fields include lambdas
val request = elicitationRequest(
message = "Enter info",
requestedSchema = { /* lambda 1 */ }
) { /* lambda 2 for optional fields */ }
```
- Less consistent DSL feel
- More verbose for simple cases
This commit is contained in:
parent
e6e38ac0a8
commit
74c93745cd
14 changed files with 2744 additions and 0 deletions
|
|
@ -0,0 +1,12 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
/**
|
||||
* DSL marker annotation for MCP builder classes.
|
||||
*
|
||||
* This annotation is used to prevent accidental access to outer DSL scopes
|
||||
* within nested DSL blocks, ensuring type-safe and unambiguous builder usage.
|
||||
*
|
||||
* @see DslMarker
|
||||
*/
|
||||
@DslMarker
|
||||
public annotation class McpDsl
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ClientCapabilities] instances.
|
||||
*
|
||||
* This builder is used within [InitializeRequestBuilder] to configure client capabilities.
|
||||
* All capabilities are optional - the presence of a capability indicates support for that feature.
|
||||
*
|
||||
* ## Available Functions (all optional)
|
||||
* - [sampling] - Indicates support for sampling from an LLM
|
||||
* - [roots] - Indicates support for listing roots
|
||||
* - [elicitation] - Indicates support for elicitation from the server
|
||||
* - [experimental] - Defines experimental, non-standard capabilities
|
||||
*
|
||||
* Example usage within [buildInitializeRequest][buildInitializeRequest]:
|
||||
* ```kotlin
|
||||
* val request = buildInitializeRequest {
|
||||
* protocolVersion = "1.0"
|
||||
* capabilities {
|
||||
* sampling(ClientCapabilities.sampling)
|
||||
* roots(listChanged = true)
|
||||
* experimental {
|
||||
* put("customFeature", JsonPrimitive(true))
|
||||
* }
|
||||
* }
|
||||
* info("MyClient", "1.0.0")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see ClientCapabilities
|
||||
* @see InitializeRequestBuilder.capabilities
|
||||
*/
|
||||
@McpDsl
|
||||
public class ClientCapabilitiesBuilder @PublishedApi internal constructor() {
|
||||
private var sampling: JsonObject? = null
|
||||
private var roots: ClientCapabilities.Roots? = null
|
||||
private var elicitation: JsonObject? = null
|
||||
private var experimental: JsonObject? = null
|
||||
|
||||
/**
|
||||
* Indicates that the client supports sampling from an LLM.
|
||||
*
|
||||
* Use [ClientCapabilities.sampling] for default empty configuration.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* sampling(ClientCapabilities.sampling)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param value The sampling capability configuration
|
||||
*/
|
||||
public fun sampling(value: JsonObject) {
|
||||
this.sampling = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the client supports sampling from an LLM with custom configuration.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* sampling {
|
||||
* put("temperature", JsonPrimitive(0.7))
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the sampling configuration
|
||||
*/
|
||||
public fun sampling(block: JsonObjectBuilder.() -> Unit): Unit = sampling(buildJsonObject(block))
|
||||
|
||||
/**
|
||||
* Indicates that the client supports listing roots.
|
||||
*
|
||||
* Example with listChanged notification:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* roots(listChanged = true)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example without listChanged:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* roots()
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param listChanged Whether the client will emit notifications when the list of roots changes
|
||||
*/
|
||||
public fun roots(listChanged: Boolean? = null) {
|
||||
this.roots = ClientCapabilities.Roots(listChanged)
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the client supports elicitation from the server.
|
||||
*
|
||||
* Use [ClientCapabilities.elicitation] for default empty configuration.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* elicitation(ClientCapabilities.elicitation)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param value The elicitation capability configuration
|
||||
*/
|
||||
public fun elicitation(value: JsonObject) {
|
||||
this.elicitation = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the client supports elicitation from the server with custom configuration.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* elicitation {
|
||||
* put("mode", JsonPrimitive("interactive"))
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the elicitation configuration
|
||||
*/
|
||||
public fun elicitation(block: JsonObjectBuilder.() -> Unit): Unit = elicitation(buildJsonObject(block))
|
||||
|
||||
/**
|
||||
* Defines experimental, non-standard capabilities that the client supports.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* experimental(buildJsonObject {
|
||||
* put("customFeature", JsonPrimitive(true))
|
||||
* put("version", JsonPrimitive("1.0"))
|
||||
* })
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param value The experimental capabilities configuration
|
||||
*/
|
||||
public fun experimental(value: JsonObject) {
|
||||
this.experimental = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines experimental, non-standard capabilities that the client supports using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* experimental {
|
||||
* put("customFeature", JsonPrimitive(true))
|
||||
* put("beta", JsonObject(mapOf(
|
||||
* "enabled" to JsonPrimitive(true),
|
||||
* "version" to JsonPrimitive("2.0")
|
||||
* )))
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the experimental capabilities configuration
|
||||
*/
|
||||
public fun experimental(block: JsonObjectBuilder.() -> Unit): Unit = experimental(buildJsonObject(block))
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): ClientCapabilities = ClientCapabilities(
|
||||
sampling = sampling,
|
||||
roots = roots,
|
||||
elicitation = elicitation,
|
||||
experimental = experimental,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [CompleteRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [argument][CompleteRequestBuilder.argument] - Sets the argument name and value to complete
|
||||
* - [ref][CompleteRequestBuilder.ref] - Sets the reference to a prompt or resource template
|
||||
*
|
||||
* ## Optional
|
||||
* - [context][CompleteRequestBuilder.context] - Adds additional context for the completion
|
||||
* - [meta][CompleteRequestBuilder.meta] - Adds metadata to the request
|
||||
*
|
||||
* Example with [PromptReference]:
|
||||
* ```kotlin
|
||||
* val request = buildCompleteRequest {
|
||||
* argument("query", "user input")
|
||||
* ref(PromptReference("searchPrompt"))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with [ResourceTemplateReference]:
|
||||
* ```kotlin
|
||||
* val request = buildCompleteRequest {
|
||||
* argument("path", "/users/123")
|
||||
* ref(ResourceTemplateReference("file:///{path}"))
|
||||
* context {
|
||||
* put("userId", "123")
|
||||
* put("role", "admin")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the completion request
|
||||
* @return A configured [CompleteRequest] instance
|
||||
* @see CompleteRequestBuilder
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildCompleteRequest(block: CompleteRequestBuilder.() -> Unit): CompleteRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return CompleteRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [CompleteRequest] instances.
|
||||
*
|
||||
* This builder provides methods to configure completion requests for prompts or resource templates.
|
||||
* Both [argument] and [ref] are required; [context] is optional.
|
||||
*
|
||||
* @see buildCompleteRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class CompleteRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
private var arg: CompleteRequestParams.Argument? = null
|
||||
private var ref: Reference? = null
|
||||
private var ctx: CompleteRequestParams.Context? = null
|
||||
|
||||
/**
|
||||
* Sets the argument for completion.
|
||||
*
|
||||
* This method specifies the name and value of the argument to be completed.
|
||||
* This is a required field and must be called exactly once.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* completeRequest {
|
||||
* argument("query", "SELECT * FROM use")
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param name The name of the argument to complete
|
||||
* @param value The partial or full value of the argument
|
||||
*/
|
||||
public fun argument(name: String, value: String) {
|
||||
arg = CompleteRequestParams.Argument(name, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reference to a prompt or resource template.
|
||||
*
|
||||
* This method specifies which prompt or resource template the completion request refers to.
|
||||
*
|
||||
* Example with prompt:
|
||||
* ```kotlin
|
||||
* completeRequest {
|
||||
* ref(PromptReference("sqlQuery", "SQL Query Builder"))
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with resource template:
|
||||
* ```kotlin
|
||||
* completeRequest {
|
||||
* ref(ResourceTemplateReference("file:///{path}"))
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param value The [Reference] (either [PromptReference] or [ResourceTemplateReference])
|
||||
*/
|
||||
public fun ref(value: Reference) {
|
||||
ref = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets additional context for the completion request using a Map.
|
||||
*
|
||||
* This method allows providing additional key-value pairs that may be relevant
|
||||
* for generating completions. This is an optional field.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* completeRequest {
|
||||
* context(mapOf("userId" to "123", "role" to "admin"))
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param arguments A map of context key-value pairs
|
||||
*/
|
||||
public fun context(arguments: Map<String, String>) {
|
||||
ctx = CompleteRequestParams.Context(arguments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets additional context for the completion request using a DSL builder.
|
||||
*
|
||||
* This method allows providing additional key-value pairs that may be relevant
|
||||
* for generating completions using a type-safe builder syntax. This is an optional field.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* completeRequest {
|
||||
* context {
|
||||
* put("userId", "123")
|
||||
* put("role", "admin")
|
||||
* put("environment", "production")
|
||||
* }
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda with receiver for building the context map
|
||||
*/
|
||||
public fun context(block: MutableMap<String, String>.() -> Unit) {
|
||||
ctx = CompleteRequestParams.Context(buildMap(block))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): CompleteRequest {
|
||||
val argument = requireNotNull(arg) {
|
||||
"Missing required field 'argument(name, value)'. Example: argument(\"query\", \"user input\")"
|
||||
}
|
||||
|
||||
val reference = requireNotNull(ref) {
|
||||
"Missing required field 'ref(Reference)'. Use ref(PromptReference(\"name\")) or ref(ResourceTemplateReference(\"uri\"))"
|
||||
}
|
||||
|
||||
val params = CompleteRequestParams(argument = argument, ref = reference, context = ctx, meta = meta)
|
||||
return CompleteRequest(params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
|
||||
/**
|
||||
* Base DSL builder for constructing [MediaContent] instances.
|
||||
*
|
||||
* This abstract class provides common functionality for all media content builders:
|
||||
* - [annotations] - Optional metadata annotations
|
||||
* - [meta] - Optional additional metadata
|
||||
*
|
||||
* Concrete implementations:
|
||||
* - [TextContentBuilder] - For text content
|
||||
* - [ImageContentBuilder] - For image content (base64-encoded)
|
||||
* - [AudioContentBuilder] - For audio content (base64-encoded)
|
||||
*
|
||||
* @see TextContentBuilder
|
||||
* @see ImageContentBuilder
|
||||
* @see AudioContentBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public abstract class MediaContentBuilder {
|
||||
protected var annotations: Annotations? = null
|
||||
protected var meta: JsonObject? = null
|
||||
|
||||
/**
|
||||
* Sets optional annotations for the content.
|
||||
*
|
||||
* Annotations provide additional metadata about the content such as audience,
|
||||
* priority, and last modification time.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* userText {
|
||||
* text = "Hello"
|
||||
* annotations(Annotations(priority = 0.8))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param annotations The [Annotations] instance
|
||||
*/
|
||||
public fun annotations(annotations: Annotations) {
|
||||
this.annotations = annotations
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets optional annotations for the content with individual parameters.
|
||||
*
|
||||
* Example with all parameters:
|
||||
* ```kotlin
|
||||
* userText {
|
||||
* text = "Important update"
|
||||
* annotations(
|
||||
* audience = listOf(Role.User, Role.Assistant),
|
||||
* priority = 0.8,
|
||||
* lastModified = "2025-01-12T15:00:58Z"
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param audience The intended audience for this content (list of [Role])
|
||||
* @param priority Priority hint for this content (0.0 to 1.0)
|
||||
* @param lastModified ISO 8601 timestamp of the last modification
|
||||
* @see Annotations
|
||||
*/
|
||||
public fun annotations(audience: List<Role>? = null, priority: Double? = null, lastModified: String? = null) {
|
||||
this.annotations = Annotations(audience, priority, lastModified)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets optional metadata for the content using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* userText {
|
||||
* text = "Hello"
|
||||
* meta {
|
||||
* put("source", JsonPrimitive("user-input"))
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the metadata
|
||||
*/
|
||||
public fun meta(block: JsonObjectBuilder.() -> Unit) {
|
||||
meta = buildJsonObject(block)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal abstract fun build(): MediaContent
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [TextContent] instances.
|
||||
*
|
||||
* ## Required
|
||||
* - [text] - The text content string
|
||||
*
|
||||
* ## Optional
|
||||
* - [annotations] - Content annotations (inherited from [MediaContentBuilder])
|
||||
* - [meta] - Additional metadata (inherited from [MediaContentBuilder])
|
||||
*
|
||||
* Example usage in sampling messages:
|
||||
* ```kotlin
|
||||
* createMessageRequest {
|
||||
* maxTokens = 100
|
||||
* messages {
|
||||
* userText {
|
||||
* text = "What is the capital of France?"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with annotations:
|
||||
* ```kotlin
|
||||
* userText {
|
||||
* text = "Important message"
|
||||
* annotations(Annotations(priority = 1.0))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see TextContent
|
||||
* @see MediaContentBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class TextContentBuilder @PublishedApi internal constructor() : MediaContentBuilder() {
|
||||
/**
|
||||
* The text content. This is a required field.
|
||||
*/
|
||||
public var text: String? = null
|
||||
|
||||
override fun build(): TextContent {
|
||||
val text = requireNotNull(text) {
|
||||
"Missing required field 'text'. Example: text = \"Hello, world!\""
|
||||
}
|
||||
|
||||
return TextContent(text = text, annotations = annotations, meta = meta)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ImageContent] instances.
|
||||
*
|
||||
* ## Required
|
||||
* - [data] - The base64-encoded image data
|
||||
* - [mimeType] - The MIME type of the image (e.g., "image/png", "image/jpeg")
|
||||
*
|
||||
* ## Optional
|
||||
* - [annotations] - Content annotations (inherited from [MediaContentBuilder])
|
||||
* - [meta] - Additional metadata (inherited from [MediaContentBuilder])
|
||||
*
|
||||
* Example usage in sampling messages:
|
||||
* ```kotlin
|
||||
* createMessageRequest {
|
||||
* maxTokens = 100
|
||||
* messages {
|
||||
* userImage {
|
||||
* data = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB..."
|
||||
* mimeType = "image/png"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with annotations:
|
||||
* ```kotlin
|
||||
* userImage {
|
||||
* data = base64EncodedImageData
|
||||
* mimeType = "image/jpeg"
|
||||
* annotations(Annotations(priority = 0.9))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see ImageContent
|
||||
* @see MediaContentBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class ImageContentBuilder @PublishedApi internal constructor() : MediaContentBuilder() {
|
||||
/**
|
||||
* The base64-encoded image data. This is a required field.
|
||||
*/
|
||||
public var data: String? = null
|
||||
|
||||
/**
|
||||
* The MIME type of the image (e.g., "image/png", "image/jpeg"). This is a required field.
|
||||
*/
|
||||
public var mimeType: String? = null
|
||||
|
||||
override fun build(): ImageContent {
|
||||
val data = requireNotNull(data) {
|
||||
"Missing required field 'data'. Provide base64-encoded image data"
|
||||
}
|
||||
val mime = requireNotNull(mimeType) {
|
||||
"Missing required field 'mimeType'. Example: mimeType = \"image/png\""
|
||||
}
|
||||
|
||||
return ImageContent(
|
||||
data = data,
|
||||
mimeType = mime,
|
||||
annotations = annotations,
|
||||
meta = meta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [AudioContent] instances.
|
||||
*
|
||||
* ## Required
|
||||
* - [data] - The base64-encoded audio data
|
||||
* - [mimeType] - The MIME type of the audio (e.g., "audio/wav", "audio/mpeg")
|
||||
*
|
||||
* ## Optional
|
||||
* - [annotations] - Content annotations (inherited from [MediaContentBuilder])
|
||||
* - [meta] - Additional metadata (inherited from [MediaContentBuilder])
|
||||
*
|
||||
* Example usage in sampling messages:
|
||||
* ```kotlin
|
||||
* createMessageRequest {
|
||||
* maxTokens = 100
|
||||
* messages {
|
||||
* userAudio {
|
||||
* data = "UklGRiQAAABXQVZFZm10IBAAAAABAAEA..."
|
||||
* mimeType = "audio/wav"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with annotations:
|
||||
* ```kotlin
|
||||
* userAudio {
|
||||
* data = base64EncodedAudioData
|
||||
* mimeType = "audio/mpeg"
|
||||
* annotations(Annotations(priority = 0.7))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see AudioContent
|
||||
* @see MediaContentBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class AudioContentBuilder @PublishedApi internal constructor() : MediaContentBuilder() {
|
||||
/**
|
||||
* The base64-encoded audio data. This is a required field.
|
||||
*/
|
||||
public var data: String? = null
|
||||
|
||||
/**
|
||||
* The MIME type of the audio (e.g., "audio/wav", "audio/mpeg"). This is a required field.
|
||||
*/
|
||||
public var mimeType: String? = null
|
||||
|
||||
override fun build(): AudioContent {
|
||||
val data = requireNotNull(data) {
|
||||
"Missing required field 'data'. Provide base64-encoded audio data"
|
||||
}
|
||||
val mime = requireNotNull(mimeType) {
|
||||
"Missing required field 'mimeType'. Example: mimeType = \"audio/wav\""
|
||||
}
|
||||
|
||||
return AudioContent(
|
||||
data = data,
|
||||
mimeType = mime,
|
||||
annotations = annotations,
|
||||
meta = meta,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates an [ElicitRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [message][ElicitRequestBuilder.message] - The message to present to the user
|
||||
* - [requestedSchema][ElicitRequestBuilder.requestedSchema] - Schema defining the structure of requested data
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][ElicitRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example requesting user information:
|
||||
* ```kotlin
|
||||
* val request = buildElicitRequest {
|
||||
* message = "Please provide your contact information"
|
||||
* requestedSchema {
|
||||
* properties {
|
||||
* put("email", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string"),
|
||||
* "description" to JsonPrimitive("Your email address")
|
||||
* )))
|
||||
* put("name", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string")
|
||||
* )))
|
||||
* }
|
||||
* required = listOf("email")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with simple text input:
|
||||
* ```kotlin
|
||||
* val request = buildElicitRequest {
|
||||
* message = "Enter a project name"
|
||||
* requestedSchema {
|
||||
* properties {
|
||||
* put("projectName", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string"),
|
||||
* "description" to JsonPrimitive("Name for the new project")
|
||||
* )))
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the elicitation request
|
||||
* @return A configured [ElicitRequest] instance
|
||||
* @see ElicitRequestBuilder
|
||||
* @see ElicitRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildElicitRequest(block: ElicitRequestBuilder.() -> Unit): ElicitRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ElicitRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ElicitRequest] instances.
|
||||
*
|
||||
* This builder is used to create requests that prompt users for structured input
|
||||
* through forms or dialogs presented by the client.
|
||||
*
|
||||
* ## Required
|
||||
* - [message] - The message to present to the user explaining what is being requested
|
||||
* - [requestedSchema] - Schema defining the structure of the data to collect
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildElicitRequest
|
||||
* @see ElicitRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class ElicitRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The message to present to the user. This should clearly explain what information
|
||||
* is being requested and why. This is a required field.
|
||||
*/
|
||||
public var message: String? = null
|
||||
|
||||
private var requestedSchema: ElicitRequestParams.RequestedSchema? = null
|
||||
|
||||
/**
|
||||
* Sets the requested schema directly.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* buildElicitRequest {
|
||||
* message = "Enter details"
|
||||
* requestedSchema(ElicitRequestParams.RequestedSchema(
|
||||
* properties = buildJsonObject {
|
||||
* put("name", JsonObject(mapOf("type" to JsonPrimitive("string"))))
|
||||
* }
|
||||
* ))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param schema The [ElicitRequestParams.RequestedSchema] instance
|
||||
*/
|
||||
public fun requestedSchema(schema: ElicitRequestParams.RequestedSchema) {
|
||||
requestedSchema = schema
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the requested schema using a DSL builder.
|
||||
*
|
||||
* This is the recommended way to define schemas. The schema defines the structure
|
||||
* of data to be collected from the user, supporting only top-level primitive properties.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* buildElicitRequest {
|
||||
* message = "Configure settings"
|
||||
* requestedSchema {
|
||||
* properties {
|
||||
* put("enabled", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("boolean"),
|
||||
* "description" to JsonPrimitive("Enable feature")
|
||||
* )))
|
||||
* put("apiKey", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string")
|
||||
* )))
|
||||
* }
|
||||
* required = listOf("apiKey")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the schema
|
||||
* @see ElicitRequestedSchemaBuilder
|
||||
*/
|
||||
public fun requestedSchema(block: ElicitRequestedSchemaBuilder.() -> Unit) {
|
||||
requestedSchema = ElicitRequestedSchemaBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): ElicitRequest {
|
||||
val message = requireNotNull(message) {
|
||||
"Missing required field 'message'. Example: message = \"Please enter your name\""
|
||||
}
|
||||
val requestedSchema = requireNotNull(requestedSchema) {
|
||||
"Missing required field 'requestedSchema'. Use requestedSchema { properties { ... } }"
|
||||
}
|
||||
|
||||
val params = ElicitRequestParams(message = message, requestedSchema = requestedSchema, meta = meta)
|
||||
return ElicitRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ElicitRequestParams.RequestedSchema] instances.
|
||||
*
|
||||
* Defines the JSON Schema structure for data to be collected from the user.
|
||||
* Only supports top-level primitive properties.
|
||||
*
|
||||
* ## Required
|
||||
* - [properties] - Schema definitions for each field
|
||||
*
|
||||
* ## Optional
|
||||
* - [required] - List of required property names
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* requestedSchema {
|
||||
* properties {
|
||||
* put("username", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string"),
|
||||
* "description" to JsonPrimitive("Your username")
|
||||
* )))
|
||||
* }
|
||||
* required = listOf("username")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see ElicitRequestParams.RequestedSchema
|
||||
*/
|
||||
@McpDsl
|
||||
public class ElicitRequestedSchemaBuilder @PublishedApi internal constructor() {
|
||||
private var properties: JsonObject? = null
|
||||
|
||||
/**
|
||||
* List of required property names. If null, all fields are optional.
|
||||
*/
|
||||
public var required: List<String>? = null
|
||||
|
||||
/**
|
||||
* Sets the schema properties directly.
|
||||
*
|
||||
* @param properties JsonObject containing property schemas
|
||||
*/
|
||||
public fun properties(properties: JsonObject) {
|
||||
this.properties = properties
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the schema properties using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* properties {
|
||||
* put("email", JsonObject(mapOf(
|
||||
* "type" to JsonPrimitive("string")
|
||||
* )))
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the properties
|
||||
*/
|
||||
public fun properties(block: JsonObjectBuilder.() -> Unit): Unit = properties(buildJsonObject(block))
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): ElicitRequestParams.RequestedSchema {
|
||||
val properties = requireNotNull(properties) {
|
||||
"Missing required field 'properties'. Use properties { put(\"fieldName\", schema) }"
|
||||
}
|
||||
return ElicitRequestParams.RequestedSchema(properties, required)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates an [InitializeRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [protocolVersion][InitializeRequestBuilder.protocolVersion] - MCP protocol version
|
||||
* - [capabilities][InitializeRequestBuilder.capabilities] - Client capabilities
|
||||
* - [info][InitializeRequestBuilder.info] - Client implementation information
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][InitializeRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val request = buildInitializeRequest {
|
||||
* protocolVersion = "2024-11-05"
|
||||
* capabilities {
|
||||
* sampling(ClientCapabilities.sampling)
|
||||
* roots(listChanged = true)
|
||||
* }
|
||||
* info("MyClient", "1.0.0")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with full client info:
|
||||
* ```kotlin
|
||||
* val request = buildInitializeRequest {
|
||||
* protocolVersion = "2024-11-05"
|
||||
* capabilities {
|
||||
* sampling(ClientCapabilities.sampling)
|
||||
* experimental {
|
||||
* put("feature", JsonPrimitive(true))
|
||||
* }
|
||||
* }
|
||||
* info(
|
||||
* name = "MyAdvancedClient",
|
||||
* version = "2.0.0",
|
||||
* title = "Advanced MCP Client",
|
||||
* websiteUrl = "https://example.com"
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the initialize request
|
||||
* @return A configured [InitializeRequest] instance
|
||||
* @see InitializeRequestBuilder
|
||||
* @see InitializeRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildInitializeRequest(block: InitializeRequestBuilder.() -> Unit): InitializeRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return InitializeRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [InitializeRequest] instances.
|
||||
*
|
||||
* This builder creates the initial handshake request to establish
|
||||
* an MCP protocol connection between client and server.
|
||||
*
|
||||
* ## Required
|
||||
* - [protocolVersion] - MCP protocol version string
|
||||
* - [capabilities] - Client capabilities configuration
|
||||
* - [info] - Client implementation details
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildInitializeRequest
|
||||
* @see InitializeRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class InitializeRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The MCP protocol version. This is a required field.
|
||||
*
|
||||
* Example: `protocolVersion = "2024-11-05"`
|
||||
*/
|
||||
public var protocolVersion: String? = null
|
||||
|
||||
private var capabilities: ClientCapabilities? = null
|
||||
private var info: Implementation? = null
|
||||
|
||||
/**
|
||||
* Sets client capabilities directly.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities(ClientCapabilities(
|
||||
* sampling = ClientCapabilities.sampling,
|
||||
* roots = ClientCapabilities.Roots(listChanged = true)
|
||||
* ))
|
||||
* ```
|
||||
*
|
||||
* @param value The [ClientCapabilities] instance
|
||||
*/
|
||||
public fun capabilities(value: ClientCapabilities) {
|
||||
capabilities = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets client capabilities using a DSL builder.
|
||||
*
|
||||
* This is the recommended way to configure capabilities.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* capabilities {
|
||||
* sampling(ClientCapabilities.sampling)
|
||||
* roots(listChanged = true)
|
||||
* elicitation(ClientCapabilities.elicitation)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building capabilities
|
||||
* @see ClientCapabilitiesBuilder
|
||||
*/
|
||||
public fun capabilities(block: ClientCapabilitiesBuilder.() -> Unit) {
|
||||
capabilities = ClientCapabilitiesBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets client implementation info directly.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* info(Implementation(
|
||||
* name = "MyClient",
|
||||
* version = "1.0.0"
|
||||
* ))
|
||||
* ```
|
||||
*
|
||||
* @param value The [Implementation] instance
|
||||
*/
|
||||
public fun info(value: Implementation) {
|
||||
info = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets client implementation info using individual parameters.
|
||||
*
|
||||
* This is the recommended way to configure client info.
|
||||
*
|
||||
* Example with required fields only:
|
||||
* ```kotlin
|
||||
* info("MyClient", "1.0.0")
|
||||
* ```
|
||||
*
|
||||
* Example with all fields:
|
||||
* ```kotlin
|
||||
* info(
|
||||
* name = "MyClient",
|
||||
* version = "2.0.0",
|
||||
* title = "My MCP Client",
|
||||
* websiteUrl = "https://example.com",
|
||||
* icons = listOf(Icon(
|
||||
* src = "https://example.com/icon.png",
|
||||
* mimeType = "image/png"
|
||||
* ))
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @param name Client implementation name
|
||||
* @param version Client version string
|
||||
* @param title Optional human-readable title
|
||||
* @param websiteUrl Optional URL to client website
|
||||
* @param icons Optional list of client icons
|
||||
*/
|
||||
public fun info(
|
||||
name: String,
|
||||
version: String,
|
||||
title: String? = null,
|
||||
websiteUrl: String? = null,
|
||||
icons: List<Icon>? = null,
|
||||
) {
|
||||
info = Implementation(name = name, version = version, title = title, websiteUrl = websiteUrl, icons = icons)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): InitializeRequest {
|
||||
val version = requireNotNull(protocolVersion) {
|
||||
"Missing required field 'protocolVersion'. Example: protocolVersion = \"2024-11-05\""
|
||||
}
|
||||
val capabilities = requireNotNull(capabilities) {
|
||||
"Missing required field 'capabilities'. Use capabilities { ... }"
|
||||
}
|
||||
val info = requireNotNull(info) {
|
||||
"Missing required field 'info'. Use info(\"clientName\", \"1.0.0\")"
|
||||
}
|
||||
|
||||
val params = InitializeRequestParams(
|
||||
protocolVersion = version,
|
||||
capabilities = capabilities,
|
||||
clientInfo = info,
|
||||
meta = meta,
|
||||
)
|
||||
return InitializeRequest(params = params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [SetLevelRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [loggingLevel][SetLevelRequestBuilder.loggingLevel] - The logging level to set
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][SetLevelRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example setting info level:
|
||||
* ```kotlin
|
||||
* val request = buildSetLevelRequest {
|
||||
* loggingLevel = LoggingLevel.Info
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example setting debug level:
|
||||
* ```kotlin
|
||||
* val request = buildSetLevelRequest {
|
||||
* loggingLevel = LoggingLevel.Debug
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the logging level request
|
||||
* @return A configured [SetLevelRequest] instance
|
||||
* @see SetLevelRequestBuilder
|
||||
* @see SetLevelRequest
|
||||
* @see LoggingLevel
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildSetLevelRequest(block: SetLevelRequestBuilder.() -> Unit): SetLevelRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return SetLevelRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [SetLevelRequest] instances.
|
||||
*
|
||||
* This builder creates requests to set the logging level for the server.
|
||||
*
|
||||
* ## Required
|
||||
* - [loggingLevel] - The logging level to set
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildSetLevelRequest
|
||||
* @see SetLevelRequest
|
||||
* @see LoggingLevel
|
||||
*/
|
||||
@McpDsl
|
||||
public class SetLevelRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The logging level to set. This is a required field.
|
||||
*
|
||||
* Available levels (from least to most severe):
|
||||
* - [LoggingLevel.Debug]
|
||||
* - [LoggingLevel.Info]
|
||||
* - [LoggingLevel.Notice]
|
||||
* - [LoggingLevel.Warning]
|
||||
* - [LoggingLevel.Error]
|
||||
* - [LoggingLevel.Critical]
|
||||
* - [LoggingLevel.Alert]
|
||||
* - [LoggingLevel.Emergency]
|
||||
*
|
||||
* Example: `loggingLevel = LoggingLevel.Warning`
|
||||
*/
|
||||
public var loggingLevel: LoggingLevel? = null
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): SetLevelRequest {
|
||||
val level = requireNotNull(loggingLevel) {
|
||||
"Missing required field 'loggingLevel'. Example: loggingLevel = LoggingLevel.Info"
|
||||
}
|
||||
|
||||
val params = SetLevelRequestParams(level = level, meta = meta)
|
||||
return SetLevelRequest(params = params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [PingRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][PingRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example with no parameters:
|
||||
* ```kotlin
|
||||
* val request = buildPingRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with metadata:
|
||||
* ```kotlin
|
||||
* val request = buildPingRequest {
|
||||
* meta {
|
||||
* put("timestamp", JsonPrimitive(System.currentTimeMillis()))
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the ping request
|
||||
* @return A configured [PingRequest] instance
|
||||
* @see PingRequestBuilder
|
||||
* @see PingRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildPingRequest(block: PingRequestBuilder.() -> Unit): PingRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return PingRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [PingRequest] instances.
|
||||
*
|
||||
* This builder creates ping requests to check connection status with the server.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildPingRequest
|
||||
* @see PingRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class PingRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): PingRequest {
|
||||
val params = meta?.let { BaseRequestParams(meta = it) }
|
||||
return PingRequest(params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [GetPromptRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [name][GetPromptRequestBuilder.name] - The name of the prompt to retrieve
|
||||
*
|
||||
* ## Optional
|
||||
* - [arguments][GetPromptRequestBuilder.arguments] - Arguments to pass to the prompt
|
||||
* - [meta][GetPromptRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without arguments:
|
||||
* ```kotlin
|
||||
* val request = buildGetPromptRequest {
|
||||
* name = "greeting"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with arguments:
|
||||
* ```kotlin
|
||||
* val request = buildGetPromptRequest {
|
||||
* name = "userProfile"
|
||||
* arguments = mapOf(
|
||||
* "userId" to "123",
|
||||
* "includeDetails" to "true"
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the get prompt request
|
||||
* @return A configured [GetPromptRequest] instance
|
||||
* @see GetPromptRequestBuilder
|
||||
* @see GetPromptRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildGetPromptRequest(block: GetPromptRequestBuilder.() -> Unit): GetPromptRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return GetPromptRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [GetPromptRequest] instances.
|
||||
*
|
||||
* This builder retrieves a specific prompt by name, optionally with arguments.
|
||||
*
|
||||
* ## Required
|
||||
* - [name] - The name of the prompt to retrieve
|
||||
*
|
||||
* ## Optional
|
||||
* - [arguments] - Arguments to pass to the prompt
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildGetPromptRequest
|
||||
* @see GetPromptRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class GetPromptRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The name of the prompt to retrieve. This is a required field.
|
||||
*
|
||||
* Example: `name = "greeting"`
|
||||
*/
|
||||
public var name: String? = null
|
||||
|
||||
/**
|
||||
* Optional arguments to pass to the prompt.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* arguments = mapOf("userId" to "123", "lang" to "en")
|
||||
* ```
|
||||
*/
|
||||
public var arguments: Map<String, String>? = null
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): GetPromptRequest {
|
||||
val name = requireNotNull(name) {
|
||||
"Missing required field 'name'. Example: name = \"promptName\""
|
||||
}
|
||||
|
||||
val params = GetPromptRequestParams(name = name, arguments = arguments, meta = meta)
|
||||
return GetPromptRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [ListPromptsRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor][ListPromptsRequestBuilder.cursor] - Pagination cursor for fetching next page
|
||||
* - [meta][ListPromptsRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListPromptsRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListPromptsRequest {
|
||||
* cursor = "eyJwYWdlIjogMn0="
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the list prompts request
|
||||
* @return A configured [ListPromptsRequest] instance
|
||||
* @see ListPromptsRequestBuilder
|
||||
* @see ListPromptsRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildListPromptsRequest(block: ListPromptsRequestBuilder.() -> Unit): ListPromptsRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListPromptsRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ListPromptsRequest] instances.
|
||||
*
|
||||
* This builder retrieves a list of available prompts, with optional pagination support.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor] - Pagination cursor (inherited from [PaginatedRequestBuilder])
|
||||
* - [meta] - Metadata for the request (inherited from [RequestBuilder])
|
||||
*
|
||||
* @see buildListPromptsRequest
|
||||
* @see ListPromptsRequest
|
||||
* @see PaginatedRequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class ListPromptsRequestBuilder @PublishedApi internal constructor() : PaginatedRequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): ListPromptsRequest {
|
||||
val params = paginatedRequestParams(cursor = cursor, meta = meta)
|
||||
return ListPromptsRequest(params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,208 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import kotlinx.serialization.json.JsonArrayBuilder
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.buildJsonArray
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
|
||||
/**
|
||||
* Base DSL builder for constructing MCP request instances.
|
||||
*
|
||||
* This abstract class provides common functionality for all request builders,
|
||||
* including optional metadata support.
|
||||
*
|
||||
* All concrete request builder classes extend this base to inherit [meta] functionality.
|
||||
*
|
||||
* @see RequestMetaBuilder
|
||||
* @see PaginatedRequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public abstract class RequestBuilder {
|
||||
protected var meta: RequestMeta? = null
|
||||
|
||||
/**
|
||||
* Sets request metadata using a DSL builder.
|
||||
*
|
||||
* Metadata can include progress tokens and custom fields for tracking requests.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* initializeRequest {
|
||||
* protocolVersion = "2024-11-05"
|
||||
* meta {
|
||||
* progressToken("progress-123")
|
||||
* put("customField", "value")
|
||||
* }
|
||||
* // ... other configuration
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param builderAction Lambda for building request metadata
|
||||
* @see RequestMetaBuilder
|
||||
*/
|
||||
public fun meta(builderAction: RequestMetaBuilder.() -> Unit) {
|
||||
meta = RequestMetaBuilder().apply(builderAction).build()
|
||||
}
|
||||
|
||||
internal abstract fun build(): Request
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [RequestMeta] instances.
|
||||
*
|
||||
* This builder creates metadata for MCP requests, supporting progress tokens
|
||||
* and custom key-value pairs.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* meta {
|
||||
* progressToken("progress-123")
|
||||
* put("requestId", "req-456")
|
||||
* put("priority", 1)
|
||||
* putJsonObject("context") {
|
||||
* put("source", "api")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see RequestMeta
|
||||
* @see RequestBuilder.meta
|
||||
*/
|
||||
@McpDsl
|
||||
public class RequestMetaBuilder internal constructor() {
|
||||
private val content: MutableMap<String, JsonElement> = linkedMapOf()
|
||||
|
||||
/**
|
||||
* Sets the progress token as a string.
|
||||
*
|
||||
* Progress tokens are used for out-of-band progress notifications.
|
||||
*
|
||||
* Example: `progressToken("progress-123")`
|
||||
*/
|
||||
public fun progressToken(value: String) {
|
||||
content["progressToken"] = JsonPrimitive(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress token as a `Long`.
|
||||
*
|
||||
* Example: `progressToken(123L)`
|
||||
*/
|
||||
public fun progressToken(value: Long) {
|
||||
content["progressToken"] = JsonPrimitive(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress token as an Int.
|
||||
*
|
||||
* Example: `progressToken(123)`
|
||||
*/
|
||||
public fun progressToken(value: Int) {
|
||||
content["progressToken"] = JsonPrimitive(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a JsonElement value.
|
||||
*
|
||||
* @param key The metadata field name
|
||||
* @param value The JsonElement value
|
||||
* @return The previous value associated with the key, or null
|
||||
*/
|
||||
public fun put(key: String, value: JsonElement): JsonElement? = content.put(key, value)
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a String value.
|
||||
*
|
||||
* Example: `put("requestId", "req-456")`
|
||||
*/
|
||||
public fun put(key: String, value: String): JsonElement? = put(key, JsonPrimitive(value))
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a Number value.
|
||||
*
|
||||
* Example: `put("priority", 1)`
|
||||
*/
|
||||
public fun put(key: String, value: Number): JsonElement? = put(key, JsonPrimitive(value))
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a Boolean value.
|
||||
*
|
||||
* Example: `put("urgent", true)`
|
||||
*/
|
||||
public fun put(key: String, value: Boolean): JsonElement? = put(key, JsonPrimitive(value))
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a null value.
|
||||
*
|
||||
* Example: `put("optionalField", null)`
|
||||
*/
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public fun put(key: String, value: Nothing?): JsonElement? = put(key, JsonNull)
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a JsonObject value using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* putJsonObject("context") {
|
||||
* put("source", "api")
|
||||
* put("version", 2)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param key The metadata field name
|
||||
* @param builderAction Lambda for building the JsonObject
|
||||
*/
|
||||
public fun putJsonObject(key: String, builderAction: JsonObjectBuilder.() -> Unit): JsonElement? =
|
||||
put(key, buildJsonObject(builderAction))
|
||||
|
||||
/**
|
||||
* Adds a custom metadata field with a JsonArray value using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* putJsonArray("tags") {
|
||||
* add("important")
|
||||
* add("urgent")
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param key The metadata field name
|
||||
* @param builderAction Lambda for building the JsonArray
|
||||
*/
|
||||
public fun putJsonArray(key: String, builderAction: JsonArrayBuilder.() -> Unit): JsonElement? =
|
||||
put(key, buildJsonArray(builderAction))
|
||||
|
||||
internal fun build(): RequestMeta = RequestMeta(JsonObject(content))
|
||||
}
|
||||
|
||||
/**
|
||||
* Base DSL builder for constructing paginated MCP request instances.
|
||||
*
|
||||
* This abstract class extends [RequestBuilder] and adds pagination support
|
||||
* through an optional cursor field.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* listPromptsRequest {
|
||||
* cursor = "eyJwYWdlIjogMn0="
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see RequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public abstract class PaginatedRequestBuilder : RequestBuilder() {
|
||||
/**
|
||||
* Optional pagination cursor for fetching the next page of results.
|
||||
*
|
||||
* The cursor value is typically obtained from the previous page's response.
|
||||
*
|
||||
* Example: `cursor = "eyJwYWdlIjogMn0="`
|
||||
*/
|
||||
public var cursor: String? = null
|
||||
}
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [ListResourcesRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor][ListResourcesRequestBuilder.cursor] - Pagination cursor for fetching next page
|
||||
* - [meta][ListResourcesRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListResourcesRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListResourcesRequest {
|
||||
* cursor = "eyJwYWdlIjogMn0="
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the list resources request
|
||||
* @return A configured [ListResourcesRequest] instance
|
||||
* @see ListResourcesRequestBuilder
|
||||
* @see ListResourcesRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildListResourcesRequest(block: ListResourcesRequestBuilder.() -> Unit): ListResourcesRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListResourcesRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ListResourcesRequest] instances.
|
||||
*
|
||||
* This builder retrieves a list of available resources, with optional pagination support.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor] - Pagination cursor (inherited from [PaginatedRequestBuilder])
|
||||
* - [meta] - Metadata for the request (inherited from [RequestBuilder])
|
||||
*
|
||||
* @see buildListResourcesRequest
|
||||
* @see ListResourcesRequest
|
||||
* @see PaginatedRequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class ListResourcesRequestBuilder @PublishedApi internal constructor() : PaginatedRequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): ListResourcesRequest {
|
||||
val params = paginatedRequestParams(cursor = cursor, meta = meta)
|
||||
return ListResourcesRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [ReadResourceRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri][ReadResourceRequestBuilder.uri] - The URI of the resource to read
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][ReadResourceRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val request = buildReadResourceRequest {
|
||||
* uri = "file:///path/to/resource.txt"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the read resource request
|
||||
* @return A configured [ReadResourceRequest] instance
|
||||
* @see ReadResourceRequestBuilder
|
||||
* @see ReadResourceRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildReadResourceRequest(block: ReadResourceRequestBuilder.() -> Unit): ReadResourceRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ReadResourceRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ReadResourceRequest] instances.
|
||||
*
|
||||
* This builder reads the contents of a specific resource by URI.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri] - The URI of the resource to read
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildReadResourceRequest
|
||||
* @see ReadResourceRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class ReadResourceRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The URI of the resource to read. This is a required field.
|
||||
*
|
||||
* Example: `uri = "file:///path/to/resource.txt"`
|
||||
*/
|
||||
public var uri: String? = null
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): ReadResourceRequest {
|
||||
val uri = requireNotNull(uri) {
|
||||
"Missing required field 'uri'. Example: uri = \"file:///path/to/resource.txt\""
|
||||
}
|
||||
|
||||
val params = ReadResourceRequestParams(uri = uri, meta = meta)
|
||||
return ReadResourceRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [SubscribeRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri][SubscribeRequestBuilder.uri] - The URI of the resource to subscribe to
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][SubscribeRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val request = buildSubscribeRequest {
|
||||
* uri = "file:///path/to/resource.txt"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the subscribe request
|
||||
* @return A configured [SubscribeRequest] instance
|
||||
* @see SubscribeRequestBuilder
|
||||
* @see SubscribeRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildSubscribeRequest(block: SubscribeRequestBuilder.() -> Unit): SubscribeRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return SubscribeRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [SubscribeRequest] instances.
|
||||
*
|
||||
* This builder subscribes to updates for a specific resource by URI.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri] - The URI of the resource to subscribe to
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildSubscribeRequest
|
||||
* @see SubscribeRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class SubscribeRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The URI of the resource to subscribe to. This is a required field.
|
||||
*
|
||||
* Example: `uri = "file:///path/to/resource.txt"`
|
||||
*/
|
||||
public var uri: String? = null
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): SubscribeRequest {
|
||||
val uri = requireNotNull(uri) {
|
||||
"Missing required field 'uri'. Example: uri = \"file:///path/to/resource.txt\""
|
||||
}
|
||||
|
||||
val params = SubscribeRequestParams(uri = uri, meta = meta)
|
||||
return SubscribeRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an [UnsubscribeRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri][UnsubscribeRequestBuilder.uri] - The URI of the resource to unsubscribe from
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][UnsubscribeRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val request = buildUnsubscribeRequest {
|
||||
* uri = "file:///path/to/resource.txt"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the unsubscribe request
|
||||
* @return A configured [UnsubscribeRequest] instance
|
||||
* @see UnsubscribeRequestBuilder
|
||||
* @see UnsubscribeRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildUnsubscribeRequest(block: UnsubscribeRequestBuilder.() -> Unit): UnsubscribeRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return UnsubscribeRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [UnsubscribeRequest] instances.
|
||||
*
|
||||
* This builder unsubscribes from updates for a specific resource by URI.
|
||||
*
|
||||
* ## Required
|
||||
* - [uri] - The URI of the resource to unsubscribe from
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildUnsubscribeRequest
|
||||
* @see UnsubscribeRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class UnsubscribeRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The URI of the resource to unsubscribe from. This is a required field.
|
||||
*
|
||||
* Example: `uri = "file:///path/to/resource.txt"`
|
||||
*/
|
||||
public var uri: String? = null
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): UnsubscribeRequest {
|
||||
val uri = requireNotNull(uri) {
|
||||
"Missing required field 'uri'. Example: uri = \"file:///path/to/resource.txt\""
|
||||
}
|
||||
|
||||
val params = UnsubscribeRequestParams(uri = uri, meta = meta)
|
||||
return UnsubscribeRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [ListResourceTemplatesRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor][ListResourceTemplatesRequestBuilder.cursor] - Pagination cursor for fetching next page
|
||||
* - [meta][ListResourceTemplatesRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListResourceTemplatesRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListResourceTemplatesRequest {
|
||||
* cursor = "eyJwYWdlIjogMn0="
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the list resource templates request
|
||||
* @return A configured [ListResourceTemplatesRequest] instance
|
||||
* @see ListResourceTemplatesRequestBuilder
|
||||
* @see ListResourceTemplatesRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildListResourceTemplatesRequest(
|
||||
block: ListResourceTemplatesRequestBuilder.() -> Unit,
|
||||
): ListResourceTemplatesRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListResourceTemplatesRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ListResourceTemplatesRequest] instances.
|
||||
*
|
||||
* This builder retrieves a list of available resource templates, with optional pagination support.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor] - Pagination cursor (inherited from [PaginatedRequestBuilder])
|
||||
* - [meta] - Metadata for the request (inherited from [RequestBuilder])
|
||||
*
|
||||
* @see buildListResourceTemplatesRequest
|
||||
* @see ListResourceTemplatesRequest
|
||||
* @see PaginatedRequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class ListResourceTemplatesRequestBuilder @PublishedApi internal constructor() : PaginatedRequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): ListResourceTemplatesRequest {
|
||||
val params = paginatedRequestParams(cursor = cursor, meta = meta)
|
||||
return ListResourceTemplatesRequest(params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [ListRootsRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta][ListRootsRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example with no parameters:
|
||||
* ```kotlin
|
||||
* val request = buildListRootsRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with metadata:
|
||||
* ```kotlin
|
||||
* val request = buildListRootsRequest {
|
||||
* meta {
|
||||
* put("context", "initialization")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the list roots request
|
||||
* @return A configured [ListRootsRequest] instance
|
||||
* @see ListRootsRequestBuilder
|
||||
* @see ListRootsRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildListRootsRequest(block: ListRootsRequestBuilder.() -> Unit): ListRootsRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListRootsRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ListRootsRequest] instances.
|
||||
*
|
||||
* This builder retrieves the list of root URIs provided by the client.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildListRootsRequest
|
||||
* @see ListRootsRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class ListRootsRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): ListRootsRequest {
|
||||
val params = meta?.let { BaseRequestParams(meta = it) }
|
||||
return ListRootsRequest(params)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [CreateMessageRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [maxTokens][CreateMessageRequestBuilder.maxTokens] - Maximum number of tokens to generate
|
||||
* - [messages][CreateMessageRequestBuilder.messages] - List of conversation messages
|
||||
*
|
||||
* ## Optional
|
||||
* - [systemPrompt][CreateMessageRequestBuilder.systemPrompt] - System-level instructions
|
||||
* - [context][CreateMessageRequestBuilder.context] - Context inclusion settings
|
||||
* - [temperature][CreateMessageRequestBuilder.temperature] - Sampling temperature
|
||||
* - [stopSequences][CreateMessageRequestBuilder.stopSequences] - Sequences that stop generation
|
||||
* - [preferences][CreateMessageRequestBuilder.preferences] - Model selection preferences
|
||||
* - [metadata][CreateMessageRequestBuilder.metadata] - Additional metadata
|
||||
* - [meta][CreateMessageRequestBuilder.meta] - Request metadata
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* val request = buildCreateMessageRequest {
|
||||
* maxTokens = 1000
|
||||
* systemPrompt = "You are a helpful assistant"
|
||||
* messages {
|
||||
* user { "What is the capital of France?" }
|
||||
* assistant { "The capital of France is Paris." }
|
||||
* user { "What about Germany?" }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with preferences:
|
||||
* ```kotlin
|
||||
* val request = buildCreateMessageRequest {
|
||||
* maxTokens = 500
|
||||
* temperature = 0.7
|
||||
* preferences(
|
||||
* hints = listOf("claude-3-sonnet"),
|
||||
* intelligence = 0.8
|
||||
* )
|
||||
* messages {
|
||||
* user { "Explain quantum computing" }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the create message request
|
||||
* @return A configured [CreateMessageRequest] instance
|
||||
* @see CreateMessageRequestBuilder
|
||||
* @see CreateMessageRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildCreateMessageRequest(block: CreateMessageRequestBuilder.() -> Unit): CreateMessageRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return CreateMessageRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [CreateMessageRequest] instances.
|
||||
*
|
||||
* This builder creates LLM sampling requests with conversation history.
|
||||
*
|
||||
* ## Required
|
||||
* - [maxTokens] - Maximum number of tokens to generate
|
||||
* - [messages] - List of conversation messages
|
||||
*
|
||||
* ## Optional
|
||||
* - [systemPrompt] - System-level instructions
|
||||
* - [context] - Context inclusion settings
|
||||
* - [temperature] - Sampling temperature (0.0-1.0)
|
||||
* - [stopSequences] - Sequences that stop generation
|
||||
* - [preferences] - Model selection preferences
|
||||
* - [metadata] - Additional metadata
|
||||
* - [meta] - Request metadata
|
||||
*
|
||||
* @see buildCreateMessageRequest
|
||||
* @see CreateMessageRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class CreateMessageRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/** Maximum number of tokens to generate. This is a required field. */
|
||||
public var maxTokens: Int? = null
|
||||
|
||||
/** Optional system-level instructions for the model. */
|
||||
public var systemPrompt: String? = null
|
||||
|
||||
/** Optional context inclusion settings. */
|
||||
public var context: IncludeContext? = null
|
||||
|
||||
/** Optional sampling temperature (0.0-1.0). Lower values are more deterministic. */
|
||||
public var temperature: Double? = null
|
||||
|
||||
/** Optional sequences that will stop generation when encountered. */
|
||||
public var stopSequences: List<String>? = null
|
||||
|
||||
private var messages: List<SamplingMessage>? = null
|
||||
private var preferences: ModelPreferences? = null
|
||||
private var metadata: JsonObject? = null
|
||||
|
||||
/**
|
||||
* Sets messages directly from a list.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages(listOf(
|
||||
* SamplingMessage(Role.User, TextContent("Hello")),
|
||||
* SamplingMessage(Role.Assistant, TextContent("Hi!"))
|
||||
* ))
|
||||
* ```
|
||||
*/
|
||||
public fun messages(messages: List<SamplingMessage>) {
|
||||
this.messages = messages
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets messages using a DSL builder.
|
||||
*
|
||||
* This is the recommended way to define conversation messages.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* user { "What is 2+2?" }
|
||||
* assistant { "2+2 equals 4." }
|
||||
* user { "What about 3+3?" }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public fun messages(block: SamplingMessageBuilder.() -> Unit) {
|
||||
this.messages = SamplingMessageBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets model preferences directly.
|
||||
*/
|
||||
public fun preferences(value: ModelPreferences) {
|
||||
this.preferences = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets model selection preferences using individual parameters.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* preferences(
|
||||
* hints = listOf("claude-3-sonnet"),
|
||||
* intelligence = 0.9,
|
||||
* speed = 0.5
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @param hints Model name hints for selection
|
||||
* @param cost Cost optimization priority (0.0-1.0)
|
||||
* @param speed Speed optimization priority (0.0-1.0)
|
||||
* @param intelligence Intelligence optimization priority (0.0-1.0)
|
||||
*/
|
||||
public fun preferences(
|
||||
hints: List<String>? = null,
|
||||
cost: Double? = null,
|
||||
speed: Double? = null,
|
||||
intelligence: Double? = null,
|
||||
) {
|
||||
this.preferences = ModelPreferences(
|
||||
hints = hints?.map { ModelHint(it) },
|
||||
costPriority = cost,
|
||||
speedPriority = speed,
|
||||
intelligencePriority = intelligence,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets additional metadata using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* metadata {
|
||||
* put("userId", "123")
|
||||
* put("sessionId", "abc")
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
public fun metadata(block: JsonObjectBuilder.() -> Unit) {
|
||||
this.metadata = buildJsonObject(block)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): CreateMessageRequest {
|
||||
val maxTokens = requireNotNull(maxTokens) {
|
||||
"Missing required field 'maxTokens'. Example: maxTokens = 1000"
|
||||
}
|
||||
val messages = requireNotNull(messages) {
|
||||
"Missing required field 'messages'. Use messages { user { \"text\" } }"
|
||||
}
|
||||
|
||||
val params = CreateMessageRequestParams(
|
||||
maxTokens = maxTokens,
|
||||
messages = messages,
|
||||
modelPreferences = preferences,
|
||||
systemPrompt = systemPrompt,
|
||||
includeContext = context,
|
||||
temperature = temperature,
|
||||
stopSequences = stopSequences,
|
||||
metadata = metadata,
|
||||
meta = meta,
|
||||
)
|
||||
return CreateMessageRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing lists of [SamplingMessage] instances.
|
||||
*
|
||||
* This builder creates a conversation history for LLM sampling requests.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* user { "Hello!" }
|
||||
* assistant { "Hi! How can I help?" }
|
||||
* user { "What's 2+2?" }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see SamplingMessage
|
||||
* @see CreateMessageRequestBuilder.messages
|
||||
*/
|
||||
@McpDsl
|
||||
public class SamplingMessageBuilder @PublishedApi internal constructor() {
|
||||
private val messages = mutableListOf<SamplingMessage>()
|
||||
|
||||
/**
|
||||
* Adds a user message with the specified content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* user(TextContent("Hello"))
|
||||
* ```
|
||||
*/
|
||||
public fun user(content: MediaContent) {
|
||||
messages.add(SamplingMessage(Role.User, content))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an assistant message with the specified content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* assistant(TextContent("Hi there!"))
|
||||
* ```
|
||||
*/
|
||||
public fun assistant(content: MediaContent) {
|
||||
messages.add(SamplingMessage(Role.Assistant, content))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): List<SamplingMessage> = messages
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a user message with simple text content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* user { "What is the weather today?" }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.user(block: () -> String): Unit = this.user(TextContent(text = block()))
|
||||
|
||||
/**
|
||||
* Adds a user message with text content using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* userText {
|
||||
* text = "Important message"
|
||||
* annotations(priority = 1.0)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.userText(block: TextContentBuilder.() -> Unit): Unit =
|
||||
this.user(TextContentBuilder().apply(block).build())
|
||||
|
||||
/**
|
||||
* Adds a user message with image content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* userImage {
|
||||
* data = base64ImageData
|
||||
* mimeType = "image/png"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.userImage(block: ImageContentBuilder.() -> Unit): Unit =
|
||||
this.user(ImageContentBuilder().apply(block).build())
|
||||
|
||||
/**
|
||||
* Adds a user message with audio content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* userAudio {
|
||||
* data = base64AudioData
|
||||
* mimeType = "audio/wav"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.userAudio(block: AudioContentBuilder.() -> Unit): Unit =
|
||||
this.user(AudioContentBuilder().apply(block).build())
|
||||
|
||||
/**
|
||||
* Adds an assistant message with simple text content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* assistant { "The weather is sunny today." }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.assistant(block: () -> String): Unit = this.assistant(TextContent(text = block()))
|
||||
|
||||
/**
|
||||
* Adds an assistant message with text content using a DSL builder.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* assistantText {
|
||||
* text = "Here's the answer"
|
||||
* annotations(priority = 0.8)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.assistantText(block: TextContentBuilder.() -> Unit): Unit =
|
||||
this.assistant(TextContentBuilder().apply(block).build())
|
||||
|
||||
/**
|
||||
* Adds an assistant message with image content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* assistantImage {
|
||||
* data = generatedImageData
|
||||
* mimeType = "image/jpeg"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.assistantImage(block: ImageContentBuilder.() -> Unit): Unit =
|
||||
this.assistant(ImageContentBuilder().apply(block).build())
|
||||
|
||||
/**
|
||||
* Adds an assistant message with audio content.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* messages {
|
||||
* assistantAudio {
|
||||
* data = generatedAudioData
|
||||
* mimeType = "audio/mpeg"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@ExperimentalMcpApi
|
||||
public fun SamplingMessageBuilder.assistantAudio(block: AudioContentBuilder.() -> Unit): Unit =
|
||||
this.assistant(AudioContentBuilder().apply(block).build())
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
package io.modelcontextprotocol.kotlin.sdk.types
|
||||
|
||||
import io.modelcontextprotocol.kotlin.sdk.ExperimentalMcpApi
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* Creates a [CallToolRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Required
|
||||
* - [name][CallToolRequestBuilder.name] - The name of the tool to call
|
||||
*
|
||||
* ## Optional
|
||||
* - [arguments][CallToolRequestBuilder.arguments] - Arguments to pass to the tool
|
||||
* - [meta][CallToolRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without arguments:
|
||||
* ```kotlin
|
||||
* val request = buildCallToolRequest {
|
||||
* name = "getCurrentTime"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Example with arguments:
|
||||
* ```kotlin
|
||||
* val request = buildCallToolRequest {
|
||||
* name = "searchDatabase"
|
||||
* arguments {
|
||||
* put("query", "users")
|
||||
* put("limit", 10)
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the call tool request
|
||||
* @return A configured [CallToolRequest] instance
|
||||
* @see CallToolRequestBuilder
|
||||
* @see CallToolRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildCallToolRequest(block: CallToolRequestBuilder.() -> Unit): CallToolRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return CallToolRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [CallToolRequest] instances.
|
||||
*
|
||||
* This builder invokes a specific tool by name with optional arguments.
|
||||
*
|
||||
* ## Required
|
||||
* - [name] - The name of the tool to call
|
||||
*
|
||||
* ## Optional
|
||||
* - [arguments] - Arguments to pass to the tool
|
||||
* - [meta] - Metadata for the request
|
||||
*
|
||||
* @see buildCallToolRequest
|
||||
* @see CallToolRequest
|
||||
*/
|
||||
@McpDsl
|
||||
public class CallToolRequestBuilder @PublishedApi internal constructor() : RequestBuilder() {
|
||||
/**
|
||||
* The name of the tool to call. This is a required field.
|
||||
*
|
||||
* Example: `name = "getCurrentTime"`
|
||||
*/
|
||||
public var name: String? = null
|
||||
|
||||
private var arguments: JsonObject? = null
|
||||
|
||||
/**
|
||||
* Sets tool arguments directly from a JsonObject.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* arguments(buildJsonObject {
|
||||
* put("query", "users")
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
public fun arguments(arguments: JsonObject) {
|
||||
this.arguments = arguments
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tool arguments using a DSL builder.
|
||||
*
|
||||
* This is the recommended way to provide tool arguments.
|
||||
*
|
||||
* Example:
|
||||
* ```kotlin
|
||||
* arguments {
|
||||
* put("query", "SELECT * FROM users")
|
||||
* put("limit", 100)
|
||||
* put("includeDeleted", false)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Lambda for building the arguments JsonObject
|
||||
*/
|
||||
public fun arguments(block: JsonObjectBuilder.() -> Unit): Unit = arguments(buildJsonObject(block))
|
||||
|
||||
@PublishedApi
|
||||
override fun build(): CallToolRequest {
|
||||
val name = requireNotNull(name) {
|
||||
"Missing required field 'name'. Example: name = \"toolName\""
|
||||
}
|
||||
|
||||
val params = CallToolRequestParams(name = name, arguments = arguments, meta = meta)
|
||||
return CallToolRequest(params)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [ListToolsRequest] using a type-safe DSL builder.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor][ListToolsRequestBuilder.cursor] - Pagination cursor for fetching next page
|
||||
* - [meta][ListToolsRequestBuilder.meta] - Metadata for the request
|
||||
*
|
||||
* Example without pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListToolsRequest { }
|
||||
* ```
|
||||
*
|
||||
* Example with pagination:
|
||||
* ```kotlin
|
||||
* val request = buildListToolsRequest {
|
||||
* cursor = "eyJwYWdlIjogMn0="
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param block Configuration lambda for setting up the list tools request
|
||||
* @return A configured [ListToolsRequest] instance
|
||||
* @see ListToolsRequestBuilder
|
||||
* @see ListToolsRequest
|
||||
*/
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@ExperimentalMcpApi
|
||||
internal inline fun buildListToolsRequest(block: ListToolsRequestBuilder.() -> Unit): ListToolsRequest {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListToolsRequestBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* DSL builder for constructing [ListToolsRequest] instances.
|
||||
*
|
||||
* This builder retrieves a list of available tools, with optional pagination support.
|
||||
* All fields are optional.
|
||||
*
|
||||
* ## Optional
|
||||
* - [cursor] - Pagination cursor (inherited from [PaginatedRequestBuilder])
|
||||
* - [meta] - Metadata for the request (inherited from [RequestBuilder])
|
||||
*
|
||||
* @see buildListToolsRequest
|
||||
* @see ListToolsRequest
|
||||
* @see PaginatedRequestBuilder
|
||||
*/
|
||||
@McpDsl
|
||||
public class ListToolsRequestBuilder @PublishedApi internal constructor() : PaginatedRequestBuilder() {
|
||||
@PublishedApi
|
||||
override fun build(): ListToolsRequest {
|
||||
val params = paginatedRequestParams(cursor = cursor, meta = meta)
|
||||
return ListToolsRequest(params)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue