feat(server): add onSessionClose hook to ClientConnection#737
Conversation
|
@devcrocod follow-up to #733 — same access pattern, just delegating to the existing |
There was a problem hiding this comment.
Pull request overview
Adds a new public cleanup hook to the server-side handler surface by exposing ServerSession.onClose via ClientConnection.onSessionClose, enabling tools/prompts/resources to register session-scoped resource cleanup directly.
Changes:
- Add
ClientConnection.onSessionClose(block: () -> Unit)and delegate toServerSession.onClose. - Update public API dump to include the new method.
- Add integration tests asserting callback execution on close and registration-order invocation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| kotlin-sdk-server/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnection.kt | Adds the onSessionClose API and delegates to ServerSession close callback chain. |
| kotlin-sdk-server/api/kotlin-sdk-server.api | Updates API surface to include onSessionClose. |
| integration-test/src/jvmTest/kotlin/io/modelcontextprotocol/kotlin/sdk/server/ClientConnectionTest.kt | Adds integration tests for onSessionClose execution and ordering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| override fun onSessionClose(block: () -> Unit) { | ||
| session.onClose(block) | ||
| } |
| } | ||
|
|
||
| override fun onSessionClose(block: () -> Unit) { | ||
| session.onClose(block) |
devcrocod
left a comment
There was a problem hiding this comment.
I have some doubts
On the one hand, this is a useful method. On the other hand, it significantly blurs the responsibility of ClientConnection, since it adds lifecycle management to it
| notification(notification) | ||
| } | ||
|
|
||
| override fun onSessionClose(block: () -> Unit) { |
There was a problem hiding this comment.
If a callback is registered after the session has already been closed, it will never be invoked
| notification(notification) | ||
| } | ||
|
|
||
| override fun onSessionClose(block: () -> Unit) { |
There was a problem hiding this comment.
It seems like this could potentially cause a leak. Would it make sense to use DisposableHandle?
Adds an
onSessionClose(block: () -> Unit)hook onClientConnection, delegating to the existing callback chain onServerSession.onClose.closes #553
Motivation and Context
Tool, prompt, and resource handlers often acquire session-scoped resources — DB connections, temporary files, background coroutines — that need to be released when the session terminates. Today there's no first-class way for a handler to register that cleanup: the only workaround is to fish the
ServerSessionout of theServerviasessionIdand call its internalonClose, which is awkward and easy to get wrong.This mirrors the access pattern from #552 (#733): expose what
ServerSessionalready does through the publicClientConnectionsurface so handlers can reach it directly.How Has This Been Tested?
Two integration tests in
ClientConnectionTest:onSessionClose callback runs when the session closes— register from a tool handler, close the client, assert the callback fires.multiple onSessionClose callbacks run in registration order— verifies the documented ordering guarantee inherited fromServerSession.onClose.Only the tool-handler case is exercised because
onSessionCloseis session-scoped — the registration site (tool vs. prompt vs. resource) doesn't change behavior, and adding three near-identical tests would just be noise.Breaking Changes
None for consumers. Adds one abstract method to
ClientConnection, which would require any external implementer to recompile — butClientConnectionImplis the only implementation and isinternal.Types of changes
Checklist