fix: reject duplicate initialize requests in ServerSession (#624)

`ServerSession.handleInitialize()` now rejects duplicate `initialize`
requests with `INVALID_REQUEST` (-32600) error. `clientCapabilities` and
`clientVersion` changed from `var` to `AtomicRef`-backed `val`, with
atomic `compareAndSet(null, ...)` serving as both the guard and the
write

## How Has This Been Tested?
second `initialize` returns error, original capabilities preserved

## 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
- [x] I have added or updated documentation as needed

## Additional context
<!-- Add any other context, implementation notes, or design decisions
-->
This commit is contained in:
Pavel Gorgulov 2026-03-27 16:16:10 +01:00 • committed by GitHub
commit 9c0aa45e2a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -20,8 +20,10 @@ import io.modelcontextprotocol.kotlin.sdk.types.ListRootsRequest
import io.modelcontextprotocol.kotlin.sdk.types.ListRootsResult
import io.modelcontextprotocol.kotlin.sdk.types.LoggingLevel
import io.modelcontextprotocol.kotlin.sdk.types.LoggingMessageNotification
import io.modelcontextprotocol.kotlin.sdk.types.McpException
import io.modelcontextprotocol.kotlin.sdk.types.Method
import io.modelcontextprotocol.kotlin.sdk.types.Method.Defined
import io.modelcontextprotocol.kotlin.sdk.types.RPCError
import io.modelcontextprotocol.kotlin.sdk.types.RequestMeta
import io.modelcontextprotocol.kotlin.sdk.types.ResourceUpdatedNotification
import io.modelcontextprotocol.kotlin.sdk.types.SUPPORTED_PROTOCOL_VERSIONS
@ -52,17 +54,18 @@ public open class ServerSession(
private var _onClose: () -> Unit = {}
private val _clientCapabilities: AtomicRef<ClientCapabilities?> = atomic(null)
private val _clientVersion: AtomicRef<Implementation?> = atomic(null)
/**
* The client's reported capabilities after initialization.
*/
public var clientCapabilities: ClientCapabilities? = null
private set
public val clientCapabilities: ClientCapabilities? get() = _clientCapabilities.value
/**
* The client's version information after initialization.
*/
public var clientVersion: Implementation? = null
private set
public val clientVersion: Implementation? get() = _clientVersion.value
/**
* The capabilities supported by the server, related to the session.
@ -286,9 +289,15 @@ public open class ServerSession(
}
private fun handleInitialize(request: InitializeRequest): InitializeResult {
if (!_clientCapabilities.compareAndSet(null, request.params.capabilities)) {
throw McpException(
code = RPCError.ErrorCode.INVALID_REQUEST,
message = "Server already initialized",
)
}
logger.debug { "Handling initialization request from client" }
clientCapabilities = request.params.capabilities
clientVersion = request.params.clientInfo
_clientVersion.value = request.params.clientInfo
val requestedVersion = request.params.protocolVersion
val protocolVersion = if (SUPPORTED_PROTOCOL_VERSIONS.contains(requestedVersion)) {