Add backwards compatibility constructors and tests (#395)

- Updated integration tests to include assertions for `meta` being
`null` in the `listTools`, `listResources`, `readResource`, and
`callTool` results.
- Renamed test cases in `SseServerIntegrationTest` for clarity.
- Added (deprecated) synthetic constructors for various request
parameter classes.
- Enhanced naming conventions and structure in integration test cases.
- Replaced `throw Error(...)` with `error(...)` for cleaner error
handling.

## Motivation and Context
To verify backwards-compatibility after schema change

## How Has This Been Tested?
CI, integration tests, regression tests (samples)

## Breaking Changes
<!-- Will users need to update their code or configurations? -->

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [x] Test update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [ ] New and existing tests pass locally
- [ ] I have added appropriate error handling
- [ ] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
This commit is contained in:
Konstantin Pavlov 2025-11-12 20:18:57 +02:00 • committed by GitHub
commit 8bdbd36c32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 250 additions and 71 deletions

View file

@ -16,6 +16,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertNull
import org.junit.jupiter.api.assertThrows
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.Ignore
@ -145,6 +146,7 @@ abstract class OldSchemaAbstractResourceIntegrationTest : OldSchemaKotlinTestBas
val result = client.listResources()
assertNotNull(result, "List resources result should not be null")
assertNull(actual = result.meta, "List resources meta should be null")
assertTrue(result.resources.isNotEmpty(), "Resources list should not be empty")
val testResource = result.resources.find { it.uri == testResourceUri }
@ -158,6 +160,7 @@ abstract class OldSchemaAbstractResourceIntegrationTest : OldSchemaKotlinTestBas
val result = client.readResource(ReadResourceRequest(ReadResourceRequestParams(uri = testResourceUri)))
assertNotNull(result, "Read resource result should not be null")
assertNull(actual = result.meta, "Read resource result meta should be null")
assertTrue(result.contents.isNotEmpty(), "Resource contents should not be empty")
val content = result.contents.firstOrNull() as? TextResourceContents

View file

@ -21,6 +21,7 @@ import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertNull
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale
@ -431,7 +432,8 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
fun testListTools(): Unit = runBlocking(Dispatchers.IO) {
val result = client.listTools()
assertNotNull(result, "List utils result should not be null")
assertNotNull(result, "List tools result should not be null")
assertNull(actual = result.meta, "List tools result meta should be null")
assertTrue(result.tools.isNotEmpty(), "Tools list should not be empty")
val testTool = result.tools.find { it.name == testToolName }
@ -449,7 +451,8 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val testText = "Hello, world!"
val arguments = mapOf("text" to testText)
val result = client.callTool(testToolName, arguments) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
val result = client.callTool(testToolName, arguments)
assertNull(actual = result.meta, "CallTool result meta should be null")
val actualContent = result.structuredContent.toString()
val expectedContent = """
@ -478,7 +481,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val result = client.callTool(
complexToolName,
arguments,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
val actualContent = result.structuredContent.toString()
val expectedContent = """
@ -518,7 +521,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val errorResult = client.callTool(
errorToolName,
errorArgs,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
val actualError = errorResult.structuredContent.toString()
val expectedError = """
@ -538,7 +541,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val exceptionResult = client.callTool(
errorToolName,
exceptionArgs,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
assertTrue(exceptionResult.isError ?: false, "isError should be true for exception")
@ -563,7 +566,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val result = client.callTool(
multiContentToolName,
arguments,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
assertEquals(
2,
@ -603,7 +606,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val textOnlyResult = client.callTool(
multiContentToolName,
textOnlyArgs,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
assertEquals(
1,
@ -645,7 +648,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
arguments = arguments,
),
),
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
val actualContent = result.structuredContent.toString()
val expectedContent = """
@ -671,7 +674,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val result = client.callTool(
largeToolName,
arguments,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
val content = result.content.firstOrNull() as TextContent
assertNotNull(content, "Tool result content should be TextContent")
@ -692,7 +695,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val arguments = mapOf("delay" to delay)
val startTime = System.currentTimeMillis()
val result = client.callTool(slowToolName, arguments) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
val result = client.callTool(slowToolName, arguments)
val endTime = System.currentTimeMillis()
val content = result.content.firstOrNull() as? TextContent
@ -718,7 +721,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
val result = client.callTool(
specialCharsToolName,
arguments,
) as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
)
val content = result.content.firstOrNull() as? TextContent
assertNotNull(content, "Tool result content should be TextContent")
@ -802,7 +805,7 @@ abstract class OldSchemaAbstractToolIntegrationTest : OldSchemaKotlinTestBase()
}
assertNotNull(result, "Tool call result should not be null")
val callResult = result as io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
val callResult = result
assertTrue(callResult.isError ?: false, "isError should be true for non-existent tool")
val textContent = callResult.content.firstOrNull { it is TextContent } as? TextContent