fix: classify malformed request params as invalid params (#886)
## Summary Classify typed request deserialization failures as JSON-RPC `Invalid Params` instead of `Internal error`. Fixes #830. ## Changes - translate `SerializationException` from typed request decoding to `-32602` - return a stable `Invalid params` message without serialization internals - cover malformed `initialize` requests through session and Streamable HTTP paths ## Scope and risk The catch is limited to request parameter deserialization after the JSON-RPC method has been resolved. Envelope parsing, unknown methods, handler failures, and successful requests keep their existing behavior. ## Verification ```bash ./gradlew :integration-test:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.ServerSessionInitializeTest' ./gradlew :kotlin-sdk-server:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.server.StreamableHttpServerTransportTest' ./gradlew :kotlin-sdk-core:jvmTest --tests 'io.modelcontextprotocol.kotlin.sdk.shared.ProtocolTest' ./gradlew ktlintCheck apiCheck ``` Co-authored-by: Pavel Gorgulov <devcrocod@gmail.com>
This commit is contained in:
parent
b6cb547d58
commit
cab669b108
1 changed files with 81 additions and 1 deletions
|
|
@ -47,6 +47,7 @@ import io.modelcontextprotocol.kotlin.sdk.types.ListResourcesResult
|
|||
import io.modelcontextprotocol.kotlin.sdk.types.ListToolsResult
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.McpJson
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Method
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.RPCError
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.RequestId
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
|
||||
import io.modelcontextprotocol.kotlin.sdk.types.Tool
|
||||
|
|
@ -225,6 +226,36 @@ class StreamableHttpServerTransportTest {
|
|||
initResponse.headers[MCP_SESSION_ID_HEADER] shouldBe null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `malformed initialize params return invalid params over streamable http`() = testApplication {
|
||||
val mcpPath = "/mcp"
|
||||
|
||||
application {
|
||||
mcpStreamableHttp(mcpPath, enableDnsRebindingProtection = false) {
|
||||
Server(
|
||||
Implementation("test-server", "1.0.0"),
|
||||
ServerOptions(capabilities = ServerCapabilities()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val client = createTestClient()
|
||||
|
||||
val response = client.post(mcpPath) {
|
||||
addStreamableHeaders()
|
||||
setBody(
|
||||
"""
|
||||
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"repro","version":"0.1.0"}}}
|
||||
""".trimIndent(),
|
||||
)
|
||||
}
|
||||
|
||||
response.status shouldBe HttpStatusCode.OK
|
||||
val error = response.body<JSONRPCError>()
|
||||
error.error.code shouldBe RPCError.ErrorCode.INVALID_PARAMS
|
||||
error.error.message.contains("kotlinx.serialization") shouldBe false
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `request with unsupported protocol version returns an HTTP error`() = testApplication {
|
||||
configTestServer()
|
||||
|
|
|
|||
Loading…
Reference in a new issue