Handle additional error types in client initialization handling (#404)
May throw the following exceptions: `CancellationException`,
`McpException`, `StreamableHttpError`, and `SerializationException`
## Motivation and Context
This makes it possible to handle errors directly without needing to
inspect the cause. For example:
```kotlin
try {
client.connect(transport)
} catch (e: StreamableHttpError) {
// ...
}
```
## How Has This Been Tested?
locally
## Breaking Changes
None
## Types of changes
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] 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
- [ ] I have added or updated documentation as needed
This commit is contained in:
parent
42c92608dd
commit
0f9209ad4a
1 changed files with 88 additions and 5 deletions
|
|
@ -26,6 +26,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ListToolsResult
|
|||
import io.modelcontextprotocol.kotlin.sdk.types.LoggingLevel
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.LoggingMessageNotification
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.LoggingMessageNotificationParams
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.McpException
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Method
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Role
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Root
|
||||
|
|
@ -232,6 +233,82 @@ class ClientTest {
|
|||
assertTrue(closed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should rethrow McpException as is`() = runTest {
|
||||
var closed = false
|
||||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw McpException(
|
||||
code = -32600,
|
||||
message = "Invalid Request",
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun close() {
|
||||
closed = true
|
||||
}
|
||||
}
|
||||
|
||||
val client = Client(
|
||||
clientInfo = Implementation(
|
||||
name = "test client",
|
||||
version = "1.0",
|
||||
),
|
||||
options = ClientOptions(),
|
||||
)
|
||||
|
||||
val exception = assertFailsWith<McpException> {
|
||||
client.connect(failingTransport)
|
||||
}
|
||||
|
||||
assertEquals(-32600, exception.code)
|
||||
assertEquals("MCP error -32600: Invalid Request", exception.message)
|
||||
|
||||
assertTrue(closed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should rethrow StreamableHttpError as is`() = runTest {
|
||||
var closed = false
|
||||
val failingTransport = object : AbstractTransport() {
|
||||
override suspend fun start() {}
|
||||
|
||||
override suspend fun send(message: JSONRPCMessage) {
|
||||
if (message !is JSONRPCRequest) return
|
||||
check(message.method == Method.Defined.Initialize.value)
|
||||
throw StreamableHttpError(
|
||||
code = 500,
|
||||
message = "Internal Server Error",
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun close() {
|
||||
closed = true
|
||||
}
|
||||
}
|
||||
|
||||
val client = Client(
|
||||
clientInfo = Implementation(
|
||||
name = "test client",
|
||||
version = "1.0",
|
||||
),
|
||||
options = ClientOptions(),
|
||||
)
|
||||
|
||||
val exception = assertFailsWith<StreamableHttpError> {
|
||||
client.connect(failingTransport)
|
||||
}
|
||||
|
||||
assertEquals(500, exception.code)
|
||||
assertEquals("Streamable HTTP error: Internal Server Error", exception.message)
|
||||
|
||||
assertTrue(closed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should respect server capabilities`() = runTest {
|
||||
val serverOptions = ServerOptions(
|
||||
|
|
@ -922,7 +999,7 @@ class ClientTest {
|
|||
println("Client connected")
|
||||
},
|
||||
launch {
|
||||
serverSessionResult.complete(server.connect(serverTransport))
|
||||
serverSessionResult.complete(server.createSession(serverTransport))
|
||||
println("Server connected")
|
||||
},
|
||||
).joinAll()
|
||||
|
|
|
|||
Loading…
Reference in a new issue