Add options in Transport.send method (#408)
Add support for `TransportSendOptions` in `Transport.send` method ## Motivation and Context This change extends the `Transport.send` method signature to support advanced transport features like resumption tokens and progress callbacks. This is needed to enable: - Long-running request resumption after reconnection - Request-response association tracking - Progress token handling in transport layer needed for #235 ## How Has This Been Tested? All transport tests passed ## Breaking Changes Yes, it’s necessary to update the custom Transport implementations. For users who rely on the transports provided by the sdk, there’s no breaking change ## Types of changes - [x] 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 - [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
This commit is contained in:
parent
74c93745cd
commit
2b9dfd9466
6 changed files with 186 additions and 63 deletions
|
|
@ -5,6 +5,7 @@ import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
|
|||
import io.modelcontextprotocol.kotlin.sdk.server.ServerSession
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.InMemoryTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.ClientCapabilities
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageRequest
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.CreateMessageResult
|
||||
|
|
@ -63,7 +64,7 @@ class ClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
initialised = true
|
||||
val result = InitializeResult(
|
||||
|
|
@ -109,7 +110,7 @@ class ClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
|
||||
|
|
@ -158,7 +159,7 @@ class ClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
|
||||
|
|
@ -205,7 +206,7 @@ class ClientTest {
|
|||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw IllegalStateException("Test error")
|
||||
|
|
@ -239,7 +240,7 @@ class ClientTest {
|
|||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw McpException(
|
||||
|
|
@ -277,7 +278,7 @@ class ClientTest {
|
|||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw StreamableHttpError(
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
|
|||
import io.modelcontextprotocol.kotlin.sdk.server.ServerSession
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.InMemoryTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.cancel
|
||||
|
|
@ -57,7 +58,7 @@ class OldSchemaClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
initialised = true
|
||||
val result = InitializeResult(
|
||||
|
|
@ -103,7 +104,7 @@ class OldSchemaClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
|
||||
|
|
@ -152,7 +153,7 @@ class OldSchemaClientTest {
|
|||
val clientTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
|
||||
|
|
@ -199,7 +200,7 @@ class OldSchemaClientTest {
|
|||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw IllegalStateException("Test error")
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class InMemoryTransport : AbstractTransport() {
|
|||
_onClose.invoke()
|
||||
}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
val other = otherTransport ?: throw IllegalStateException("Not connected")
|
||||
|
||||
other._onMessage.invoke(message)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class OldSchemaInMemoryTransport : AbstractTransport() {
|
|||
_onClose.invoke()
|
||||
}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
val other = otherTransport ?: throw IllegalStateException("Not connected")
|
||||
|
||||
other._onMessage.invoke(message)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.ktor.server.routing.routing
|
|||
import io.modelcontextprotocol.kotlin.sdk.server.Server
|
||||
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.GetPromptResult
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Implementation
|
||||
|
|
@ -427,7 +428,7 @@ class HttpServerTransport(private val sessionId: String) : AbstractTransport() {
|
|||
logger.debug { "Starting HTTP server transport for session: $sessionId" }
|
||||
}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
logger.info { "Sending message: $message" }
|
||||
|
||||
if (message is JSONRPCResponse) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import io.modelcontextprotocol.kotlin.sdk.server.Server
|
|||
import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.AbstractTransport
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.McpJson
|
||||
import io.modelcontextprotocol.kotlin.sdk.shared.TransportSendOptions
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.RPCError
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
|
|
@ -428,7 +429,7 @@ class OldSchemaHttpServerTransport(private val sessionId: String) : AbstractTran
|
|||
logger.debug { "Starting HTTP server transport for session: $sessionId" }
|
||||
}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
override suspend fun send(message: JSONRPCMessage, options: TransportSendOptions?) {
|
||||
logger.info { "Sending message: $message" }
|
||||
|
||||
if (message is JSONRPCResponse) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue